summaryrefslogtreecommitdiffstats
path: root/drivers/w1
diff options
context:
space:
mode:
authorDavid Fries <david@fries.net>2014-04-16 02:21:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-16 17:07:51 -0400
commit18d7f891bcc7e49f2900215f17a861ccec34b138 (patch)
treeb70c5385376b8463fc4d1850574d7c7d8be9e4b1 /drivers/w1
parent593ceb0c7046c640cf463022189428a45219f595 (diff)
w1: avoid recursive device_add
__w1_attach_slave_device calls device_add which calls w1_bus_notify which calls the w1_bq27000 slave driver, which calls platform_device_add and device_add and deadlocks on getting &(&priv->bus_notifier)->rwsem as it is still held in the previous device_add. This avoids the problem by processing the family add/remove outside of the slave device_add call. Commit 47eba33a0997fc7362a introduced this deadlock and added a KOBJ_ADD, as the add was already reported in device_register two add events were being sent. This change suppresses the device_register add so that any slave device sysfs entries are setup before the add goes out. Belisko Marek reported this change fixed the deadlock he was seeing on ARM device tree, while testing on my x86-64 system never saw the deadlock. Reported-by: Belisko Marek <marek.belisko@gmail.com> Signed-off-by: David Fries <David@Fries.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/w1')
-rw-r--r--drivers/w1/w1.c32
1 files changed, 6 insertions, 26 deletions
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index b96f61b15dc6..ff52618cafbe 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -614,27 +614,11 @@ end:
614 return err; 614 return err;
615} 615}
616 616
617/* 617static int w1_family_notify(unsigned long action, struct w1_slave *sl)
618 * Handle sysfs file creation and removal here, before userspace is told that
619 * the device is added / removed from the system
620 */
621static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
622 void *data)
623{ 618{
624 struct device *dev = data;
625 struct w1_slave *sl;
626 struct w1_family_ops *fops; 619 struct w1_family_ops *fops;
627 int err; 620 int err;
628 621
629 /*
630 * Only care about slave devices at the moment. Yes, we should use a
631 * separate "type" for this, but for now, look at the release function
632 * to know which type it is...
633 */
634 if (dev->release != w1_slave_release)
635 return 0;
636
637 sl = dev_to_w1_slave(dev);
638 fops = sl->family->fops; 622 fops = sl->family->fops;
639 623
640 if (!fops) 624 if (!fops)
@@ -673,10 +657,6 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action,
673 return 0; 657 return 0;
674} 658}
675 659
676static struct notifier_block w1_bus_nb = {
677 .notifier_call = w1_bus_notify,
678};
679
680static int __w1_attach_slave_device(struct w1_slave *sl) 660static int __w1_attach_slave_device(struct w1_slave *sl)
681{ 661{
682 int err; 662 int err;
@@ -698,6 +678,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
698 dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, 678 dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__,
699 dev_name(&sl->dev), sl); 679 dev_name(&sl->dev), sl);
700 680
681 /* suppress for w1_family_notify before sending KOBJ_ADD */
682 dev_set_uevent_suppress(&sl->dev, true);
683
701 err = device_register(&sl->dev); 684 err = device_register(&sl->dev);
702 if (err < 0) { 685 if (err < 0) {
703 dev_err(&sl->dev, 686 dev_err(&sl->dev,
@@ -705,7 +688,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
705 dev_name(&sl->dev), err); 688 dev_name(&sl->dev), err);
706 return err; 689 return err;
707 } 690 }
708 691 w1_family_notify(BUS_NOTIFY_ADD_DEVICE, sl);
709 692
710 dev_set_uevent_suppress(&sl->dev, false); 693 dev_set_uevent_suppress(&sl->dev, false);
711 kobject_uevent(&sl->dev.kobj, KOBJ_ADD); 694 kobject_uevent(&sl->dev.kobj, KOBJ_ADD);
@@ -799,6 +782,7 @@ int w1_unref_slave(struct w1_slave *sl)
799 msg.type = W1_SLAVE_REMOVE; 782 msg.type = W1_SLAVE_REMOVE;
800 w1_netlink_send(sl->master, &msg); 783 w1_netlink_send(sl->master, &msg);
801 784
785 w1_family_notify(BUS_NOTIFY_DEL_DEVICE, sl);
802 device_unregister(&sl->dev); 786 device_unregister(&sl->dev);
803 #ifdef DEBUG 787 #ifdef DEBUG
804 memset(sl, 0, sizeof(*sl)); 788 memset(sl, 0, sizeof(*sl));
@@ -1186,10 +1170,6 @@ static int __init w1_init(void)
1186 goto err_out_exit_init; 1170 goto err_out_exit_init;
1187 } 1171 }
1188 1172
1189 retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb);
1190 if (retval)
1191 goto err_out_bus_unregister;
1192
1193 retval = driver_register(&w1_master_driver); 1173 retval = driver_register(&w1_master_driver);
1194 if (retval) { 1174 if (retval) {
1195 printk(KERN_ERR 1175 printk(KERN_ERR