aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/psmouse-base.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2010-01-05 20:56:02 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-01-06 03:14:32 -0500
commit59b015133cd0034f5904a76969d73476380aac46 (patch)
tree578643cc919b7e62b5086718d5c3f9b0fee836a9 /drivers/input/mouse/psmouse-base.c
parentabf2a117c67a67fbb611913a31109d0ff66ab073 (diff)
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 <ebiederm@xmission.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse/psmouse-base.c')
-rw-r--r--drivers/input/mouse/psmouse-base.c32
1 files changed, 3 insertions, 29 deletions
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
1450 struct serio *serio = to_serio_port(dev); 1450 struct serio *serio = to_serio_port(dev);
1451 struct psmouse_attribute *attr = to_psmouse_attr(devattr); 1451 struct psmouse_attribute *attr = to_psmouse_attr(devattr);
1452 struct psmouse *psmouse; 1452 struct psmouse *psmouse;
1453 int retval;
1454
1455 retval = serio_pin_driver(serio);
1456 if (retval)
1457 return retval;
1458
1459 if (serio->drv != &psmouse_drv) {
1460 retval = -ENODEV;
1461 goto out;
1462 }
1463 1453
1464 psmouse = serio_get_drvdata(serio); 1454 psmouse = serio_get_drvdata(serio);
1465 1455
1466 retval = attr->show(psmouse, attr->data, buf); 1456 return attr->show(psmouse, attr->data, buf);
1467
1468out:
1469 serio_unpin_driver(serio);
1470 return retval;
1471} 1457}
1472 1458
1473ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, 1459ssize_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
1478 struct psmouse *psmouse, *parent = NULL; 1464 struct psmouse *psmouse, *parent = NULL;
1479 int retval; 1465 int retval;
1480 1466
1481 retval = serio_pin_driver(serio);
1482 if (retval)
1483 return retval;
1484
1485 if (serio->drv != &psmouse_drv) {
1486 retval = -ENODEV;
1487 goto out_unpin;
1488 }
1489
1490 retval = mutex_lock_interruptible(&psmouse_mutex); 1467 retval = mutex_lock_interruptible(&psmouse_mutex);
1491 if (retval) 1468 if (retval)
1492 goto out_unpin; 1469 goto out;
1493 1470
1494 psmouse = serio_get_drvdata(serio); 1471 psmouse = serio_get_drvdata(serio);
1495 1472
@@ -1519,8 +1496,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
1519 1496
1520 out_unlock: 1497 out_unlock:
1521 mutex_unlock(&psmouse_mutex); 1498 mutex_unlock(&psmouse_mutex);
1522 out_unpin: 1499 out:
1523 serio_unpin_driver(serio);
1524 return retval; 1500 return retval;
1525} 1501}
1526 1502
@@ -1582,9 +1558,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
1582 } 1558 }
1583 1559
1584 mutex_unlock(&psmouse_mutex); 1560 mutex_unlock(&psmouse_mutex);
1585 serio_unpin_driver(serio);
1586 serio_unregister_child_port(serio); 1561 serio_unregister_child_port(serio);
1587 serio_pin_driver_uninterruptible(serio);
1588 mutex_lock(&psmouse_mutex); 1562 mutex_lock(&psmouse_mutex);
1589 1563
1590 if (serio->drv != &psmouse_drv) { 1564 if (serio->drv != &psmouse_drv) {