소스 검색

Input: psmouse - ignore parity error for basic protocols

Observing behavior of the other OS it appears that parity errors reported
by the keyboard controller are being ignored and the data is processed
as usual. Let's do the same for standard PS/2 protocols (bare, Intellimouse
and Intellimouse Explorer) to provide better compatibility. Thsi should fix
teh following bug:

	https://bugzilla.kernel.org/show_bug.cgi?id=6105

Thanks for Damjan Jovanovic for locating the source of issue and ideas
for the patch.

Tested-by: Damjan Jovanovic <damjan.jov@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Dmitry Torokhov 15 년 전
부모
커밋
6b9d363c49
2개의 변경된 파일16개의 추가작업 그리고 3개의 파일을 삭제
  1. 15 3
      drivers/input/mouse/psmouse-base.c
  2. 1 0
      drivers/input/mouse/psmouse.h

+ 15 - 3
drivers/input/mouse/psmouse-base.c

@@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq;
 struct psmouse_protocol {
 	enum psmouse_type type;
 	bool maxproto;
+	bool ignore_parity; /* Protocol should ignore parity errors from KBC */
 	const char *name;
 	const char *alias;
 	int (*detect)(struct psmouse *, bool);
@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
 	if (psmouse->state == PSMOUSE_IGNORE)
 		goto out;
 
-	if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) {
+	if (unlikely((flags & SERIO_TIMEOUT) ||
+		     ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
+
 		if (psmouse->state == PSMOUSE_ACTIVATED)
 			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
 				flags & SERIO_TIMEOUT ? " timeout" : "",
@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 		.name		= "PS/2",
 		.alias		= "bare",
 		.maxproto	= true,
+		.ignore_parity	= true,
 		.detect		= ps2bare_detect,
 	},
 #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 		.name		= "ImPS/2",
 		.alias		= "imps",
 		.maxproto	= true,
+		.ignore_parity	= true,
 		.detect		= intellimouse_detect,
 	},
 	{
@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 		.name		= "ImExPS/2",
 		.alias		= "exps",
 		.maxproto	= true,
+		.ignore_parity	= true,
 		.detect		= im_explorer_detect,
 	},
 #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio)
 static int psmouse_switch_protocol(struct psmouse *psmouse,
 				   const struct psmouse_protocol *proto)
 {
+	const struct psmouse_protocol *selected_proto;
 	struct input_dev *input_dev = psmouse->dev;
 
 	input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
@@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
 			return -1;
 
 		psmouse->type = proto->type;
-	} else
+		selected_proto = proto;
+	} else {
 		psmouse->type = psmouse_extensions(psmouse,
 						   psmouse_max_proto, true);
+		selected_proto = psmouse_protocol_by_type(psmouse->type);
+	}
+
+	psmouse->ignore_parity = selected_proto->ignore_parity;
 
 	/*
 	 * If mouse's packet size is 3 there is no point in polling the
@@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
 		psmouse->resync_time = 0;
 
 	snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s",
-		 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
+		 selected_proto->name, psmouse->vendor, psmouse->name);
 
 	input_dev->name = psmouse->devname;
 	input_dev->phys = psmouse->phys;

+ 1 - 0
drivers/input/mouse/psmouse.h

@@ -47,6 +47,7 @@ struct psmouse {
 	unsigned char pktcnt;
 	unsigned char pktsize;
 	unsigned char type;
+	bool ignore_parity;
 	bool acks_disable_command;
 	unsigned int model;
 	unsigned long last;