From 94b49086bcdff836f86cb0dabc30a018af10672e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 18 Dec 2003 05:31:47 -0800 Subject: [PATCH] serio: possible race between port removal and kseriod Input: There is a possibility that serio might get deleted while there are outstanding events involving that serio waiting for kseriod to process them. Invalidate them so kseriod thread will just drop dead events. --- drivers/input/serio/serio.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 4f20e7eab7a8..225762d29bc4 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -87,6 +87,15 @@ static void serio_find_dev(struct serio *serio) static DECLARE_WAIT_QUEUE_HEAD(serio_wait); static DECLARE_COMPLETION(serio_exited); +static void serio_invalidate_pending_events(struct serio *serio) +{ + struct serio_event *event; + + list_for_each_entry(event, &serio_event_list, node) + if (event->serio == serio) + event->serio = NULL; +} + void serio_handle_events(void) { struct list_head *node, *next; @@ -95,17 +104,21 @@ void serio_handle_events(void) list_for_each_safe(node, next, &serio_event_list) { event = container_of(node, struct serio_event, node); + down(&serio_sem); + if (event->serio == NULL) + goto event_done; + switch (event->type) { case SERIO_RESCAN : - down(&serio_sem); if (event->serio->dev && event->serio->dev->disconnect) event->serio->dev->disconnect(event->serio); serio_find_dev(event->serio); - up(&serio_sem); break; default: break; } +event_done: + up(&serio_sem); list_del_init(node); kfree(event); } @@ -192,6 +205,7 @@ void serio_unregister_port(struct serio *serio) */ void __serio_unregister_port(struct serio *serio) { + serio_invalidate_pending_events(serio); list_del_init(&serio->node); if (serio->dev && serio->dev->disconnect) serio->dev->disconnect(serio); -- cgit v1.2.3