diff options
author | David Vrabel <david.vrabel@csr.com> | 2008-11-07 12:37:33 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-11-07 12:37:33 -0500 |
commit | 307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0 (patch) | |
tree | 535e10e6bd399c1f1d1f55a546e0c6aa92ba9dee /drivers/uwb/reset.c | |
parent | fec1a5932f16c0eb1b3f5ca2e18d81d860924088 (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/reset.c')
-rw-r--r-- | drivers/uwb/reset.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/drivers/uwb/reset.c b/drivers/uwb/reset.c index 8de856fa7958..e39b32099af3 100644 --- a/drivers/uwb/reset.c +++ b/drivers/uwb/reset.c | |||
@@ -323,17 +323,16 @@ int uwbd_msg_handle_reset(struct uwb_event *evt) | |||
323 | struct uwb_rc *rc = evt->rc; | 323 | struct uwb_rc *rc = evt->rc; |
324 | int ret; | 324 | int ret; |
325 | 325 | ||
326 | /* Need to prevent the RC hardware module going away while in | ||
327 | the rc->reset() call. */ | ||
328 | if (!try_module_get(rc->owner)) | ||
329 | return 0; | ||
330 | |||
331 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); | 326 | dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); |
332 | ret = rc->reset(rc); | 327 | ret = rc->reset(rc); |
333 | if (ret) | 328 | if (ret) { |
334 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); | 329 | dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); |
335 | 330 | goto error; | |
336 | module_put(rc->owner); | 331 | } |
332 | return 0; | ||
333 | error: | ||
334 | /* Nothing can be done except try the reset again. */ | ||
335 | uwb_rc_reset_all(rc); | ||
337 | return ret; | 336 | return ret; |
338 | } | 337 | } |
339 | 338 | ||
@@ -360,3 +359,37 @@ void uwb_rc_reset_all(struct uwb_rc *rc) | |||
360 | uwbd_event_queue(evt); | 359 | uwbd_event_queue(evt); |
361 | } | 360 | } |
362 | EXPORT_SYMBOL_GPL(uwb_rc_reset_all); | 361 | EXPORT_SYMBOL_GPL(uwb_rc_reset_all); |
362 | |||
363 | void uwb_rc_pre_reset(struct uwb_rc *rc) | ||
364 | { | ||
365 | rc->stop(rc); | ||
366 | uwbd_flush(rc); | ||
367 | |||
368 | mutex_lock(&rc->uwb_dev.mutex); | ||
369 | rc->beaconing = -1; | ||
370 | rc->scanning = -1; | ||
371 | mutex_unlock(&rc->uwb_dev.mutex); | ||
372 | |||
373 | uwb_rsv_remove_all(rc); | ||
374 | } | ||
375 | EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); | ||
376 | |||
377 | void uwb_rc_post_reset(struct uwb_rc *rc) | ||
378 | { | ||
379 | int ret; | ||
380 | |||
381 | ret = rc->start(rc); | ||
382 | if (ret) | ||
383 | goto error; | ||
384 | ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); | ||
385 | if (ret) | ||
386 | goto error; | ||
387 | ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); | ||
388 | if (ret) | ||
389 | goto error; | ||
390 | return; | ||
391 | error: | ||
392 | /* Nothing can be done except try the reset again. */ | ||
393 | uwb_rc_reset_all(rc); | ||
394 | } | ||
395 | EXPORT_SYMBOL_GPL(uwb_rc_post_reset); | ||