From 59b015133cd0034f5904a76969d73476380aac46 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 5 Jan 2010 17:56:02 -0800 Subject: Input: serio - fix potential deadlock when unbinding drivers sysfs_remove_group() waits for sysfs attributes to be removed, therefore we do not need to worry about driver-specific attributes being accessed after driver has been detached from the device. In fact, attempts to take serio->drv_mutex in attribute methods may lead to the following deadlock: sysfs_read_file() fill_read_buffer() sysfs_get_active_two() psmouse_attr_show_helper() serio_pin_driver() serio_disconnect_driver() mutex_lock(&serio->drv_mutex); <--------> mutex_lock(&serio_drv_mutex); psmouse_disconnect() sysfs_remove_group(... psmouse_attr_group); .... sysfs_deactivate(); wait_for_completion(); Fix this by removing calls to serio_[un]pin_driver() and functions themselves and using driver-private mutexes to serialize access to attribute's set() methods that may change device state. Signed-off-by: Eric W. Biederman Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) (limited to 'drivers/input/mouse/psmouse-base.c') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 401ac6b6edd4..d59e18b24ede 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1450,24 +1450,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); struct psmouse *psmouse; - int retval; - - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out; - } psmouse = serio_get_drvdata(serio); - retval = attr->show(psmouse, attr->data, buf); - -out: - serio_unpin_driver(serio); - return retval; + return attr->show(psmouse, attr->data, buf); } ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, @@ -1478,18 +1464,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev struct psmouse *psmouse, *parent = NULL; int retval; - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out_unpin; - } - retval = mutex_lock_interruptible(&psmouse_mutex); if (retval) - goto out_unpin; + goto out; psmouse = serio_get_drvdata(serio); @@ -1519,8 +1496,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev out_unlock: mutex_unlock(&psmouse_mutex); - out_unpin: - serio_unpin_driver(serio); + out: return retval; } @@ -1582,9 +1558,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co } mutex_unlock(&psmouse_mutex); - serio_unpin_driver(serio); serio_unregister_child_port(serio); - serio_pin_driver_uninterruptible(serio); mutex_lock(&psmouse_mutex); if (serio->drv != &psmouse_drv) { -- cgit v1.2.3 From e4e6efd2df4b5754bd519b516207eb723d1f17df Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 7 Jan 2010 01:52:39 -0800 Subject: Input: psmouse - fix Synaptics detection when protocol is disabled For configurations where Synaptics hardware is present but the Synaptics extensions support is not compiled in, the mouse is reprobed and a new device is allocated on every suspend/resume. During probe, psmouse_switch_protocol() calls psmouse_extensions() with set_properties=1. This calls the dummy synaptics_init() which returns an error code, instructing us not to use the synaptics extensions. During resume, psmouse_reconnect() calls psmouse_extensions() with set_properties=0, in which case call to synaptics_init() is bypassed and PSMOUSE_SYNAPTICS is returned. Since the result is different from previous attempt psmouse_reconnect() fails and full re-probe happens. Fix this by tweaking the set_properties=0 codepath in psmouse_extensions() to be more careful about offering PSMOUSE_SYNAPTICS extensions. Signed-off-by: Daniel Drake Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 9 ++++++++- drivers/input/mouse/synaptics.c | 10 ++++++++++ drivers/input/mouse/synaptics.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/input/mouse/psmouse-base.c') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d59e18b24ede..cabf4e1caacc 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -627,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse, synaptics_hardware = true; if (max_proto > PSMOUSE_IMEX) { - if (!set_properties || synaptics_init(psmouse) == 0) +/* + * Try activating protocol, but check if support is enabled first, since + * we try detecting Synaptics even when protocol is disabled. + */ + if (synaptics_supported() && + (!set_properties || synaptics_init(psmouse) == 0)) { return PSMOUSE_SYNAPTICS; + } + /* * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). * Unfortunately Logitech/Genius probes confuse some firmware versions so diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 05689e732191..d3f5243fa093 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -743,6 +743,11 @@ int synaptics_init(struct psmouse *psmouse) return -1; } +bool synaptics_supported(void) +{ + return true; +} + #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ void __init synaptics_module_init(void) @@ -754,5 +759,10 @@ int synaptics_init(struct psmouse *psmouse) return -ENOSYS; } +bool synaptics_supported(void) +{ + return false; +} + #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 838e7f2c9b30..f0f40a331dc8 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -109,5 +109,6 @@ void synaptics_module_init(void); int synaptics_detect(struct psmouse *psmouse, bool set_properties); int synaptics_init(struct psmouse *psmouse); void synaptics_reset(struct psmouse *psmouse); +bool synaptics_supported(void); #endif /* _SYNAPTICS_H */ -- cgit v1.2.3 From 4a18b3ab6ed537b055e3fcfca64ab870b4f9acf0 Mon Sep 17 00:00:00 2001 From: Tai-hwa Liang Date: Wed, 13 Jan 2010 00:16:27 -0800 Subject: Input: pmouse - move Sentelic probe down the list Sentelic probes confuse IBM trackpoints so they stop responding to TP_READ_ID command. See: http://bugzilla.kernel.org/show_bug.cgi?id=14970 Let's move FSP detection lower so it is probed after trackpoint and others, just before we strat probing for Intellimouse Explorer. Signed-off-by: Tai-hwa Liang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/input/mouse/psmouse-base.c') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cabf4e1caacc..9774bdfaa482 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -690,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse, max_proto = PSMOUSE_IMEX; } -/* - * Try Finger Sensing Pad - */ - if (max_proto > PSMOUSE_IMEX) { - if (fsp_detect(psmouse, set_properties) == 0) { - if (!set_properties || fsp_init(psmouse) == 0) - return PSMOUSE_FSP; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - } if (max_proto > PSMOUSE_IMEX) { if (genius_detect(psmouse, set_properties) == 0) @@ -718,6 +705,21 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_TOUCHKIT_PS2; } +/* + * Try Finger Sensing Pad. We do it here because its probe upsets + * Trackpoint devices (causing TP_READ_ID command to time out). + */ + if (max_proto > PSMOUSE_IMEX) { + if (fsp_detect(psmouse, set_properties) == 0) { + if (!set_properties || fsp_init(psmouse) == 0) + return PSMOUSE_FSP; +/* + * Init failed, try basic relative protocols + */ + max_proto = PSMOUSE_IMEX; + } + } + /* * Reset to defaults in case the device got confused by extended * protocol probes. Note that we follow up with full reset because -- cgit v1.2.3 From a9f0c381973097462d9688dc26fe66f4f020502e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 7 Feb 2010 23:10:04 -0800 Subject: Input: psmouse - make sure we don't schedule reconnects after cleanup Set state of the device as "initializing" during and after cleanup to ensure that unsolicited data from the device is not passed on. We especially want to avoid processing new device announcements "0xaa 0x00" that can come up before we perform reconnect operation. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/input/mouse/psmouse-base.c') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 9774bdfaa482..d8c0c8d6992c 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1141,7 +1141,14 @@ static void psmouse_cleanup(struct serio *serio) psmouse_deactivate(parent); } - psmouse_deactivate(psmouse); + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); + + /* + * Disable stream mode so cleanup routine can proceed undisturbed. + */ + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) + printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n", + psmouse->ps2dev.serio->phys); if (psmouse->cleanup) psmouse->cleanup(psmouse); -- cgit v1.2.3