summaryrefslogtreecommitdiffstats
path: root/drivers/input/gameport
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/gameport')
-rw-r--r--drivers/input/gameport/gameport.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index d7dfa6f..c77a82e 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);
OpenPOWER on IntegriCloud