Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+155 -42
+21 -1
drivers/uwb/hwa-rc.c
··· 881 881 uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ 882 882 } 883 883 884 + static int hwarc_pre_reset(struct usb_interface *iface) 885 + { 886 + struct hwarc *hwarc = usb_get_intfdata(iface); 887 + struct uwb_rc *uwb_rc = hwarc->uwb_rc; 888 + 889 + uwb_rc_pre_reset(uwb_rc); 890 + return 0; 891 + } 892 + 893 + static int hwarc_post_reset(struct usb_interface *iface) 894 + { 895 + struct hwarc *hwarc = usb_get_intfdata(iface); 896 + struct uwb_rc *uwb_rc = hwarc->uwb_rc; 897 + 898 + uwb_rc_post_reset(uwb_rc); 899 + return 0; 900 + } 901 + 884 902 /** USB device ID's that we handle */ 885 903 static struct usb_device_id hwarc_id_table[] = { 886 904 /* D-Link DUB-1210 */ ··· 915 897 916 898 static struct usb_driver hwarc_driver = { 917 899 .name = "hwa-rc", 900 + .id_table = hwarc_id_table, 918 901 .probe = hwarc_probe, 919 902 .disconnect = hwarc_disconnect, 920 - .id_table = hwarc_id_table, 903 + .pre_reset = hwarc_pre_reset, 904 + .post_reset = hwarc_post_reset, 921 905 }; 922 906 923 907 static int __init hwarc_driver_init(void)
+41 -8
drivers/uwb/reset.c
··· 323 323 struct uwb_rc *rc = evt->rc; 324 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 326 dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); 332 327 ret = rc->reset(rc); 333 - if (ret) 328 + if (ret) { 334 329 dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); 335 - 336 - module_put(rc->owner); 330 + goto error; 331 + } 332 + return 0; 333 + error: 334 + /* Nothing can be done except try the reset again. */ 335 + uwb_rc_reset_all(rc); 337 336 return ret; 338 337 } 339 338 ··· 359 360 uwbd_event_queue(evt); 360 361 } 361 362 EXPORT_SYMBOL_GPL(uwb_rc_reset_all); 363 + 364 + void uwb_rc_pre_reset(struct uwb_rc *rc) 365 + { 366 + rc->stop(rc); 367 + uwbd_flush(rc); 368 + 369 + mutex_lock(&rc->uwb_dev.mutex); 370 + rc->beaconing = -1; 371 + rc->scanning = -1; 372 + mutex_unlock(&rc->uwb_dev.mutex); 373 + 374 + uwb_rsv_remove_all(rc); 375 + } 376 + EXPORT_SYMBOL_GPL(uwb_rc_pre_reset); 377 + 378 + void uwb_rc_post_reset(struct uwb_rc *rc) 379 + { 380 + int ret; 381 + 382 + ret = rc->start(rc); 383 + if (ret) 384 + goto error; 385 + ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); 386 + if (ret) 387 + goto error; 388 + ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); 389 + if (ret) 390 + goto error; 391 + return; 392 + error: 393 + /* Nothing can be done except try the reset again. */ 394 + uwb_rc_reset_all(rc); 395 + } 396 + EXPORT_SYMBOL_GPL(uwb_rc_post_reset);
+20 -9
drivers/uwb/rsv.c
··· 659 659 uwb_rsv_sched_update(rsv->rc); 660 660 } 661 661 662 + /** 663 + * uwb_rsv_remove_all - remove all reservations 664 + * @rc: the radio controller 665 + * 666 + * A DRP IE update is not done. 667 + */ 668 + void uwb_rsv_remove_all(struct uwb_rc *rc) 669 + { 670 + struct uwb_rsv *rsv, *t; 671 + 672 + mutex_lock(&rc->rsvs_mutex); 673 + list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { 674 + uwb_rsv_remove(rsv); 675 + } 676 + mutex_unlock(&rc->rsvs_mutex); 677 + 678 + cancel_work_sync(&rc->rsv_update_work); 679 + } 680 + 662 681 void uwb_rsv_init(struct uwb_rc *rc) 663 682 { 664 683 INIT_LIST_HEAD(&rc->reservations); ··· 701 682 702 683 void uwb_rsv_cleanup(struct uwb_rc *rc) 703 684 { 704 - struct uwb_rsv *rsv, *t; 705 - 706 - mutex_lock(&rc->rsvs_mutex); 707 - list_for_each_entry_safe(rsv, t, &rc->reservations, rc_node) { 708 - uwb_rsv_remove(rsv); 709 - } 710 - mutex_unlock(&rc->rsvs_mutex); 711 - 712 - cancel_work_sync(&rc->rsv_update_work); 685 + uwb_rsv_remove_all(rc); 713 686 destroy_workqueue(rc->rsv_workq); 714 687 }
+43 -19
drivers/uwb/umc-bus.c
··· 11 11 #include <linux/uwb/umc.h> 12 12 #include <linux/pci.h> 13 13 14 - static int umc_bus_unbind_helper(struct device *dev, void *data) 14 + static 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) 19 - device_release_driver(dev); 20 - return 0; 18 + if (dev->driver) { 19 + struct umc_dev *umc = to_umc_dev(dev); 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 + 30 + static 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 47 * umc_controller_reset - reset the whole UMC controller 25 48 * @umc: the UMC device for the radio controller. 26 49 * 27 - * Drivers will be unbound from all UMC devices belonging to the 28 - * controller and then the radio controller will be rebound. The 29 - * radio controller is expected to do a full hardware reset when it is 30 - * probed. 50 + * Drivers or all capabilities of the controller will have their 51 + * pre_reset methods called or be unbound from their device. Then all 52 + * post_reset methods will be called or the drivers will be rebound. 53 + * 54 + * Radio controllers must provide pre_reset and post_reset methods and 55 + * reset the hardware in their start method. 31 56 * 32 57 * If this is called while a probe() or remove() is in progress it 33 58 * will return -EAGAIN and not perform the reset. ··· 60 35 int umc_controller_reset(struct umc_dev *umc) 61 36 { 62 37 struct device *parent = umc->dev.parent; 63 - int ret; 38 + int ret = 0; 64 39 65 - if (down_trylock(&parent->sem)) 40 + if(down_trylock(&parent->sem)) 66 41 return -EAGAIN; 67 - bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper); 68 - ret = device_attach(&umc->dev); 69 - if (ret == 1) 70 - ret = 0; 42 + ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper); 43 + if (ret >= 0) 44 + device_for_each_child(parent, parent, umc_bus_post_reset_helper); 71 45 up(&parent->sem); 72 46 73 47 return ret; ··· 99 75 if (!dev->driver) 100 76 ret = device_attach(dev); 101 77 102 - return ret < 0 ? ret : 0; 78 + return ret; 103 79 } 104 80 105 - static void umc_bus_rescan(void) 81 + static void umc_bus_rescan(struct device *parent) 106 82 { 107 83 int err; 108 84 ··· 110 86 * We can't use bus_rescan_devices() here as it deadlocks when 111 87 * it tries to retake the dev->parent semaphore. 112 88 */ 113 - err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper); 89 + err = device_for_each_child(parent, NULL, umc_bus_rescan_helper); 114 90 if (err < 0) 115 91 printk(KERN_WARNING "%s: rescan of bus failed: %d\n", 116 92 KBUILD_MODNAME, err); ··· 144 120 if (err) 145 121 put_device(dev); 146 122 else 147 - umc_bus_rescan(); 123 + umc_bus_rescan(dev->parent); 148 124 149 125 return err; 150 126 }
+1
drivers/uwb/uwb-internal.h
··· 248 248 void uwb_rsv_init(struct uwb_rc *rc); 249 249 int uwb_rsv_setup(struct uwb_rc *rc); 250 250 void uwb_rsv_cleanup(struct uwb_rc *rc); 251 + void uwb_rsv_remove_all(struct uwb_rc *rc); 251 252 252 253 void uwb_rsv_set_state(struct uwb_rsv *rsv, enum uwb_rsv_state new_state); 253 254 void uwb_rsv_remove(struct uwb_rsv *rsv);
+25 -5
drivers/uwb/whc-rc.c
··· 394 394 395 395 le_writel(0, whcrc->rc_base + URCCMD); 396 396 whci_wait_for(&umc_dev->dev, whcrc->rc_base + URCSTS, 397 - URCSTS_HALTED, 0, 40, "URCSTS.HALTED"); 397 + URCSTS_HALTED, URCSTS_HALTED, 100, "URCSTS.HALTED"); 398 398 } 399 399 400 400 static void whcrc_init(struct whcrc *whcrc) ··· 488 488 d_printf(1, &umc_dev->dev, "freed whcrc %p\n", whcrc); 489 489 } 490 490 491 + static int whcrc_pre_reset(struct umc_dev *umc) 492 + { 493 + struct whcrc *whcrc = umc_get_drvdata(umc); 494 + struct uwb_rc *uwb_rc = whcrc->uwb_rc; 495 + 496 + uwb_rc_pre_reset(uwb_rc); 497 + return 0; 498 + } 499 + 500 + static int whcrc_post_reset(struct umc_dev *umc) 501 + { 502 + struct whcrc *whcrc = umc_get_drvdata(umc); 503 + struct uwb_rc *uwb_rc = whcrc->uwb_rc; 504 + 505 + uwb_rc_post_reset(uwb_rc); 506 + return 0; 507 + } 508 + 491 509 /* PCI device ID's that we handle [so it gets loaded] */ 492 510 static struct pci_device_id whcrc_id_table[] = { 493 511 { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, ··· 514 496 MODULE_DEVICE_TABLE(pci, whcrc_id_table); 515 497 516 498 static struct umc_driver whcrc_driver = { 517 - .name = "whc-rc", 518 - .cap_id = UMC_CAP_ID_WHCI_RC, 519 - .probe = whcrc_probe, 520 - .remove = whcrc_remove, 499 + .name = "whc-rc", 500 + .cap_id = UMC_CAP_ID_WHCI_RC, 501 + .probe = whcrc_probe, 502 + .remove = whcrc_remove, 503 + .pre_reset = whcrc_pre_reset, 504 + .post_reset = whcrc_post_reset, 521 505 }; 522 506 523 507 static int __init whcrc_driver_init(void)
+2
include/linux/uwb.h
··· 540 540 void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t); 541 541 void uwb_rc_neh_error(struct uwb_rc *, int); 542 542 void uwb_rc_reset_all(struct uwb_rc *rc); 543 + void uwb_rc_pre_reset(struct uwb_rc *rc); 544 + void uwb_rc_post_reset(struct uwb_rc *rc); 543 545 544 546 /** 545 547 * uwb_rsv_is_owner - is the owner of this reservation the RC?
+2
include/linux/uwb/umc.h
··· 89 89 void (*remove)(struct umc_dev *); 90 90 int (*suspend)(struct umc_dev *, pm_message_t state); 91 91 int (*resume)(struct umc_dev *); 92 + int (*pre_reset)(struct umc_dev *); 93 + int (*post_reset)(struct umc_dev *); 92 94 93 95 struct device_driver driver; 94 96 };