Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
[firefly-linux-kernel-4.4.55.git] / drivers / bluetooth / btusb.c
index b6aceaf82aa88c7617c4fd8e93506b8461314426..247b1062cb9affc67d9e7f7a0234c167f90f4b79 100644 (file)
@@ -940,9 +940,6 @@ static int btusb_open(struct hci_dev *hdev)
 
        data->intf->needs_remote_wakeup = 1;
 
-       if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
-               goto done;
-
        if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
                goto done;
 
@@ -965,7 +962,6 @@ done:
 
 failed:
        clear_bit(BTUSB_INTR_RUNNING, &data->flags);
-       clear_bit(HCI_RUNNING, &hdev->flags);
        usb_autopm_put_interface(data->intf);
        return err;
 }
@@ -984,9 +980,6 @@ static int btusb_close(struct hci_dev *hdev)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
-               return 0;
-
        cancel_work_sync(&data->work);
        cancel_work_sync(&data->waker);
 
@@ -1156,9 +1149,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 
        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);
@@ -1277,6 +1267,20 @@ static void btusb_work(struct work_struct *work)
                        clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
                        usb_kill_anchored_urbs(&data->isoc_anchor);
 
+                       /* When isochronous alternate setting needs to be
+                        * changed, because SCO connection has been added
+                        * or removed, a packet fragment may be left in the
+                        * reassembling state. This could lead to wrongly
+                        * assembled fragments.
+                        *
+                        * Clear outstanding fragment when selecting a new
+                        * alternate setting.
+                        */
+                       spin_lock(&data->rxlock);
+                       kfree_skb(data->sco_skb);
+                       data->sco_skb = NULL;
+                       spin_unlock(&data->rxlock);
+
                        if (__set_isoc_interface(hdev, new_alts) < 0)
                                return;
                }
@@ -1348,7 +1352,9 @@ static int btusb_setup_csr(struct hci_dev *hdev)
 
        rp = (struct hci_rp_read_local_version *)skb->data;
 
-       if (le16_to_cpu(rp->manufacturer) != 10) {
+       /* Detect controllers which aren't real CSR ones. */
+       if (le16_to_cpu(rp->manufacturer) != 10 ||
+           le16_to_cpu(rp->lmp_subver) == 0x0c5c) {
                /* Clear the reset quirk since this is not an actual
                 * early Bluetooth 1.1 device from CSR.
                 */
@@ -1827,9 +1833,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_bit(HCI_RUNNING, &hdev->flags))
-               return -EBUSY;
-
        switch (bt_cb(skb)->pkt_type) {
        case HCI_COMMAND_PKT:
                if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
@@ -2217,36 +2220,7 @@ done:
         * The device can work without DDC parameters, so even if it fails
         * to load the file, no need to fail the setup.
         */
-       err = request_firmware_direct(&fw, fwname, &hdev->dev);
-       if (err < 0)
-               return 0;
-
-       BT_INFO("%s: Found Intel DDC parameters: %s", hdev->name, fwname);
-
-       fw_ptr = fw->data;
-
-       /* DDC file contains one or more DDC structure which has
-        * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
-        */
-       while (fw->size > fw_ptr - fw->data) {
-               u8 cmd_plen = fw_ptr[0] + sizeof(u8);
-
-               skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
-                                    HCI_INIT_TIMEOUT);
-               if (IS_ERR(skb)) {
-                       BT_ERR("%s: Failed to send Intel_Write_DDC (%ld)",
-                              hdev->name, PTR_ERR(skb));
-                       release_firmware(fw);
-                       return PTR_ERR(skb);
-               }
-
-               fw_ptr += cmd_plen;
-               kfree_skb(skb);
-       }
-
-       release_firmware(fw);
-
-       BT_INFO("%s: Applying Intel DDC parameters completed", hdev->name);
+       btintel_load_ddc_config(hdev, fwname);
 
        return 0;
 }
@@ -2782,7 +2756,7 @@ static int btusb_probe(struct usb_interface *intf,
                        set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
 
                /* Fake CSR devices with broken commands */
-               if (bcdDevice <= 0x100)
+               if (bcdDevice <= 0x100 || bcdDevice == 0x134)
                        hdev->setup = btusb_setup_csr;
 
                set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);