diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 116 |
1 files changed, 67 insertions, 49 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index f73a27ea28cc..cd2e5cf14ea5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -374,6 +374,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8723DE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8821AE Bluetooth devices */ @@ -509,9 +510,10 @@ static inline void btusb_free_frags(struct btusb_data *data) static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count) { struct sk_buff *skb; + unsigned long flags; int err = 0; - spin_lock(&data->rxlock); + spin_lock_irqsave(&data->rxlock, flags); skb = data->evt_skb; while (count) { @@ -556,7 +558,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count) } data->evt_skb = skb; - spin_unlock(&data->rxlock); + spin_unlock_irqrestore(&data->rxlock, flags); return err; } @@ -564,9 +566,10 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count) static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) { struct sk_buff *skb; + unsigned long flags; int err = 0; - spin_lock(&data->rxlock); + spin_lock_irqsave(&data->rxlock, flags); skb = data->acl_skb; while (count) { @@ -613,7 +616,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) } data->acl_skb = skb; - spin_unlock(&data->rxlock); + spin_unlock_irqrestore(&data->rxlock, flags); return err; } @@ -621,9 +624,10 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) { struct sk_buff *skb; + unsigned long flags; int err = 0; - spin_lock(&data->rxlock); + spin_lock_irqsave(&data->rxlock, flags); skb = data->sco_skb; while (count) { @@ -668,7 +672,7 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) } data->sco_skb = skb; - spin_unlock(&data->rxlock); + spin_unlock_irqrestore(&data->rxlock, flags); return err; } @@ -1066,6 +1070,7 @@ static void btusb_tx_complete(struct urb *urb) struct sk_buff *skb = urb->context; struct hci_dev *hdev = (struct hci_dev *)skb->dev; struct btusb_data *data = hci_get_drvdata(hdev); + unsigned long flags; BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, urb->actual_length); @@ -1079,9 +1084,9 @@ static void btusb_tx_complete(struct urb *urb) hdev->stat.err_tx++; done: - spin_lock(&data->txlock); + spin_lock_irqsave(&data->txlock, flags); data->tx_in_flight--; - spin_unlock(&data->txlock); + spin_unlock_irqrestore(&data->txlock, flags); kfree(urb->setup_packet); @@ -1593,13 +1598,13 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, ret = request_firmware(&fw, fwname, &hdev->dev); if (ret < 0) { if (ret == -EINVAL) { - BT_ERR("%s Intel firmware file request failed (%d)", - hdev->name, ret); + bt_dev_err(hdev, "Intel firmware file request failed (%d)", + ret); return NULL; } - BT_ERR("%s failed to open Intel firmware file: %s(%d)", - hdev->name, fwname, ret); + bt_dev_err(hdev, "failed to open Intel firmware file: %s (%d)", + fwname, ret); /* If the correct firmware patch file is not found, use the * default firmware patch file instead @@ -1607,8 +1612,8 @@ static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", ver->hw_platform, ver->hw_variant); if (request_firmware(&fw, fwname, &hdev->dev) < 0) { - BT_ERR("%s failed to open default Intel fw file: %s", - hdev->name, fwname); + bt_dev_err(hdev, "failed to open default fw file: %s", + fwname); return NULL; } } @@ -1637,7 +1642,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, * process. */ if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { - BT_ERR("%s Intel fw corrupted: invalid cmd read", hdev->name); + bt_dev_err(hdev, "Intel fw corrupted: invalid cmd read"); return -EINVAL; } (*fw_ptr)++; @@ -1651,7 +1656,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, * of command parameter. If not, the firmware file is corrupted. */ if (remain < cmd->plen) { - BT_ERR("%s Intel fw corrupted: invalid cmd len", hdev->name); + bt_dev_err(hdev, "Intel fw corrupted: invalid cmd len"); return -EFAULT; } @@ -1684,8 +1689,7 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, remain -= sizeof(*evt); if (remain < evt->plen) { - BT_ERR("%s Intel fw corrupted: invalid evt len", - hdev->name); + bt_dev_err(hdev, "Intel fw corrupted: invalid evt len"); return -EFAULT; } @@ -1699,15 +1703,15 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, * file is corrupted. */ if (!evt || !evt_param || remain < 0) { - BT_ERR("%s Intel fw corrupted: invalid evt read", hdev->name); + bt_dev_err(hdev, "Intel fw corrupted: invalid evt read"); return -EFAULT; } skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, cmd_param, evt->evt, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { - BT_ERR("%s sending Intel patch command (0x%4.4x) failed (%ld)", - hdev->name, cmd->opcode, PTR_ERR(skb)); + bt_dev_err(hdev, "sending Intel patch command (0x%4.4x) failed (%ld)", + cmd->opcode, PTR_ERR(skb)); return PTR_ERR(skb); } @@ -1716,15 +1720,15 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, * the contents of the event. */ if (skb->len != evt->plen) { - BT_ERR("%s mismatch event length (opcode 0x%4.4x)", hdev->name, - le16_to_cpu(cmd->opcode)); + bt_dev_err(hdev, "mismatch event length (opcode 0x%4.4x)", + le16_to_cpu(cmd->opcode)); kfree_skb(skb); return -EFAULT; } if (memcmp(skb->data, evt_param, evt->plen)) { - BT_ERR("%s mismatch event parameter (opcode 0x%4.4x)", - hdev->name, le16_to_cpu(cmd->opcode)); + bt_dev_err(hdev, "mismatch event parameter (opcode 0x%4.4x)", + le16_to_cpu(cmd->opcode)); kfree_skb(skb); return -EFAULT; } @@ -1753,8 +1757,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) */ skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { - BT_ERR("%s sending initial HCI reset command failed (%ld)", - hdev->name, PTR_ERR(skb)); + bt_dev_err(hdev, "sending initial HCI reset command failed (%ld)", + PTR_ERR(skb)); return PTR_ERR(skb); } kfree_skb(skb); @@ -1890,7 +1894,7 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) struct hci_event_hdr *hdr; struct hci_ev_cmd_complete *evt; - skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_ATOMIC); + skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL); if (!skb) return -ENOMEM; @@ -2084,8 +2088,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * for now only accept this single value. */ if (ver.hw_platform != 0x37) { - BT_ERR("%s: Unsupported Intel hardware platform (%u)", - hdev->name, ver.hw_platform); + bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)", + ver.hw_platform); return -EINVAL; } @@ -2104,8 +2108,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) case 0x14: /* QnJ, IcP */ break; default: - BT_ERR("%s: Unsupported Intel hardware variant (%u)", - hdev->name, ver.hw_variant); + bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", + ver.hw_variant); return -EINVAL; } @@ -2134,8 +2138,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * choice is to return an error and abort the device initialization. */ if (ver.fw_variant != 0x06) { - BT_ERR("%s: Unsupported Intel firmware variant (%u)", - hdev->name, ver.fw_variant); + bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)", + ver.fw_variant); return -ENODEV; } @@ -2151,8 +2155,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * that this bootloader does not send them, then abort the setup. */ if (params.limited_cce != 0x00) { - BT_ERR("%s: Unsupported Intel firmware loading method (%u)", - hdev->name, params.limited_cce); + bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", + params.limited_cce); return -EINVAL; } @@ -2202,14 +2206,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) le16_to_cpu(ver.fw_revision)); break; default: - BT_ERR("%s: Unsupported Intel firmware naming", hdev->name); + bt_dev_err(hdev, "Unsupported Intel firmware naming"); return -EINVAL; } err = request_firmware(&fw, fwname, &hdev->dev); if (err < 0) { - BT_ERR("%s: Failed to load Intel firmware file (%d)", - hdev->name, err); + bt_dev_err(hdev, "Failed to load Intel firmware file (%d)", err); return err; } @@ -2235,13 +2238,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) le16_to_cpu(ver.fw_revision)); break; default: - BT_ERR("%s: Unsupported Intel firmware naming", hdev->name); + bt_dev_err(hdev, "Unsupported Intel firmware naming"); return -EINVAL; } if (fw->size < 644) { - BT_ERR("%s: Invalid size of firmware file (%zu)", - hdev->name, fw->size); + bt_dev_err(hdev, "Invalid size of firmware file (%zu)", + fw->size); err = -EBADF; goto done; } @@ -2272,18 +2275,18 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) TASK_INTERRUPTIBLE, msecs_to_jiffies(5000)); if (err == -EINTR) { - BT_ERR("%s: Firmware loading interrupted", hdev->name); + bt_dev_err(hdev, "Firmware loading interrupted"); goto done; } if (err) { - BT_ERR("%s: Firmware loading timeout", hdev->name); + bt_dev_err(hdev, "Firmware loading timeout"); err = -ETIMEDOUT; goto done; } if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) { - BT_ERR("%s: Firmware loading failed", hdev->name); + bt_dev_err(hdev, "Firmware loading failed"); err = -ENOEXEC; goto done; } @@ -2322,12 +2325,12 @@ done: msecs_to_jiffies(1000)); if (err == -EINTR) { - BT_ERR("%s: Device boot interrupted", hdev->name); + bt_dev_err(hdev, "Device boot interrupted"); return -EINTR; } if (err) { - BT_ERR("%s: Device boot timeout", hdev->name); + bt_dev_err(hdev, "Device boot timeout"); return -ETIMEDOUT; } @@ -2364,6 +2367,22 @@ static int btusb_shutdown_intel(struct hci_dev *hdev) struct sk_buff *skb; long ret; + /* In the shutdown sequence where Bluetooth is turned off followed + * by WiFi being turned off, turning WiFi back on causes issue with + * the RF calibration. + * + * To ensure that any RF activity has been stopped, issue HCI Reset + * command to clear all ongoing activity including advertising, + * scanning etc. + */ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); + bt_dev_err(hdev, "HCI reset during shutdown failed"); + return ret; + } + kfree_skb(skb); + /* Some platforms have an issue with BT LED when the interface is * down or BT radio is turned off, which takes 5 seconds to BT LED * goes off. This command turns off the BT LED immediately. @@ -2371,8 +2390,7 @@ static int btusb_shutdown_intel(struct hci_dev *hdev) skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { ret = PTR_ERR(skb); - BT_ERR("%s: turning off Intel device LED failed (%ld)", - hdev->name, ret); + bt_dev_err(hdev, "turning off Intel device LED failed"); return ret; } kfree_skb(skb); |