diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/serio/i8042.c | 178 |
1 files changed, 100 insertions, 78 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 708a1d3beab..f0d9c5f9cc3 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -338,10 +338,10 @@ static int i8042_open(struct serio *serio) return 0; -activate_fail: + activate_fail: free_irq(port->irq, i8042_request_irq_cookie); -irq_fail: + irq_fail: serio_unregister_port_delayed(serio); return -1; @@ -485,7 +485,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) serio_interrupt(port->serio, data, dfl, regs); ret = 1; -out: + out: return IRQ_RETVAL(ret); } @@ -552,7 +552,7 @@ static int i8042_enable_mux_ports(void) * Enable all muxed ports. */ - for (i = 0; i < 4; i++) { + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { i8042_command(¶m, I8042_CMD_MUX_PFX + i); i8042_command(¶m, I8042_CMD_AUX_ENABLE); } @@ -682,7 +682,7 @@ static int __init i8042_port_register(struct i8042_port *port) kfree(port->serio); port->serio = NULL; i8042_ctr |= port->disable; - return -1; + return -EIO; } printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", @@ -977,80 +977,83 @@ static struct device_driver i8042_driver = { .shutdown = i8042_shutdown, }; -static void __init i8042_create_kbd_port(void) +static int __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) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; - serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; - serio->open = i8042_open; - serio->close = i8042_close; - 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)); - - port->serio = serio; - i8042_port_register(port); - } + serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL; + serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; + serio->open = i8042_open; + serio->close = i8042_close; + 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)); + + port->serio = serio; + + return i8042_port_register(port); } -static void __init i8042_create_aux_port(void) +static int __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) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_8042; - serio->write = i8042_aux_write; - serio->open = i8042_open; - serio->close = i8042_close; - 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)); - - port->serio = serio; - i8042_port_register(port); - } + serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + serio->id.type = SERIO_8042; + serio->write = i8042_aux_write; + serio->open = i8042_open; + serio->close = i8042_close; + 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)); + + port->serio = serio; + + return i8042_port_register(port); } -static void __init i8042_create_mux_port(int index) +static int __init i8042_create_mux_port(int index) { struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); - if (serio) { - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_8042; - serio->write = i8042_aux_write; - serio->open = i8042_open; - serio->close = i8042_close; - 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); - - *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); - } + serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); + if (!serio) + return -ENOMEM; + + serio->id.type = SERIO_8042; + serio->write = i8042_aux_write; + serio->open = i8042_open; + serio->close = i8042_close; + 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); + + *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; + + return i8042_port_register(port); } static int __init i8042_init(void) @@ -1070,36 +1073,55 @@ static int __init i8042_init(void) i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ; if (i8042_controller_init()) { - i8042_platform_exit(); - return -ENODEV; + err = -ENODEV; + goto err_platform_exit; } err = driver_register(&i8042_driver); - if (err) { - i8042_platform_exit(); - return err; - } + if (err) + goto err_controller_cleanup; i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); if (IS_ERR(i8042_platform_device)) { - driver_unregister(&i8042_driver); - i8042_platform_exit(); - return PTR_ERR(i8042_platform_device); + err = PTR_ERR(i8042_platform_device); + goto err_unregister_driver; } 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(); + if (!i8042_nomux && !i8042_check_mux()) { + for (i = 0; i < I8042_NUM_MUX_PORTS; i++) { + err = i8042_create_mux_port(i); + if (err) + goto err_unregister_ports; + } + } else { + err = i8042_create_aux_port(); + if (err) + goto err_unregister_ports; + } } - i8042_create_kbd_port(); + err = i8042_create_kbd_port(); + if (err) + goto err_unregister_ports; mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); return 0; + + err_unregister_ports: + for (i = 0; i < I8042_NUM_PORTS; i++) + if (i8042_ports[i].serio) + serio_unregister_port(i8042_ports[i].serio); + platform_device_unregister(i8042_platform_device); + err_unregister_driver: + driver_unregister(&i8042_driver); + err_controller_cleanup: + i8042_controller_cleanup(); + err_platform_exit: + i8042_platform_exit(); + + return err; } static void __exit i8042_exit(void) |