aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio
diff options
context:
space:
mode:
authorMarcos Paulo de Souza <marcos.souza.org@gmail.com>2016-10-01 15:07:35 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-10-11 19:58:25 -0400
commit930e19248e9b61da36c967687ca79c4d5f977919 (patch)
tree40a11f8280090ffe6e5cc97b8283f6458d48874d /drivers/input/serio
parent4e1bff07d7e7bc9fc3fc62100dcb8f708e1e96d2 (diff)
Input: i8042 - skip selftest on ASUS laptops
On suspend/resume cycle, selftest is executed to reset i8042 controller. But when this is done in Asus devices, subsequent calls to detect/init functions to elantech driver fails. Skipping selftest fixes this problem. An easier step to reproduce this problem is adding i8042.reset=1 as a kernel parameter. On Asus laptops, it'll make the system to start with the touchpad already stuck, since psmouse_probe forcibly calls the selftest function. This patch was inspired by John Hiesey's change[1], but, since this problem affects a lot of models of Asus, let's avoid running selftests on them. All models affected by this problem: A455LD K401LB K501LB K501LX R409L V502LX X302LA X450LCP X450LD X455LAB X455LDB X455LF Z450LA [1]: https://marc.info/?l=linux-input&m=144312209020616&w=2 Fixes: "ETPS/2 Elantech Touchpad dies after resume from suspend" (https://bugzilla.kernel.org/show_bug.cgi?id=107971) Signed-off-by: Marcos Paulo de Souza <marcos.souza.org@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/serio')
-rw-r--r--drivers/input/serio/i8042-io.h2
-rw-r--r--drivers/input/serio/i8042-ip22io.h2
-rw-r--r--drivers/input/serio/i8042-ppcio.h2
-rw-r--r--drivers/input/serio/i8042-sparcio.h2
-rw-r--r--drivers/input/serio/i8042-unicore32io.h2
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h96
-rw-r--r--drivers/input/serio/i8042.c55
7 files changed, 142 insertions, 19 deletions
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index a5eed2ade53d..34da81c006b6 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -81,7 +81,7 @@ static inline int i8042_platform_init(void)
81 return -EBUSY; 81 return -EBUSY;
82#endif 82#endif
83 83
84 i8042_reset = 1; 84 i8042_reset = I8042_RESET_ALWAYS;
85 return 0; 85 return 0;
86} 86}
87 87
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h
index ee1ad27d6ed0..08a1c10a1448 100644
--- a/drivers/input/serio/i8042-ip22io.h
+++ b/drivers/input/serio/i8042-ip22io.h
@@ -61,7 +61,7 @@ static inline int i8042_platform_init(void)
61 return -EBUSY; 61 return -EBUSY;
62#endif 62#endif
63 63
64 i8042_reset = 1; 64 i8042_reset = I8042_RESET_ALWAYS;
65 65
66 return 0; 66 return 0;
67} 67}
diff --git a/drivers/input/serio/i8042-ppcio.h b/drivers/input/serio/i8042-ppcio.h
index f708c75d16f1..1aabea43329e 100644
--- a/drivers/input/serio/i8042-ppcio.h
+++ b/drivers/input/serio/i8042-ppcio.h
@@ -44,7 +44,7 @@ static inline void i8042_write_command(int val)
44 44
45static inline int i8042_platform_init(void) 45static inline int i8042_platform_init(void)
46{ 46{
47 i8042_reset = 1; 47 i8042_reset = I8042_RESET_ALWAYS;
48 return 0; 48 return 0;
49} 49}
50 50
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index afcd1c1a05b2..6231d63860ee 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -130,7 +130,7 @@ static int __init i8042_platform_init(void)
130 } 130 }
131 } 131 }
132 132
133 i8042_reset = 1; 133 i8042_reset = I8042_RESET_ALWAYS;
134 134
135 return 0; 135 return 0;
136} 136}
diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
index 73f5cc124a36..455747552f85 100644
--- a/drivers/input/serio/i8042-unicore32io.h
+++ b/drivers/input/serio/i8042-unicore32io.h
@@ -61,7 +61,7 @@ static inline int i8042_platform_init(void)
61 if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) 61 if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
62 return -EBUSY; 62 return -EBUSY;
63 63
64 i8042_reset = 1; 64 i8042_reset = I8042_RESET_ALWAYS;
65 return 0; 65 return 0;
66} 66}
67 67
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 68f5f4a0f1e7..f4bfb4b2d50a 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -510,6 +510,90 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
510 { } 510 { }
511}; 511};
512 512
513/*
514 * On some Asus laptops, just running self tests cause problems.
515 */
516static const struct dmi_system_id i8042_dmi_noselftest_table[] = {
517 {
518 .matches = {
519 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
520 DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"),
521 },
522 },
523 {
524 .matches = {
525 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
526 DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"),
527 },
528 },
529 {
530 .matches = {
531 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
532 DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"),
533 },
534 },
535 {
536 .matches = {
537 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
538 DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"),
539 },
540 },
541 {
542 .matches = {
543 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
544 DMI_MATCH(DMI_PRODUCT_NAME, "R409L"),
545 },
546 },
547 {
548 .matches = {
549 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
550 DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"),
551 },
552 },
553 {
554 .matches = {
555 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
556 DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"),
557 },
558 },
559 {
560 .matches = {
561 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
562 DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
563 },
564 },
565 {
566 .matches = {
567 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
568 DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"),
569 },
570 },
571 {
572 .matches = {
573 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
574 DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"),
575 },
576 },
577 {
578 .matches = {
579 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
580 DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"),
581 },
582 },
583 {
584 .matches = {
585 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
586 DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"),
587 },
588 },
589 {
590 .matches = {
591 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
592 DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"),
593 },
594 },
595 { }
596};
513static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { 597static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
514 { 598 {
515 /* MSI Wind U-100 */ 599 /* MSI Wind U-100 */
@@ -1072,12 +1156,18 @@ static int __init i8042_platform_init(void)
1072 return retval; 1156 return retval;
1073 1157
1074#if defined(__ia64__) 1158#if defined(__ia64__)
1075 i8042_reset = true; 1159 i8042_reset = I8042_RESET_ALWAYS;
1076#endif 1160#endif
1077 1161
1078#ifdef CONFIG_X86 1162#ifdef CONFIG_X86
1079 if (dmi_check_system(i8042_dmi_reset_table)) 1163 /* Honor module parameter when value is not default */
1080 i8042_reset = true; 1164 if (i8042_reset == I8042_RESET_DEFAULT) {
1165 if (dmi_check_system(i8042_dmi_reset_table))
1166 i8042_reset = I8042_RESET_ALWAYS;
1167
1168 if (dmi_check_system(i8042_dmi_noselftest_table))
1169 i8042_reset = I8042_RESET_NEVER;
1170 }
1081 1171
1082 if (dmi_check_system(i8042_dmi_noloop_table)) 1172 if (dmi_check_system(i8042_dmi_noloop_table))
1083 i8042_noloop = true; 1173 i8042_noloop = true;
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index b4d34086e73f..674a760f5221 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -48,9 +48,39 @@ static bool i8042_unlock;
48module_param_named(unlock, i8042_unlock, bool, 0); 48module_param_named(unlock, i8042_unlock, bool, 0);
49MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); 49MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
50 50
51static bool i8042_reset; 51enum i8042_controller_reset_mode {
52module_param_named(reset, i8042_reset, bool, 0); 52 I8042_RESET_NEVER,
53MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); 53 I8042_RESET_ALWAYS,
54 I8042_RESET_ON_S2RAM,
55#define I8042_RESET_DEFAULT I8042_RESET_ON_S2RAM
56};
57static enum i8042_controller_reset_mode i8042_reset = I8042_RESET_DEFAULT;
58static int i8042_set_reset(const char *val, const struct kernel_param *kp)
59{
60 enum i8042_controller_reset_mode *arg = kp->arg;
61 int error;
62 bool reset;
63
64 if (val) {
65 error = kstrtobool(val, &reset);
66 if (error)
67 return error;
68 } else {
69 reset = true;
70 }
71
72 *arg = reset ? I8042_RESET_ALWAYS : I8042_RESET_NEVER;
73 return 0;
74}
75
76static const struct kernel_param_ops param_ops_reset_param = {
77 .flags = KERNEL_PARAM_OPS_FL_NOARG,
78 .set = i8042_set_reset,
79};
80#define param_check_reset_param(name, p) \
81 __param_check(name, p, enum i8042_controller_reset_mode)
82module_param_named(reset, i8042_reset, reset_param, 0);
83MODULE_PARM_DESC(reset, "Reset controller on resume, cleanup or both");
54 84
55static bool i8042_direct; 85static bool i8042_direct;
56module_param_named(direct, i8042_direct, bool, 0); 86module_param_named(direct, i8042_direct, bool, 0);
@@ -1019,7 +1049,7 @@ static int i8042_controller_init(void)
1019 * Reset the controller and reset CRT to the original value set by BIOS. 1049 * Reset the controller and reset CRT to the original value set by BIOS.
1020 */ 1050 */
1021 1051
1022static void i8042_controller_reset(bool force_reset) 1052static void i8042_controller_reset(bool s2r_wants_reset)
1023{ 1053{
1024 i8042_flush(); 1054 i8042_flush();
1025 1055
@@ -1044,8 +1074,10 @@ static void i8042_controller_reset(bool force_reset)
1044 * Reset the controller if requested. 1074 * Reset the controller if requested.
1045 */ 1075 */
1046 1076
1047 if (i8042_reset || force_reset) 1077 if (i8042_reset == I8042_RESET_ALWAYS ||
1078 (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) {
1048 i8042_controller_selftest(); 1079 i8042_controller_selftest();
1080 }
1049 1081
1050/* 1082/*
1051 * Restore the original control register setting. 1083 * Restore the original control register setting.
@@ -1110,7 +1142,7 @@ static void i8042_dritek_enable(void)
1110 * before suspending. 1142 * before suspending.
1111 */ 1143 */
1112 1144
1113static int i8042_controller_resume(bool force_reset) 1145static int i8042_controller_resume(bool s2r_wants_reset)
1114{ 1146{
1115 int error; 1147 int error;
1116 1148
@@ -1118,7 +1150,8 @@ static int i8042_controller_resume(bool force_reset)
1118 if (error) 1150 if (error)
1119 return error; 1151 return error;
1120 1152
1121 if (i8042_reset || force_reset) { 1153 if (i8042_reset == I8042_RESET_ALWAYS ||
1154 (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) {
1122 error = i8042_controller_selftest(); 1155 error = i8042_controller_selftest();
1123 if (error) 1156 if (error)
1124 return error; 1157 return error;
@@ -1195,7 +1228,7 @@ static int i8042_pm_resume_noirq(struct device *dev)
1195 1228
1196static int i8042_pm_resume(struct device *dev) 1229static int i8042_pm_resume(struct device *dev)
1197{ 1230{
1198 bool force_reset; 1231 bool want_reset;
1199 int i; 1232 int i;
1200 1233
1201 for (i = 0; i < I8042_NUM_PORTS; i++) { 1234 for (i = 0; i < I8042_NUM_PORTS; i++) {
@@ -1218,9 +1251,9 @@ static int i8042_pm_resume(struct device *dev)
1218 * off control to the platform firmware, otherwise we can simply restore 1251 * off control to the platform firmware, otherwise we can simply restore
1219 * the mode. 1252 * the mode.
1220 */ 1253 */
1221 force_reset = pm_resume_via_firmware(); 1254 want_reset = pm_resume_via_firmware();
1222 1255
1223 return i8042_controller_resume(force_reset); 1256 return i8042_controller_resume(want_reset);
1224} 1257}
1225 1258
1226static int i8042_pm_thaw(struct device *dev) 1259static int i8042_pm_thaw(struct device *dev)
@@ -1481,7 +1514,7 @@ static int __init i8042_probe(struct platform_device *dev)
1481 1514
1482 i8042_platform_device = dev; 1515 i8042_platform_device = dev;
1483 1516
1484 if (i8042_reset) { 1517 if (i8042_reset == I8042_RESET_ALWAYS) {
1485 error = i8042_controller_selftest(); 1518 error = i8042_controller_selftest();
1486 if (error) 1519 if (error)
1487 return error; 1520 return error;