[PATCH] i8042 self test causes trackpad to fail on Asus X455L

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <john@xxxxxxxxxx>
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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux