diff options
Diffstat (limited to 'kernel/drivers/input/serio')
-rw-r--r-- | kernel/drivers/input/serio/i8042-io.h | 2 | ||||
-rw-r--r-- | kernel/drivers/input/serio/i8042-ip22io.h | 2 | ||||
-rw-r--r-- | kernel/drivers/input/serio/i8042-ppcio.h | 2 | ||||
-rw-r--r-- | kernel/drivers/input/serio/i8042-sparcio.h | 2 | ||||
-rw-r--r-- | kernel/drivers/input/serio/i8042-unicore32io.h | 2 | ||||
-rw-r--r-- | kernel/drivers/input/serio/i8042-x86ia64io.h | 109 | ||||
-rw-r--r-- | kernel/drivers/input/serio/i8042.c | 72 | ||||
-rw-r--r-- | kernel/drivers/input/serio/libps2.c | 10 |
8 files changed, 161 insertions, 40 deletions
diff --git a/kernel/drivers/input/serio/i8042-io.h b/kernel/drivers/input/serio/i8042-io.h index a5eed2ade..34da81c00 100644 --- a/kernel/drivers/input/serio/i8042-io.h +++ b/kernel/drivers/input/serio/i8042-io.h @@ -81,7 +81,7 @@ static inline int i8042_platform_init(void) return -EBUSY; #endif - i8042_reset = 1; + i8042_reset = I8042_RESET_ALWAYS; return 0; } diff --git a/kernel/drivers/input/serio/i8042-ip22io.h b/kernel/drivers/input/serio/i8042-ip22io.h index ee1ad27d6..08a1c10a1 100644 --- a/kernel/drivers/input/serio/i8042-ip22io.h +++ b/kernel/drivers/input/serio/i8042-ip22io.h @@ -61,7 +61,7 @@ static inline int i8042_platform_init(void) return -EBUSY; #endif - i8042_reset = 1; + i8042_reset = I8042_RESET_ALWAYS; return 0; } diff --git a/kernel/drivers/input/serio/i8042-ppcio.h b/kernel/drivers/input/serio/i8042-ppcio.h index f708c75d1..1aabea433 100644 --- a/kernel/drivers/input/serio/i8042-ppcio.h +++ b/kernel/drivers/input/serio/i8042-ppcio.h @@ -44,7 +44,7 @@ static inline void i8042_write_command(int val) static inline int i8042_platform_init(void) { - i8042_reset = 1; + i8042_reset = I8042_RESET_ALWAYS; return 0; } diff --git a/kernel/drivers/input/serio/i8042-sparcio.h b/kernel/drivers/input/serio/i8042-sparcio.h index afcd1c1a0..6231d6386 100644 --- a/kernel/drivers/input/serio/i8042-sparcio.h +++ b/kernel/drivers/input/serio/i8042-sparcio.h @@ -130,7 +130,7 @@ static int __init i8042_platform_init(void) } } - i8042_reset = 1; + i8042_reset = I8042_RESET_ALWAYS; return 0; } diff --git a/kernel/drivers/input/serio/i8042-unicore32io.h b/kernel/drivers/input/serio/i8042-unicore32io.h index 73f5cc124..455747552 100644 --- a/kernel/drivers/input/serio/i8042-unicore32io.h +++ b/kernel/drivers/input/serio/i8042-unicore32io.h @@ -61,7 +61,7 @@ static inline int i8042_platform_init(void) if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) return -EBUSY; - i8042_reset = 1; + i8042_reset = I8042_RESET_ALWAYS; return 0; } diff --git a/kernel/drivers/input/serio/i8042-x86ia64io.h b/kernel/drivers/input/serio/i8042-x86ia64io.h index 68f5f4a0f..0cdd95801 100644 --- a/kernel/drivers/input/serio/i8042-x86ia64io.h +++ b/kernel/drivers/input/serio/i8042-x86ia64io.h @@ -211,6 +211,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"), + DMI_MATCH(DMI_PRODUCT_NAME, "C15B"), + }, + }, { } }; @@ -510,6 +516,90 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { { } }; +/* + * On some Asus laptops, just running self tests cause problems. + */ +static const struct dmi_system_id i8042_dmi_noselftest_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "R409L"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"), + }, + }, + { } +}; static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { { /* MSI Wind U-100 */ @@ -793,6 +883,13 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "P34"), }, }, + { + /* Schenker XMG C504 - Elantech touchpad */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "XMG"), + DMI_MATCH(DMI_PRODUCT_NAME, "C504"), + }, + }, { } }; @@ -1072,12 +1169,18 @@ static int __init i8042_platform_init(void) return retval; #if defined(__ia64__) - i8042_reset = true; + i8042_reset = I8042_RESET_ALWAYS; #endif #ifdef CONFIG_X86 - if (dmi_check_system(i8042_dmi_reset_table)) - i8042_reset = true; + /* Honor module parameter when value is not default */ + if (i8042_reset == I8042_RESET_DEFAULT) { + if (dmi_check_system(i8042_dmi_reset_table)) + i8042_reset = I8042_RESET_ALWAYS; + + if (dmi_check_system(i8042_dmi_noselftest_table)) + i8042_reset = I8042_RESET_NEVER; + } if (dmi_check_system(i8042_dmi_noloop_table)) i8042_noloop = true; diff --git a/kernel/drivers/input/serio/i8042.c b/kernel/drivers/input/serio/i8042.c index 454195709..89abfdb53 100644 --- a/kernel/drivers/input/serio/i8042.c +++ b/kernel/drivers/input/serio/i8042.c @@ -48,9 +48,39 @@ static bool i8042_unlock; module_param_named(unlock, i8042_unlock, bool, 0); MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); -static bool i8042_reset; -module_param_named(reset, i8042_reset, bool, 0); -MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); +enum i8042_controller_reset_mode { + I8042_RESET_NEVER, + I8042_RESET_ALWAYS, + I8042_RESET_ON_S2RAM, +#define I8042_RESET_DEFAULT I8042_RESET_ON_S2RAM +}; +static enum i8042_controller_reset_mode i8042_reset = I8042_RESET_DEFAULT; +static int i8042_set_reset(const char *val, const struct kernel_param *kp) +{ + enum i8042_controller_reset_mode *arg = kp->arg; + int error; + bool reset; + + if (val) { + error = kstrtobool(val, &reset); + if (error) + return error; + } else { + reset = true; + } + + *arg = reset ? I8042_RESET_ALWAYS : I8042_RESET_NEVER; + return 0; +} + +static const struct kernel_param_ops param_ops_reset_param = { + .flags = KERNEL_PARAM_OPS_FL_NOARG, + .set = i8042_set_reset, +}; +#define param_check_reset_param(name, p) \ + __param_check(name, p, enum i8042_controller_reset_mode) +module_param_named(reset, i8042_reset, reset_param, 0); +MODULE_PARM_DESC(reset, "Reset controller on resume, cleanup or both"); static bool i8042_direct; module_param_named(direct, i8042_direct, bool, 0); @@ -1019,7 +1049,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(bool force_reset) +static void i8042_controller_reset(bool s2r_wants_reset) { i8042_flush(); @@ -1044,8 +1074,10 @@ static void i8042_controller_reset(bool force_reset) * Reset the controller if requested. */ - if (i8042_reset || force_reset) + if (i8042_reset == I8042_RESET_ALWAYS || + (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) { i8042_controller_selftest(); + } /* * Restore the original control register setting. @@ -1110,7 +1142,7 @@ static void i8042_dritek_enable(void) * before suspending. */ -static int i8042_controller_resume(bool force_reset) +static int i8042_controller_resume(bool s2r_wants_reset) { int error; @@ -1118,7 +1150,8 @@ static int i8042_controller_resume(bool force_reset) if (error) return error; - if (i8042_reset || force_reset) { + if (i8042_reset == I8042_RESET_ALWAYS || + (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) { error = i8042_controller_selftest(); if (error) return error; @@ -1195,7 +1228,7 @@ static int i8042_pm_resume_noirq(struct device *dev) static int i8042_pm_resume(struct device *dev) { - bool force_reset; + bool want_reset; int i; for (i = 0; i < I8042_NUM_PORTS; i++) { @@ -1218,9 +1251,9 @@ static int i8042_pm_resume(struct device *dev) * off control to the platform firmware, otherwise we can simply restore * the mode. */ - force_reset = pm_resume_via_firmware(); + want_reset = pm_resume_via_firmware(); - return i8042_controller_resume(force_reset); + return i8042_controller_resume(want_reset); } static int i8042_pm_thaw(struct device *dev) @@ -1277,6 +1310,7 @@ static int __init i8042_create_kbd_port(void) serio->start = i8042_start; serio->stop = i8042_stop; serio->close = i8042_port_close; + serio->ps2_cmd_mutex = &i8042_mutex; serio->port_data = port; serio->dev.parent = &i8042_platform_device->dev; strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); @@ -1304,6 +1338,7 @@ static int __init i8042_create_aux_port(int idx) serio->write = i8042_aux_write; serio->start = i8042_start; serio->stop = i8042_stop; + serio->ps2_cmd_mutex = &i8042_mutex; serio->port_data = port; serio->dev.parent = &i8042_platform_device->dev; if (idx < 0) { @@ -1373,21 +1408,6 @@ static void i8042_unregister_ports(void) } } -/* - * Checks whether port belongs to i8042 controller. - */ -bool i8042_check_port_owner(const struct serio *port) -{ - int i; - - for (i = 0; i < I8042_NUM_PORTS; i++) - if (i8042_ports[i].serio == port) - return true; - - return false; -} -EXPORT_SYMBOL(i8042_check_port_owner); - static void i8042_free_irqs(void) { if (i8042_aux_irq_registered) @@ -1495,7 +1515,7 @@ static int __init i8042_probe(struct platform_device *dev) i8042_platform_device = dev; - if (i8042_reset) { + if (i8042_reset == I8042_RESET_ALWAYS) { error = i8042_controller_selftest(); if (error) return error; diff --git a/kernel/drivers/input/serio/libps2.c b/kernel/drivers/input/serio/libps2.c index 316f2c897..83e9c663a 100644 --- a/kernel/drivers/input/serio/libps2.c +++ b/kernel/drivers/input/serio/libps2.c @@ -56,19 +56,17 @@ EXPORT_SYMBOL(ps2_sendbyte); void ps2_begin_command(struct ps2dev *ps2dev) { - mutex_lock(&ps2dev->cmd_mutex); + struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; - if (i8042_check_port_owner(ps2dev->serio)) - i8042_lock_chip(); + mutex_lock(m); } EXPORT_SYMBOL(ps2_begin_command); void ps2_end_command(struct ps2dev *ps2dev) { - if (i8042_check_port_owner(ps2dev->serio)) - i8042_unlock_chip(); + struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex; - mutex_unlock(&ps2dev->cmd_mutex); + mutex_unlock(m); } EXPORT_SYMBOL(ps2_end_command); |