diff -u b/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- b/Documentation/kernel-parameters.txt 2004-11-29 22:08:48 -08:00 +++ b/Documentation/kernel-parameters.txt 2004-11-29 21:56:08 -08:00 @@ -503,6 +503,9 @@ i8042.noaux [HW] Don't check for auxiliary (== mouse) port i8042.nomux [HW] Don't check presence of an active multiplexing controller + i8042.panicblink= + [HW] Frequency with which keyboard LEDs should blink + when kernel panics (default is 0.5 sec) i8042.reset [HW] Reset the controller during init and cleanup i8042.unlock [HW] Unlock (ignore) the keylock diff -u b/drivers/input/evdev.c b/drivers/input/evdev.c --- b/drivers/input/evdev.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/evdev.c 2004-11-29 21:56:07 -08:00 @@ -169,6 +169,9 @@ struct evdev_list *list = file->private_data; int retval; + if (count < sizeof(struct input_event)) + return -EINVAL; + if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; diff -u b/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- b/drivers/input/keyboard/atkbd.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/keyboard/atkbd.c 2004-11-29 21:56:08 -08:00 @@ -756,6 +756,10 @@ set_bit(BTN_MIDDLE, atkbd->dev.keybit); } + atkbd->dev.keycode = atkbd->keycode; + atkbd->dev.keycodesize = sizeof(unsigned char); + atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode); + for (i = 0; i < 512; i++) if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) set_bit(atkbd->keycode[i], atkbd->dev.keybit); @@ -805,8 +809,4 @@ atkbd->softraw = 1; - atkbd->dev.keycode = atkbd->keycode; - atkbd->dev.keycodesize = sizeof(unsigned char); - atkbd->dev.keycodemax = ARRAY_SIZE(atkbd_set2_keycode); - serio->private = atkbd; diff -u b/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c --- b/drivers/input/mouse/logips2pp.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/mouse/logips2pp.c 2004-11-29 21:56:07 -08:00 @@ -245,7 +245,8 @@ * Set up input device's properties based on the detected mouse model. */ -static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info) +static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_info *model_info, + int using_ps2pp) { if (model_info->features & PS2PP_SIDE_BTN) set_bit(BTN_SIDE, psmouse->dev.keybit); @@ -279,6 +280,16 @@ case PS2PP_KIND_TP3: psmouse->name = "TouchPad 3"; break; + + default: + /* + * Set name to "Mouse" only when using PS2++, + * otherwise let other protocols define suitable + * name + */ + if (using_ps2pp) + psmouse->name = "Mouse"; + break; } } @@ -371,7 +382,7 @@ clear_bit(BTN_RIGHT, psmouse->dev.keybit); if (model_info) - ps2pp_set_model_properties(psmouse, model_info); + ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); } return use_ps2pp ? 0 : -1; diff -u b/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c --- b/drivers/input/mouse/synaptics.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/mouse/synaptics.c 2004-11-29 21:56:07 -08:00 @@ -604,6 +604,20 @@ return 0; } +#if defined(__i386__) +#include +static struct dmi_system_id toshiba_dmi_table[] = { + { + .ident = "Toshiba Satellite", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"), + }, + }, + { } +}; +#endif + int synaptics_init(struct psmouse *psmouse) { struct synaptics_data *priv; @@ -638,4 +652,16 @@ psmouse->pktsize = 6; +#if defined(__i386__) + /* + * Toshiba's KBC seems to have trouble handling data from + * Synaptics as full rate, switch to lower rate which is roughly + * thye same as rate of standard PS/2 mouse. + */ + if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) { + printk(KERN_INFO "synaptics: Toshiba Satellite detected, limiting rate to 40pps.\n"); + psmouse->rate = 40; + } +#endif + return 0; diff -u b/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c --- b/drivers/input/serio/i8042.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/serio/i8042.c 2004-11-29 21:56:07 -08:00 @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -54,6 +55,10 @@ module_param_named(noloop, i8042_noloop, bool, 0); MODULE_PARM_DESC(dumbkbd, "Disable the AUX Loopback command while probing for the AUX port"); +static unsigned int i8042_blink_frequency = 500; +module_param_named(panicblink, i8042_blink_frequency, uint, 0600); +MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); + #ifdef CONFIG_ACPI static int i8042_noacpi; module_param_named(noacpi, i8042_noacpi, bool, 0); @@ -63,7 +68,7 @@ #define DEBUG #ifdef DEBUG static int i8042_debug; -module_param_named(debug, i8042_debug, bool, 600); +module_param_named(debug, i8042_debug, bool, 0600); MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); #endif @@ -78,7 +83,8 @@ spinlock_t i8042_lock = SPIN_LOCK_UNLOCKED; -struct i8042_values { +struct i8042_port { + struct serio *serio; int irq; unsigned char disable; unsigned char irqen; @@ -87,25 +93,25 @@ char name[8]; }; -static struct i8042_values i8042_kbd_values = { - .disable = I8042_CTR_KBDDIS, - .irqen = I8042_CTR_KBDINT, - .mux = -1, - .name = "KBD", -}; - -static struct i8042_values i8042_aux_values = { - .disable = I8042_CTR_AUXDIS, - .irqen = I8042_CTR_AUXINT, - .mux = -1, - .name = "AUX", +#define I8042_KBD_PORT_NO 0 +#define I8042_AUX_PORT_NO 1 +#define I8042_MUX_PORT_NO 2 +#define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2) +static struct i8042_port i8042_ports[I8042_NUM_PORTS] = { + { + .disable = I8042_CTR_KBDDIS, + .irqen = I8042_CTR_KBDINT, + .mux = -1, + .name = "KBD", + }, + { + .disable = I8042_CTR_AUXDIS, + .irqen = I8042_CTR_AUXINT, + .mux = -1, + .name = "AUX", + } }; -static struct i8042_values i8042_mux_values[I8042_NUM_MUX_PORTS]; - -static struct serio *i8042_kbd_port; -static struct serio *i8042_aux_port; -static struct serio *i8042_mux_port[I8042_NUM_MUX_PORTS]; static unsigned char i8042_initial_ctr; static unsigned char i8042_ctr; static unsigned char i8042_mux_open; @@ -113,6 +119,7 @@ static struct timer_list i8042_timer; static struct platform_device *i8042_platform_device; + /* * Shared IRQ's require a device pointer, but this driver doesn't support * multiple devices @@ -246,19 +253,19 @@ * i8042_aux_write() sends a byte out through the aux interface. */ -static int i8042_aux_write(struct serio *port, unsigned char c) +static int i8042_aux_write(struct serio *serio, unsigned char c) { - struct i8042_values *values = port->port_data; + struct i8042_port *port = serio->port_data; int retval; /* * Send the byte out. */ - if (values->mux == -1) + if (port->mux == -1) retval = i8042_command(&c, I8042_CMD_AUX_SEND); else - retval = i8042_command(&c, I8042_CMD_MUX_SEND + values->mux); + retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux); /* * Make sure the interrupt happens and the character is received even @@ -274,9 +281,10 @@ * i8042_activate_port() enables port on a chip. */ -static int i8042_activate_port(struct serio *port) +static int i8042_activate_port(struct i8042_port *port) { - struct i8042_values *values = port->port_data; + if (!port->serio) + return -1; i8042_flush(); @@ -284,12 +292,12 @@ * Enable port again here because it is disabled if we are * resuming (normally it is enabled already). */ - i8042_ctr &= ~values->disable; + i8042_ctr &= ~port->disable; - i8042_ctr |= values->irqen; + i8042_ctr |= port->irqen; if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { - i8042_ctr &= ~values->irqen; + i8042_ctr &= ~port->irqen; return -1; } @@ -302,22 +310,22 @@ * It allocates the interrupt and calls i8042_enable_port. */ -static int i8042_open(struct serio *port) +static int i8042_open(struct serio *serio) { - struct i8042_values *values = port->port_data; + struct i8042_port *port = serio->port_data; - if (values->mux != -1) + if (port->mux != -1) if (i8042_mux_open++) return 0; - if (request_irq(values->irq, i8042_interrupt, + if (request_irq(port->irq, i8042_interrupt, SA_SHIRQ, "i8042", i8042_request_irq_cookie)) { - printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name); + printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name); goto irq_fail; } if (i8042_activate_port(port)) { - printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", values->name); + printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name); goto activate_fail; } @@ -326,11 +334,10 @@ return 0; activate_fail: - free_irq(values->irq, i8042_request_irq_cookie); + free_irq(port->irq, i8042_request_irq_cookie); irq_fail: - values->exists = 0; - serio_unregister_port_delayed(port); + serio_unregister_port_delayed(serio); return -1; } @@ -341,27 +348,58 @@ * the BIOS could have used the AUX interrupt for PCI. */ -static void i8042_close(struct serio *port) +static void i8042_close(struct serio *serio) { - struct i8042_values *values = port->port_data; + struct i8042_port *port = serio->port_data; - if (values->mux != -1) + if (port->mux != -1) if (--i8042_mux_open) return; - i8042_ctr &= ~values->irqen; + i8042_ctr &= ~port->irqen; if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { - printk(KERN_ERR "i8042.c: Can't write CTR while closing %s.\n", values->name); - return; + printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name); +/* + * We still want to continue and free IRQ so if more data keeps coming in + * kernel will just ignore the irq. + */ } - free_irq(values->irq, i8042_request_irq_cookie); + free_irq(port->irq, i8042_request_irq_cookie); i8042_flush(); } /* + * i8042_start() is called by serio core when port is about to finish + * registering. It will mark port as existing so i8042_interrupt can + * start sending data through it. + */ +static int i8042_start(struct serio *serio) +{ + struct i8042_port *port = serio->port_data; + + port->exists = 1; + mb(); + return 0; +} + +/* + * i8042_stop() marks serio port as non-existing so i8042_interrupt + * will not try to send data to the port that is about to go away. + * The function is called by serio core as part of unregister procedure. + */ +static void i8042_stop(struct serio *serio) +{ + struct i8042_port *port = serio->port_data; + + port->exists = 0; + synchronize_kernel(); + port->serio = NULL; +} + +/* * i8042_interrupt() is the most important function in this driver - * it handles the interrupts from the i8042, and sends incoming bytes * to the upper layers. @@ -369,25 +407,25 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + struct i8042_port *port; unsigned long flags; - unsigned char str, data = 0; + unsigned char str, data; unsigned int dfl; - unsigned int aux_idx; + unsigned int port_no; int ret; mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); spin_lock_irqsave(&i8042_lock, flags); str = i8042_read_status(); - if (str & I8042_STR_OBF) - data = i8042_read_data(); - spin_unlock_irqrestore(&i8042_lock, flags); - - if (~str & I8042_STR_OBF) { + if (unlikely(~str & I8042_STR_OBF)) { + spin_unlock_irqrestore(&i8042_lock, flags); if (irq) dbg("Interrupt %d, without any data", irq); 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; @@ -419,39 +457,28 @@ } } - aux_idx = (str >> 6) & 3; - - dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)", - data, aux_idx, irq, - dfl & SERIO_PARITY ? ", bad parity" : "", - dfl & SERIO_TIMEOUT ? ", timeout" : ""); - - if (likely(i8042_mux_values[aux_idx].exists)) - serio_interrupt(i8042_mux_port[aux_idx], data, dfl, regs); - + port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3); last_str = str; last_transmit = jiffies; - goto irq_ret; + } else { + + dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | + ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); + + port_no = (str & I8042_STR_AUXDATA) ? + I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; } - dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | - ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); + port = &i8042_ports[port_no]; dbg("%02x <- i8042 (interrupt, %s, %d%s%s)", - data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, - dfl & SERIO_PARITY ? ", bad parity" : "", - dfl & SERIO_TIMEOUT ? ", timeout" : ""); + data, port->name, irq, + dfl & SERIO_PARITY ? ", bad parity" : "", + dfl & SERIO_TIMEOUT ? ", timeout" : ""); + if (likely(port->exists)) + serio_interrupt(port->serio, data, dfl, regs); - if (str & I8042_STR_AUXDATA) { - if (likely(i8042_aux_values.exists)) - serio_interrupt(i8042_aux_port, data, dfl, regs); - } else { - if (likely(i8042_kbd_values.exists)) - serio_interrupt(i8042_kbd_port, data, dfl, regs); - } - -irq_ret: ret = 1; out: return IRQ_RETVAL(ret); @@ -463,7 +490,7 @@ * Legacy) mode. */ -static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux_version) +static int i8042_enable_mux_mode(unsigned char *mux_version) { unsigned char param; @@ -501,7 +528,7 @@ * the controller has been switched into Multiplexed mode */ -static int i8042_enable_mux_ports(struct i8042_values *values) +static int i8042_enable_mux_ports(void) { unsigned char param; int i; @@ -536,11 +563,11 @@ * LCS/Telegraphics. */ -static int __init i8042_check_mux(struct i8042_values *values) +static int __init i8042_check_mux(void) { unsigned char mux_version; - if (i8042_enable_mux_mode(values, &mux_version)) + if (i8042_enable_mux_mode(&mux_version)) return -1; /* Workaround for broken chips which seem to support MUX, but in reality don't. */ @@ -551,7 +578,7 @@ printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", (mux_version >> 4) & 0xf, mux_version & 0xf); - if (i8042_enable_mux_ports(values)) + if (i8042_enable_mux_ports()) return -1; i8042_mux_present = 1; @@ -564,7 +591,7 @@ * the presence of an AUX interface. */ -static int __init i8042_check_aux(struct i8042_values *values) +static int __init i8042_check_aux(void) { unsigned char param; static int i8042_check_aux_cookie; @@ -574,10 +601,10 @@ * in trying to detect AUX presence. */ - if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, - "i8042", &i8042_check_aux_cookie)) + if (request_irq(i8042_ports[I8042_AUX_PORT_NO].irq, i8042_interrupt, + SA_SHIRQ, "i8042", &i8042_check_aux_cookie)) return -1; - free_irq(values->irq, &i8042_check_aux_cookie); + free_irq(i8042_ports[I8042_AUX_PORT_NO].irq, &i8042_check_aux_cookie); /* * Get rid of bytes in the queue. @@ -642,27 +669,25 @@ * registers it, and reports to the user. */ -static int __init i8042_port_register(struct serio *port) +static int __init i8042_port_register(struct i8042_port *port) { - struct i8042_values *values = port->port_data; - - values->exists = 1; - - i8042_ctr &= ~values->disable; + i8042_ctr &= ~port->disable; if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n"); - values->exists = 0; + kfree(port->serio); + port->serio = NULL; + i8042_ctr |= port->disable; return -1; } printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", - values->name, + port->name, (unsigned long) I8042_DATA_REG, (unsigned long) I8042_COMMAND_REG, - values->irq); + port->irq); - serio_register_port(port); + serio_register_port(port->serio); return 0; } @@ -807,39 +832,37 @@ * Reset anything that is connected to the ports. */ - if (i8042_kbd_values.exists) - serio_cleanup(i8042_kbd_port); - - if (i8042_aux_values.exists) - serio_cleanup(i8042_aux_port); - - for (i = 0; i < I8042_NUM_MUX_PORTS; i++) - if (i8042_mux_values[i].exists) - serio_cleanup(i8042_mux_port[i]); + for (i = 0; i < I8042_NUM_PORTS; i++) + if (i8042_ports[i].exists) + serio_cleanup(i8042_ports[i].serio); i8042_controller_reset(); } -static int blink_frequency = 500; -module_param_named(panicblink, blink_frequency, int, 0600); - -/* Catch the case when the kbd interrupt is off */ -#define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) - -/* Tell the user who may be running in X and not see the console that we have - panic'ed. This is to distingush panics from "real" lockups. */ +/* + * i8042_panic_blink() will flash the keyboard LEDs and is called when + * kernel panics. Flashing LEDs is useful for users running X who may + * not see the console and will help distingushing panics from "real" + * lockups. + */ static long i8042_panic_blink(long count) { long delay = 0; static long last_blink; static char led; - /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is - different. */ - if (!blink_frequency) + + /* + * We expect frequency to be about 1/2s. KDB uses about 1s. + * Make sure they are different. + */ + if (!i8042_blink_frequency) return 0; - if (count - last_blink < blink_frequency) + if (count - last_blink < i8042_blink_frequency) return 0; + + /* Ensures that we will not get stuck here if kbd interrupt is off */ +#define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0) led ^= 0x01 | 0x04; while (i8042_read_status() & I8042_STR_IBF) DELAY; @@ -850,11 +873,12 @@ DELAY; i8042_write_data(led); DELAY; +#undef DELAY + last_blink = count; return delay; } -#undef DELAY /* * Here we try to restore the original BIOS settings @@ -888,8 +912,7 @@ } if (i8042_mux_present) - if (i8042_enable_mux_mode(&i8042_aux_values, NULL) || - i8042_enable_mux_ports(&i8042_aux_values)) { + if (i8042_enable_mux_mode(NULL) || i8042_enable_mux_ports()) { printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n"); } @@ -897,15 +920,9 @@ * Reconnect anything that was connected to the ports. */ - if (i8042_kbd_values.exists && i8042_activate_port(i8042_kbd_port) == 0) - serio_reconnect(i8042_kbd_port); - - if (i8042_aux_values.exists && i8042_activate_port(i8042_aux_port) == 0) - serio_reconnect(i8042_aux_port); - - for (i = 0; i < I8042_NUM_MUX_PORTS; i++) - if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port[i]) == 0) - serio_reconnect(i8042_mux_port[i]); + for (i = 0; i < I8042_NUM_PORTS; i++) + if (i8042_activate_port(&i8042_ports[i]) == 0) + serio_reconnect(i8042_ports[i].serio); /* * Restart timer (for polling "stuck" data) */ @@ -935,9 +952,10 @@ .shutdown = i8042_shutdown, }; -static struct serio * __init i8042_allocate_kbd_port(void) +static void __init i8042_create_kbd_port(void) { struct serio *serio; + struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; serio = kmalloc(sizeof(struct serio), GFP_KERNEL); if (serio) { @@ -946,18 +964,22 @@ serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write, serio->open = i8042_open, serio->close = i8042_close, - serio->port_data = &i8042_kbd_values, + serio->start = i8042_start, + serio->stop = i8042_stop, + serio->port_data = port, serio->dev.parent = &i8042_platform_device->dev; strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); - } - return serio; + port->serio = serio; + i8042_port_register(port); + } } -static struct serio * __init i8042_allocate_aux_port(void) +static void __init i8042_create_aux_port(void) { struct serio *serio; + struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; serio = kmalloc(sizeof(struct serio), GFP_KERNEL); if (serio) { @@ -966,38 +988,44 @@ serio->write = i8042_aux_write; serio->open = i8042_open; serio->close = i8042_close; - serio->port_data = &i8042_aux_values, + serio->start = i8042_start, + serio->stop = i8042_stop, + serio->port_data = port, serio->dev.parent = &i8042_platform_device->dev; strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); - } - return serio; + port->serio = serio; + i8042_port_register(port); + } } -static struct serio * __init i8042_allocate_mux_port(int index) +static void __init i8042_create_mux_port(int index) { struct serio *serio; - struct i8042_values *values = &i8042_mux_values[index]; + struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; serio = kmalloc(sizeof(struct serio), GFP_KERNEL); if (serio) { - *values = i8042_aux_values; - snprintf(values->name, sizeof(values->name), "AUX%d", index); - values->mux = index; - memset(serio, 0, sizeof(struct serio)); serio->type = SERIO_8042; serio->write = i8042_aux_write; serio->open = i8042_open; serio->close = i8042_close; - serio->port_data = values; + serio->start = i8042_start, + serio->stop = i8042_stop, + serio->port_data = port; serio->dev.parent = &i8042_platform_device->dev; snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); - } - return serio; + *port = i8042_ports[I8042_AUX_PORT_NO]; + port->exists = 0; + snprintf(port->name, sizeof(port->name), "AUX%d", index); + port->mux = index; + port->serio = serio; + i8042_port_register(port); + } } int __init i8042_init(void) @@ -1013,8 +1041,8 @@ if (i8042_platform_init()) return -EBUSY; - i8042_aux_values.irq = I8042_AUX_IRQ; - i8042_kbd_values.irq = I8042_KBD_IRQ; + i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ; + i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; if (i8042_controller_init()) return -ENODEV; @@ -1029,23 +1057,15 @@ return PTR_ERR(i8042_platform_device); } - if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values)) { - if (!i8042_nomux && !i8042_check_mux(&i8042_aux_values)) - for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { - i8042_mux_port[i] = i8042_allocate_mux_port(i); - if (i8042_mux_port[i]) - i8042_port_register(i8042_mux_port[i]); - } - else { - i8042_aux_port = i8042_allocate_aux_port(); - if (i8042_aux_port) - i8042_port_register(i8042_aux_port); - } + if (!i8042_noaux && !i8042_check_aux()) { + if (!i8042_nomux && !i8042_check_mux()) + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) + i8042_create_mux_port(i); + else + i8042_create_aux_port(); } - i8042_kbd_port = i8042_allocate_kbd_port(); - if (i8042_kbd_port) - i8042_port_register(i8042_kbd_port); + i8042_create_kbd_port(); mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); @@ -1058,15 +1078,9 @@ i8042_controller_cleanup(); - if (i8042_kbd_values.exists) - serio_unregister_port(i8042_kbd_port); - - if (i8042_aux_values.exists) - serio_unregister_port(i8042_aux_port); - - for (i = 0; i < I8042_NUM_MUX_PORTS; i++) - if (i8042_mux_values[i].exists) - serio_unregister_port(i8042_mux_port[i]); + for (i = 0; i < I8042_NUM_PORTS; i++) + if (i8042_ports[i].exists) + serio_unregister_port(i8042_ports[i].serio); del_timer_sync(&i8042_timer); diff -u b/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h --- b/drivers/input/serio/i8042.h 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/serio/i8042.h 2004-11-29 21:56:07 -08:00 @@ -117,13 +117,13 @@ */ #ifdef DEBUG -static unsigned long i8042_start; -#define dbg_init() do { i8042_start = jiffies; } while (0) +static unsigned long i8042_start_time; +#define dbg_init() do { i8042_start_time = jiffies; } while (0) #define dbg(format, arg...) \ do { \ if (i8042_debug) \ printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" , \ - ## arg, (int) (jiffies - i8042_start)); \ + ## arg, (int) (jiffies - i8042_start_time)); \ } while (0) #else #define dbg_init() do { } while (0) diff -u b/drivers/input/serio/serio.c b/drivers/input/serio/serio.c --- b/drivers/input/serio/serio.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/input/serio/serio.c 2004-11-29 21:56:07 -08:00 @@ -120,13 +120,28 @@ static DECLARE_COMPLETION(serio_exited); static int serio_pid; -static void serio_queue_event(struct serio *serio, int event_type) +static void serio_queue_event(struct serio *serio, enum serio_event_type event_type) { unsigned long flags; struct serio_event *event; spin_lock_irqsave(&serio_event_lock, flags); + /* + * Scan event list for the other events for the same serio port, + * starting with the most recent one. If event is the same we + * do not need add new one. If event is of different type we + * need to add this event and should not look further because + * we need to preseve sequence of distinct events. + */ + list_for_each_entry_reverse(event, &serio_event_list, node) { + if (event->serio == serio) { + if (event->type == event_type) + goto out; + break; + } + } + if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { event->type = event_type; event->serio = serio; @@ -135,9 +150,37 @@ wake_up(&serio_wait); } +out: spin_unlock_irqrestore(&serio_event_lock, flags); } +static void serio_remove_duplicate_events(struct serio_event *event) +{ + struct list_head *node, *next; + struct serio_event *e; + unsigned long flags; + + spin_lock_irqsave(&serio_event_lock, flags); + + list_for_each_safe(node, next, &serio_event_list) { + e = container_of(node, struct serio_event, node); + if (event->serio == e->serio) { + /* + * If this event is of different type we should not + * look further - we only suppress duplicate events + * that were sent back-to-back. + */ + if (event->type != e->type) + break; /* Stop, when need to preserve event flow */ + list_del_init(node); + kfree(e); + } + } + + spin_unlock_irqrestore(&serio_event_lock, flags); +} + + static struct serio_event *serio_get_event(void) { struct serio_event *event; @@ -192,6 +235,7 @@ } up(&serio_sem); + serio_remove_duplicate_events(event); kfree(event); } } @@ -328,7 +372,10 @@ serio->dev.release = serio_release_port; if (serio->parent) serio->dev.parent = &serio->parent->dev; - device_register(&serio->dev); + device_initialize(&serio->dev); + if (serio->start) + serio->start(serio); + device_add(&serio->dev); } /* @@ -351,6 +398,9 @@ put_driver(&drv->driver); } + if (serio->stop) + serio->stop(serio); + if (serio->parent) { spin_lock_irqsave(&serio->parent->lock, flags); serio->parent->child = NULL; @@ -631,14 +681,9 @@ if (likely(serio->drv)) { ret = serio->drv->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; - } - } + } else if (!dfl) { + serio_rescan(serio); + ret = IRQ_HANDLED; } spin_unlock_irqrestore(&serio->lock, flags); diff -u b/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- b/drivers/usb/input/hid-core.c 2004-11-29 22:08:48 -08:00 +++ b/drivers/usb/input/hid-core.c 2004-11-29 21:56:07 -08:00 @@ -1478,0 +1479,3 @@ + +#define USB_VENDOR_ID_DELORME 0x1163 +#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 diff -u b/include/linux/serio.h b/include/linux/serio.h --- b/include/linux/serio.h 2004-11-29 22:08:48 -08:00 +++ b/include/linux/serio.h 2004-11-29 21:56:07 -08:00 @@ -42,6 +42,8 @@ int (*write)(struct serio *, unsigned char); int (*open)(struct serio *); void (*close)(struct serio *); + int (*start)(struct serio *); + void (*stop)(struct serio *); struct serio *parent, *child;