diff options
Diffstat (limited to 'drivers/input/serio/i8042.c')
| -rw-r--r-- | drivers/input/serio/i8042.c | 155 | 
1 files changed, 86 insertions, 69 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 18db5a8c747..3807c3e971c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -10,6 +10,8 @@   * the Free Software Foundation.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/types.h>  #include <linux/delay.h>  #include <linux/module.h> @@ -61,6 +63,10 @@ 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"); +static bool i8042_notimeout; +module_param_named(notimeout, i8042_notimeout, bool, 0); +MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); +  #ifdef CONFIG_X86  static bool i8042_dritek;  module_param_named(dritek, i8042_dritek, bool, 0); @@ -81,6 +87,8 @@ MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");  #endif  static bool i8042_bypass_aux_irq_test; +static char i8042_kbd_firmware_id[128]; +static char i8042_aux_firmware_id[128];  #include "i8042.h" @@ -217,21 +225,26 @@ static int i8042_flush(void)  {  	unsigned long flags;  	unsigned char data, str; -	int i = 0; +	int count = 0; +	int retval = 0;  	spin_lock_irqsave(&i8042_lock, flags); -	while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) { -		udelay(50); -		data = i8042_read_data(); -		i++; -		dbg("%02x <- i8042 (flush, %s)", data, -			str & I8042_STR_AUXDATA ? "aux" : "kbd"); +	while ((str = i8042_read_status()) & I8042_STR_OBF) { +		if (count++ < I8042_BUFFER_SIZE) { +			udelay(50); +			data = i8042_read_data(); +			dbg("%02x <- i8042 (flush, %s)\n", +			    data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); +		} else { +			retval = -EIO; +			break; +		}  	}  	spin_unlock_irqrestore(&i8042_lock, flags); -	return i; +	return retval;  }  /* @@ -253,32 +266,32 @@ static int __i8042_command(unsigned char *param, int command)  	if (error)  		return error; -	dbg("%02x -> i8042 (command)", command & 0xff); +	dbg("%02x -> i8042 (command)\n", command & 0xff);  	i8042_write_command(command & 0xff);  	for (i = 0; i < ((command >> 12) & 0xf); i++) {  		error = i8042_wait_write();  		if (error)  			return error; -		dbg("%02x -> i8042 (parameter)", param[i]); +		dbg("%02x -> i8042 (parameter)\n", param[i]);  		i8042_write_data(param[i]);  	}  	for (i = 0; i < ((command >> 8) & 0xf); i++) {  		error = i8042_wait_read();  		if (error) { -			dbg("     -- i8042 (timeout)"); +			dbg("     -- i8042 (timeout)\n");  			return error;  		}  		if (command == I8042_CMD_AUX_LOOP &&  		    !(i8042_read_status() & I8042_STR_AUXDATA)) { -			dbg("     -- i8042 (auxerr)"); +			dbg("     -- i8042 (auxerr)\n");  			return -1;  		}  		param[i] = i8042_read_data(); -		dbg("%02x <- i8042 (return)", param[i]); +		dbg("%02x <- i8042 (return)\n", param[i]);  	}  	return 0; @@ -309,7 +322,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c)  	spin_lock_irqsave(&i8042_lock, flags);  	if (!(retval = i8042_wait_write())) { -		dbg("%02x -> i8042 (kbd-data)", c); +		dbg("%02x -> i8042 (kbd-data)\n", c);  		i8042_write_data(c);  	} @@ -355,17 +368,14 @@ static void i8042_port_close(struct serio *serio)  	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); +		pr_warn("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); +		pr_err("Can't reactivate %s port\n", port_name);  	/*  	 * See if there is any data appeared while we were messing with @@ -456,7 +466,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)  	str = i8042_read_status();  	if (unlikely(~str & I8042_STR_OBF)) {  		spin_unlock_irqrestore(&i8042_lock, flags); -		if (irq) dbg("Interrupt %d, without any data", irq); +		if (irq) +			dbg("Interrupt %d, without any data\n", irq);  		ret = 0;  		goto out;  	} @@ -469,7 +480,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)  		dfl = 0;  		if (str & I8042_STR_MUXERR) { -			dbg("MUX error, status is %02x, data is %02x", str, data); +			dbg("MUX error, status is %02x, data is %02x\n", +			    str, data);  /*   * When MUXERR condition is signalled the data register can only contain   * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately @@ -503,7 +515,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)  	} else {  		dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | -		      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); +		      ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0);  		port_no = (str & I8042_STR_AUXDATA) ?  				I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; @@ -512,7 +524,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)  	port = &i8042_ports[port_no];  	serio = port->exists ? port->serio : NULL; -	dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", +	dbg("%02x <- i8042 (interrupt, %d, %d%s%s)\n",  	    data, port_no, irq,  	    dfl & SERIO_PARITY ? ", bad parity" : "",  	    dfl & SERIO_TIMEOUT ? ", timeout" : ""); @@ -540,7 +552,7 @@ static int i8042_enable_kbd_port(void)  	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {  		i8042_ctr &= ~I8042_CTR_KBDINT;  		i8042_ctr |= I8042_CTR_KBDDIS; -		printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); +		pr_err("Failed to enable KBD port\n");  		return -EIO;  	} @@ -559,7 +571,7 @@ static int i8042_enable_aux_port(void)  	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {  		i8042_ctr &= ~I8042_CTR_AUXINT;  		i8042_ctr |= I8042_CTR_AUXDIS; -		printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); +		pr_err("Failed to enable AUX port\n");  		return -EIO;  	} @@ -641,7 +653,7 @@ static int __init i8042_check_mux(void)  	if (i8042_set_mux_mode(true, &mux_version))  		return -1; -	printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", +	pr_info("Detected active multiplexing controller, rev %d.%d\n",  		(mux_version >> 4) & 0xf, mux_version & 0xf);  /* @@ -651,7 +663,7 @@ static int __init i8042_check_mux(void)  	i8042_ctr &= ~I8042_CTR_AUXINT;  	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { -		printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n"); +		pr_err("Failed to disable AUX port, can't use MUX\n");  		return -EIO;  	} @@ -676,8 +688,8 @@ static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)  	str = i8042_read_status();  	if (str & I8042_STR_OBF) {  		data = i8042_read_data(); -		dbg("%02x <- i8042 (aux_test_irq, %s)", -			data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); +		dbg("%02x <- i8042 (aux_test_irq, %s)\n", +		    data, str & I8042_STR_AUXDATA ? "aux" : "kbd");  		if (i8042_irq_being_tested &&  		    data == 0xa5 && (str & I8042_STR_AUXDATA))  			complete(&i8042_aux_irq_delivered); @@ -770,8 +782,8 @@ static int __init i8042_check_aux(void)   */  	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"); +		pr_warn("Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); +		pr_warn("If AUX port is really absent please use the 'i8042.noaux' option\n");  	}  	if (i8042_toggle_aux(true)) @@ -819,7 +831,7 @@ static int __init i8042_check_aux(void)   * AUX IRQ was never delivered so we need to flush the controller to   * get rid of the byte we put there; otherwise keyboard may not work.   */ -		dbg("     -- i8042 (aux irq test timeout)"); +		dbg("     -- i8042 (aux irq test timeout)\n");  		i8042_flush();  		retval = -1;  	} @@ -844,8 +856,8 @@ static int __init i8042_check_aux(void)  static int i8042_controller_check(void)  { -	if (i8042_flush() == I8042_BUFFER_SIZE) { -		printk(KERN_ERR "i8042.c: No controller found.\n"); +	if (i8042_flush()) { +		pr_err("No controller found\n");  		return -ENODEV;  	} @@ -864,15 +876,15 @@ static int i8042_controller_selftest(void)  	do {  		if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { -			printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); +			pr_err("i8042 controller selftest timeout\n");  			return -ENODEV;  		}  		if (param == I8042_RET_CTL_TEST)  			return 0; -		printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", -			param, I8042_RET_CTL_TEST); +		dbg("i8042 controller selftest: %#x != %#x\n", +		    param, I8042_RET_CTL_TEST);  		msleep(50);  	} while (i++ < 5); @@ -883,10 +895,10 @@ static int i8042_controller_selftest(void)  	 * and user will still get a working keyboard. This is especially  	 * important on netbooks. On other arches we trust hardware more.  	 */ -	printk(KERN_INFO -		"i8042: giving up on controller selftest, continuing anyway...\n"); +	pr_info("giving up on controller selftest, continuing anyway...\n");  	return 0;  #else +	pr_err("i8042 controller selftest failed\n");  	return -EIO;  #endif  } @@ -909,8 +921,7 @@ static int i8042_controller_init(void)  	do {  		if (n >= 10) { -			printk(KERN_ERR -				"i8042.c: Unable to get stable CTR read.\n"); +			pr_err("Unable to get stable CTR read\n");  			return -EIO;  		} @@ -918,8 +929,7 @@ static int i8042_controller_init(void)  			udelay(50);  		if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) { -			printk(KERN_ERR -				"i8042.c: Can't read CTR while initializing i8042.\n"); +			pr_err("Can't read CTR while initializing i8042\n");  			return -EIO;  		} @@ -943,7 +953,7 @@ static int i8042_controller_init(void)  		if (i8042_unlock)  			i8042_ctr |= I8042_CTR_IGNKEYLOCK;  		else -			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n"); +			pr_warn("Warning: Keylock active\n");  	}  	spin_unlock_irqrestore(&i8042_lock, flags); @@ -970,7 +980,7 @@ static int i8042_controller_init(void)   */  	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { -		printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n"); +		pr_err("Can't write CTR while initializing i8042\n");  		return -EIO;  	} @@ -988,7 +998,7 @@ static int i8042_controller_init(void)   * Reset the controller and reset CRT to the original value set by BIOS.   */ -static void i8042_controller_reset(void) +static void i8042_controller_reset(bool force_reset)  {  	i8042_flush(); @@ -1000,7 +1010,7 @@ static void i8042_controller_reset(void)  	i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);  	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) -		printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); +		pr_warn("Can't write CTR while resetting\n");  /*   * Disable MUX mode if present. @@ -1013,7 +1023,7 @@ static void i8042_controller_reset(void)   * Reset the controller if requested.   */ -	if (i8042_reset) +	if (i8042_reset || force_reset)  		i8042_controller_selftest();  /* @@ -1021,14 +1031,14 @@ static void i8042_controller_reset(void)   */  	if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) -		printk(KERN_WARNING "i8042.c: Can't restore CTR.\n"); +		pr_warn("Can't restore CTR\n");  }  /*   * i8042_panic_blink() will turn the keyboard LEDs on or off 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" + * not see the console and will help distinguishing panics from "real"   * lockups.   *   * Note that DELAY has a limit of 10ms so we will not get stuck here @@ -1045,14 +1055,14 @@ static long i8042_panic_blink(int state)  	led = (state) ? 0x01 | 0x04 : 0;  	while (i8042_read_status() & I8042_STR_IBF)  		DELAY; -	dbg("%02x -> i8042 (panic blink)", 0xed); +	dbg("%02x -> i8042 (panic blink)\n", 0xed);  	i8042_suppress_kbd_ack = 2;  	i8042_write_data(0xed); /* set leds */  	DELAY;  	while (i8042_read_status() & I8042_STR_IBF)  		DELAY;  	DELAY; -	dbg("%02x -> i8042 (panic blink)", led); +	dbg("%02x -> i8042 (panic blink)\n", led);  	i8042_write_data(led);  	DELAY;  	return delay; @@ -1068,9 +1078,7 @@ static void i8042_dritek_enable(void)  	error = i8042_command(¶m, 0x1059);  	if (error) -		printk(KERN_WARNING -			"Failed to enable DRITEK extension: %d\n", -			error); +		pr_warn("Failed to enable DRITEK extension: %d\n", error);  }  #endif @@ -1105,10 +1113,10 @@ static int i8042_controller_resume(bool force_reset)  	i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS;  	i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT);  	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { -		printk(KERN_WARNING "i8042: Can't write CTR to resume, retrying...\n"); +		pr_warn("Can't write CTR to resume, retrying...\n");  		msleep(50);  		if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { -			printk(KERN_ERR "i8042: CTR write retry failed\n"); +			pr_err("CTR write retry failed\n");  			return -EIO;  		}  	} @@ -1121,9 +1129,7 @@ static int i8042_controller_resume(bool force_reset)  	if (i8042_mux_present) {  		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"); +			pr_warn("failed to resume active multiplexor, mouse won't work\n");  	} else if (i8042_ports[I8042_AUX_PORT_NO].serio)  		i8042_enable_aux_port(); @@ -1140,9 +1146,9 @@ static int i8042_controller_resume(bool force_reset)   * upsetting it.   */ -static int i8042_pm_reset(struct device *dev) +static int i8042_pm_suspend(struct device *dev)  { -	i8042_controller_reset(); +	i8042_controller_reset(true);  	return 0;  } @@ -1164,13 +1170,20 @@ static int i8042_pm_thaw(struct device *dev)  	return 0;  } +static int i8042_pm_reset(struct device *dev) +{ +	i8042_controller_reset(false); + +	return 0; +} +  static int i8042_pm_restore(struct device *dev)  {  	return i8042_controller_resume(false);  }  static const struct dev_pm_ops i8042_pm_ops = { -	.suspend	= i8042_pm_reset, +	.suspend	= i8042_pm_suspend,  	.resume		= i8042_pm_resume,  	.thaw		= i8042_pm_thaw,  	.poweroff	= i8042_pm_reset, @@ -1186,7 +1199,7 @@ static const struct dev_pm_ops i8042_pm_ops = {  static void i8042_shutdown(struct platform_device *dev)  { -	i8042_controller_reset(); +	i8042_controller_reset(false);  }  static int __init i8042_create_kbd_port(void) @@ -1207,6 +1220,8 @@ static int __init i8042_create_kbd_port(void)  	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)); +	strlcpy(serio->firmware_id, i8042_kbd_firmware_id, +		sizeof(serio->firmware_id));  	port->serio = serio;  	port->irq = I8042_KBD_IRQ; @@ -1233,6 +1248,8 @@ static int __init 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)); +		strlcpy(serio->firmware_id, i8042_aux_firmware_id, +			sizeof(serio->firmware_id));  		serio->close = i8042_port_close;  	} else {  		snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); @@ -1278,7 +1295,7 @@ static void __init i8042_register_ports(void)  	}  } -static void __devexit i8042_unregister_ports(void) +static void i8042_unregister_ports(void)  {  	int i; @@ -1425,17 +1442,17 @@ static int __init i8042_probe(struct platform_device *dev)   out_fail:  	i8042_free_aux_ports();	/* in case KBD failed but AUX not */  	i8042_free_irqs(); -	i8042_controller_reset(); +	i8042_controller_reset(false);  	i8042_platform_device = NULL;  	return error;  } -static int __devexit i8042_remove(struct platform_device *dev) +static int i8042_remove(struct platform_device *dev)  {  	i8042_unregister_ports();  	i8042_free_irqs(); -	i8042_controller_reset(); +	i8042_controller_reset(false);  	i8042_platform_device = NULL;  	return 0; @@ -1449,7 +1466,7 @@ static struct platform_driver i8042_driver = {  		.pm	= &i8042_pm_ops,  #endif  	}, -	.remove		= __devexit_p(i8042_remove), +	.remove		= i8042_remove,  	.shutdown	= i8042_shutdown,  };  | 
