Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / drivers / bluetooth / btusb.c
index 292c38e8aa1760c000cdcce9ee6d223e9f819559..edfc17bfcd44e02a8c8fb8748687cf265770863d 100644 (file)
@@ -165,6 +165,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
@@ -267,20 +268,24 @@ struct btusb_data {
        struct usb_interface *intf;
        struct usb_interface *isoc;
 
-       spinlock_t lock;
-
        unsigned long flags;
 
        struct work_struct work;
        struct work_struct waker;
 
+       struct usb_anchor deferred;
        struct usb_anchor tx_anchor;
+       int tx_in_flight;
+       spinlock_t txlock;
+
        struct usb_anchor intr_anchor;
        struct usb_anchor bulk_anchor;
        struct usb_anchor isoc_anchor;
-       struct usb_anchor deferred;
-       int tx_in_flight;
-       spinlock_t txlock;
+       spinlock_t rxlock;
+
+       struct sk_buff *evt_skb;
+       struct sk_buff *acl_skb;
+       struct sk_buff *sco_skb;
 
        struct usb_endpoint_descriptor *intr_ep;
        struct usb_endpoint_descriptor *bulk_tx_ep;
@@ -295,18 +300,189 @@ struct btusb_data {
        int suspend_count;
 };
 
-static int inc_tx(struct btusb_data *data)
+static inline void btusb_free_frags(struct btusb_data *data)
 {
        unsigned long flags;
-       int rv;
 
-       spin_lock_irqsave(&data->txlock, flags);
-       rv = test_bit(BTUSB_SUSPENDING, &data->flags);
-       if (!rv)
-               data->tx_in_flight++;
-       spin_unlock_irqrestore(&data->txlock, flags);
+       spin_lock_irqsave(&data->rxlock, flags);
+
+       kfree_skb(data->evt_skb);
+       data->evt_skb = NULL;
+
+       kfree_skb(data->acl_skb);
+       data->acl_skb = NULL;
+
+       kfree_skb(data->sco_skb);
+       data->sco_skb = NULL;
+
+       spin_unlock_irqrestore(&data->rxlock, flags);
+}
+
+static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
+{
+       struct sk_buff *skb;
+       int err = 0;
+
+       spin_lock(&data->rxlock);
+       skb = data->evt_skb;
+
+       while (count) {
+               int len;
+
+               if (!skb) {
+                       skb = bt_skb_alloc(HCI_MAX_EVENT_SIZE, GFP_ATOMIC);
+                       if (!skb) {
+                               err = -ENOMEM;
+                               break;
+                       }
+
+                       bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+                       bt_cb(skb)->expect = HCI_EVENT_HDR_SIZE;
+               }
+
+               len = min_t(uint, bt_cb(skb)->expect, count);
+               memcpy(skb_put(skb, len), buffer, len);
+
+               count -= len;
+               buffer += len;
+               bt_cb(skb)->expect -= len;
+
+               if (skb->len == HCI_EVENT_HDR_SIZE) {
+                       /* Complete event header */
+                       bt_cb(skb)->expect = hci_event_hdr(skb)->plen;
+
+                       if (skb_tailroom(skb) < bt_cb(skb)->expect) {
+                               kfree_skb(skb);
+                               skb = NULL;
+
+                               err = -EILSEQ;
+                               break;
+                       }
+               }
+
+               if (bt_cb(skb)->expect == 0) {
+                       /* Complete frame */
+                       hci_recv_frame(data->hdev, skb);
+                       skb = NULL;
+               }
+       }
+
+       data->evt_skb = skb;
+       spin_unlock(&data->rxlock);
 
-       return rv;
+       return err;
+}
+
+static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
+{
+       struct sk_buff *skb;
+       int err = 0;
+
+       spin_lock(&data->rxlock);
+       skb = data->acl_skb;
+
+       while (count) {
+               int len;
+
+               if (!skb) {
+                       skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
+                       if (!skb) {
+                               err = -ENOMEM;
+                               break;
+                       }
+
+                       bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+                       bt_cb(skb)->expect = HCI_ACL_HDR_SIZE;
+               }
+
+               len = min_t(uint, bt_cb(skb)->expect, count);
+               memcpy(skb_put(skb, len), buffer, len);
+
+               count -= len;
+               buffer += len;
+               bt_cb(skb)->expect -= len;
+
+               if (skb->len == HCI_ACL_HDR_SIZE) {
+                       __le16 dlen = hci_acl_hdr(skb)->dlen;
+
+                       /* Complete ACL header */
+                       bt_cb(skb)->expect = __le16_to_cpu(dlen);
+
+                       if (skb_tailroom(skb) < bt_cb(skb)->expect) {
+                               kfree_skb(skb);
+                               skb = NULL;
+
+                               err = -EILSEQ;
+                               break;
+                       }
+               }
+
+               if (bt_cb(skb)->expect == 0) {
+                       /* Complete frame */
+                       hci_recv_frame(data->hdev, skb);
+                       skb = NULL;
+               }
+       }
+
+       data->acl_skb = skb;
+       spin_unlock(&data->rxlock);
+
+       return err;
+}
+
+static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
+{
+       struct sk_buff *skb;
+       int err = 0;
+
+       spin_lock(&data->rxlock);
+       skb = data->sco_skb;
+
+       while (count) {
+               int len;
+
+               if (!skb) {
+                       skb = bt_skb_alloc(HCI_MAX_SCO_SIZE, GFP_ATOMIC);
+                       if (!skb) {
+                               err = -ENOMEM;
+                               break;
+                       }
+
+                       bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
+                       bt_cb(skb)->expect = HCI_SCO_HDR_SIZE;
+               }
+
+               len = min_t(uint, bt_cb(skb)->expect, count);
+               memcpy(skb_put(skb, len), buffer, len);
+
+               count -= len;
+               buffer += len;
+               bt_cb(skb)->expect -= len;
+
+               if (skb->len == HCI_SCO_HDR_SIZE) {
+                       /* Complete SCO header */
+                       bt_cb(skb)->expect = hci_sco_hdr(skb)->dlen;
+
+                       if (skb_tailroom(skb) < bt_cb(skb)->expect) {
+                               kfree_skb(skb);
+                               skb = NULL;
+
+                               err = -EILSEQ;
+                               break;
+                       }
+               }
+
+               if (bt_cb(skb)->expect == 0) {
+                       /* Complete frame */
+                       hci_recv_frame(data->hdev, skb);
+                       skb = NULL;
+               }
+       }
+
+       data->sco_skb = skb;
+       spin_unlock(&data->rxlock);
+
+       return err;
 }
 
 static void btusb_intr_complete(struct urb *urb)
@@ -315,8 +491,8 @@ static void btusb_intr_complete(struct urb *urb)
        struct btusb_data *data = hci_get_drvdata(hdev);
        int err;
 
-       BT_DBG("%s urb %p status %d count %d", hdev->name,
-                                       urb, urb->status, urb->actual_length);
+       BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+              urb->actual_length);
 
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                return;
@@ -324,12 +500,14 @@ static void btusb_intr_complete(struct urb *urb)
        if (urb->status == 0) {
                hdev->stat.byte_rx += urb->actual_length;
 
-               if (hci_recv_fragment(hdev, HCI_EVENT_PKT,
-                                               urb->transfer_buffer,
-                                               urb->actual_length) < 0) {
+               if (btusb_recv_intr(data, urb->transfer_buffer,
+                                   urb->actual_length) < 0) {
                        BT_ERR("%s corrupted event packet", hdev->name);
                        hdev->stat.err_rx++;
                }
+       } else if (urb->status == -ENOENT) {
+               /* Avoid suspend failed when usb_kill_urb */
+               return;
        }
 
        if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
@@ -344,7 +522,7 @@ static void btusb_intr_complete(struct urb *urb)
                 * -ENODEV: device got disconnected */
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
 }
@@ -377,8 +555,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
        pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
 
        usb_fill_int_urb(urb, data->udev, pipe, buf, size,
-                                               btusb_intr_complete, hdev,
-                                               data->intr_ep->bInterval);
+                        btusb_intr_complete, hdev, data->intr_ep->bInterval);
 
        urb->transfer_flags |= URB_FREE_BUFFER;
 
@@ -388,7 +565,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
        if (err < 0) {
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p submission failed (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
 
@@ -403,8 +580,8 @@ static void btusb_bulk_complete(struct urb *urb)
        struct btusb_data *data = hci_get_drvdata(hdev);
        int err;
 
-       BT_DBG("%s urb %p status %d count %d", hdev->name,
-                                       urb, urb->status, urb->actual_length);
+       BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+              urb->actual_length);
 
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                return;
@@ -412,12 +589,14 @@ static void btusb_bulk_complete(struct urb *urb)
        if (urb->status == 0) {
                hdev->stat.byte_rx += urb->actual_length;
 
-               if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT,
-                                               urb->transfer_buffer,
-                                               urb->actual_length) < 0) {
+               if (btusb_recv_bulk(data, urb->transfer_buffer,
+                                   urb->actual_length) < 0) {
                        BT_ERR("%s corrupted ACL packet", hdev->name);
                        hdev->stat.err_rx++;
                }
+       } else if (urb->status == -ENOENT) {
+               /* Avoid suspend failed when usb_kill_urb */
+               return;
        }
 
        if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
@@ -432,7 +611,7 @@ static void btusb_bulk_complete(struct urb *urb)
                 * -ENODEV: device got disconnected */
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
 }
@@ -462,8 +641,8 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
 
        pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
 
-       usb_fill_bulk_urb(urb, data->udev, pipe,
-                                       buf, size, btusb_bulk_complete, hdev);
+       usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
+                         btusb_bulk_complete, hdev);
 
        urb->transfer_flags |= URB_FREE_BUFFER;
 
@@ -474,7 +653,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
        if (err < 0) {
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p submission failed (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
 
@@ -489,8 +668,8 @@ static void btusb_isoc_complete(struct urb *urb)
        struct btusb_data *data = hci_get_drvdata(hdev);
        int i, err;
 
-       BT_DBG("%s urb %p status %d count %d", hdev->name,
-                                       urb, urb->status, urb->actual_length);
+       BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+              urb->actual_length);
 
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                return;
@@ -505,13 +684,15 @@ static void btusb_isoc_complete(struct urb *urb)
 
                        hdev->stat.byte_rx += length;
 
-                       if (hci_recv_fragment(hdev, HCI_SCODATA_PKT,
-                                               urb->transfer_buffer + offset,
-                                                               length) < 0) {
+                       if (btusb_recv_isoc(data, urb->transfer_buffer + offset,
+                                           length) < 0) {
                                BT_ERR("%s corrupted SCO packet", hdev->name);
                                hdev->stat.err_rx++;
                        }
                }
+       } else if (urb->status == -ENOENT) {
+               /* Avoid suspend failed when usb_kill_urb */
+               return;
        }
 
        if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
@@ -525,7 +706,7 @@ static void btusb_isoc_complete(struct urb *urb)
                 * -ENODEV: device got disconnected */
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p failed to resubmit (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
 }
@@ -580,12 +761,12 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
        pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
 
        usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
-                               hdev, data->isoc_rx_ep->bInterval);
+                        hdev, data->isoc_rx_ep->bInterval);
 
-       urb->transfer_flags  = URB_FREE_BUFFER | URB_ISO_ASAP;
+       urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
 
        __fill_isoc_descriptor(urb, size,
-                       le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
+                              le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
 
        usb_anchor_urb(urb, &data->isoc_anchor);
 
@@ -593,7 +774,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
        if (err < 0) {
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p submission failed (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                usb_unanchor_urb(urb);
        }
 
@@ -605,11 +786,11 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
 static void btusb_tx_complete(struct urb *urb)
 {
        struct sk_buff *skb = urb->context;
-       struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+       struct hci_dev *hdev = (struct hci_dev *)skb->dev;
        struct btusb_data *data = hci_get_drvdata(hdev);
 
-       BT_DBG("%s urb %p status %d count %d", hdev->name,
-                                       urb, urb->status, urb->actual_length);
+       BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+              urb->actual_length);
 
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                goto done;
@@ -632,10 +813,10 @@ done:
 static void btusb_isoc_tx_complete(struct urb *urb)
 {
        struct sk_buff *skb = urb->context;
-       struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+       struct hci_dev *hdev = (struct hci_dev *)skb->dev;
 
-       BT_DBG("%s urb %p status %d count %d", hdev->name,
-                                       urb, urb->status, urb->actual_length);
+       BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
+              urb->actual_length);
 
        if (!test_bit(HCI_RUNNING, &hdev->flags))
                goto done;
@@ -719,6 +900,8 @@ static int btusb_close(struct hci_dev *hdev)
        clear_bit(BTUSB_INTR_RUNNING, &data->flags);
 
        btusb_stop_traffic(data);
+       btusb_free_frags(data);
+
        err = usb_autopm_get_interface(data->intf);
        if (err < 0)
                goto failed;
@@ -738,122 +921,181 @@ static int btusb_flush(struct hci_dev *hdev)
        BT_DBG("%s", hdev->name);
 
        usb_kill_anchored_urbs(&data->tx_anchor);
+       btusb_free_frags(data);
 
        return 0;
 }
 
-static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct btusb_data *data = hci_get_drvdata(hdev);
        struct usb_ctrlrequest *dr;
        struct urb *urb;
        unsigned int pipe;
-       int err;
 
-       BT_DBG("%s", hdev->name);
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb)
+               return ERR_PTR(-ENOMEM);
 
-       if (!test_bit(HCI_RUNNING, &hdev->flags))
-               return -EBUSY;
+       dr = kmalloc(sizeof(*dr), GFP_KERNEL);
+       if (!dr) {
+               usb_free_urb(urb);
+               return ERR_PTR(-ENOMEM);
+       }
 
-       skb->dev = (void *) hdev;
+       dr->bRequestType = data->cmdreq_type;
+       dr->bRequest     = 0;
+       dr->wIndex       = 0;
+       dr->wValue       = 0;
+       dr->wLength      = __cpu_to_le16(skb->len);
 
-       switch (bt_cb(skb)->pkt_type) {
-       case HCI_COMMAND_PKT:
-               urb = usb_alloc_urb(0, GFP_ATOMIC);
-               if (!urb)
-                       return -ENOMEM;
-
-               dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
-               if (!dr) {
-                       usb_free_urb(urb);
-                       return -ENOMEM;
-               }
+       pipe = usb_sndctrlpipe(data->udev, 0x00);
 
-               dr->bRequestType = data->cmdreq_type;
-               dr->bRequest     = 0;
-               dr->wIndex       = 0;
-               dr->wValue       = 0;
-               dr->wLength      = __cpu_to_le16(skb->len);
+       usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
+                            skb->data, skb->len, btusb_tx_complete, skb);
 
-               pipe = usb_sndctrlpipe(data->udev, 0x00);
+       skb->dev = (void *)hdev;
 
-               usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
-                               skb->data, skb->len, btusb_tx_complete, skb);
+       return urb;
+}
 
-               hdev->stat.cmd_tx++;
-               break;
+static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct urb *urb;
+       unsigned int pipe;
 
-       case HCI_ACLDATA_PKT:
-               if (!data->bulk_tx_ep)
-                       return -ENODEV;
+       if (!data->bulk_tx_ep)
+               return ERR_PTR(-ENODEV);
+
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb)
+               return ERR_PTR(-ENOMEM);
 
-               urb = usb_alloc_urb(0, GFP_ATOMIC);
-               if (!urb)
-                       return -ENOMEM;
+       pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
 
-               pipe = usb_sndbulkpipe(data->udev,
-                                       data->bulk_tx_ep->bEndpointAddress);
+       usb_fill_bulk_urb(urb, data->udev, pipe,
+                         skb->data, skb->len, btusb_tx_complete, skb);
 
-               usb_fill_bulk_urb(urb, data->udev, pipe,
-                               skb->data, skb->len, btusb_tx_complete, skb);
+       skb->dev = (void *)hdev;
 
-               hdev->stat.acl_tx++;
-               break;
+       return urb;
+}
 
-       case HCI_SCODATA_PKT:
-               if (!data->isoc_tx_ep || hci_conn_num(hdev, SCO_LINK) < 1)
-                       return -ENODEV;
+static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct urb *urb;
+       unsigned int pipe;
 
-               urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC);
-               if (!urb)
-                       return -ENOMEM;
+       if (!data->isoc_tx_ep)
+               return ERR_PTR(-ENODEV);
 
-               pipe = usb_sndisocpipe(data->udev,
-                                       data->isoc_tx_ep->bEndpointAddress);
+       urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
+       if (!urb)
+               return ERR_PTR(-ENOMEM);
 
-               usb_fill_int_urb(urb, data->udev, pipe,
-                               skb->data, skb->len, btusb_isoc_tx_complete,
-                               skb, data->isoc_tx_ep->bInterval);
+       pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
 
-               urb->transfer_flags  = URB_ISO_ASAP;
+       usb_fill_int_urb(urb, data->udev, pipe,
+                        skb->data, skb->len, btusb_isoc_tx_complete,
+                        skb, data->isoc_tx_ep->bInterval);
 
-               __fill_isoc_descriptor(urb, skb->len,
-                               le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
+       urb->transfer_flags  = URB_ISO_ASAP;
 
-               hdev->stat.sco_tx++;
-               goto skip_waking;
+       __fill_isoc_descriptor(urb, skb->len,
+                              le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
 
-       default:
-               return -EILSEQ;
-       }
+       skb->dev = (void *)hdev;
 
-       err = inc_tx(data);
-       if (err) {
-               usb_anchor_urb(urb, &data->deferred);
-               schedule_work(&data->waker);
-               err = 0;
-               goto done;
-       }
+       return urb;
+}
+
+static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       int err;
 
-skip_waking:
        usb_anchor_urb(urb, &data->tx_anchor);
 
-       err = usb_submit_urb(urb, GFP_ATOMIC);
+       err = usb_submit_urb(urb, GFP_KERNEL);
        if (err < 0) {
                if (err != -EPERM && err != -ENODEV)
                        BT_ERR("%s urb %p submission failed (%d)",
-                                               hdev->name, urb, -err);
+                              hdev->name, urb, -err);
                kfree(urb->setup_packet);
                usb_unanchor_urb(urb);
        } else {
                usb_mark_last_busy(data->udev);
        }
 
-done:
        usb_free_urb(urb);
        return err;
 }
 
+static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
+{
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       unsigned long flags;
+       bool suspending;
+
+       spin_lock_irqsave(&data->txlock, flags);
+       suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
+       if (!suspending)
+               data->tx_in_flight++;
+       spin_unlock_irqrestore(&data->txlock, flags);
+
+       if (!suspending)
+               return submit_tx_urb(hdev, urb);
+
+       usb_anchor_urb(urb, &data->deferred);
+       schedule_work(&data->waker);
+
+       usb_free_urb(urb);
+       return 0;
+}
+
+static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct urb *urb;
+
+       BT_DBG("%s", hdev->name);
+
+       if (!test_bit(HCI_RUNNING, &hdev->flags))
+               return -EBUSY;
+
+       switch (bt_cb(skb)->pkt_type) {
+       case HCI_COMMAND_PKT:
+               urb = alloc_ctrl_urb(hdev, skb);
+               if (IS_ERR(urb))
+                       return PTR_ERR(urb);
+
+               hdev->stat.cmd_tx++;
+               return submit_or_queue_tx_urb(hdev, urb);
+
+       case HCI_ACLDATA_PKT:
+               urb = alloc_bulk_urb(hdev, skb);
+               if (IS_ERR(urb))
+                       return PTR_ERR(urb);
+
+               hdev->stat.acl_tx++;
+               return submit_or_queue_tx_urb(hdev, urb);
+
+       case HCI_SCODATA_PKT:
+               if (hci_conn_num(hdev, SCO_LINK) < 1)
+                       return -ENODEV;
+
+               urb = alloc_isoc_urb(hdev, skb);
+               if (IS_ERR(urb))
+                       return PTR_ERR(urb);
+
+               hdev->stat.sco_tx++;
+               return submit_tx_urb(hdev, urb);
+       }
+
+       return -EILSEQ;
+}
+
 static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
 {
        struct btusb_data *data = hci_get_drvdata(hdev);
@@ -930,6 +1172,7 @@ static void btusb_work(struct work_struct *work)
 
                if (hdev->voice_setting & 0x0020) {
                        static const int alts[3] = { 2, 4, 5 };
+
                        new_alts = alts[data->sco_num - 1];
                } else {
                        new_alts = data->sco_num;
@@ -1002,7 +1245,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
                return -PTR_ERR(skb);
        }
 
-       rp = (struct hci_rp_read_local_version *) skb->data;
+       rp = (struct hci_rp_read_local_version *)skb->data;
 
        if (!rp->status) {
                if (le16_to_cpu(rp->manufacturer) != 10) {
@@ -1040,7 +1283,7 @@ struct intel_version {
 } __packed;
 
 static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
-                                               struct intel_version *ver)
+                                                      struct intel_version *ver)
 {
        const struct firmware *fw;
        char fwname[64];
@@ -1216,7 +1459,7 @@ static int btusb_check_bdaddr_intel(struct hci_dev *hdev)
                return -EIO;
        }
 
-       rp = (struct hci_rp_read_bd_addr *) skb->data;
+       rp = (struct hci_rp_read_bd_addr *)skb->data;
        if (rp->status) {
                BT_ERR("%s Intel device address result failed (%02x)",
                       hdev->name, rp->status);
@@ -1346,6 +1589,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
 
        if (skb->data[0]) {
                u8 evt_status = skb->data[0];
+
                BT_ERR("%s enable Intel manufacturer mode event failed (%02x)",
                       hdev->name, evt_status);
                kfree_skb(skb);
@@ -1455,7 +1699,7 @@ static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
        if (IS_ERR(skb)) {
                ret = PTR_ERR(skb);
                BT_ERR("%s: changing Intel device address failed (%ld)",
-                       hdev->name, ret);
+                      hdev->name, ret);
                return ret;
        }
        kfree_skb(skb);
@@ -1530,19 +1774,19 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
        if (IS_ERR(skb)) {
                ret = PTR_ERR(skb);
                BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
-                       hdev->name, ret);
+                      hdev->name, ret);
                goto done;
        }
 
        if (skb->len != sizeof(*ver)) {
                BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
-                       hdev->name);
+                      hdev->name);
                kfree_skb(skb);
                ret = -EIO;
                goto done;
        }
 
-       ver = (struct hci_rp_read_local_version *) skb->data;
+       ver = (struct hci_rp_read_local_version *)skb->data;
        BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
                "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
                ver->lmp_ver, ver->lmp_subver);
@@ -1553,7 +1797,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
        if (IS_ERR(skb)) {
                ret = PTR_ERR(skb);
                BT_ERR("%s: BCM: Download Minidrv command failed (%ld)",
-                       hdev->name, ret);
+                      hdev->name, ret);
                goto reset_fw;
        }
        kfree_skb(skb);
@@ -1565,13 +1809,13 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
        fw_size = fw->size;
 
        while (fw_size >= sizeof(*cmd)) {
-               cmd = (struct hci_command_hdr *) fw_ptr;
+               cmd = (struct hci_command_hdr *)fw_ptr;
                fw_ptr += sizeof(*cmd);
                fw_size -= sizeof(*cmd);
 
                if (fw_size < cmd->plen) {
                        BT_ERR("%s: BCM: patch %s is corrupted",
-                               hdev->name, fw_name);
+                              hdev->name, fw_name);
                        ret = -EINVAL;
                        goto reset_fw;
                }
@@ -1587,7 +1831,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
                if (IS_ERR(skb)) {
                        ret = PTR_ERR(skb);
                        BT_ERR("%s: BCM: patch command %04x failed (%ld)",
-                               hdev->name, opcode, ret);
+                              hdev->name, opcode, ret);
                        goto reset_fw;
                }
                kfree_skb(skb);
@@ -1612,19 +1856,19 @@ reset_fw:
        if (IS_ERR(skb)) {
                ret = PTR_ERR(skb);
                BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
-                       hdev->name, ret);
+                      hdev->name, ret);
                goto done;
        }
 
        if (skb->len != sizeof(*ver)) {
                BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
-                       hdev->name);
+                      hdev->name);
                kfree_skb(skb);
                ret = -EIO;
                goto done;
        }
 
-       ver = (struct hci_rp_read_local_version *) skb->data;
+       ver = (struct hci_rp_read_local_version *)skb->data;
        BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
                "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
                ver->lmp_ver, ver->lmp_subver);
@@ -1636,19 +1880,19 @@ reset_fw:
        if (IS_ERR(skb)) {
                ret = PTR_ERR(skb);
                BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)",
-                       hdev->name, ret);
+                      hdev->name, ret);
                goto done;
        }
 
        if (skb->len != sizeof(*bda)) {
                BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch",
-                       hdev->name);
+                      hdev->name);
                kfree_skb(skb);
                ret = -EIO;
                goto done;
        }
 
-       bda = (struct hci_rp_read_bd_addr *) skb->data;
+       bda = (struct hci_rp_read_bd_addr *)skb->data;
        if (bda->status) {
                BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)",
                       hdev->name, bda->status);
@@ -1683,7 +1927,7 @@ static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr)
        if (IS_ERR(skb)) {
                ret = PTR_ERR(skb);
                BT_ERR("%s: BCM: Change address command failed (%ld)",
-                       hdev->name, ret);
+                      hdev->name, ret);
                return ret;
        }
        kfree_skb(skb);
@@ -1692,7 +1936,7 @@ static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr)
 }
 
 static int btusb_probe(struct usb_interface *intf,
-                               const struct usb_device_id *id)
+                      const struct usb_device_id *id)
 {
        struct usb_endpoint_descriptor *ep_desc;
        struct btusb_data *data;
@@ -1707,6 +1951,7 @@ static int btusb_probe(struct usb_interface *intf,
 
        if (!id->driver_info) {
                const struct usb_device_id *match;
+
                match = usb_match_id(intf, blacklist_table);
                if (match)
                        id = match;
@@ -1755,17 +2000,16 @@ static int btusb_probe(struct usb_interface *intf,
        data->udev = interface_to_usbdev(intf);
        data->intf = intf;
 
-       spin_lock_init(&data->lock);
-
        INIT_WORK(&data->work, btusb_work);
        INIT_WORK(&data->waker, btusb_waker);
+       init_usb_anchor(&data->deferred);
+       init_usb_anchor(&data->tx_anchor);
        spin_lock_init(&data->txlock);
 
-       init_usb_anchor(&data->tx_anchor);
        init_usb_anchor(&data->intr_anchor);
        init_usb_anchor(&data->bulk_anchor);
        init_usb_anchor(&data->isoc_anchor);
-       init_usb_anchor(&data->deferred);
+       spin_lock_init(&data->rxlock);
 
        hdev = hci_alloc_dev();
        if (!hdev)
@@ -1857,7 +2101,7 @@ static int btusb_probe(struct usb_interface *intf,
 
        if (data->isoc) {
                err = usb_driver_claim_interface(&btusb_driver,
-                                                       data->isoc, data);
+                                                data->isoc, data);
                if (err < 0) {
                        hci_free_dev(hdev);
                        return err;
@@ -1898,6 +2142,7 @@ static void btusb_disconnect(struct usb_interface *intf)
        else if (data->isoc)
                usb_driver_release_interface(&btusb_driver, data->isoc);
 
+       btusb_free_frags(data);
        hci_free_dev(hdev);
 }