Commit 3adcc00c authored by Vojtech Pavlik's avatar Vojtech Pavlik

input: Expect only one character in interrupt in i8042.c, this eases

       the load on the controller (only one status read per interrupt). Also
       do polling only some time after an interrupt happened.
parent c0fd6178
...@@ -371,65 +371,60 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -371,65 +371,60 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned long flags; unsigned long flags;
unsigned char str, data; unsigned char str, data;
unsigned int dfl; unsigned int dfl;
struct {
int data;
int str;
} buffer[I8042_BUFFER_SIZE];
int i, j = 0;
spin_lock_irqsave(&i8042_lock, flags); spin_lock_irqsave(&i8042_lock, flags);
str = i8042_read_status();
while (j < I8042_BUFFER_SIZE && data = i8042_read_data();
(buffer[j].str = i8042_read_status()) & I8042_STR_OBF)
buffer[j++].data = i8042_read_data();
spin_unlock_irqrestore(&i8042_lock, flags); spin_unlock_irqrestore(&i8042_lock, flags);
for (i = 0; i < j; i++) { if (~str & I8042_STR_OBF) {
if (irq) dbg("Interrupt %d, without any data", irq);
str = buffer[i].str; return IRQ_RETVAL(0);
data = buffer[i].data; }
dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
if (i8042_mux_values[0].exists && (str & I8042_STR_AUXDATA)) {
if (str & I8042_STR_MUXERR) { dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
switch (data) { ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
case 0xfd:
case 0xfe: dfl = SERIO_TIMEOUT; break;
case 0xff: dfl = SERIO_PARITY; break;
}
data = 0xfe;
} else dfl = 0;
dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)", if (i8042_mux_values[0].exists && (str & I8042_STR_AUXDATA)) {
data, (str >> 6), irq,
dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : "");
serio_interrupt(i8042_mux_port + ((str >> 6) & 3), data, dfl, regs); if (str & I8042_STR_MUXERR) {
continue; switch (data) {
} case 0xfd:
case 0xfe: dfl = SERIO_TIMEOUT; break;
case 0xff: dfl = SERIO_PARITY; break;
}
data = 0xfe;
} else dfl = 0;
dbg("%02x <- i8042 (interrupt, %s, %d%s%s)", dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)",
data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, data, (str >> 6), irq,
dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : ""); dfl & SERIO_TIMEOUT ? ", timeout" : "");
if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) { serio_interrupt(i8042_mux_port + ((str >> 6) & 3), data, dfl, regs);
serio_interrupt(&i8042_aux_port, data, dfl, regs);
continue; goto irq_ret;
} }
if (!i8042_kbd_values.exists) dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",
continue; data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq,
dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : "");
serio_interrupt(&i8042_kbd_port, data, dfl, regs); if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) {
serio_interrupt(&i8042_aux_port, data, dfl, regs);
goto irq_ret;
} }
return IRQ_RETVAL(j); if (!i8042_kbd_values.exists)
goto irq_ret;
serio_interrupt(&i8042_kbd_port, data, dfl, regs);
irq_ret:
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
return IRQ_RETVAL(1);
} }
/* /*
...@@ -645,7 +640,6 @@ static int __init i8042_port_register(struct i8042_values *values, struct serio ...@@ -645,7 +640,6 @@ static int __init i8042_port_register(struct i8042_values *values, struct serio
static void i8042_timer_func(unsigned long data) static void i8042_timer_func(unsigned long data)
{ {
i8042_interrupt(0, NULL, NULL); i8042_interrupt(0, NULL, NULL);
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
} }
...@@ -899,6 +893,9 @@ int __init i8042_init(void) ...@@ -899,6 +893,9 @@ int __init i8042_init(void)
dbg_init(); dbg_init();
init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func;
if (i8042_platform_init()) if (i8042_platform_init())
return -EBUSY; return -EBUSY;
...@@ -923,8 +920,6 @@ int __init i8042_init(void) ...@@ -923,8 +920,6 @@ int __init i8042_init(void)
i8042_port_register(&i8042_kbd_values, &i8042_kbd_port); i8042_port_register(&i8042_kbd_values, &i8042_kbd_port);
init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func;
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
if (sysdev_class_register(&kbc_sysclass) == 0) { if (sysdev_class_register(&kbc_sysclass) == 0) {
......
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