diff options
Diffstat (limited to 'drivers/input/gameport')
-rw-r--r-- | drivers/input/gameport/gameport.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index d7dfa6f53cf..c77a82e4605 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -17,10 +17,11 @@ #include <linux/init.h> #include <linux/gameport.h> #include <linux/wait.h> +#include <linux/completion.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/kthread.h> /*#include <asm/io.h>*/ @@ -133,7 +134,7 @@ static int gameport_measure_speed(struct gameport *gameport) } gameport_close(gameport); - return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); + return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); #else @@ -237,7 +238,8 @@ struct gameport_event { static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ static LIST_HEAD(gameport_event_list); static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); -static struct task_struct *gameport_task; +static DECLARE_COMPLETION(gameport_exited); +static int gameport_pid; static void gameport_queue_event(void *object, struct module *owner, enum gameport_event_type event_type) @@ -248,12 +250,12 @@ static void gameport_queue_event(void *object, struct module *owner, spin_lock_irqsave(&gameport_event_lock, flags); /* - * Scan event list for the other events for the same gameport port, + * Scan event list for the other events for the same gameport port, * starting with the most recent one. If event is the same we * do not need add new one. If event is of different type we * need to add this event and should not look further because * we need to preseve sequence of distinct events. - */ + */ list_for_each_entry_reverse(event, &gameport_event_list, node) { if (event->object == object) { if (event->type == event_type) @@ -430,15 +432,20 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) static int gameport_thread(void *nothing) { + lock_kernel(); + daemonize("kgameportd"); + allow_signal(SIGTERM); + do { gameport_handle_events(); - wait_event_interruptible(gameport_wait, - kthread_should_stop() || !list_empty(&gameport_event_list)); - try_to_freeze(PF_FREEZE); - } while (!kthread_should_stop()); + wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list)); + try_to_freeze(); + } while (!signal_pending(current)); printk(KERN_DEBUG "gameport: kgameportd exiting\n"); - return 0; + + unlock_kernel(); + complete_and_exit(&gameport_exited, 0); } @@ -446,13 +453,13 @@ static int gameport_thread(void *nothing) * Gameport port operations */ -static ssize_t gameport_show_description(struct device *dev, char *buf) +static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf) { struct gameport *gameport = to_gameport_port(dev); return sprintf(buf, "%s\n", gameport->name); } -static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count) +static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gameport *gameport = to_gameport_port(dev); struct device_driver *drv; @@ -766,10 +773,9 @@ void gameport_close(struct gameport *gameport) static int __init gameport_init(void) { - gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); - if (IS_ERR(gameport_task)) { + if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) { printk(KERN_ERR "gameport: Failed to start kgameportd\n"); - return PTR_ERR(gameport_task); + return -1; } gameport_bus.dev_attrs = gameport_device_attrs; @@ -783,7 +789,8 @@ static int __init gameport_init(void) static void __exit gameport_exit(void) { bus_unregister(&gameport_bus); - kthread_stop(gameport_task); + kill_proc(gameport_pid, SIGTERM, 1); + wait_for_completion(&gameport_exited); } module_init(gameport_init); |