port->serio = NULL;
}
+/*
+ * i8042_filter() filters out unwanted bytes from the input data stream.
+ * It is called from i8042_interrupt and thus is running with interrupts
+ * off and i8042_lock held.
+ */
+static bool i8042_filter(unsigned char data, unsigned char str)
+{
+ if (unlikely(i8042_suppress_kbd_ack)) {
+ if ((~str & I8042_STR_AUXDATA) &&
+ (data == 0xfa || data == 0xfe)) {
+ i8042_suppress_kbd_ack--;
+ dbg("Extra keyboard ACK - filtered out\n");
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*
* i8042_interrupt() is the most important function in this driver -
* it handles the interrupts from the i8042, and sends incoming bytes
unsigned char str, data;
unsigned int dfl;
unsigned int port_no;
+ bool filtered;
int ret = 1;
spin_lock_irqsave(&i8042_lock, flags);
+
str = i8042_read_status();
if (unlikely(~str & I8042_STR_OBF)) {
spin_unlock_irqrestore(&i8042_lock, flags);
ret = 0;
goto out;
}
+
data = i8042_read_data();
- spin_unlock_irqrestore(&i8042_lock, flags);
if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
static unsigned long last_transmit;
dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : "");
- if (unlikely(i8042_suppress_kbd_ack))
- if (port_no == I8042_KBD_PORT_NO &&
- (data == 0xfa || data == 0xfe)) {
- i8042_suppress_kbd_ack--;
- goto out;
- }
+ filtered = i8042_filter(data, str);
+
+ spin_unlock_irqrestore(&i8042_lock, flags);
- if (likely(port->exists))
+ if (likely(port->exists && !filtered))
serio_interrupt(port->serio, data, dfl);
out: