diff options
author | David Vrabel <david.vrabel@csr.com> | 2009-08-25 11:41:06 -0400 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2009-08-26 07:39:29 -0400 |
commit | 0396c215f301e92677d1e9a064b405e31501dc1d (patch) | |
tree | a54229672abc6f244fcf184701b8a8bf98b70544 /drivers/uwb | |
parent | a9e75a389254801ca160b72c6e221e5bb7e35df9 (diff) |
uwb: avoid radio controller reset loops
If a radio controller reset attempt occurs while a probe() or remove()
is in progress it fails and is retried endlessly, potentially preventing
the probe() or remove() from completing.
If a reset fails, sleep for a bit before retrying the reset. This
allows the probe()/remove() to complete.
Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/uwb')
-rw-r--r-- | drivers/uwb/hwa-rc.c | 3 | ||||
-rw-r--r-- | drivers/uwb/reset.c | 21 | ||||
-rw-r--r-- | drivers/uwb/umc-bus.c | 2 | ||||
-rw-r--r-- | drivers/uwb/whc-rc.c | 3 |
4 files changed, 14 insertions, 15 deletions
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 9052bcb4f528..e7eeb63fab23 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c | |||
@@ -887,8 +887,7 @@ static int hwarc_post_reset(struct usb_interface *iface) | |||
887 | struct hwarc *hwarc = usb_get_intfdata(iface); | 887 | struct hwarc *hwarc = usb_get_intfdata(iface); |
888 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | 888 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; |
889 | 889 | ||
890 | uwb_rc_post_reset(uwb_rc); | 890 | return uwb_rc_post_reset(uwb_rc); |
891 | return 0; | ||
892 | } | 891 | } |
893 | 892 | ||
894 | /** USB device ID's that we handle */ | 893 | /** USB device ID's that we handle */ |
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c index 70f8050221ff..7f0512e43d9d 100644 --- a/drivers/uwb/reset.c +++ b/drivers/uwb/reset.c | |||
@@ -30,6 +30,7 @@ | |||
30 | */ | 30 | */ |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/delay.h> | ||
33 | 34 | ||
34 | #include "uwb-internal.h" | 35 | #include "uwb-internal.h" |
35 | 36 | ||
@@ -323,13 +324,15 @@ int uwbd_msg_handle_reset(struct uwb_event *evt) | |||
323 | 324 | ||
324 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); | 325 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); |
325 | ret = rc->reset(rc); | 326 | ret = rc->reset(rc); |
326 | if (ret) { | 327 | if (ret < 0) { |
327 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); | 328 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); |
328 | goto error; | 329 | goto error; |
329 | } | 330 | } |
330 | return 0; | 331 | return 0; |
331 | error: | 332 | error: |
332 | /* Nothing can be done except try the reset again. */ | 333 | /* Nothing can be done except try the reset again. Wait a bit |
334 | to avoid reset loops during probe() or remove(). */ | ||
335 | msleep(1000); | ||
333 | uwb_rc_reset_all(rc); | 336 | uwb_rc_reset_all(rc); |
334 | return ret; | 337 | return ret; |
335 | } | 338 | } |
@@ -368,22 +371,20 @@ void uwb_rc_pre_reset(struct uwb_rc *rc) | |||
368 | } | 371 | } |
369 | EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); | 372 | EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); |
370 | 373 | ||
371 | void uwb_rc_post_reset(struct uwb_rc *rc) | 374 | int uwb_rc_post_reset(struct uwb_rc *rc) |
372 | { | 375 | { |
373 | int ret; | 376 | int ret; |
374 | 377 | ||
375 | ret = rc->start(rc); | 378 | ret = rc->start(rc); |
376 | if (ret) | 379 | if (ret) |
377 | goto error; | 380 | goto out; |
378 | ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); | 381 | ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); |
379 | if (ret) | 382 | if (ret) |
380 | goto error; | 383 | goto out; |
381 | ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); | 384 | ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); |
382 | if (ret) | 385 | if (ret) |
383 | goto error; | 386 | goto out; |
384 | return; | 387 | out: |
385 | error: | 388 | return ret; |
386 | /* Nothing can be done except try the reset again. */ | ||
387 | uwb_rc_reset_all(rc); | ||
388 | } | 389 | } |
389 | EXPORT_SYMBOL_GPL(uwb_rc_post_reset); | 390 | EXPORT_SYMBOL_GPL(uwb_rc_post_reset); |
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c index 5ad36164c13b..cdd6c8efc9f8 100644 --- a/drivers/uwb/umc-bus.c +++ b/drivers/uwb/umc-bus.c | |||
@@ -66,7 +66,7 @@ int umc_controller_reset(struct umc_dev *umc) | |||
66 | return -EAGAIN; | 66 | return -EAGAIN; |
67 | ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); | 67 | ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); |
68 | if (ret >= 0) | 68 | if (ret >= 0) |
69 | device_for_each_child(parent, parent, umc_bus_post_reset_helper); | 69 | ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper); |
70 | up(&parent->sem); | 70 | up(&parent->sem); |
71 | 71 | ||
72 | return ret; | 72 | return ret; |
diff --git a/drivers/uwb/whc-rc.c b/drivers/uwb/whc-rc.c index 19a1dd129212..1d9a6f54658e 100644 --- a/drivers/uwb/whc-rc.c +++ b/drivers/uwb/whc-rc.c | |||
@@ -443,8 +443,7 @@ static int whcrc_post_reset(struct umc_dev *umc) | |||
443 | struct whcrc *whcrc = umc_get_drvdata(umc); | 443 | struct whcrc *whcrc = umc_get_drvdata(umc); |
444 | struct uwb_rc *uwb_rc = whcrc->uwb_rc; | 444 | struct uwb_rc *uwb_rc = whcrc->uwb_rc; |
445 | 445 | ||
446 | uwb_rc_post_reset(uwb_rc); | 446 | return uwb_rc_post_reset(uwb_rc); |
447 | return 0; | ||
448 | } | 447 | } |
449 | 448 | ||
450 | /* PCI device ID's that we handle [so it gets loaded] */ | 449 | /* PCI device ID's that we handle [so it gets loaded] */ |