diff options
| -rw-r--r-- | drivers/input/serio/serio.c | 90 | ||||
| -rw-r--r-- | include/linux/serio.h | 39 |
2 files changed, 60 insertions, 69 deletions
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index b45bd1a1a3f4..82e118a12ba6 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -37,6 +37,7 @@ #include <linux/sched.h> #include <linux/smp_lock.h> #include <linux/suspend.h> +#include <linux/slab.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Serio abstraction core"); @@ -51,19 +52,27 @@ EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_close); EXPORT_SYMBOL(serio_rescan); -static struct serio *serio_list; -static struct serio_dev *serio_dev; +struct serio_event { + int type; + struct serio *serio; + struct list_head node; +}; + +static LIST_HEAD(serio_list); +static LIST_HEAD(serio_dev_list); +static LIST_HEAD(serio_event_list); static int serio_pid; static void serio_find_dev(struct serio *serio) { - struct serio_dev *dev = serio_dev; + struct serio_dev *dev; - while (dev && !serio->dev) { + list_for_each_entry(dev, &serio_dev_list, node) { + if (serio->dev) + break; if (dev->connect) - dev->connect(serio, dev); - dev = dev->next; - } + dev->connect(serio, dev); + } } #define SERIO_RESCAN 1 @@ -73,17 +82,23 @@ static DECLARE_COMPLETION(serio_exited); void serio_handle_events(void) { - struct serio *serio = serio_list; - - while (serio) { - if (serio->event & SERIO_RESCAN) { - if (serio->dev && serio->dev->disconnect) - serio->dev->disconnect(serio); - serio_find_dev(serio); + struct list_head *node, *next; + struct serio_event *event; + + list_for_each_safe(node, next, &serio_event_list) { + event = container_of(node, struct serio_event, node); + + switch (event->type) { + case SERIO_RESCAN : + if (event->serio->dev && event->serio->dev->disconnect) + event->serio->dev->disconnect(event->serio); + serio_find_dev(event->serio); + break; + default: + break; } - - serio->event = 0; - serio = serio->next; + list_del_init(node); + kfree(event); } } @@ -95,7 +110,7 @@ static int serio_thread(void *nothing) do { serio_handle_events(); - interruptible_sleep_on(&serio_wait); + wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); if (current->flags & PF_FREEZE) refrigerator(PF_IOTHREAD); } while (!signal_pending(current)); @@ -108,7 +123,15 @@ static int serio_thread(void *nothing) void serio_rescan(struct serio *serio) { - serio->event |= SERIO_RESCAN; + struct serio_event *event; + + if (!(event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) + return; + + event->type = SERIO_RESCAN; + event->serio = serio; + + list_add_tail(&event->node, &serio_event_list); wake_up(&serio_wait); } @@ -122,49 +145,36 @@ void serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags void serio_register_port(struct serio *serio) { - serio->next = serio_list; - serio_list = serio; + list_add_tail(&serio->node, &serio_list); serio_find_dev(serio); } void serio_unregister_port(struct serio *serio) { - struct serio **serioptr = &serio_list; - - while (*serioptr && (*serioptr != serio)) serioptr = &((*serioptr)->next); - *serioptr = (*serioptr)->next; - + list_del_init(&serio->node); if (serio->dev && serio->dev->disconnect) serio->dev->disconnect(serio); } void serio_register_device(struct serio_dev *dev) { - struct serio *serio = serio_list; - - dev->next = serio_dev; - serio_dev = dev; - - while (serio) { + struct serio *serio; + list_add_tail(&dev->node, &serio_dev_list); + list_for_each_entry(serio, &serio_list, node) if (!serio->dev && dev->connect) dev->connect(serio, dev); - serio = serio->next; - } } void serio_unregister_device(struct serio_dev *dev) { - struct serio_dev **devptr = &serio_dev; - struct serio *serio = serio_list; + struct serio *serio; - while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next); - *devptr = (*devptr)->next; + list_del_init(&dev->node); - while (serio) { + list_for_each_entry(serio, &serio_list, node) { if (serio->dev == dev && dev->disconnect) dev->disconnect(serio); serio_find_dev(serio); - serio = serio->next; } } diff --git a/include/linux/serio.h b/include/linux/serio.h index fa424cf68902..b0690405229d 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -2,36 +2,16 @@ #define _SERIO_H /* - * $Id: serio.h,v 1.21 2001/12/19 05:15:21 skids Exp $ - * - * Copyright (C) 1999-2001 Vojtech Pavlik - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -/* - * The serial port set type ioctl. + * Copyright (C) 1999-2002 Vojtech Pavlik +* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. */ #include <linux/ioctl.h> +#include <linux/list.h> + #define SPIOCSTYPE _IOW('q', 0x01, unsigned long) struct serio; @@ -57,7 +37,8 @@ struct serio { void (*close)(struct serio *); struct serio_dev *dev; - struct serio *next; + + struct list_head node; }; struct serio_dev { @@ -71,7 +52,7 @@ struct serio_dev { void (*disconnect)(struct serio *); void (*cleanup)(struct serio *); - struct serio_dev *next; + struct list_head node; }; int serio_open(struct serio *serio, struct serio_dev *dev); |
