summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/input/serio/serio.c90
-rw-r--r--include/linux/serio.h39
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);