I have an Asus laptop with a PS/2 trackpad that stops working until reboot any 
time i8042_controller_selftest() is called. By “stops working" I mean that 
there are no interrupts generated when the trackpad is touched/clicked.

Normally i8042_controller_selftest() seems to be called on suspend and resume 
only, which led to my originally observed problem where the trackpad wouldn’t 
work after resume.

If never calling i8042_controller_selftest()/never sending the 
I8042_CMD_CTL_TEST command seems to work properly on this hardware, are there 
any consequences of doing this that I might not be aware of?

Here’s the draft of my patch that works on this hardware:

>From 32b4766f4afe349dde51043f4c9dd06b69e323cc Mon Sep 17 00:00:00 2001
From: John Hiesey <j...@hiesey.com>
Date: Wed, 23 Sep 2015 19:09:33 -0700
Subject: [PATCH] Input: i8042 - don't run self test on Asus X455LAB

On this model, any time the self test command is sent to the
i8042 controller the trackpad stops sending data. Never send the
self test command when this model is detected with DMI.

---
 drivers/input/serio/i8042.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index cb5ece7..469e4d2 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/i8042.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 
 #include <asm/io.h>
 
@@ -133,6 +134,7 @@ 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;
+static bool i8042_noselftest;
 
 static irqreturn_t i8042_interrupt(int irq, void *dev_id);
 static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
@@ -884,6 +886,13 @@ static int i8042_controller_selftest(void)
        int i = 0;
 
        /*
+        * On some hardware just running the self test causes problems.
+        * In that case, don't run the test and just assume success.
+        */
+       if (i8042_noselftest)
+               return 0;
+
+       /*
         * We try this 5 times; on some really fragile systems this does not
         * take the first time...
         */
@@ -1496,6 +1505,16 @@ static int i8042_remove(struct platform_device *dev)
        return 0;
 }
 
+static const struct dmi_system_id i8042_dmi_noselftest_table[] __initconst = {
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"),
+               },
+       },
+       {}
+};
+
 static struct platform_driver i8042_driver = {
        .driver         = {
                .name   = "i8042",
@@ -1513,6 +1532,8 @@ static int __init i8042_init(void)
        int err;
 
        dbg_init();
+       if (dmi_check_system(i8042_dmi_noselftest_table))
+               i8042_noselftest = true;
 
        err = i8042_platform_init();
        if (err)
-- 
2.5.3


--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to