From ebd7768daeb39b0691e25175e25b980f13e913e2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 22 Jul 2009 21:51:32 -0700 Subject: Input: i8042 - switch to using dev_pm_ops Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'drivers/input/serio/i8042.c') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 582245c497eb..9f5c0506242f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -923,41 +923,27 @@ static void i8042_dritek_enable(void) #ifdef CONFIG_PM -static bool i8042_suspended; - /* - * Here we try to restore the original BIOS settings. We only want to - * do that once, when we really suspend, not when we taking memory - * snapshot for swsusp (in this case we'll perform required cleanup - * as part of shutdown process). + * Here we try to restore the original BIOS settings to avoid + * upsetting it. */ -static int i8042_suspend(struct platform_device *dev, pm_message_t state) +static int i8042_pm_reset(struct device *dev) { - if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) - i8042_controller_reset(); - - i8042_suspended = state.event == PM_EVENT_SUSPEND || - state.event == PM_EVENT_FREEZE; + i8042_controller_reset(); return 0; } - /* - * Here we try to reset everything back to a state in which suspended + * Here we try to reset everything back to a state we had + * before suspending. */ -static int i8042_resume(struct platform_device *dev) +static int i8042_pm_restore(struct device *dev) { int error; -/* - * Do not bother with restoring state if we haven't suspened yet - */ - if (!i8042_suspended) - return 0; - error = i8042_controller_check(); if (error) return error; @@ -1001,11 +987,18 @@ static int i8042_resume(struct platform_device *dev) if (i8042_ports[I8042_KBD_PORT_NO].serio) i8042_enable_kbd_port(); - i8042_suspended = false; i8042_interrupt(0, NULL); return 0; } + +static const struct dev_pm_ops i8042_pm_ops = { + .suspend = i8042_pm_reset, + .resume = i8042_pm_restore, + .poweroff = i8042_pm_reset, + .restore = i8042_pm_restore, +}; + #endif /* CONFIG_PM */ /* @@ -1251,14 +1244,13 @@ static struct platform_driver i8042_driver = { .driver = { .name = "i8042", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &i8042_pm_ops, +#endif }, .probe = i8042_probe, .remove = __devexit_p(i8042_remove), .shutdown = i8042_shutdown, -#ifdef CONFIG_PM - .suspend = i8042_suspend, - .resume = i8042_resume, -#endif }; static int __init i8042_init(void) -- cgit v1.2.1 From 1c7827ae70e7c8456e08f7bb9ef2238d27814cbe Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 3 Sep 2009 21:45:34 -0700 Subject: Input: i8042 - bypass AUX IRQ delivery test on laptops It seems that many laptops do not fully implement AUX LOOP command in their keyboard controllers, causing issues with touchpad detection. We know however that almost every laptop/portable uses a PS/2 pointing device and, even if user disables it in favor of an external mouse, the system will not use IRQ 12 for anything else. Therefore we may bypass AUX IRQ delivery test when running on a laptop and assume that it is routed properly. Just to be safe we require the box to have good PNP data in order to bypass the test. [Jin Dongming : fix crash caused by missing terminator in the DMI table] Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/input/serio/i8042.c') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 9f5c0506242f..b53a015bf8a5 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -83,6 +83,8 @@ module_param_named(debug, i8042_debug, bool, 0600); MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); #endif +static bool i8042_bypass_aux_irq_test; + #include "i8042.h" static DEFINE_SPINLOCK(i8042_lock); @@ -641,7 +643,7 @@ static int __devinit i8042_check_aux(void) * used it for a PCI card or somethig else. */ - if (i8042_noloop || aux_loop_broken) { + if (i8042_noloop || i8042_bypass_aux_irq_test || aux_loop_broken) { /* * Without LOOP command we can't test AUX IRQ delivery. Assume the port * is working and hope we are right. -- cgit v1.2.1 From 5ddbc77c3eb54336fcd44b7b66b44784d65677e2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 9 Sep 2009 19:08:15 -0700 Subject: Input: i8042 - try disabling and re-enabling AUX port at close Ever since we switched from having a polling timer to registering IRQ handlers for both keyboard and AUX ports at the driver registration time, on certain boxes probing for a mouse results in keyboard stopping working. The only real difference between old and new way is that before we disabled ports after unsuccessful probe whereas now we leave them as is. Try to emulate the old behavior by disabling and immediately re-enabling AUX and KBD ports when corresponding serio port is being closed. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 50 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/input/serio/i8042.c') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index b53a015bf8a5..8aaf8fcacf62 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -264,6 +264,49 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) I8042_CMD_MUX_SEND + port->mux); } + +/* + * i8042_aux_close attempts to clear AUX or KBD port state by disabling + * and then re-enabling it. + */ + +static void i8042_port_close(struct serio *serio) +{ + int irq_bit; + int disable_bit; + const char *port_name; + + if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { + irq_bit = I8042_CTR_AUXINT; + disable_bit = I8042_CTR_AUXDIS; + port_name = "AUX"; + } else { + irq_bit = I8042_CTR_KBDINT; + disable_bit = I8042_CTR_KBDDIS; + port_name = "KBD"; + } + + i8042_ctr &= ~irq_bit; + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) + printk(KERN_WARNING + "i8042.c: Can't write CTR while closing %s port.\n", + port_name); + + udelay(50); + + i8042_ctr &= ~disable_bit; + i8042_ctr |= irq_bit; + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) + printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", + port_name); + + /* + * See if there is any data appeared while we were messing with + * port state. + */ + i8042_interrupt(0, NULL); +} + /* * i8042_start() is called by serio core when port is about to finish * registering. It will mark port as existing so i8042_interrupt can @@ -393,7 +436,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) } /* - * i8042_enable_kbd_port enables keybaord port on chip + * i8042_enable_kbd_port enables keyboard port on chip */ static int i8042_enable_kbd_port(void) @@ -841,6 +884,9 @@ static void i8042_controller_reset(void) i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); + if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) + printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); + /* * Disable MUX mode if present. */ @@ -1026,6 +1072,7 @@ static int __devinit i8042_create_kbd_port(void) serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; serio->start = i8042_start; serio->stop = i8042_stop; + serio->close = i8042_port_close; serio->port_data = port; serio->dev.parent = &i8042_platform_device->dev; strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); @@ -1056,6 +1103,7 @@ static int __devinit i8042_create_aux_port(int idx) if (idx < 0) { strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); + serio->close = i8042_port_close; } else { snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); -- cgit v1.2.1 From 386b384900a200d5fcabdd4a9c27eb21db606cd4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 9 Sep 2009 19:08:16 -0700 Subject: Input: i8042 - use boolean type where it makes sense Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 103 ++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 51 deletions(-) (limited to 'drivers/input/serio/i8042.c') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 8aaf8fcacf62..61ed7a966c60 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -28,35 +28,35 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); MODULE_LICENSE("GPL"); -static unsigned int i8042_nokbd; +static bool i8042_nokbd; module_param_named(nokbd, i8042_nokbd, bool, 0); MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); -static unsigned int i8042_noaux; +static bool i8042_noaux; module_param_named(noaux, i8042_noaux, bool, 0); MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); -static unsigned int i8042_nomux; +static bool i8042_nomux; module_param_named(nomux, i8042_nomux, bool, 0); MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); -static unsigned int i8042_unlock; +static bool i8042_unlock; module_param_named(unlock, i8042_unlock, bool, 0); MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); -static unsigned int i8042_reset; +static bool i8042_reset; module_param_named(reset, i8042_reset, bool, 0); MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); -static unsigned int i8042_direct; +static bool i8042_direct; module_param_named(direct, i8042_direct, bool, 0); MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); -static unsigned int i8042_dumbkbd; +static bool i8042_dumbkbd; module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); -static unsigned int i8042_noloop; +static bool i8042_noloop; module_param_named(noloop, i8042_noloop, bool, 0); MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); @@ -65,20 +65,20 @@ 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_X86 -static unsigned int i8042_dritek; +static bool i8042_dritek; module_param_named(dritek, i8042_dritek, bool, 0); MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); #endif #ifdef CONFIG_PNP -static int i8042_nopnp; +static bool i8042_nopnp; module_param_named(nopnp, i8042_nopnp, bool, 0); MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); #endif #define DEBUG #ifdef DEBUG -static int i8042_debug; +static bool i8042_debug; module_param_named(debug, i8042_debug, bool, 0600); MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); #endif @@ -92,7 +92,7 @@ static DEFINE_SPINLOCK(i8042_lock); struct i8042_port { struct serio *serio; int irq; - unsigned char exists; + bool exists; signed char mux; }; @@ -105,9 +105,9 @@ static struct i8042_port i8042_ports[I8042_NUM_PORTS]; static unsigned char i8042_initial_ctr; static unsigned char i8042_ctr; -static unsigned char i8042_mux_present; -static unsigned char i8042_kbd_irq_registered; -static unsigned char i8042_aux_irq_registered; +static bool i8042_mux_present; +static bool i8042_kbd_irq_registered; +static bool i8042_aux_irq_registered; static unsigned char i8042_suppress_kbd_ack; static struct platform_device *i8042_platform_device; @@ -316,7 +316,7 @@ static int i8042_start(struct serio *serio) { struct i8042_port *port = serio->port_data; - port->exists = 1; + port->exists = true; mb(); return 0; } @@ -330,7 +330,7 @@ static void i8042_stop(struct serio *serio) { struct i8042_port *port = serio->port_data; - port->exists = 0; + port->exists = false; /* * We synchronize with both AUX and KBD IRQs because there is @@ -492,14 +492,15 @@ static int i8042_enable_mux_ports(void) } /* - * i8042_set_mux_mode checks whether the controller has an active - * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. + * i8042_set_mux_mode checks whether the controller has an + * active multiplexor and puts the chip into Multiplexed (true) + * or Legacy (false) mode. */ -static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) +static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) { - unsigned char param; + unsigned char param, val; /* * Get rid of bytes in the queue. */ @@ -511,14 +512,21 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) * mouse interface, the last should be version. */ - param = 0xf0; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xf0) + param = val = 0xf0; + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) + return -1; + param = val = multiplex ? 0x56 : 0xf6; + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) return -1; - param = mode ? 0x56 : 0xf6; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6)) + param = val = multiplex ? 0xa4 : 0xa5; + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == val) return -1; - param = mode ? 0xa4 : 0xa5; - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5)) + +/* + * Workaround for interference with USB Legacy emulation + * that causes a v10.12 MUX to be found. + */ + if (param == 0xac) return -1; if (mux_version) @@ -537,14 +545,7 @@ static int __devinit i8042_check_mux(void) { unsigned char mux_version; - if (i8042_set_mux_mode(1, &mux_version)) - return -1; - -/* - * Workaround for interference with USB Legacy emulation - * that causes a v10.12 MUX to be found. - */ - if (mux_version == 0xAC) + if (i8042_set_mux_mode(true, &mux_version)) return -1; printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", @@ -561,7 +562,7 @@ static int __devinit i8042_check_mux(void) return -EIO; } - i8042_mux_present = 1; + i8042_mux_present = true; return 0; } @@ -570,7 +571,7 @@ static int __devinit i8042_check_mux(void) * The following is used to test AUX IRQ delivery. */ static struct completion i8042_aux_irq_delivered __devinitdata; -static int i8042_irq_being_tested __devinitdata; +static bool i8042_irq_being_tested __devinitdata; static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) { @@ -597,7 +598,7 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) * verifies success by readinng CTR. Used when testing for presence of AUX * port. */ -static int __devinit i8042_toggle_aux(int on) +static int __devinit i8042_toggle_aux(bool on) { unsigned char param; int i; @@ -628,8 +629,8 @@ static int __devinit i8042_toggle_aux(int on) static int __devinit i8042_check_aux(void) { int retval = -1; - int irq_registered = 0; - int aux_loop_broken = 0; + bool irq_registered = false; + bool aux_loop_broken = false; unsigned long flags; unsigned char param; @@ -666,19 +667,19 @@ static int __devinit i8042_check_aux(void) * mark it as broken */ if (!retval) - aux_loop_broken = 1; + aux_loop_broken = true; } /* * Bit assignment test - filters out PS/2 i8042's in AT mode */ - if (i8042_toggle_aux(0)) { + if (i8042_toggle_aux(false)) { printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); } - if (i8042_toggle_aux(1)) + if (i8042_toggle_aux(true)) return -1; /* @@ -699,7 +700,7 @@ static int __devinit i8042_check_aux(void) "i8042", i8042_platform_device)) goto out; - irq_registered = 1; + irq_registered = true; if (i8042_enable_aux_port()) goto out; @@ -707,7 +708,7 @@ static int __devinit i8042_check_aux(void) spin_lock_irqsave(&i8042_lock, flags); init_completion(&i8042_aux_irq_delivered); - i8042_irq_being_tested = 1; + i8042_irq_being_tested = true; param = 0xa5; retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); @@ -844,7 +845,7 @@ static int i8042_controller_init(void) */ if (~i8042_ctr & I8042_CTR_XLATE) - i8042_direct = 1; + i8042_direct = true; /* * Set nontranslated mode for the kbd interface if requested by an option. @@ -892,7 +893,7 @@ static void i8042_controller_reset(void) */ if (i8042_mux_present) - i8042_set_mux_mode(0, NULL); + i8042_set_mux_mode(false, NULL); /* * Reset the controller if requested. @@ -1025,7 +1026,7 @@ static int i8042_pm_restore(struct device *dev) #endif if (i8042_mux_present) { - if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) + if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) printk(KERN_WARNING "i8042: failed to resume active multiplexor, " "mouse won't work.\n"); @@ -1167,7 +1168,7 @@ static void i8042_free_irqs(void) if (i8042_kbd_irq_registered) free_irq(I8042_KBD_IRQ, i8042_platform_device); - i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; + i8042_aux_irq_registered = i8042_kbd_irq_registered = false; } static int __devinit i8042_setup_aux(void) @@ -1201,7 +1202,7 @@ static int __devinit i8042_setup_aux(void) if (aux_enable()) goto err_free_irq; - i8042_aux_irq_registered = 1; + i8042_aux_irq_registered = true; return 0; err_free_irq: @@ -1228,7 +1229,7 @@ static int __devinit i8042_setup_kbd(void) if (error) goto err_free_irq; - i8042_kbd_irq_registered = 1; + i8042_kbd_irq_registered = true; return 0; err_free_irq: -- cgit v1.2.1 From f81134163fc785622f58af27363079ba1de7c7aa Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 9 Sep 2009 19:08:17 -0700 Subject: Input: i8042 - use platform_driver_probe i8042 is not hot-pluggable and we create the device when we register the driver, so let's save some memory by using platform_device_probe and using __init instead of __devinit. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers/input/serio/i8042.c') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 61ed7a966c60..eb3ff94af58c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -541,7 +541,7 @@ static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) * LCS/Telegraphics. */ -static int __devinit i8042_check_mux(void) +static int __init i8042_check_mux(void) { unsigned char mux_version; @@ -570,10 +570,10 @@ static int __devinit i8042_check_mux(void) /* * The following is used to test AUX IRQ delivery. */ -static struct completion i8042_aux_irq_delivered __devinitdata; -static bool i8042_irq_being_tested __devinitdata; +static struct completion i8042_aux_irq_delivered __initdata; +static bool i8042_irq_being_tested __initdata; -static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) +static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) { unsigned long flags; unsigned char str, data; @@ -598,7 +598,7 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) * verifies success by readinng CTR. Used when testing for presence of AUX * port. */ -static int __devinit i8042_toggle_aux(bool on) +static int __init i8042_toggle_aux(bool on) { unsigned char param; int i; @@ -626,7 +626,7 @@ static int __devinit i8042_toggle_aux(bool on) * the presence of an AUX interface. */ -static int __devinit i8042_check_aux(void) +static int __init i8042_check_aux(void) { int retval = -1; bool irq_registered = false; @@ -1060,7 +1060,7 @@ static void i8042_shutdown(struct platform_device *dev) i8042_controller_reset(); } -static int __devinit 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]; @@ -1085,7 +1085,7 @@ static int __devinit i8042_create_kbd_port(void) return 0; } -static int __devinit i8042_create_aux_port(int idx) +static int __init i8042_create_aux_port(int idx) { struct serio *serio; int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; @@ -1117,13 +1117,13 @@ static int __devinit i8042_create_aux_port(int idx) return 0; } -static void __devinit i8042_free_kbd_port(void) +static void __init i8042_free_kbd_port(void) { kfree(i8042_ports[I8042_KBD_PORT_NO].serio); i8042_ports[I8042_KBD_PORT_NO].serio = NULL; } -static void __devinit i8042_free_aux_ports(void) +static void __init i8042_free_aux_ports(void) { int i; @@ -1133,7 +1133,7 @@ static void __devinit i8042_free_aux_ports(void) } } -static void __devinit i8042_register_ports(void) +static void __init i8042_register_ports(void) { int i; @@ -1171,7 +1171,7 @@ static void i8042_free_irqs(void) i8042_aux_irq_registered = i8042_kbd_irq_registered = false; } -static int __devinit i8042_setup_aux(void) +static int __init i8042_setup_aux(void) { int (*aux_enable)(void); int error; @@ -1212,7 +1212,7 @@ static int __devinit i8042_setup_aux(void) return error; } -static int __devinit i8042_setup_kbd(void) +static int __init i8042_setup_kbd(void) { int error; @@ -1239,7 +1239,7 @@ static int __devinit i8042_setup_kbd(void) return error; } -static int __devinit i8042_probe(struct platform_device *dev) +static int __init i8042_probe(struct platform_device *dev) { int error; @@ -1299,7 +1299,6 @@ static struct platform_driver i8042_driver = { .pm = &i8042_pm_ops, #endif }, - .probe = i8042_probe, .remove = __devexit_p(i8042_remove), .shutdown = i8042_shutdown, }; @@ -1318,28 +1317,28 @@ static int __init i8042_init(void) if (err) goto err_platform_exit; - err = platform_driver_register(&i8042_driver); - if (err) - goto err_platform_exit; - i8042_platform_device = platform_device_alloc("i8042", -1); if (!i8042_platform_device) { err = -ENOMEM; - goto err_unregister_driver; + goto err_platform_exit; } err = platform_device_add(i8042_platform_device); if (err) goto err_free_device; + err = platform_driver_probe(&i8042_driver, i8042_probe); + if (err) + goto err_del_device; + panic_blink = i8042_panic_blink; return 0; + err_del_device: + platform_device_del(i8042_platform_device); err_free_device: platform_device_put(i8042_platform_device); - err_unregister_driver: - platform_driver_unregister(&i8042_driver); err_platform_exit: i8042_platform_exit(); @@ -1348,8 +1347,8 @@ static int __init i8042_init(void) static void __exit i8042_exit(void) { - platform_device_unregister(i8042_platform_device); platform_driver_unregister(&i8042_driver); + platform_device_unregister(i8042_platform_device); i8042_platform_exit(); panic_blink = NULL; -- cgit v1.2.1