aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-09-22 18:16:36 -0400
committerMarcel Holtmann <marcel@holtmann.org>2008-09-22 18:16:36 -0400
commit5fbcd260c2c52f78cd699f65e9c7af2e60b5380c (patch)
tree6decac9498b66653f7e327ae82903fa89366f486 /drivers
parente8c3c3d22b340a406a9aab1b7a9f436636c3de9d (diff)
[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 <oneukum@suse.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bluetooth/btusb.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index b4756a6a3a68..29ae99817c60 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -172,6 +172,7 @@ static struct usb_device_id blacklist_table[] = {
172struct btusb_data { 172struct btusb_data {
173 struct hci_dev *hdev; 173 struct hci_dev *hdev;
174 struct usb_device *udev; 174 struct usb_device *udev;
175 struct usb_interface *intf;
175 struct usb_interface *isoc; 176 struct usb_interface *isoc;
176 177
177 spinlock_t lock; 178 spinlock_t lock;
@@ -826,6 +827,7 @@ static int btusb_probe(struct usb_interface *intf,
826 } 827 }
827 828
828 data->udev = interface_to_usbdev(intf); 829 data->udev = interface_to_usbdev(intf);
830 data->intf = intf;
829 831
830 spin_lock_init(&data->lock); 832 spin_lock_init(&data->lock);
831 833
@@ -894,7 +896,7 @@ static int btusb_probe(struct usb_interface *intf,
894 896
895 if (data->isoc) { 897 if (data->isoc) {
896 err = usb_driver_claim_interface(&btusb_driver, 898 err = usb_driver_claim_interface(&btusb_driver,
897 data->isoc, NULL); 899 data->isoc, data);
898 if (err < 0) { 900 if (err < 0) {
899 hci_free_dev(hdev); 901 hci_free_dev(hdev);
900 kfree(data); 902 kfree(data);
@@ -926,13 +928,22 @@ static void btusb_disconnect(struct usb_interface *intf)
926 928
927 hdev = data->hdev; 929 hdev = data->hdev;
928 930
929 if (data->isoc) 931 __hci_dev_hold(hdev);
930 usb_driver_release_interface(&btusb_driver, data->isoc);
931 932
932 usb_set_intfdata(intf, NULL); 933 usb_set_intfdata(data->intf, NULL);
934
935 if (data->isoc)
936 usb_set_intfdata(data->isoc, NULL);
933 937
934 hci_unregister_dev(hdev); 938 hci_unregister_dev(hdev);
935 939
940 if (intf == data->isoc)
941 usb_driver_release_interface(&btusb_driver, data->intf);
942 else if (data->isoc)
943 usb_driver_release_interface(&btusb_driver, data->isoc);
944
945 __hci_dev_put(hdev);
946
936 hci_free_dev(hdev); 947 hci_free_dev(hdev);
937} 948}
938 949