Commit 0854e52d authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: i8042 - clean up initialization code; abort if we

       can't create all ports.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 4cee9956
...@@ -338,10 +338,10 @@ static int i8042_open(struct serio *serio) ...@@ -338,10 +338,10 @@ static int i8042_open(struct serio *serio)
return 0; return 0;
activate_fail: activate_fail:
free_irq(port->irq, i8042_request_irq_cookie); free_irq(port->irq, i8042_request_irq_cookie);
irq_fail: irq_fail:
serio_unregister_port_delayed(serio); serio_unregister_port_delayed(serio);
return -1; return -1;
...@@ -485,7 +485,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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); serio_interrupt(port->serio, data, dfl, regs);
ret = 1; ret = 1;
out: out:
return IRQ_RETVAL(ret); return IRQ_RETVAL(ret);
} }
...@@ -552,7 +552,7 @@ static int i8042_enable_mux_ports(void) ...@@ -552,7 +552,7 @@ static int i8042_enable_mux_ports(void)
* Enable all muxed ports. * Enable all muxed ports.
*/ */
for (i = 0; i < 4; i++) { for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
i8042_command(&param, I8042_CMD_MUX_PFX + i); i8042_command(&param, I8042_CMD_MUX_PFX + i);
i8042_command(&param, I8042_CMD_AUX_ENABLE); i8042_command(&param, I8042_CMD_AUX_ENABLE);
} }
...@@ -682,7 +682,7 @@ static int __init i8042_port_register(struct i8042_port *port) ...@@ -682,7 +682,7 @@ static int __init i8042_port_register(struct i8042_port *port)
kfree(port->serio); kfree(port->serio);
port->serio = NULL; port->serio = NULL;
i8042_ctr |= port->disable; i8042_ctr |= port->disable;
return -1; return -EIO;
} }
printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n", printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
...@@ -977,80 +977,83 @@ static struct device_driver i8042_driver = { ...@@ -977,80 +977,83 @@ static struct device_driver i8042_driver = {
.shutdown = i8042_shutdown, .shutdown = i8042_shutdown,
}; };
static void __init i8042_create_kbd_port(void) static int __init i8042_create_kbd_port(void)
{ {
struct serio *serio; struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
if (serio) { if (!serio)
memset(serio, 0, sizeof(struct serio)); return -ENOMEM;
serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
serio->open = i8042_open; serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
serio->close = i8042_close; serio->open = i8042_open;
serio->start = i8042_start; serio->close = i8042_close;
serio->stop = i8042_stop; serio->start = i8042_start;
serio->port_data = port; serio->stop = i8042_stop;
serio->dev.parent = &i8042_platform_device->dev; serio->port_data = port;
strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name)); serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys)); 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); 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 serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO]; struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
if (serio) { if (!serio)
memset(serio, 0, sizeof(struct serio)); return -ENOMEM;
serio->id.type = SERIO_8042;
serio->write = i8042_aux_write; serio->id.type = SERIO_8042;
serio->open = i8042_open; serio->write = i8042_aux_write;
serio->close = i8042_close; serio->open = i8042_open;
serio->start = i8042_start; serio->close = i8042_close;
serio->stop = i8042_stop; serio->start = i8042_start;
serio->port_data = port; serio->stop = i8042_stop;
serio->dev.parent = &i8042_platform_device->dev; serio->port_data = port;
strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name)); serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); 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); 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 serio *serio;
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index]; struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
serio = kmalloc(sizeof(struct serio), GFP_KERNEL); serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
if (serio) { if (!serio)
memset(serio, 0, sizeof(struct serio)); return -ENOMEM;
serio->id.type = SERIO_8042;
serio->write = i8042_aux_write; serio->id.type = SERIO_8042;
serio->open = i8042_open; serio->write = i8042_aux_write;
serio->close = i8042_close; serio->open = i8042_open;
serio->start = i8042_start; serio->close = i8042_close;
serio->stop = i8042_stop; serio->start = i8042_start;
serio->port_data = port; serio->stop = i8042_stop;
serio->dev.parent = &i8042_platform_device->dev; serio->port_data = port;
snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index); serio->dev.parent = &i8042_platform_device->dev;
snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1); 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; *port = i8042_ports[I8042_AUX_PORT_NO];
snprintf(port->name, sizeof(port->name), "AUX%d", index); port->exists = 0;
port->mux = index; snprintf(port->name, sizeof(port->name), "AUX%d", index);
port->serio = serio; port->mux = index;
i8042_port_register(port); port->serio = serio;
}
return i8042_port_register(port);
} }
static int __init i8042_init(void) static int __init i8042_init(void)
...@@ -1070,36 +1073,55 @@ 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; i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
if (i8042_controller_init()) { if (i8042_controller_init()) {
i8042_platform_exit(); err = -ENODEV;
return -ENODEV; goto err_platform_exit;
} }
err = driver_register(&i8042_driver); err = driver_register(&i8042_driver);
if (err) { if (err)
i8042_platform_exit(); goto err_controller_cleanup;
return err;
}
i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0); i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
if (IS_ERR(i8042_platform_device)) { if (IS_ERR(i8042_platform_device)) {
driver_unregister(&i8042_driver); err = PTR_ERR(i8042_platform_device);
i8042_platform_exit(); goto err_unregister_driver;
return PTR_ERR(i8042_platform_device);
} }
if (!i8042_noaux && !i8042_check_aux()) { if (!i8042_noaux && !i8042_check_aux()) {
if (!i8042_nomux && !i8042_check_mux()) if (!i8042_nomux && !i8042_check_mux()) {
for (i = 0; i < I8042_NUM_MUX_PORTS; i++) for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
i8042_create_mux_port(i); err = i8042_create_mux_port(i);
else if (err)
i8042_create_aux_port(); 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); mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
return 0; 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) static void __exit i8042_exit(void)
......
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