Skip to content

Commit 930e192

Browse files
marcospsdtor
authored andcommitted
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 <[email protected]> Cc: [email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 4e1bff0 commit 930e192

File tree

8 files changed

+150
-20
lines changed

8 files changed

+150
-20
lines changed

Documentation/kernel-parameters.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
14091409
i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
14101410
controllers
14111411
i8042.notimeout [HW] Ignore timeout condition signalled by controller
1412-
i8042.reset [HW] Reset the controller during init and cleanup
1412+
i8042.reset [HW] Reset the controller during init, cleanup and
1413+
suspend-to-ram transitions, only during s2r
1414+
transitions, or never reset
1415+
Format: { 1 | Y | y | 0 | N | n }
1416+
1, Y, y: always reset controller
1417+
0, N, n: don't ever reset controller
1418+
Default: only on s2r transitions on x86; most other
1419+
architectures force reset to be always executed
14131420
i8042.unlock [HW] Unlock (ignore) the keylock
14141421
i8042.kbdreset [HW] Reset device connected to KBD port
14151422

drivers/input/serio/i8042-io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static inline int i8042_platform_init(void)
8181
return -EBUSY;
8282
#endif
8383

84-
i8042_reset = 1;
84+
i8042_reset = I8042_RESET_ALWAYS;
8585
return 0;
8686
}
8787

drivers/input/serio/i8042-ip22io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static inline int i8042_platform_init(void)
6161
return -EBUSY;
6262
#endif
6363

64-
i8042_reset = 1;
64+
i8042_reset = I8042_RESET_ALWAYS;
6565

6666
return 0;
6767
}

drivers/input/serio/i8042-ppcio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static inline void i8042_write_command(int val)
4444

4545
static inline int i8042_platform_init(void)
4646
{
47-
i8042_reset = 1;
47+
i8042_reset = I8042_RESET_ALWAYS;
4848
return 0;
4949
}
5050

drivers/input/serio/i8042-sparcio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static int __init i8042_platform_init(void)
130130
}
131131
}
132132

133-
i8042_reset = 1;
133+
i8042_reset = I8042_RESET_ALWAYS;
134134

135135
return 0;
136136
}

drivers/input/serio/i8042-unicore32io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static inline int i8042_platform_init(void)
6161
if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
6262
return -EBUSY;
6363

64-
i8042_reset = 1;
64+
i8042_reset = I8042_RESET_ALWAYS;
6565
return 0;
6666
}
6767

drivers/input/serio/i8042-x86ia64io.h

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,90 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
510510
{ }
511511
};
512512

513+
/*
514+
* On some Asus laptops, just running self tests cause problems.
515+
*/
516+
static 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+
};
513597
static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
514598
{
515599
/* MSI Wind U-100 */
@@ -1072,12 +1156,18 @@ static int __init i8042_platform_init(void)
10721156
return retval;
10731157

10741158
#if defined(__ia64__)
1075-
i8042_reset = true;
1159+
i8042_reset = I8042_RESET_ALWAYS;
10761160
#endif
10771161

10781162
#ifdef CONFIG_X86
1079-
if (dmi_check_system(i8042_dmi_reset_table))
1080-
i8042_reset = true;
1163+
/* Honor module parameter when value is not default */
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+
}
10811171

10821172
if (dmi_check_system(i8042_dmi_noloop_table))
10831173
i8042_noloop = true;

drivers/input/serio/i8042.c

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,39 @@ static bool i8042_unlock;
4848
module_param_named(unlock, i8042_unlock, bool, 0);
4949
MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
5050

51-
static bool i8042_reset;
52-
module_param_named(reset, i8042_reset, bool, 0);
53-
MODULE_PARM_DESC(reset, "Reset controller during init and cleanup.");
51+
enum i8042_controller_reset_mode {
52+
I8042_RESET_NEVER,
53+
I8042_RESET_ALWAYS,
54+
I8042_RESET_ON_S2RAM,
55+
#define I8042_RESET_DEFAULT I8042_RESET_ON_S2RAM
56+
};
57+
static enum i8042_controller_reset_mode i8042_reset = I8042_RESET_DEFAULT;
58+
static 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+
76+
static 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)
82+
module_param_named(reset, i8042_reset, reset_param, 0);
83+
MODULE_PARM_DESC(reset, "Reset controller on resume, cleanup or both");
5484

5585
static bool i8042_direct;
5686
module_param_named(direct, i8042_direct, bool, 0);
@@ -1019,7 +1049,7 @@ static int i8042_controller_init(void)
10191049
* Reset the controller and reset CRT to the original value set by BIOS.
10201050
*/
10211051

1022-
static void i8042_controller_reset(bool force_reset)
1052+
static void i8042_controller_reset(bool s2r_wants_reset)
10231053
{
10241054
i8042_flush();
10251055

@@ -1044,8 +1074,10 @@ static void i8042_controller_reset(bool force_reset)
10441074
* Reset the controller if requested.
10451075
*/
10461076

1047-
if (i8042_reset || force_reset)
1077+
if (i8042_reset == I8042_RESET_ALWAYS ||
1078+
(i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) {
10481079
i8042_controller_selftest();
1080+
}
10491081

10501082
/*
10511083
* Restore the original control register setting.
@@ -1110,15 +1142,16 @@ static void i8042_dritek_enable(void)
11101142
* before suspending.
11111143
*/
11121144

1113-
static int i8042_controller_resume(bool force_reset)
1145+
static int i8042_controller_resume(bool s2r_wants_reset)
11141146
{
11151147
int error;
11161148

11171149
error = i8042_controller_check();
11181150
if (error)
11191151
return error;
11201152

1121-
if (i8042_reset || force_reset) {
1153+
if (i8042_reset == I8042_RESET_ALWAYS ||
1154+
(i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) {
11221155
error = i8042_controller_selftest();
11231156
if (error)
11241157
return error;
@@ -1195,7 +1228,7 @@ static int i8042_pm_resume_noirq(struct device *dev)
11951228

11961229
static int i8042_pm_resume(struct device *dev)
11971230
{
1198-
bool force_reset;
1231+
bool want_reset;
11991232
int i;
12001233

12011234
for (i = 0; i < I8042_NUM_PORTS; i++) {
@@ -1218,9 +1251,9 @@ static int i8042_pm_resume(struct device *dev)
12181251
* off control to the platform firmware, otherwise we can simply restore
12191252
* the mode.
12201253
*/
1221-
force_reset = pm_resume_via_firmware();
1254+
want_reset = pm_resume_via_firmware();
12221255

1223-
return i8042_controller_resume(force_reset);
1256+
return i8042_controller_resume(want_reset);
12241257
}
12251258

12261259
static int i8042_pm_thaw(struct device *dev)
@@ -1481,7 +1514,7 @@ static int __init i8042_probe(struct platform_device *dev)
14811514

14821515
i8042_platform_device = dev;
14831516

1484-
if (i8042_reset) {
1517+
if (i8042_reset == I8042_RESET_ALWAYS) {
14851518
error = i8042_controller_selftest();
14861519
if (error)
14871520
return error;

0 commit comments

Comments
 (0)