From bdbef3d696ca83489eb653459b5a7a62ecf5596a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Sep 2008 00:16:35 +0200 Subject: [Bluetooth] Fix I/O errors on MacBooks with Broadcom chips The newer MacBooks contain a Broadcom based Bluetooth chip and to make this work properly, HCI_Reset must be send first. If HCI_Reset is not used then a lot of I/O errors show up and its triggers packets from non-existent ACL links. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 6a010681ecf..7665347238c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -104,6 +104,9 @@ static struct usb_device_id blacklist_table[] = { /* Broadcom BCM2046 */ { USB_DEVICE(0x0a5c, 0x2151), .driver_info = BTUSB_RESET }, + /* Apple MacBook Pro with Broadcom chip */ + { USB_DEVICE(0x05ac, 0x820f), .driver_info = BTUSB_RESET }, + /* IBM/Lenovo ThinkPad with Broadcom chip */ { USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_RESET | BTUSB_WRONG_SCO_MTU }, -- cgit v1.2.3 From e8c3c3d22b340a406a9aab1b7a9f436636c3de9d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Sep 2008 00:16:36 +0200 Subject: [Bluetooth] Fix wrong URB handling of btusb driver The btusb driver contains two typos that result in some buggy behavior, but the impact is not immediately visible. During initialization the submitting of interrupt URBs might fail and then make sure to remove the correct flag and not one of the hci_dev flags. When closing down the interface make sure to kill the anchor for the ISOC URBs and not kill the interrupt URBs twice. Also cancel any scheduled work when closing down the interface. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7665347238c..b4756a6a3a6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -519,7 +519,7 @@ static int btusb_open(struct hci_dev *hdev) err = btusb_submit_intr_urb(hdev); if (err < 0) { - clear_bit(BTUSB_INTR_RUNNING, &hdev->flags); + clear_bit(BTUSB_INTR_RUNNING, &data->flags); clear_bit(HCI_RUNNING, &hdev->flags); } @@ -535,8 +535,10 @@ static int btusb_close(struct hci_dev *hdev) if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; + cancel_work_sync(&data->work); + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->intr_anchor); + usb_kill_anchored_urbs(&data->isoc_anchor); clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); -- cgit v1.2.3 From 5fbcd260c2c52f78cd699f65e9c7af2e60b5380c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 23 Sep 2008 00:16:36 +0200 Subject: [Bluetooth] Fix USB disconnect handling of btusb driver The USB transport specification for Bluetooth splits the ACL and SCO handling into two separate interfaces. In Linux it possible to probe and disconnect these interfaces independently. So make sure that both interfaces are tightly bound together. This fixes the suspend regression that some people have expierenced. Signed-off-by: Oliver Neukum Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b4756a6a3a6..29ae99817c6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -172,6 +172,7 @@ static struct usb_device_id blacklist_table[] = { struct btusb_data { struct hci_dev *hdev; struct usb_device *udev; + struct usb_interface *intf; struct usb_interface *isoc; spinlock_t lock; @@ -826,6 +827,7 @@ static int btusb_probe(struct usb_interface *intf, } data->udev = interface_to_usbdev(intf); + data->intf = intf; spin_lock_init(&data->lock); @@ -894,7 +896,7 @@ static int btusb_probe(struct usb_interface *intf, if (data->isoc) { err = usb_driver_claim_interface(&btusb_driver, - data->isoc, NULL); + data->isoc, data); if (err < 0) { hci_free_dev(hdev); kfree(data); @@ -926,13 +928,22 @@ static void btusb_disconnect(struct usb_interface *intf) hdev = data->hdev; - if (data->isoc) - usb_driver_release_interface(&btusb_driver, data->isoc); + __hci_dev_hold(hdev); - usb_set_intfdata(intf, NULL); + usb_set_intfdata(data->intf, NULL); + + if (data->isoc) + usb_set_intfdata(data->isoc, NULL); hci_unregister_dev(hdev); + if (intf == data->isoc) + usb_driver_release_interface(&btusb_driver, data->intf); + else if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); + + __hci_dev_put(hdev); + hci_free_dev(hdev); } -- cgit v1.2.3