Commit 214b7805 authored by Vojtech Pavlik's avatar Vojtech Pavlik

Input: rearrangements and cleanups in serio.c

Signed-off-by: default avatarVojtech Pavlik <vojtech@suse.cz>
parent bb92d1c3
/*
* $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/* /*
* The Serio abstraction module * The Serio abstraction module
*
* Copyright (c) 1999-2004 Vojtech Pavlik
* Copyright (c) 2004 Dmitry Torokhov
* Copyright (c) 2003 Daniele Bellucci
*/ */
/* /*
...@@ -26,10 +24,6 @@ ...@@ -26,10 +24,6 @@
* Should you need to contact me, the author, you can do so either by * 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: * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*
* Changes:
* 20 Jul. 2003 Daniele Bellucci <bellucda@tiscali.it>
* Minor cleanups.
*/ */
#include <linux/stddef.h> #include <linux/stddef.h>
...@@ -61,23 +55,11 @@ EXPORT_SYMBOL(serio_close); ...@@ -61,23 +55,11 @@ EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL(serio_rescan); EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect); EXPORT_SYMBOL(serio_reconnect);
struct serio_event {
int type;
struct serio *serio;
struct list_head node;
};
static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED; /* protects serio_event_list */
static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_dev_list */ static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_dev_list */
static LIST_HEAD(serio_list); static LIST_HEAD(serio_list);
static LIST_HEAD(serio_dev_list); static LIST_HEAD(serio_dev_list);
static LIST_HEAD(serio_event_list);
static int serio_pid;
/* /* serio_find_dev() must be called with serio_sem down. */
* serio_find_dev() must be called with serio_sem down.
*/
static void serio_find_dev(struct serio *serio) static void serio_find_dev(struct serio *serio)
{ {
...@@ -91,47 +73,58 @@ static void serio_find_dev(struct serio *serio) ...@@ -91,47 +73,58 @@ static void serio_find_dev(struct serio *serio)
} }
} }
#define SERIO_RESCAN 1 /*
#define SERIO_RECONNECT 2 * Serio event processing.
#define SERIO_REGISTER_PORT 3 */
#define SERIO_UNREGISTER_PORT 4
struct serio_event {
int type;
struct serio *serio;
struct list_head node;
};
enum serio_event_type {
SERIO_RESCAN,
SERIO_RECONNECT,
SERIO_REGISTER_PORT,
SERIO_UNREGISTER_PORT,
};
static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED; /* protects serio_event_list */
static LIST_HEAD(serio_event_list);
static DECLARE_WAIT_QUEUE_HEAD(serio_wait); static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited); static DECLARE_COMPLETION(serio_exited);
static int serio_pid;
static void serio_remove_pending_events(struct serio *serio) static void serio_queue_event(struct serio *serio, int event_type)
{ {
struct list_head *node, *next;
struct serio_event *event;
unsigned long flags; unsigned long flags;
struct serio_event *event;
spin_lock_irqsave(&serio_event_lock, flags); spin_lock_irqsave(&serio_event_lock, flags);
list_for_each_safe(node, next, &serio_event_list) { if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
event = container_of(node, struct serio_event, node); event->type = event_type;
if (event->serio == serio) { event->serio = serio;
list_del_init(node);
kfree(event); list_add_tail(&event->node, &serio_event_list);
} wake_up(&serio_wait);
} }
spin_unlock_irqrestore(&serio_event_lock, flags); spin_unlock_irqrestore(&serio_event_lock, flags);
} }
void serio_handle_events(void) static struct serio_event *serio_get_event(void)
{ {
struct list_head *node;
struct serio_event *event; struct serio_event *event;
struct list_head *node;
unsigned long flags; unsigned long flags;
while (1) {
spin_lock_irqsave(&serio_event_lock, flags); spin_lock_irqsave(&serio_event_lock, flags);
if (list_empty(&serio_event_list)) { if (list_empty(&serio_event_list)) {
spin_unlock_irqrestore(&serio_event_lock, flags); spin_unlock_irqrestore(&serio_event_lock, flags);
break; return NULL;
} }
node = serio_event_list.next; node = serio_event_list.next;
...@@ -140,6 +133,15 @@ void serio_handle_events(void) ...@@ -140,6 +133,15 @@ void serio_handle_events(void)
spin_unlock_irqrestore(&serio_event_lock, flags); spin_unlock_irqrestore(&serio_event_lock, flags);
return event;
}
static void serio_handle_events(void)
{
struct serio_event *event;
while ((event = serio_get_event())) {
down(&serio_sem); down(&serio_sem);
switch (event->type) { switch (event->type) {
...@@ -171,6 +173,26 @@ void serio_handle_events(void) ...@@ -171,6 +173,26 @@ void serio_handle_events(void)
} }
} }
static void serio_remove_pending_events(struct serio *serio)
{
struct list_head *node, *next;
struct serio_event *event;
unsigned long flags;
spin_lock_irqsave(&serio_event_lock, flags);
list_for_each_safe(node, next, &serio_event_list) {
event = container_of(node, struct serio_event, node);
if (event->serio == serio) {
list_del_init(node);
kfree(event);
}
}
spin_unlock_irqrestore(&serio_event_lock, flags);
}
static int serio_thread(void *nothing) static int serio_thread(void *nothing)
{ {
lock_kernel(); lock_kernel();
...@@ -190,23 +212,10 @@ static int serio_thread(void *nothing) ...@@ -190,23 +212,10 @@ static int serio_thread(void *nothing)
complete_and_exit(&serio_exited, 0); complete_and_exit(&serio_exited, 0);
} }
static void serio_queue_event(struct serio *serio, int event_type)
{
unsigned long flags;
struct serio_event *event;
spin_lock_irqsave(&serio_event_lock, flags);
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { /*
event->type = event_type; * Serio port operations
event->serio = serio; */
list_add_tail(&event->node, &serio_event_list);
wake_up(&serio_wait);
}
spin_unlock_irqrestore(&serio_event_lock, flags);
}
void serio_rescan(struct serio *serio) void serio_rescan(struct serio *serio)
{ {
...@@ -218,31 +227,6 @@ void serio_reconnect(struct serio *serio) ...@@ -218,31 +227,6 @@ void serio_reconnect(struct serio *serio)
serio_queue_event(serio, SERIO_RECONNECT); serio_queue_event(serio, SERIO_RECONNECT);
} }
irqreturn_t serio_interrupt(struct serio *serio,
unsigned char data, unsigned int dfl, struct pt_regs *regs)
{
unsigned long flags;
irqreturn_t ret = IRQ_NONE;
spin_lock_irqsave(&serio->lock, flags);
if (likely(serio->dev)) {
ret = serio->dev->interrupt(serio, data, dfl, regs);
} else {
if (!dfl) {
if ((serio->type != SERIO_8042 &&
serio->type != SERIO_8042_XL) || (data == 0xaa)) {
serio_rescan(serio);
ret = IRQ_HANDLED;
}
}
}
spin_unlock_irqrestore(&serio->lock, flags);
return ret;
}
void serio_register_port(struct serio *serio) void serio_register_port(struct serio *serio)
{ {
down(&serio_sem); down(&serio_sem);
...@@ -302,6 +286,10 @@ void __serio_unregister_port(struct serio *serio) ...@@ -302,6 +286,10 @@ void __serio_unregister_port(struct serio *serio)
serio->dev->disconnect(serio); serio->dev->disconnect(serio);
} }
/*
* Serio device operations
*/
void serio_register_device(struct serio_dev *dev) void serio_register_device(struct serio_dev *dev)
{ {
struct serio *serio; struct serio *serio;
...@@ -357,6 +345,31 @@ void serio_close(struct serio *serio) ...@@ -357,6 +345,31 @@ void serio_close(struct serio *serio)
spin_unlock_irqrestore(&serio->lock, flags); spin_unlock_irqrestore(&serio->lock, flags);
} }
irqreturn_t serio_interrupt(struct serio *serio,
unsigned char data, unsigned int dfl, struct pt_regs *regs)
{
unsigned long flags;
irqreturn_t ret = IRQ_NONE;
spin_lock_irqsave(&serio->lock, flags);
if (likely(serio->dev)) {
ret = serio->dev->interrupt(serio, data, dfl, regs);
} else {
if (!dfl) {
if ((serio->type != SERIO_8042 &&
serio->type != SERIO_8042_XL) || (data == 0xaa)) {
serio_rescan(serio);
ret = IRQ_HANDLED;
}
}
}
spin_unlock_irqrestore(&serio->lock, flags);
return ret;
}
static int __init serio_init(void) static int __init serio_init(void)
{ {
int pid; int pid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment