aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/serio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/serio/serio.c')
-rw-r--r--drivers/input/serio/serio.c89
1 files changed, 62 insertions, 27 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 341824c48529..f367695e69b5 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -31,10 +31,9 @@
31#include <linux/serio.h> 31#include <linux/serio.h>
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/wait.h> 33#include <linux/wait.h>
34#include <linux/completion.h>
35#include <linux/sched.h> 34#include <linux/sched.h>
36#include <linux/smp_lock.h>
37#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/kthread.h>
38 37
39MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 38MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40MODULE_DESCRIPTION("Serio abstraction core"); 39MODULE_DESCRIPTION("Serio abstraction core");
@@ -43,6 +42,7 @@ MODULE_LICENSE("GPL");
43EXPORT_SYMBOL(serio_interrupt); 42EXPORT_SYMBOL(serio_interrupt);
44EXPORT_SYMBOL(__serio_register_port); 43EXPORT_SYMBOL(__serio_register_port);
45EXPORT_SYMBOL(serio_unregister_port); 44EXPORT_SYMBOL(serio_unregister_port);
45EXPORT_SYMBOL(serio_unregister_child_port);
46EXPORT_SYMBOL(__serio_unregister_port_delayed); 46EXPORT_SYMBOL(__serio_unregister_port_delayed);
47EXPORT_SYMBOL(__serio_register_driver); 47EXPORT_SYMBOL(__serio_register_driver);
48EXPORT_SYMBOL(serio_unregister_driver); 48EXPORT_SYMBOL(serio_unregister_driver);
@@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio);
68static void serio_reconnect_port(struct serio *serio); 68static void serio_reconnect_port(struct serio *serio);
69static void serio_disconnect_port(struct serio *serio); 69static void serio_disconnect_port(struct serio *serio);
70 70
71static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
72{
73 int retval;
74
75 down(&serio->drv_sem);
76 retval = drv->connect(serio, drv);
77 up(&serio->drv_sem);
78
79 return retval;
80}
81
82static int serio_reconnect_driver(struct serio *serio)
83{
84 int retval = -1;
85
86 down(&serio->drv_sem);
87 if (serio->drv && serio->drv->reconnect)
88 retval = serio->drv->reconnect(serio);
89 up(&serio->drv_sem);
90
91 return retval;
92}
93
94static void serio_disconnect_driver(struct serio *serio)
95{
96 down(&serio->drv_sem);
97 if (serio->drv)
98 serio->drv->disconnect(serio);
99 up(&serio->drv_sem);
100}
101
71static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) 102static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
72{ 103{
73 while (ids->type || ids->proto) { 104 while (ids->type || ids->proto) {
@@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
91 122
92 if (serio_match_port(drv->id_table, serio)) { 123 if (serio_match_port(drv->id_table, serio)) {
93 serio->dev.driver = &drv->driver; 124 serio->dev.driver = &drv->driver;
94 if (drv->connect(serio, drv)) { 125 if (serio_connect_driver(serio, drv)) {
95 serio->dev.driver = NULL; 126 serio->dev.driver = NULL;
96 goto out; 127 goto out;
97 } 128 }
@@ -138,8 +169,7 @@ struct serio_event {
138static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ 169static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
139static LIST_HEAD(serio_event_list); 170static LIST_HEAD(serio_event_list);
140static DECLARE_WAIT_QUEUE_HEAD(serio_wait); 171static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
141static DECLARE_COMPLETION(serio_exited); 172static struct task_struct *serio_task;
142static int serio_pid;
143 173
144static void serio_queue_event(void *object, struct module *owner, 174static void serio_queue_event(void *object, struct module *owner,
145 enum serio_event_type event_type) 175 enum serio_event_type event_type)
@@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner,
150 spin_lock_irqsave(&serio_event_lock, flags); 180 spin_lock_irqsave(&serio_event_lock, flags);
151 181
152 /* 182 /*
153 * Scan event list for the other events for the same serio port, 183 * Scan event list for the other events for the same serio port,
154 * starting with the most recent one. If event is the same we 184 * starting with the most recent one. If event is the same we
155 * do not need add new one. If event is of different type we 185 * do not need add new one. If event is of different type we
156 * need to add this event and should not look further because 186 * need to add this event and should not look further because
157 * we need to preseve sequence of distinct events. 187 * we need to preseve sequence of distinct events.
158 */ 188 */
159 list_for_each_entry_reverse(event, &serio_event_list, node) { 189 list_for_each_entry_reverse(event, &serio_event_list, node) {
160 if (event->object == object) { 190 if (event->object == object) {
161 if (event->type == event_type) 191 if (event->type == event_type)
@@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent)
337 367
338static int serio_thread(void *nothing) 368static int serio_thread(void *nothing)
339{ 369{
340 lock_kernel();
341 daemonize("kseriod");
342 allow_signal(SIGTERM);
343
344 do { 370 do {
345 serio_handle_events(); 371 serio_handle_events();
346 wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); 372 wait_event_interruptible(serio_wait,
373 kthread_should_stop() || !list_empty(&serio_event_list));
347 try_to_freeze(); 374 try_to_freeze();
348 } while (!signal_pending(current)); 375 } while (!kthread_should_stop());
349 376
350 printk(KERN_DEBUG "serio: kseriod exiting\n"); 377 printk(KERN_DEBUG "serio: kseriod exiting\n");
351 378 return 0;
352 unlock_kernel();
353 complete_and_exit(&serio_exited, 0);
354} 379}
355 380
356 381
@@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio)
557static void serio_reconnect_port(struct serio *serio) 582static void serio_reconnect_port(struct serio *serio)
558{ 583{
559 do { 584 do {
560 if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { 585 if (serio_reconnect_driver(serio)) {
561 serio_disconnect_port(serio); 586 serio_disconnect_port(serio);
562 serio_find_driver(serio); 587 serio_find_driver(serio);
563 /* Ok, old children are now gone, we are done */ 588 /* Ok, old children are now gone, we are done */
@@ -630,6 +655,19 @@ void serio_unregister_port(struct serio *serio)
630} 655}
631 656
632/* 657/*
658 * Safely unregisters child port if one is present.
659 */
660void serio_unregister_child_port(struct serio *serio)
661{
662 down(&serio_sem);
663 if (serio->child) {
664 serio_disconnect_port(serio->child);
665 serio_destroy_port(serio->child);
666 }
667 up(&serio_sem);
668}
669
670/*
633 * Submits register request to kseriod for subsequent execution. 671 * Submits register request to kseriod for subsequent execution.
634 * Can be used when it is not obvious whether the serio_sem is 672 * Can be used when it is not obvious whether the serio_sem is
635 * taken or not and when delayed execution is feasible. 673 * taken or not and when delayed execution is feasible.
@@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev)
686 struct serio *serio = to_serio_port(dev); 724 struct serio *serio = to_serio_port(dev);
687 struct serio_driver *drv = to_serio_driver(dev->driver); 725 struct serio_driver *drv = to_serio_driver(dev->driver);
688 726
689 return drv->connect(serio, drv); 727 return serio_connect_driver(serio, drv);
690} 728}
691 729
692static int serio_driver_remove(struct device *dev) 730static int serio_driver_remove(struct device *dev)
693{ 731{
694 struct serio *serio = to_serio_port(dev); 732 struct serio *serio = to_serio_port(dev);
695 struct serio_driver *drv = to_serio_driver(dev->driver);
696 733
697 drv->disconnect(serio); 734 serio_disconnect_driver(serio);
698 return 0; 735 return 0;
699} 736}
700 737
@@ -730,11 +767,9 @@ start_over:
730 767
731static void serio_set_drv(struct serio *serio, struct serio_driver *drv) 768static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
732{ 769{
733 down(&serio->drv_sem);
734 serio_pause_rx(serio); 770 serio_pause_rx(serio);
735 serio->drv = drv; 771 serio->drv = drv;
736 serio_continue_rx(serio); 772 serio_continue_rx(serio);
737 up(&serio->drv_sem);
738} 773}
739 774
740static int serio_bus_match(struct device *dev, struct device_driver *drv) 775static int serio_bus_match(struct device *dev, struct device_driver *drv)
@@ -794,7 +829,7 @@ static int serio_resume(struct device *dev)
794{ 829{
795 struct serio *serio = to_serio_port(dev); 830 struct serio *serio = to_serio_port(dev);
796 831
797 if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { 832 if (serio_reconnect_driver(serio)) {
798 /* 833 /*
799 * Driver re-probing can take a while, so better let kseriod 834 * Driver re-probing can take a while, so better let kseriod
800 * deal with it. 835 * deal with it.
@@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio,
848 883
849static int __init serio_init(void) 884static int __init serio_init(void)
850{ 885{
851 if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { 886 serio_task = kthread_run(serio_thread, NULL, "kseriod");
887 if (IS_ERR(serio_task)) {
852 printk(KERN_ERR "serio: Failed to start kseriod\n"); 888 printk(KERN_ERR "serio: Failed to start kseriod\n");
853 return -1; 889 return PTR_ERR(serio_task);
854 } 890 }
855 891
856 serio_bus.dev_attrs = serio_device_attrs; 892 serio_bus.dev_attrs = serio_device_attrs;
@@ -866,8 +902,7 @@ static int __init serio_init(void)
866static void __exit serio_exit(void) 902static void __exit serio_exit(void)
867{ 903{
868 bus_unregister(&serio_bus); 904 bus_unregister(&serio_bus);
869 kill_proc(serio_pid, SIGTERM, 1); 905 kthread_stop(serio_task);
870 wait_for_completion(&serio_exited);
871} 906}
872 907
873module_init(serio_init); 908module_init(serio_init);