diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
| -rw-r--r-- | drivers/bluetooth/btusb.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6a010681ecf3..af472e052732 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
| @@ -102,14 +102,19 @@ static struct usb_device_id blacklist_table[] = { | |||
| 102 | { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 102 | { USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
| 103 | 103 | ||
| 104 | /* Broadcom BCM2046 */ | 104 | /* Broadcom BCM2046 */ |
| 105 | { USB_DEVICE(0x0a5c, 0x2146), .driver_info = BTUSB_RESET }, | ||
| 105 | { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET }, | 106 | { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET }, |
| 106 | 107 | ||
| 108 | /* Apple MacBook Pro with Broadcom chip */ | ||
| 109 | { USB_DEVICE(0x05ac, 0x820f), .driver_info = BTUSB_RESET }, | ||
| 110 | |||
| 107 | /* IBM/Lenovo ThinkPad with Broadcom chip */ | 111 | /* IBM/Lenovo ThinkPad with Broadcom chip */ |
| 108 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 112 | { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
| 109 | { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 113 | { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
| 110 | 114 | ||
| 111 | /* Targus ACB10US */ | 115 | /* Targus ACB10US */ |
| 112 | { USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET }, | 116 | { USB_DEVICE(0x0a5c, 0x2100), .driver_info = BTUSB_RESET }, |
| 117 | { USB_DEVICE(0x0a5c, 0x2154), .driver_info = BTUSB_RESET }, | ||
| 113 | 118 | ||
| 114 | /* ANYCOM Bluetooth USB-200 and USB-250 */ | 119 | /* ANYCOM Bluetooth USB-200 and USB-250 */ |
| 115 | { USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET }, | 120 | { USB_DEVICE(0x0a5c, 0x2111), .driver_info = BTUSB_RESET }, |
| @@ -147,6 +152,9 @@ static struct usb_device_id blacklist_table[] = { | |||
| 147 | { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 152 | { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
| 148 | { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, | 153 | { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, |
| 149 | 154 | ||
| 155 | /* Belkin F8T016 device */ | ||
| 156 | { USB_DEVICE(0x050d, 0x016a), .driver_info = BTUSB_RESET }, | ||
| 157 | |||
| 150 | /* Digianswer devices */ | 158 | /* Digianswer devices */ |
| 151 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER }, | 159 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER }, |
| 152 | { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE }, | 160 | { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE }, |
| @@ -169,6 +177,7 @@ static struct usb_device_id blacklist_table[] = { | |||
| 169 | struct btusb_data { | 177 | struct btusb_data { |
| 170 | struct hci_dev *hdev; | 178 | struct hci_dev *hdev; |
| 171 | struct usb_device *udev; | 179 | struct usb_device *udev; |
| 180 | struct usb_interface *intf; | ||
| 172 | struct usb_interface *isoc; | 181 | struct usb_interface *isoc; |
| 173 | 182 | ||
| 174 | spinlock_t lock; | 183 | spinlock_t lock; |
| @@ -267,7 +276,6 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev) | |||
| 267 | BT_ERR("%s urb %p submission failed (%d)", | 276 | BT_ERR("%s urb %p submission failed (%d)", |
| 268 | hdev->name, urb, -err); | 277 | hdev->name, urb, -err); |
| 269 | usb_unanchor_urb(urb); | 278 | usb_unanchor_urb(urb); |
| 270 | kfree(buf); | ||
| 271 | } | 279 | } |
| 272 | 280 | ||
| 273 | usb_free_urb(urb); | 281 | usb_free_urb(urb); |
| @@ -350,7 +358,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev) | |||
| 350 | BT_ERR("%s urb %p submission failed (%d)", | 358 | BT_ERR("%s urb %p submission failed (%d)", |
| 351 | hdev->name, urb, -err); | 359 | hdev->name, urb, -err); |
| 352 | usb_unanchor_urb(urb); | 360 | usb_unanchor_urb(urb); |
| 353 | kfree(buf); | ||
| 354 | } | 361 | } |
| 355 | 362 | ||
| 356 | usb_free_urb(urb); | 363 | usb_free_urb(urb); |
| @@ -471,7 +478,6 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev) | |||
| 471 | BT_ERR("%s urb %p submission failed (%d)", | 478 | BT_ERR("%s urb %p submission failed (%d)", |
| 472 | hdev->name, urb, -err); | 479 | hdev->name, urb, -err); |
| 473 | usb_unanchor_urb(urb); | 480 | usb_unanchor_urb(urb); |
| 474 | kfree(buf); | ||
| 475 | } | 481 | } |
| 476 | 482 | ||
| 477 | usb_free_urb(urb); | 483 | usb_free_urb(urb); |
| @@ -516,7 +522,7 @@ static int btusb_open(struct hci_dev *hdev) | |||
| 516 | 522 | ||
| 517 | err = btusb_submit_intr_urb(hdev); | 523 | err = btusb_submit_intr_urb(hdev); |
| 518 | if (err < 0) { | 524 | if (err < 0) { |
| 519 | clear_bit(BTUSB_INTR_RUNNING, &hdev->flags); | 525 | clear_bit(BTUSB_INTR_RUNNING, &data->flags); |
| 520 | clear_bit(HCI_RUNNING, &hdev->flags); | 526 | clear_bit(HCI_RUNNING, &hdev->flags); |
| 521 | } | 527 | } |
| 522 | 528 | ||
| @@ -532,8 +538,10 @@ static int btusb_close(struct hci_dev *hdev) | |||
| 532 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | 538 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) |
| 533 | return 0; | 539 | return 0; |
| 534 | 540 | ||
| 541 | cancel_work_sync(&data->work); | ||
| 542 | |||
| 535 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | 543 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); |
| 536 | usb_kill_anchored_urbs(&data->intr_anchor); | 544 | usb_kill_anchored_urbs(&data->isoc_anchor); |
| 537 | 545 | ||
| 538 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); | 546 | clear_bit(BTUSB_BULK_RUNNING, &data->flags); |
| 539 | usb_kill_anchored_urbs(&data->bulk_anchor); | 547 | usb_kill_anchored_urbs(&data->bulk_anchor); |
| @@ -821,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
| 821 | } | 829 | } |
| 822 | 830 | ||
| 823 | data->udev = interface_to_usbdev(intf); | 831 | data->udev = interface_to_usbdev(intf); |
| 832 | data->intf = intf; | ||
| 824 | 833 | ||
| 825 | spin_lock_init(&data->lock); | 834 | spin_lock_init(&data->lock); |
| 826 | 835 | ||
| @@ -889,7 +898,7 @@ static int btusb_probe(struct usb_interface *intf, | |||
| 889 | 898 | ||
| 890 | if (data->isoc) { | 899 | if (data->isoc) { |
| 891 | err = usb_driver_claim_interface(&btusb_driver, | 900 | err = usb_driver_claim_interface(&btusb_driver, |
| 892 | data->isoc, NULL); | 901 | data->isoc, data); |
| 893 | if (err < 0) { | 902 | if (err < 0) { |
| 894 | hci_free_dev(hdev); | 903 | hci_free_dev(hdev); |
| 895 | kfree(data); | 904 | kfree(data); |
| @@ -921,13 +930,22 @@ static void btusb_disconnect(struct usb_interface *intf) | |||
| 921 | 930 | ||
| 922 | hdev = data->hdev; | 931 | hdev = data->hdev; |
| 923 | 932 | ||
| 924 | if (data->isoc) | 933 | __hci_dev_hold(hdev); |
| 925 | usb_driver_release_interface(&btusb_driver, data->isoc); | ||
| 926 | 934 | ||
| 927 | usb_set_intfdata(intf, NULL); | 935 | usb_set_intfdata(data->intf, NULL); |
| 936 | |||
| 937 | if (data->isoc) | ||
| 938 | usb_set_intfdata(data->isoc, NULL); | ||
| 928 | 939 | ||
| 929 | hci_unregister_dev(hdev); | 940 | hci_unregister_dev(hdev); |
| 930 | 941 | ||
| 942 | if (intf == data->isoc) | ||
| 943 | usb_driver_release_interface(&btusb_driver, data->intf); | ||
| 944 | else if (data->isoc) | ||
| 945 | usb_driver_release_interface(&btusb_driver, data->isoc); | ||
| 946 | |||
| 947 | __hci_dev_put(hdev); | ||
| 948 | |||
| 931 | hci_free_dev(hdev); | 949 | hci_free_dev(hdev); |
| 932 | } | 950 | } |
| 933 | 951 | ||
