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/reset.c | |
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/reset.c')
-rw-r--r-- | drivers/uwb/reset.c | 21 |
1 files changed, 11 insertions, 10 deletions
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); |