0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011
0012 #include <linux/stddef.h>
0013 #include <linux/module.h>
0014 #include <linux/ioport.h>
0015 #include <linux/init.h>
0016 #include <linux/gameport.h>
0017 #include <linux/slab.h>
0018 #include <linux/delay.h>
0019 #include <linux/workqueue.h>
0020 #include <linux/sched.h> /* HZ */
0021 #include <linux/mutex.h>
0022 #include <linux/timekeeping.h>
0023
0024
0025
0026 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0027 MODULE_DESCRIPTION("Generic gameport layer");
0028 MODULE_LICENSE("GPL");
0029
0030 static bool use_ktime = true;
0031 module_param(use_ktime, bool, 0400);
0032 MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed");
0033
0034
0035
0036
0037
0038 static DEFINE_MUTEX(gameport_mutex);
0039
0040 static LIST_HEAD(gameport_list);
0041
0042 static struct bus_type gameport_bus;
0043
0044 static void gameport_add_port(struct gameport *gameport);
0045 static void gameport_attach_driver(struct gameport_driver *drv);
0046 static void gameport_reconnect_port(struct gameport *gameport);
0047 static void gameport_disconnect_port(struct gameport *gameport);
0048
0049 #if defined(__i386__)
0050
0051 #include <linux/i8253.h>
0052
0053 #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
0054 #define GET_TIME(x) do { x = get_time_pit(); } while (0)
0055
0056 static unsigned int get_time_pit(void)
0057 {
0058 unsigned long flags;
0059 unsigned int count;
0060
0061 raw_spin_lock_irqsave(&i8253_lock, flags);
0062 outb_p(0x00, 0x43);
0063 count = inb_p(0x40);
0064 count |= inb_p(0x40) << 8;
0065 raw_spin_unlock_irqrestore(&i8253_lock, flags);
0066
0067 return count;
0068 }
0069
0070 #endif
0071
0072
0073
0074
0075
0076
0077
0078 static int gameport_measure_speed(struct gameport *gameport)
0079 {
0080 unsigned int i, t, tx;
0081 u64 t1, t2, t3;
0082 unsigned long flags;
0083
0084 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
0085 return 0;
0086
0087 tx = ~0;
0088
0089 for (i = 0; i < 50; i++) {
0090 local_irq_save(flags);
0091 t1 = ktime_get_ns();
0092 for (t = 0; t < 50; t++)
0093 gameport_read(gameport);
0094 t2 = ktime_get_ns();
0095 t3 = ktime_get_ns();
0096 local_irq_restore(flags);
0097 udelay(i * 10);
0098 t = (t2 - t1) - (t3 - t2);
0099 if (t < tx)
0100 tx = t;
0101 }
0102
0103 gameport_close(gameport);
0104 t = 1000000 * 50;
0105 if (tx)
0106 t /= tx;
0107 return t;
0108 }
0109
0110 static int old_gameport_measure_speed(struct gameport *gameport)
0111 {
0112 #if defined(__i386__)
0113
0114 unsigned int i, t, t1, t2, t3, tx;
0115 unsigned long flags;
0116
0117 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
0118 return 0;
0119
0120 tx = 1 << 30;
0121
0122 for(i = 0; i < 50; i++) {
0123 local_irq_save(flags);
0124 GET_TIME(t1);
0125 for (t = 0; t < 50; t++) gameport_read(gameport);
0126 GET_TIME(t2);
0127 GET_TIME(t3);
0128 local_irq_restore(flags);
0129 udelay(i * 10);
0130 if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
0131 }
0132
0133 gameport_close(gameport);
0134 return 59659 / (tx < 1 ? 1 : tx);
0135
0136 #elif defined (__x86_64__)
0137
0138 unsigned int i, t;
0139 unsigned long tx, t1, t2, flags;
0140
0141 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
0142 return 0;
0143
0144 tx = 1 << 30;
0145
0146 for(i = 0; i < 50; i++) {
0147 local_irq_save(flags);
0148 t1 = rdtsc();
0149 for (t = 0; t < 50; t++) gameport_read(gameport);
0150 t2 = rdtsc();
0151 local_irq_restore(flags);
0152 udelay(i * 10);
0153 if (t2 - t1 < tx) tx = t2 - t1;
0154 }
0155
0156 gameport_close(gameport);
0157 return (this_cpu_read(cpu_info.loops_per_jiffy) *
0158 (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
0159
0160 #else
0161
0162 unsigned int j, t = 0;
0163
0164 if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
0165 return 0;
0166
0167 j = jiffies; while (j == jiffies);
0168 j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
0169
0170 gameport_close(gameport);
0171 return t * HZ / 1000;
0172
0173 #endif
0174 }
0175
0176 void gameport_start_polling(struct gameport *gameport)
0177 {
0178 spin_lock(&gameport->timer_lock);
0179
0180 if (!gameport->poll_cnt++) {
0181 BUG_ON(!gameport->poll_handler);
0182 BUG_ON(!gameport->poll_interval);
0183 mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
0184 }
0185
0186 spin_unlock(&gameport->timer_lock);
0187 }
0188 EXPORT_SYMBOL(gameport_start_polling);
0189
0190 void gameport_stop_polling(struct gameport *gameport)
0191 {
0192 spin_lock(&gameport->timer_lock);
0193
0194 if (!--gameport->poll_cnt)
0195 del_timer(&gameport->poll_timer);
0196
0197 spin_unlock(&gameport->timer_lock);
0198 }
0199 EXPORT_SYMBOL(gameport_stop_polling);
0200
0201 static void gameport_run_poll_handler(struct timer_list *t)
0202 {
0203 struct gameport *gameport = from_timer(gameport, t, poll_timer);
0204
0205 gameport->poll_handler(gameport);
0206 if (gameport->poll_cnt)
0207 mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
0208 }
0209
0210
0211
0212
0213
0214 static int gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
0215 {
0216 int error;
0217
0218 gameport->dev.driver = &drv->driver;
0219 if (drv->connect(gameport, drv)) {
0220 gameport->dev.driver = NULL;
0221 return -ENODEV;
0222 }
0223
0224 error = device_bind_driver(&gameport->dev);
0225 if (error) {
0226 dev_warn(&gameport->dev,
0227 "device_bind_driver() failed for %s (%s) and %s, error: %d\n",
0228 gameport->phys, gameport->name,
0229 drv->description, error);
0230 drv->disconnect(gameport);
0231 gameport->dev.driver = NULL;
0232 return error;
0233 }
0234
0235 return 0;
0236 }
0237
0238 static void gameport_find_driver(struct gameport *gameport)
0239 {
0240 int error;
0241
0242 error = device_attach(&gameport->dev);
0243 if (error < 0)
0244 dev_warn(&gameport->dev,
0245 "device_attach() failed for %s (%s), error: %d\n",
0246 gameport->phys, gameport->name, error);
0247 }
0248
0249
0250
0251
0252
0253
0254 enum gameport_event_type {
0255 GAMEPORT_REGISTER_PORT,
0256 GAMEPORT_ATTACH_DRIVER,
0257 };
0258
0259 struct gameport_event {
0260 enum gameport_event_type type;
0261 void *object;
0262 struct module *owner;
0263 struct list_head node;
0264 };
0265
0266 static DEFINE_SPINLOCK(gameport_event_lock);
0267 static LIST_HEAD(gameport_event_list);
0268
0269 static struct gameport_event *gameport_get_event(void)
0270 {
0271 struct gameport_event *event = NULL;
0272 unsigned long flags;
0273
0274 spin_lock_irqsave(&gameport_event_lock, flags);
0275
0276 if (!list_empty(&gameport_event_list)) {
0277 event = list_first_entry(&gameport_event_list,
0278 struct gameport_event, node);
0279 list_del_init(&event->node);
0280 }
0281
0282 spin_unlock_irqrestore(&gameport_event_lock, flags);
0283 return event;
0284 }
0285
0286 static void gameport_free_event(struct gameport_event *event)
0287 {
0288 module_put(event->owner);
0289 kfree(event);
0290 }
0291
0292 static void gameport_remove_duplicate_events(struct gameport_event *event)
0293 {
0294 struct gameport_event *e, *next;
0295 unsigned long flags;
0296
0297 spin_lock_irqsave(&gameport_event_lock, flags);
0298
0299 list_for_each_entry_safe(e, next, &gameport_event_list, node) {
0300 if (event->object == e->object) {
0301
0302
0303
0304
0305
0306 if (event->type != e->type)
0307 break;
0308
0309 list_del_init(&e->node);
0310 gameport_free_event(e);
0311 }
0312 }
0313
0314 spin_unlock_irqrestore(&gameport_event_lock, flags);
0315 }
0316
0317
0318 static void gameport_handle_events(struct work_struct *work)
0319 {
0320 struct gameport_event *event;
0321
0322 mutex_lock(&gameport_mutex);
0323
0324
0325
0326
0327
0328
0329
0330 if ((event = gameport_get_event())) {
0331
0332 switch (event->type) {
0333
0334 case GAMEPORT_REGISTER_PORT:
0335 gameport_add_port(event->object);
0336 break;
0337
0338 case GAMEPORT_ATTACH_DRIVER:
0339 gameport_attach_driver(event->object);
0340 break;
0341 }
0342
0343 gameport_remove_duplicate_events(event);
0344 gameport_free_event(event);
0345 }
0346
0347 mutex_unlock(&gameport_mutex);
0348 }
0349
0350 static DECLARE_WORK(gameport_event_work, gameport_handle_events);
0351
0352 static int gameport_queue_event(void *object, struct module *owner,
0353 enum gameport_event_type event_type)
0354 {
0355 unsigned long flags;
0356 struct gameport_event *event;
0357 int retval = 0;
0358
0359 spin_lock_irqsave(&gameport_event_lock, flags);
0360
0361
0362
0363
0364
0365
0366
0367
0368 list_for_each_entry_reverse(event, &gameport_event_list, node) {
0369 if (event->object == object) {
0370 if (event->type == event_type)
0371 goto out;
0372 break;
0373 }
0374 }
0375
0376 event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
0377 if (!event) {
0378 pr_err("Not enough memory to queue event %d\n", event_type);
0379 retval = -ENOMEM;
0380 goto out;
0381 }
0382
0383 if (!try_module_get(owner)) {
0384 pr_warn("Can't get module reference, dropping event %d\n",
0385 event_type);
0386 kfree(event);
0387 retval = -EINVAL;
0388 goto out;
0389 }
0390
0391 event->type = event_type;
0392 event->object = object;
0393 event->owner = owner;
0394
0395 list_add_tail(&event->node, &gameport_event_list);
0396 queue_work(system_long_wq, &gameport_event_work);
0397
0398 out:
0399 spin_unlock_irqrestore(&gameport_event_lock, flags);
0400 return retval;
0401 }
0402
0403
0404
0405
0406
0407 static void gameport_remove_pending_events(void *object)
0408 {
0409 struct gameport_event *event, *next;
0410 unsigned long flags;
0411
0412 spin_lock_irqsave(&gameport_event_lock, flags);
0413
0414 list_for_each_entry_safe(event, next, &gameport_event_list, node) {
0415 if (event->object == object) {
0416 list_del_init(&event->node);
0417 gameport_free_event(event);
0418 }
0419 }
0420
0421 spin_unlock_irqrestore(&gameport_event_lock, flags);
0422 }
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432 static struct gameport *gameport_get_pending_child(struct gameport *parent)
0433 {
0434 struct gameport_event *event;
0435 struct gameport *gameport, *child = NULL;
0436 unsigned long flags;
0437
0438 spin_lock_irqsave(&gameport_event_lock, flags);
0439
0440 list_for_each_entry(event, &gameport_event_list, node) {
0441 if (event->type == GAMEPORT_REGISTER_PORT) {
0442 gameport = event->object;
0443 if (gameport->parent == parent) {
0444 child = gameport;
0445 break;
0446 }
0447 }
0448 }
0449
0450 spin_unlock_irqrestore(&gameport_event_lock, flags);
0451 return child;
0452 }
0453
0454
0455
0456
0457
0458 static ssize_t gameport_description_show(struct device *dev, struct device_attribute *attr, char *buf)
0459 {
0460 struct gameport *gameport = to_gameport_port(dev);
0461
0462 return sprintf(buf, "%s\n", gameport->name);
0463 }
0464 static DEVICE_ATTR(description, S_IRUGO, gameport_description_show, NULL);
0465
0466 static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
0467 {
0468 struct gameport *gameport = to_gameport_port(dev);
0469 struct device_driver *drv;
0470 int error;
0471
0472 error = mutex_lock_interruptible(&gameport_mutex);
0473 if (error)
0474 return error;
0475
0476 if (!strncmp(buf, "none", count)) {
0477 gameport_disconnect_port(gameport);
0478 } else if (!strncmp(buf, "reconnect", count)) {
0479 gameport_reconnect_port(gameport);
0480 } else if (!strncmp(buf, "rescan", count)) {
0481 gameport_disconnect_port(gameport);
0482 gameport_find_driver(gameport);
0483 } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
0484 gameport_disconnect_port(gameport);
0485 error = gameport_bind_driver(gameport, to_gameport_driver(drv));
0486 } else {
0487 error = -EINVAL;
0488 }
0489
0490 mutex_unlock(&gameport_mutex);
0491
0492 return error ? error : count;
0493 }
0494 static DEVICE_ATTR_WO(drvctl);
0495
0496 static struct attribute *gameport_device_attrs[] = {
0497 &dev_attr_description.attr,
0498 &dev_attr_drvctl.attr,
0499 NULL,
0500 };
0501 ATTRIBUTE_GROUPS(gameport_device);
0502
0503 static void gameport_release_port(struct device *dev)
0504 {
0505 struct gameport *gameport = to_gameport_port(dev);
0506
0507 kfree(gameport);
0508 module_put(THIS_MODULE);
0509 }
0510
0511 void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
0512 {
0513 va_list args;
0514
0515 va_start(args, fmt);
0516 vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
0517 va_end(args);
0518 }
0519 EXPORT_SYMBOL(gameport_set_phys);
0520
0521
0522
0523
0524 static void gameport_init_port(struct gameport *gameport)
0525 {
0526 static atomic_t gameport_no = ATOMIC_INIT(-1);
0527
0528 __module_get(THIS_MODULE);
0529
0530 mutex_init(&gameport->drv_mutex);
0531 device_initialize(&gameport->dev);
0532 dev_set_name(&gameport->dev, "gameport%lu",
0533 (unsigned long)atomic_inc_return(&gameport_no));
0534 gameport->dev.bus = &gameport_bus;
0535 gameport->dev.release = gameport_release_port;
0536 if (gameport->parent)
0537 gameport->dev.parent = &gameport->parent->dev;
0538
0539 INIT_LIST_HEAD(&gameport->node);
0540 spin_lock_init(&gameport->timer_lock);
0541 timer_setup(&gameport->poll_timer, gameport_run_poll_handler, 0);
0542 }
0543
0544
0545
0546
0547
0548 static void gameport_add_port(struct gameport *gameport)
0549 {
0550 int error;
0551
0552 if (gameport->parent)
0553 gameport->parent->child = gameport;
0554
0555 gameport->speed = use_ktime ?
0556 gameport_measure_speed(gameport) :
0557 old_gameport_measure_speed(gameport);
0558
0559 list_add_tail(&gameport->node, &gameport_list);
0560
0561 if (gameport->io)
0562 dev_info(&gameport->dev, "%s is %s, io %#x, speed %dkHz\n",
0563 gameport->name, gameport->phys, gameport->io, gameport->speed);
0564 else
0565 dev_info(&gameport->dev, "%s is %s, speed %dkHz\n",
0566 gameport->name, gameport->phys, gameport->speed);
0567
0568 error = device_add(&gameport->dev);
0569 if (error)
0570 dev_err(&gameport->dev,
0571 "device_add() failed for %s (%s), error: %d\n",
0572 gameport->phys, gameport->name, error);
0573 }
0574
0575
0576
0577
0578
0579 static void gameport_destroy_port(struct gameport *gameport)
0580 {
0581 struct gameport *child;
0582
0583 child = gameport_get_pending_child(gameport);
0584 if (child) {
0585 gameport_remove_pending_events(child);
0586 put_device(&child->dev);
0587 }
0588
0589 if (gameport->parent) {
0590 gameport->parent->child = NULL;
0591 gameport->parent = NULL;
0592 }
0593
0594 if (device_is_registered(&gameport->dev))
0595 device_del(&gameport->dev);
0596
0597 list_del_init(&gameport->node);
0598
0599 gameport_remove_pending_events(gameport);
0600 put_device(&gameport->dev);
0601 }
0602
0603
0604
0605
0606 static void gameport_reconnect_port(struct gameport *gameport)
0607 {
0608 do {
0609 if (!gameport->drv || !gameport->drv->reconnect || gameport->drv->reconnect(gameport)) {
0610 gameport_disconnect_port(gameport);
0611 gameport_find_driver(gameport);
0612
0613 break;
0614 }
0615 gameport = gameport->child;
0616 } while (gameport);
0617 }
0618
0619
0620
0621
0622
0623 static void gameport_disconnect_port(struct gameport *gameport)
0624 {
0625 struct gameport *s, *parent;
0626
0627 if (gameport->child) {
0628
0629
0630
0631
0632
0633 for (s = gameport; s->child; s = s->child)
0634 ;
0635
0636 do {
0637 parent = s->parent;
0638
0639 device_release_driver(&s->dev);
0640 gameport_destroy_port(s);
0641 } while ((s = parent) != gameport);
0642 }
0643
0644
0645
0646
0647 device_release_driver(&gameport->dev);
0648 }
0649
0650
0651
0652
0653
0654 void __gameport_register_port(struct gameport *gameport, struct module *owner)
0655 {
0656 gameport_init_port(gameport);
0657 gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
0658 }
0659 EXPORT_SYMBOL(__gameport_register_port);
0660
0661
0662
0663
0664 void gameport_unregister_port(struct gameport *gameport)
0665 {
0666 mutex_lock(&gameport_mutex);
0667 gameport_disconnect_port(gameport);
0668 gameport_destroy_port(gameport);
0669 mutex_unlock(&gameport_mutex);
0670 }
0671 EXPORT_SYMBOL(gameport_unregister_port);
0672
0673
0674
0675
0676
0677
0678 static ssize_t description_show(struct device_driver *drv, char *buf)
0679 {
0680 struct gameport_driver *driver = to_gameport_driver(drv);
0681 return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
0682 }
0683 static DRIVER_ATTR_RO(description);
0684
0685 static struct attribute *gameport_driver_attrs[] = {
0686 &driver_attr_description.attr,
0687 NULL
0688 };
0689 ATTRIBUTE_GROUPS(gameport_driver);
0690
0691 static int gameport_driver_probe(struct device *dev)
0692 {
0693 struct gameport *gameport = to_gameport_port(dev);
0694 struct gameport_driver *drv = to_gameport_driver(dev->driver);
0695
0696 drv->connect(gameport, drv);
0697 return gameport->drv ? 0 : -ENODEV;
0698 }
0699
0700 static void gameport_driver_remove(struct device *dev)
0701 {
0702 struct gameport *gameport = to_gameport_port(dev);
0703 struct gameport_driver *drv = to_gameport_driver(dev->driver);
0704
0705 drv->disconnect(gameport);
0706 }
0707
0708 static void gameport_attach_driver(struct gameport_driver *drv)
0709 {
0710 int error;
0711
0712 error = driver_attach(&drv->driver);
0713 if (error)
0714 pr_err("driver_attach() failed for %s, error: %d\n",
0715 drv->driver.name, error);
0716 }
0717
0718 int __gameport_register_driver(struct gameport_driver *drv, struct module *owner,
0719 const char *mod_name)
0720 {
0721 int error;
0722
0723 drv->driver.bus = &gameport_bus;
0724 drv->driver.owner = owner;
0725 drv->driver.mod_name = mod_name;
0726
0727
0728
0729
0730
0731 drv->ignore = true;
0732
0733 error = driver_register(&drv->driver);
0734 if (error) {
0735 pr_err("driver_register() failed for %s, error: %d\n",
0736 drv->driver.name, error);
0737 return error;
0738 }
0739
0740
0741
0742
0743 drv->ignore = false;
0744 error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);
0745 if (error) {
0746 driver_unregister(&drv->driver);
0747 return error;
0748 }
0749
0750 return 0;
0751 }
0752 EXPORT_SYMBOL(__gameport_register_driver);
0753
0754 void gameport_unregister_driver(struct gameport_driver *drv)
0755 {
0756 struct gameport *gameport;
0757
0758 mutex_lock(&gameport_mutex);
0759
0760 drv->ignore = true;
0761 gameport_remove_pending_events(drv);
0762
0763 start_over:
0764 list_for_each_entry(gameport, &gameport_list, node) {
0765 if (gameport->drv == drv) {
0766 gameport_disconnect_port(gameport);
0767 gameport_find_driver(gameport);
0768
0769 goto start_over;
0770 }
0771 }
0772
0773 driver_unregister(&drv->driver);
0774
0775 mutex_unlock(&gameport_mutex);
0776 }
0777 EXPORT_SYMBOL(gameport_unregister_driver);
0778
0779 static int gameport_bus_match(struct device *dev, struct device_driver *drv)
0780 {
0781 struct gameport_driver *gameport_drv = to_gameport_driver(drv);
0782
0783 return !gameport_drv->ignore;
0784 }
0785
0786 static struct bus_type gameport_bus = {
0787 .name = "gameport",
0788 .dev_groups = gameport_device_groups,
0789 .drv_groups = gameport_driver_groups,
0790 .match = gameport_bus_match,
0791 .probe = gameport_driver_probe,
0792 .remove = gameport_driver_remove,
0793 };
0794
0795 static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
0796 {
0797 mutex_lock(&gameport->drv_mutex);
0798 gameport->drv = drv;
0799 mutex_unlock(&gameport->drv_mutex);
0800 }
0801
0802 int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
0803 {
0804 if (gameport->open) {
0805 if (gameport->open(gameport, mode)) {
0806 return -1;
0807 }
0808 } else {
0809 if (mode != GAMEPORT_MODE_RAW)
0810 return -1;
0811 }
0812
0813 gameport_set_drv(gameport, drv);
0814 return 0;
0815 }
0816 EXPORT_SYMBOL(gameport_open);
0817
0818 void gameport_close(struct gameport *gameport)
0819 {
0820 del_timer_sync(&gameport->poll_timer);
0821 gameport->poll_handler = NULL;
0822 gameport->poll_interval = 0;
0823 gameport_set_drv(gameport, NULL);
0824 if (gameport->close)
0825 gameport->close(gameport);
0826 }
0827 EXPORT_SYMBOL(gameport_close);
0828
0829 static int __init gameport_init(void)
0830 {
0831 int error;
0832
0833 error = bus_register(&gameport_bus);
0834 if (error) {
0835 pr_err("failed to register gameport bus, error: %d\n", error);
0836 return error;
0837 }
0838
0839
0840 return 0;
0841 }
0842
0843 static void __exit gameport_exit(void)
0844 {
0845 bus_unregister(&gameport_bus);
0846
0847
0848
0849
0850
0851 cancel_work_sync(&gameport_event_work);
0852 }
0853
0854 subsys_initcall(gameport_init);
0855 module_exit(gameport_exit);