aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uwb/umc-bus.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-11-07 12:37:33 -0500
committerDavid Vrabel <david.vrabel@csr.com>2008-11-07 12:37:33 -0500
commit307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0 (patch)
tree535e10e6bd399c1f1d1f55a546e0c6aa92ba9dee /drivers/uwb/umc-bus.c
parentfec1a5932f16c0eb1b3f5ca2e18d81d860924088 (diff)
uwb: don't unbind the radio controller driver when resetting
Use pre_reset and post_reset methods to avoid unbinding the radio controller driver after a uwb_rc_reset_all() call. This avoids a deadlock in uwb_rc_rm() when waiting for the uwb event thread to stop. Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/uwb/umc-bus.c')
-rw-r--r--drivers/uwb/umc-bus.c62
1 files changed, 43 insertions, 19 deletions
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index 2d8d62d9f53e..5ad36164c13b 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -11,23 +11,48 @@
11#include <linux/uwb/umc.h> 11#include <linux/uwb/umc.h>
12#include <linux/pci.h> 12#include <linux/pci.h>
13 13
14static int umc_bus_unbind_helper(struct device *dev, void *data) 14static int umc_bus_pre_reset_helper(struct device *dev, void *data)
15{ 15{
16 struct device *parent = data; 16 int ret = 0;
17 17
18 if (dev->parent == parent && dev->driver) 18 if (dev->driver) {
19 device_release_driver(dev); 19 struct umc_dev *umc = to_umc_dev(dev);
20 return 0; 20 struct umc_driver *umc_drv = to_umc_driver(dev->driver);
21
22 if (umc_drv->pre_reset)
23 ret = umc_drv->pre_reset(umc);
24 else
25 device_release_driver(dev);
26 }
27 return ret;
28}
29
30static int umc_bus_post_reset_helper(struct device *dev, void *data)
31{
32 int ret = 0;
33
34 if (dev->driver) {
35 struct umc_dev *umc = to_umc_dev(dev);
36 struct umc_driver *umc_drv = to_umc_driver(dev->driver);
37
38 if (umc_drv->post_reset)
39 ret = umc_drv->post_reset(umc);
40 } else
41 ret = device_attach(dev);
42
43 return ret;
21} 44}
22 45
23/** 46/**
24 * umc_controller_reset - reset the whole UMC controller 47 * umc_controller_reset - reset the whole UMC controller
25 * @umc: the UMC device for the radio controller. 48 * @umc: the UMC device for the radio controller.
26 * 49 *
27 * Drivers will be unbound from all UMC devices belonging to the 50 * Drivers or all capabilities of the controller will have their
28 * controller and then the radio controller will be rebound. The 51 * pre_reset methods called or be unbound from their device. Then all
29 * radio controller is expected to do a full hardware reset when it is 52 * post_reset methods will be called or the drivers will be rebound.
30 * probed. 53 *
54 * Radio controllers must provide pre_reset and post_reset methods and
55 * reset the hardware in their start method.
31 * 56 *
32 * If this is called while a probe() or remove() is in progress it 57 * If this is called while a probe() or remove() is in progress it
33 * will return -EAGAIN and not perform the reset. 58 * will return -EAGAIN and not perform the reset.
@@ -35,14 +60,13 @@ static int umc_bus_unbind_helper(struct device *dev, void *data)
35int umc_controller_reset(struct umc_dev *umc) 60int umc_controller_reset(struct umc_dev *umc)
36{ 61{
37 struct device *parent = umc->dev.parent; 62 struct device *parent = umc->dev.parent;
38 int ret; 63 int ret = 0;
39 64
40 if (down_trylock(&parent->sem)) 65 if(down_trylock(&parent->sem))
41 return -EAGAIN; 66 return -EAGAIN;
42 bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper); 67 ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
43 ret = device_attach(&umc->dev); 68 if (ret >= 0)
44 if (ret == 1) 69 device_for_each_child(parent, parent, umc_bus_post_reset_helper);
45 ret = 0;
46 up(&parent->sem); 70 up(&parent->sem);
47 71
48 return ret; 72 return ret;
@@ -75,10 +99,10 @@ static int umc_bus_rescan_helper(struct device *dev, void *data)
75 if (!dev->driver) 99 if (!dev->driver)
76 ret = device_attach(dev); 100 ret = device_attach(dev);
77 101
78 return ret < 0 ? ret : 0; 102 return ret;
79} 103}
80 104
81static void umc_bus_rescan(void) 105static void umc_bus_rescan(struct device *parent)
82{ 106{
83 int err; 107 int err;
84 108
@@ -86,7 +110,7 @@ static void umc_bus_rescan(void)
86 * We can't use bus_rescan_devices() here as it deadlocks when 110 * We can't use bus_rescan_devices() here as it deadlocks when
87 * it tries to retake the dev->parent semaphore. 111 * it tries to retake the dev->parent semaphore.
88 */ 112 */
89 err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper); 113 err = device_for_each_child(parent, NULL, umc_bus_rescan_helper);
90 if (err < 0) 114 if (err < 0)
91 printk(KERN_WARNING "%s: rescan of bus failed: %d\n", 115 printk(KERN_WARNING "%s: rescan of bus failed: %d\n",
92 KBUILD_MODNAME, err); 116 KBUILD_MODNAME, err);
@@ -120,7 +144,7 @@ static int umc_device_probe(struct device *dev)
120 if (err) 144 if (err)
121 put_device(dev); 145 put_device(dev);
122 else 146 else
123 umc_bus_rescan(); 147 umc_bus_rescan(dev->parent);
124 148
125 return err; 149 return err;
126} 150}