diff options
Diffstat (limited to 'drivers/input/serio/serio.c')
-rw-r--r-- | drivers/input/serio/serio.c | 291 |
1 files changed, 157 insertions, 134 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index c3b626e9eae7..ba70058e2be3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -32,12 +32,10 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/serio.h> | 33 | #include <linux/serio.h> |
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/wait.h> | ||
36 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
38 | #include <linux/kthread.h> | 37 | #include <linux/workqueue.h> |
39 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
40 | #include <linux/freezer.h> | ||
41 | 39 | ||
42 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 40 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
43 | MODULE_DESCRIPTION("Serio abstraction core"); | 41 | MODULE_DESCRIPTION("Serio abstraction core"); |
@@ -45,7 +43,7 @@ MODULE_LICENSE("GPL"); | |||
45 | 43 | ||
46 | /* | 44 | /* |
47 | * serio_mutex protects entire serio subsystem and is taken every time | 45 | * serio_mutex protects entire serio subsystem and is taken every time |
48 | * serio port or driver registrered or unregistered. | 46 | * serio port or driver registered or unregistered. |
49 | */ | 47 | */ |
50 | static DEFINE_MUTEX(serio_mutex); | 48 | static DEFINE_MUTEX(serio_mutex); |
51 | 49 | ||
@@ -56,7 +54,7 @@ static struct bus_type serio_bus; | |||
56 | static void serio_add_port(struct serio *serio); | 54 | static void serio_add_port(struct serio *serio); |
57 | static int serio_reconnect_port(struct serio *serio); | 55 | static int serio_reconnect_port(struct serio *serio); |
58 | static void serio_disconnect_port(struct serio *serio); | 56 | static void serio_disconnect_port(struct serio *serio); |
59 | static void serio_reconnect_chain(struct serio *serio); | 57 | static void serio_reconnect_subtree(struct serio *serio); |
60 | static void serio_attach_driver(struct serio_driver *drv); | 58 | static void serio_attach_driver(struct serio_driver *drv); |
61 | 59 | ||
62 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) | 60 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) |
@@ -152,7 +150,7 @@ static void serio_find_driver(struct serio *serio) | |||
152 | enum serio_event_type { | 150 | enum serio_event_type { |
153 | SERIO_RESCAN_PORT, | 151 | SERIO_RESCAN_PORT, |
154 | SERIO_RECONNECT_PORT, | 152 | SERIO_RECONNECT_PORT, |
155 | SERIO_RECONNECT_CHAIN, | 153 | SERIO_RECONNECT_SUBTREE, |
156 | SERIO_REGISTER_PORT, | 154 | SERIO_REGISTER_PORT, |
157 | SERIO_ATTACH_DRIVER, | 155 | SERIO_ATTACH_DRIVER, |
158 | }; | 156 | }; |
@@ -166,58 +164,22 @@ struct serio_event { | |||
166 | 164 | ||
167 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ | 165 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ |
168 | static LIST_HEAD(serio_event_list); | 166 | static LIST_HEAD(serio_event_list); |
169 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | ||
170 | static struct task_struct *serio_task; | ||
171 | 167 | ||
172 | static int serio_queue_event(void *object, struct module *owner, | 168 | static struct serio_event *serio_get_event(void) |
173 | enum serio_event_type event_type) | ||
174 | { | 169 | { |
170 | struct serio_event *event = NULL; | ||
175 | unsigned long flags; | 171 | unsigned long flags; |
176 | struct serio_event *event; | ||
177 | int retval = 0; | ||
178 | 172 | ||
179 | spin_lock_irqsave(&serio_event_lock, flags); | 173 | spin_lock_irqsave(&serio_event_lock, flags); |
180 | 174 | ||
181 | /* | 175 | if (!list_empty(&serio_event_list)) { |
182 | * Scan event list for the other events for the same serio port, | 176 | event = list_first_entry(&serio_event_list, |
183 | * starting with the most recent one. If event is the same we | 177 | struct serio_event, node); |
184 | * do not need add new one. If event is of different type we | 178 | list_del_init(&event->node); |
185 | * need to add this event and should not look further because | ||
186 | * we need to preseve sequence of distinct events. | ||
187 | */ | ||
188 | list_for_each_entry_reverse(event, &serio_event_list, node) { | ||
189 | if (event->object == object) { | ||
190 | if (event->type == event_type) | ||
191 | goto out; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | ||
197 | if (!event) { | ||
198 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
199 | retval = -ENOMEM; | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | if (!try_module_get(owner)) { | ||
204 | pr_warning("Can't get module reference, dropping event %d\n", | ||
205 | event_type); | ||
206 | kfree(event); | ||
207 | retval = -EINVAL; | ||
208 | goto out; | ||
209 | } | 179 | } |
210 | 180 | ||
211 | event->type = event_type; | ||
212 | event->object = object; | ||
213 | event->owner = owner; | ||
214 | |||
215 | list_add_tail(&event->node, &serio_event_list); | ||
216 | wake_up(&serio_wait); | ||
217 | |||
218 | out: | ||
219 | spin_unlock_irqrestore(&serio_event_lock, flags); | 181 | spin_unlock_irqrestore(&serio_event_lock, flags); |
220 | return retval; | 182 | return event; |
221 | } | 183 | } |
222 | 184 | ||
223 | static void serio_free_event(struct serio_event *event) | 185 | static void serio_free_event(struct serio_event *event) |
@@ -226,7 +188,8 @@ static void serio_free_event(struct serio_event *event) | |||
226 | kfree(event); | 188 | kfree(event); |
227 | } | 189 | } |
228 | 190 | ||
229 | static void serio_remove_duplicate_events(struct serio_event *event) | 191 | static void serio_remove_duplicate_events(void *object, |
192 | enum serio_event_type type) | ||
230 | { | 193 | { |
231 | struct serio_event *e, *next; | 194 | struct serio_event *e, *next; |
232 | unsigned long flags; | 195 | unsigned long flags; |
@@ -234,13 +197,13 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
234 | spin_lock_irqsave(&serio_event_lock, flags); | 197 | spin_lock_irqsave(&serio_event_lock, flags); |
235 | 198 | ||
236 | list_for_each_entry_safe(e, next, &serio_event_list, node) { | 199 | list_for_each_entry_safe(e, next, &serio_event_list, node) { |
237 | if (event->object == e->object) { | 200 | if (object == e->object) { |
238 | /* | 201 | /* |
239 | * If this event is of different type we should not | 202 | * If this event is of different type we should not |
240 | * look further - we only suppress duplicate events | 203 | * look further - we only suppress duplicate events |
241 | * that were sent back-to-back. | 204 | * that were sent back-to-back. |
242 | */ | 205 | */ |
243 | if (event->type != e->type) | 206 | if (type != e->type) |
244 | break; | 207 | break; |
245 | 208 | ||
246 | list_del_init(&e->node); | 209 | list_del_init(&e->node); |
@@ -251,25 +214,7 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
251 | spin_unlock_irqrestore(&serio_event_lock, flags); | 214 | spin_unlock_irqrestore(&serio_event_lock, flags); |
252 | } | 215 | } |
253 | 216 | ||
254 | 217 | static void serio_handle_event(struct work_struct *work) | |
255 | static struct serio_event *serio_get_event(void) | ||
256 | { | ||
257 | struct serio_event *event = NULL; | ||
258 | unsigned long flags; | ||
259 | |||
260 | spin_lock_irqsave(&serio_event_lock, flags); | ||
261 | |||
262 | if (!list_empty(&serio_event_list)) { | ||
263 | event = list_first_entry(&serio_event_list, | ||
264 | struct serio_event, node); | ||
265 | list_del_init(&event->node); | ||
266 | } | ||
267 | |||
268 | spin_unlock_irqrestore(&serio_event_lock, flags); | ||
269 | return event; | ||
270 | } | ||
271 | |||
272 | static void serio_handle_event(void) | ||
273 | { | 218 | { |
274 | struct serio_event *event; | 219 | struct serio_event *event; |
275 | 220 | ||
@@ -292,8 +237,8 @@ static void serio_handle_event(void) | |||
292 | serio_find_driver(event->object); | 237 | serio_find_driver(event->object); |
293 | break; | 238 | break; |
294 | 239 | ||
295 | case SERIO_RECONNECT_CHAIN: | 240 | case SERIO_RECONNECT_SUBTREE: |
296 | serio_reconnect_chain(event->object); | 241 | serio_reconnect_subtree(event->object); |
297 | break; | 242 | break; |
298 | 243 | ||
299 | case SERIO_ATTACH_DRIVER: | 244 | case SERIO_ATTACH_DRIVER: |
@@ -301,13 +246,66 @@ static void serio_handle_event(void) | |||
301 | break; | 246 | break; |
302 | } | 247 | } |
303 | 248 | ||
304 | serio_remove_duplicate_events(event); | 249 | serio_remove_duplicate_events(event->object, event->type); |
305 | serio_free_event(event); | 250 | serio_free_event(event); |
306 | } | 251 | } |
307 | 252 | ||
308 | mutex_unlock(&serio_mutex); | 253 | mutex_unlock(&serio_mutex); |
309 | } | 254 | } |
310 | 255 | ||
256 | static DECLARE_WORK(serio_event_work, serio_handle_event); | ||
257 | |||
258 | static int serio_queue_event(void *object, struct module *owner, | ||
259 | enum serio_event_type event_type) | ||
260 | { | ||
261 | unsigned long flags; | ||
262 | struct serio_event *event; | ||
263 | int retval = 0; | ||
264 | |||
265 | spin_lock_irqsave(&serio_event_lock, flags); | ||
266 | |||
267 | /* | ||
268 | * Scan event list for the other events for the same serio port, | ||
269 | * starting with the most recent one. If event is the same we | ||
270 | * do not need add new one. If event is of different type we | ||
271 | * need to add this event and should not look further because | ||
272 | * we need to preseve sequence of distinct events. | ||
273 | */ | ||
274 | list_for_each_entry_reverse(event, &serio_event_list, node) { | ||
275 | if (event->object == object) { | ||
276 | if (event->type == event_type) | ||
277 | goto out; | ||
278 | break; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | ||
283 | if (!event) { | ||
284 | pr_err("Not enough memory to queue event %d\n", event_type); | ||
285 | retval = -ENOMEM; | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | if (!try_module_get(owner)) { | ||
290 | pr_warning("Can't get module reference, dropping event %d\n", | ||
291 | event_type); | ||
292 | kfree(event); | ||
293 | retval = -EINVAL; | ||
294 | goto out; | ||
295 | } | ||
296 | |||
297 | event->type = event_type; | ||
298 | event->object = object; | ||
299 | event->owner = owner; | ||
300 | |||
301 | list_add_tail(&event->node, &serio_event_list); | ||
302 | queue_work(system_long_wq, &serio_event_work); | ||
303 | |||
304 | out: | ||
305 | spin_unlock_irqrestore(&serio_event_lock, flags); | ||
306 | return retval; | ||
307 | } | ||
308 | |||
311 | /* | 309 | /* |
312 | * Remove all events that have been submitted for a given | 310 | * Remove all events that have been submitted for a given |
313 | * object, be it serio port or driver. | 311 | * object, be it serio port or driver. |
@@ -330,12 +328,10 @@ static void serio_remove_pending_events(void *object) | |||
330 | } | 328 | } |
331 | 329 | ||
332 | /* | 330 | /* |
333 | * Destroy child serio port (if any) that has not been fully registered yet. | 331 | * Locate child serio port (if any) that has not been fully registered yet. |
334 | * | 332 | * |
335 | * Note that we rely on the fact that port can have only one child and therefore | 333 | * Children are registered by driver's connect() handler so there can't be a |
336 | * only one child registration request can be pending. Additionally, children | 334 | * grandchild pending registration together with a child. |
337 | * are registered by driver's connect() handler so there can't be a grandchild | ||
338 | * pending registration together with a child. | ||
339 | */ | 335 | */ |
340 | static struct serio *serio_get_pending_child(struct serio *parent) | 336 | static struct serio *serio_get_pending_child(struct serio *parent) |
341 | { | 337 | { |
@@ -359,18 +355,6 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
359 | return child; | 355 | return child; |
360 | } | 356 | } |
361 | 357 | ||
362 | static int serio_thread(void *nothing) | ||
363 | { | ||
364 | do { | ||
365 | serio_handle_event(); | ||
366 | wait_event_interruptible(serio_wait, | ||
367 | kthread_should_stop() || !list_empty(&serio_event_list)); | ||
368 | } while (!kthread_should_stop()); | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | |||
374 | /* | 358 | /* |
375 | * Serio port operations | 359 | * Serio port operations |
376 | */ | 360 | */ |
@@ -449,14 +433,16 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
449 | if (!strncmp(buf, "none", count)) { | 433 | if (!strncmp(buf, "none", count)) { |
450 | serio_disconnect_port(serio); | 434 | serio_disconnect_port(serio); |
451 | } else if (!strncmp(buf, "reconnect", count)) { | 435 | } else if (!strncmp(buf, "reconnect", count)) { |
452 | serio_reconnect_chain(serio); | 436 | serio_reconnect_subtree(serio); |
453 | } else if (!strncmp(buf, "rescan", count)) { | 437 | } else if (!strncmp(buf, "rescan", count)) { |
454 | serio_disconnect_port(serio); | 438 | serio_disconnect_port(serio); |
455 | serio_find_driver(serio); | 439 | serio_find_driver(serio); |
440 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | ||
456 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
457 | serio_disconnect_port(serio); | 442 | serio_disconnect_port(serio); |
458 | error = serio_bind_driver(serio, to_serio_driver(drv)); | 443 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
459 | put_driver(drv); | 444 | put_driver(drv); |
445 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | ||
460 | } else { | 446 | } else { |
461 | error = -EINVAL; | 447 | error = -EINVAL; |
462 | } | 448 | } |
@@ -516,6 +502,8 @@ static void serio_init_port(struct serio *serio) | |||
516 | __module_get(THIS_MODULE); | 502 | __module_get(THIS_MODULE); |
517 | 503 | ||
518 | INIT_LIST_HEAD(&serio->node); | 504 | INIT_LIST_HEAD(&serio->node); |
505 | INIT_LIST_HEAD(&serio->child_node); | ||
506 | INIT_LIST_HEAD(&serio->children); | ||
519 | spin_lock_init(&serio->lock); | 507 | spin_lock_init(&serio->lock); |
520 | mutex_init(&serio->drv_mutex); | 508 | mutex_init(&serio->drv_mutex); |
521 | device_initialize(&serio->dev); | 509 | device_initialize(&serio->dev); |
@@ -538,12 +526,13 @@ static void serio_init_port(struct serio *serio) | |||
538 | */ | 526 | */ |
539 | static void serio_add_port(struct serio *serio) | 527 | static void serio_add_port(struct serio *serio) |
540 | { | 528 | { |
529 | struct serio *parent = serio->parent; | ||
541 | int error; | 530 | int error; |
542 | 531 | ||
543 | if (serio->parent) { | 532 | if (parent) { |
544 | serio_pause_rx(serio->parent); | 533 | serio_pause_rx(parent); |
545 | serio->parent->child = serio; | 534 | list_add_tail(&serio->child_node, &parent->children); |
546 | serio_continue_rx(serio->parent); | 535 | serio_continue_rx(parent); |
547 | } | 536 | } |
548 | 537 | ||
549 | list_add_tail(&serio->node, &serio_list); | 538 | list_add_tail(&serio->node, &serio_list); |
@@ -559,15 +548,14 @@ static void serio_add_port(struct serio *serio) | |||
559 | } | 548 | } |
560 | 549 | ||
561 | /* | 550 | /* |
562 | * serio_destroy_port() completes deregistration process and removes | 551 | * serio_destroy_port() completes unregistration process and removes |
563 | * port from the system | 552 | * port from the system |
564 | */ | 553 | */ |
565 | static void serio_destroy_port(struct serio *serio) | 554 | static void serio_destroy_port(struct serio *serio) |
566 | { | 555 | { |
567 | struct serio *child; | 556 | struct serio *child; |
568 | 557 | ||
569 | child = serio_get_pending_child(serio); | 558 | while ((child = serio_get_pending_child(serio)) != NULL) { |
570 | if (child) { | ||
571 | serio_remove_pending_events(child); | 559 | serio_remove_pending_events(child); |
572 | put_device(&child->dev); | 560 | put_device(&child->dev); |
573 | } | 561 | } |
@@ -577,7 +565,7 @@ static void serio_destroy_port(struct serio *serio) | |||
577 | 565 | ||
578 | if (serio->parent) { | 566 | if (serio->parent) { |
579 | serio_pause_rx(serio->parent); | 567 | serio_pause_rx(serio->parent); |
580 | serio->parent->child = NULL; | 568 | list_del_init(&serio->child_node); |
581 | serio_continue_rx(serio->parent); | 569 | serio_continue_rx(serio->parent); |
582 | serio->parent = NULL; | 570 | serio->parent = NULL; |
583 | } | 571 | } |
@@ -609,46 +597,82 @@ static int serio_reconnect_port(struct serio *serio) | |||
609 | } | 597 | } |
610 | 598 | ||
611 | /* | 599 | /* |
612 | * Reconnect serio port and all its children (re-initialize attached devices) | 600 | * Reconnect serio port and all its children (re-initialize attached |
601 | * devices). | ||
613 | */ | 602 | */ |
614 | static void serio_reconnect_chain(struct serio *serio) | 603 | static void serio_reconnect_subtree(struct serio *root) |
615 | { | 604 | { |
605 | struct serio *s = root; | ||
606 | int error; | ||
607 | |||
616 | do { | 608 | do { |
617 | if (serio_reconnect_port(serio)) { | 609 | error = serio_reconnect_port(s); |
618 | /* Ok, old children are now gone, we are done */ | 610 | if (!error) { |
619 | break; | 611 | /* |
612 | * Reconnect was successful, move on to do the | ||
613 | * first child. | ||
614 | */ | ||
615 | if (!list_empty(&s->children)) { | ||
616 | s = list_first_entry(&s->children, | ||
617 | struct serio, child_node); | ||
618 | continue; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * Either it was a leaf node or reconnect failed and it | ||
624 | * became a leaf node. Continue reconnecting starting with | ||
625 | * the next sibling of the parent node. | ||
626 | */ | ||
627 | while (s != root) { | ||
628 | struct serio *parent = s->parent; | ||
629 | |||
630 | if (!list_is_last(&s->child_node, &parent->children)) { | ||
631 | s = list_entry(s->child_node.next, | ||
632 | struct serio, child_node); | ||
633 | break; | ||
634 | } | ||
635 | |||
636 | s = parent; | ||
620 | } | 637 | } |
621 | serio = serio->child; | 638 | } while (s != root); |
622 | } while (serio); | ||
623 | } | 639 | } |
624 | 640 | ||
625 | /* | 641 | /* |
626 | * serio_disconnect_port() unbinds a port from its driver. As a side effect | 642 | * serio_disconnect_port() unbinds a port from its driver. As a side effect |
627 | * all child ports are unbound and destroyed. | 643 | * all children ports are unbound and destroyed. |
628 | */ | 644 | */ |
629 | static void serio_disconnect_port(struct serio *serio) | 645 | static void serio_disconnect_port(struct serio *serio) |
630 | { | 646 | { |
631 | struct serio *s, *parent; | 647 | struct serio *s = serio; |
648 | |||
649 | /* | ||
650 | * Children ports should be disconnected and destroyed | ||
651 | * first; we travel the tree in depth-first order. | ||
652 | */ | ||
653 | while (!list_empty(&serio->children)) { | ||
654 | |||
655 | /* Locate a leaf */ | ||
656 | while (!list_empty(&s->children)) | ||
657 | s = list_first_entry(&s->children, | ||
658 | struct serio, child_node); | ||
632 | 659 | ||
633 | if (serio->child) { | ||
634 | /* | 660 | /* |
635 | * Children ports should be disconnected and destroyed | 661 | * Prune this leaf node unless it is the one we |
636 | * first, staring with the leaf one, since we don't want | 662 | * started with. |
637 | * to do recursion | ||
638 | */ | 663 | */ |
639 | for (s = serio; s->child; s = s->child) | 664 | if (s != serio) { |
640 | /* empty */; | 665 | struct serio *parent = s->parent; |
641 | |||
642 | do { | ||
643 | parent = s->parent; | ||
644 | 666 | ||
645 | device_release_driver(&s->dev); | 667 | device_release_driver(&s->dev); |
646 | serio_destroy_port(s); | 668 | serio_destroy_port(s); |
647 | } while ((s = parent) != serio); | 669 | |
670 | s = parent; | ||
671 | } | ||
648 | } | 672 | } |
649 | 673 | ||
650 | /* | 674 | /* |
651 | * Ok, no children left, now disconnect this port | 675 | * OK, no children left, now disconnect this port. |
652 | */ | 676 | */ |
653 | device_release_driver(&serio->dev); | 677 | device_release_driver(&serio->dev); |
654 | } | 678 | } |
@@ -661,7 +685,7 @@ EXPORT_SYMBOL(serio_rescan); | |||
661 | 685 | ||
662 | void serio_reconnect(struct serio *serio) | 686 | void serio_reconnect(struct serio *serio) |
663 | { | 687 | { |
664 | serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN); | 688 | serio_queue_event(serio, NULL, SERIO_RECONNECT_SUBTREE); |
665 | } | 689 | } |
666 | EXPORT_SYMBOL(serio_reconnect); | 690 | EXPORT_SYMBOL(serio_reconnect); |
667 | 691 | ||
@@ -689,14 +713,16 @@ void serio_unregister_port(struct serio *serio) | |||
689 | EXPORT_SYMBOL(serio_unregister_port); | 713 | EXPORT_SYMBOL(serio_unregister_port); |
690 | 714 | ||
691 | /* | 715 | /* |
692 | * Safely unregisters child port if one is present. | 716 | * Safely unregisters children ports if they are present. |
693 | */ | 717 | */ |
694 | void serio_unregister_child_port(struct serio *serio) | 718 | void serio_unregister_child_port(struct serio *serio) |
695 | { | 719 | { |
720 | struct serio *s, *next; | ||
721 | |||
696 | mutex_lock(&serio_mutex); | 722 | mutex_lock(&serio_mutex); |
697 | if (serio->child) { | 723 | list_for_each_entry_safe(s, next, &serio->children, child_node) { |
698 | serio_disconnect_port(serio->child); | 724 | serio_disconnect_port(s); |
699 | serio_destroy_port(serio->child); | 725 | serio_destroy_port(s); |
700 | } | 726 | } |
701 | mutex_unlock(&serio_mutex); | 727 | mutex_unlock(&serio_mutex); |
702 | } | 728 | } |
@@ -1003,21 +1029,18 @@ static int __init serio_init(void) | |||
1003 | return error; | 1029 | return error; |
1004 | } | 1030 | } |
1005 | 1031 | ||
1006 | serio_task = kthread_run(serio_thread, NULL, "kseriod"); | ||
1007 | if (IS_ERR(serio_task)) { | ||
1008 | bus_unregister(&serio_bus); | ||
1009 | error = PTR_ERR(serio_task); | ||
1010 | pr_err("Failed to start kseriod, error: %d\n", error); | ||
1011 | return error; | ||
1012 | } | ||
1013 | |||
1014 | return 0; | 1032 | return 0; |
1015 | } | 1033 | } |
1016 | 1034 | ||
1017 | static void __exit serio_exit(void) | 1035 | static void __exit serio_exit(void) |
1018 | { | 1036 | { |
1019 | bus_unregister(&serio_bus); | 1037 | bus_unregister(&serio_bus); |
1020 | kthread_stop(serio_task); | 1038 | |
1039 | /* | ||
1040 | * There should not be any outstanding events but work may | ||
1041 | * still be scheduled so simply cancel it. | ||
1042 | */ | ||
1043 | cancel_work_sync(&serio_event_work); | ||
1021 | } | 1044 | } |
1022 | 1045 | ||
1023 | subsys_initcall(serio_init); | 1046 | subsys_initcall(serio_init); |