diff options
author | David S. Miller <davem@davemloft.net> | 2020-08-01 00:11:52 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-08-01 00:11:52 +0200 |
commit | 4bb540dbe442ec5e4b48af8aed12663e0754bbe2 (patch) | |
tree | a641506cb5aac389bb3c9f2d6042ce53cfb6732c /drivers/bluetooth | |
parent | net: ll_temac: Use devm_platform_ioremap_resource_byname() (diff) | |
parent | Bluetooth: Remove CRYPTO_ALG_INTERNAL flag (diff) | |
download | linux-4bb540dbe442ec5e4b48af8aed12663e0754bbe2.tar.xz linux-4bb540dbe442ec5e4b48af8aed12663e0754bbe2.zip |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says:
====================
pull request: bluetooth-next 2020-07-31
Here's the main bluetooth-next pull request for 5.9:
- Fix firmware filenames for Marvell chipsets
- Several suspend-related fixes
- Addedd mgmt commands for runtime configuration
- Multiple fixes for Qualcomm-based controllers
- Add new monitoring feature for mgmt
- Fix handling of legacy cipher (E4) together with security level 4
- Add support for Realtek 8822CE controller
- Fix issues with Chinese controllers using fake VID/PID values
- Multiple other smaller fixes & improvements
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/bcm203x.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/bluecard_cs.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.c | 59 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.h | 21 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 11 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 21 | ||||
-rw-r--r-- | drivers/bluetooth/btmtksdio.c | 16 | ||||
-rw-r--r-- | drivers/bluetooth/btqca.c | 27 | ||||
-rw-r--r-- | drivers/bluetooth/btqca.h | 2 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 303 | ||||
-rw-r--r-- | drivers/bluetooth/hci_h5.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_ll.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 134 | ||||
-rw-r--r-- | drivers/bluetooth/hci_serdev.c | 3 |
14 files changed, 448 insertions, 157 deletions
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 3b176257b993..e667933c3d70 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -106,7 +106,7 @@ static void bcm203x_complete(struct urb *urb) } data->state = BCM203X_LOAD_FIRMWARE; - /* fall through */ + fallthrough; case BCM203X_LOAD_FIRMWARE: if (data->fw_sent == data->fw_size) { usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index cc6e56223656..36eabf61717f 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -295,7 +295,6 @@ static void bluecard_write_wakeup(struct bluecard_info *info) baud_reg = REG_CONTROL_BAUD_RATE_115200; break; case PKT_BAUD_RATE_57600: - /* Fall through... */ default: baud_reg = REG_CONTROL_BAUD_RATE_57600; break; @@ -585,7 +584,6 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) hci_skb_pkt_type(skb) = PKT_BAUD_RATE_115200; break; case 57600: - /* Fall through... */ default: cmd[4] = 0x03; hci_skb_pkt_type(skb) = PKT_BAUD_RATE_57600; diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 6a0e2c5a8beb..5fa5be3c5598 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -754,6 +754,65 @@ void btintel_reset_to_bootloader(struct hci_dev *hdev) } EXPORT_SYMBOL_GPL(btintel_reset_to_bootloader); +int btintel_read_debug_features(struct hci_dev *hdev, + struct intel_debug_features *features) +{ + struct sk_buff *skb; + u8 page_no = 1; + + /* Intel controller supports two pages, each page is of 128-bit + * feature bit mask. And each bit defines specific feature support + */ + skb = __hci_cmd_sync(hdev, 0xfca6, sizeof(page_no), &page_no, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reading supported features failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + + if (skb->len != (sizeof(features->page1) + 3)) { + bt_dev_err(hdev, "Supported features event size mismatch"); + kfree_skb(skb); + return -EILSEQ; + } + + memcpy(features->page1, skb->data + 3, sizeof(features->page1)); + + /* Read the supported features page2 if required in future. + */ + kfree_skb(skb); + return 0; +} +EXPORT_SYMBOL_GPL(btintel_read_debug_features); + +int btintel_set_debug_features(struct hci_dev *hdev, + const struct intel_debug_features *features) +{ + u8 mask[11] = { 0x0a, 0x92, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; + struct sk_buff *skb; + + if (!features) + return -EINVAL; + + if (!(features->page1[0] & 0x3f)) { + bt_dev_info(hdev, "Telemetry exception format not supported"); + return 0; + } + + skb = __hci_cmd_sync(hdev, 0xfc8b, 11, mask, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Setting Intel telemetry ddc write event mask failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + + kfree_skb(skb); + return 0; +} +EXPORT_SYMBOL_GPL(btintel_set_debug_features); + MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index a69ea8a87b9b..08e20606fb58 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -62,6 +62,10 @@ struct intel_reset { __le32 boot_param; } __packed; +struct intel_debug_features { + __u8 page1[16]; +} __packed; + #if IS_ENABLED(CONFIG_BT_INTEL) int btintel_check_bdaddr(struct hci_dev *hdev); @@ -88,6 +92,10 @@ int btintel_read_boot_params(struct hci_dev *hdev, int btintel_download_firmware(struct hci_dev *dev, const struct firmware *fw, u32 *boot_param); void btintel_reset_to_bootloader(struct hci_dev *hdev); +int btintel_read_debug_features(struct hci_dev *hdev, + struct intel_debug_features *features); +int btintel_set_debug_features(struct hci_dev *hdev, + const struct intel_debug_features *features); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -186,4 +194,17 @@ static inline int btintel_download_firmware(struct hci_dev *dev, static inline void btintel_reset_to_bootloader(struct hci_dev *hdev) { } + +static inline int btintel_read_debug_features(struct hci_dev *hdev, + struct intel_debug_features *features) +{ + return -EOPNOTSUPP; +} + +static inline int btintel_set_debug_features(struct hci_dev *hdev, + const struct intel_debug_features *features) +{ + return -EOPNOTSUPP; +} + #endif diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 708ad21683eb..8b9d78ce6bb2 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -587,6 +587,14 @@ static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) return 0; } +static bool btmrvl_prevent_wake(struct hci_dev *hdev) +{ + struct btmrvl_private *priv = hci_get_drvdata(hdev); + struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; + + return !device_may_wakeup(&card->func->dev); +} + /* * This function handles the event generated by firmware, rx data * received from firmware, and tx data sent from kernel. @@ -669,6 +677,7 @@ static int btmrvl_service_main_thread(void *data) int btmrvl_register_hdev(struct btmrvl_private *priv) { struct hci_dev *hdev = NULL; + struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; int ret; hdev = hci_alloc_dev(); @@ -687,6 +696,8 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) hdev->send = btmrvl_send_frame; hdev->setup = btmrvl_setup; hdev->set_bdaddr = btmrvl_set_bdaddr; + hdev->prevent_wake = btmrvl_prevent_wake; + SET_HCIDEV_DEV(hdev, &card->func->dev); hdev->dev_type = priv->btmrvl_dev.dev_type; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index a296f8526433..d15fd5be0216 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -111,6 +111,9 @@ static int btmrvl_sdio_probe_of(struct device *dev, "Failed to request irq_bt %d (%d)\n", cfg->irq_bt, ret); } + + /* Configure wakeup (enabled by default) */ + device_init_wakeup(dev, true); disable_irq(cfg->irq_bt); } } @@ -328,7 +331,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = { .helper = NULL, - .firmware = "mrvl/sd8977_uapsta.bin", + .firmware = "mrvl/sdsd8977_combo_v2.bin", .reg = &btmrvl_reg_8977, .support_pscan_win_report = true, .sd_blksz_fw_dl = 256, @@ -346,7 +349,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8987 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = { .helper = NULL, - .firmware = "mrvl/sd8997_uapsta.bin", + .firmware = "mrvl/sdsd8997_combo_v4.bin", .reg = &btmrvl_reg_8997, .support_pscan_win_report = true, .sd_blksz_fw_dl = 256, @@ -1654,6 +1657,7 @@ static void btmrvl_sdio_remove(struct sdio_func *func) MODULE_SHUTDOWN_REQ); btmrvl_sdio_disable_host_int(card); } + BT_DBG("unregister dev"); card->priv->surprise_removed = true; btmrvl_sdio_unregister_dev(card); @@ -1690,7 +1694,8 @@ static int btmrvl_sdio_suspend(struct device *dev) } /* Enable platform specific wakeup interrupt */ - if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) { + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 && + device_may_wakeup(dev)) { card->plt_wake_cfg->wake_by_bt = false; enable_irq(card->plt_wake_cfg->irq_bt); enable_irq_wake(card->plt_wake_cfg->irq_bt); @@ -1707,7 +1712,8 @@ static int btmrvl_sdio_suspend(struct device *dev) BT_ERR("HS not activated, suspend failed!"); /* Disable platform specific wakeup interrupt */ if (card->plt_wake_cfg && - card->plt_wake_cfg->irq_bt >= 0) { + card->plt_wake_cfg->irq_bt >= 0 && + device_may_wakeup(dev)) { disable_irq_wake(card->plt_wake_cfg->irq_bt); disable_irq(card->plt_wake_cfg->irq_bt); } @@ -1767,7 +1773,8 @@ static int btmrvl_sdio_resume(struct device *dev) hci_resume_dev(hcidev); /* Disable platform specific wakeup interrupt */ - if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) { + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 && + device_may_wakeup(dev)) { disable_irq_wake(card->plt_wake_cfg->irq_bt); disable_irq(card->plt_wake_cfg->irq_bt); if (card->plt_wake_cfg->wake_by_bt) @@ -1831,6 +1838,6 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); -MODULE_FIRMWARE("mrvl/sd8977_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sdsd8977_combo_v2.bin"); MODULE_FIRMWARE("mrvl/sd8987_uapsta.bin"); -MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sdsd8997_combo_v4.bin"); diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index bff095be2f97..c7ab7a23bd67 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -685,7 +685,7 @@ static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) const u8 *fw_ptr; size_t fw_size; int err, dlen; - u8 flag; + u8 flag, param; err = request_firmware(&fw, fwname, &hdev->dev); if (err < 0) { @@ -693,6 +693,20 @@ static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) return err; } + /* Power on data RAM the firmware relies on. */ + param = 1; + wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.flag = 3; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to power on data RAM (%d)", err); + return err; + } + fw_ptr = fw->data; fw_size = fw->size; diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index c5984966f315..ce9dcffdc5bf 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -400,6 +400,27 @@ out: return ret; } +static int qca_disable_soc_logging(struct hci_dev *hdev) +{ + struct sk_buff *skb; + u8 cmd[2]; + int err; + + cmd[0] = QCA_DISABLE_LOGGING_SUB_OP; + cmd[1] = 0x00; + skb = __hci_cmd_sync_ev(hdev, QCA_DISABLE_LOGGING, sizeof(cmd), cmd, + HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "QCA Failed to disable soc logging(%d)", err); + return err; + } + + kfree_skb(skb); + + return 0; +} + int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) { struct sk_buff *skb; @@ -486,6 +507,12 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, return err; } + if (soc_type >= QCA_WCN3991) { + err = qca_disable_soc_logging(hdev); + if (err < 0) + return err; + } + /* Perform HCI reset */ err = qca_send_reset(hdev); if (err < 0) { diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 6e1e62dd4b95..d81b74c408a5 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -14,6 +14,7 @@ #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01) #define MAX_SIZE_PER_TLV_SEGMENT (243) #define QCA_PRE_SHUTDOWN_CMD (0xFC08) +#define QCA_DISABLE_LOGGING (0xFC17) #define EDL_CMD_REQ_RES_EVT (0x00) #define EDL_PATCH_VER_RES_EVT (0x19) @@ -22,6 +23,7 @@ #define EDL_CMD_EXE_STATUS_EVT (0x00) #define EDL_SET_BAUDRATE_RSP_EVT (0x92) #define EDL_NVM_ACCESS_CODE_EVT (0x0B) +#define QCA_DISABLE_LOGGING_SUB_OP (0x14) #define EDL_TAG_ID_HCI (17) #define EDL_TAG_ID_DEEP_SLEEP (27) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5f022e9cf667..8d2608ddfd08 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -359,6 +359,10 @@ static const struct usb_device_id blacklist_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01), .driver_info = BTUSB_IGNORE }, + /* Realtek 8822CE Bluetooth devices */ + { USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + /* Realtek Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), .driver_info = BTUSB_REALTEK }, @@ -453,6 +457,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = { #define BTUSB_HW_RESET_ACTIVE 12 #define BTUSB_TX_WAIT_VND_EVT 13 #define BTUSB_WAKEUP_DISABLE 14 +#define BTUSB_USE_ALT1_FOR_WBS 15 struct btusb_data { struct hci_dev *hdev; @@ -511,7 +516,6 @@ struct btusb_data { unsigned cmd_timeout_cnt; }; - static void btusb_intel_cmd_timeout(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); @@ -573,6 +577,23 @@ static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) gpiod_set_value_cansleep(reset_gpio, 0); } +static void btusb_qca_cmd_timeout(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + int err; + + if (++data->cmd_timeout_cnt < 5) + return; + + bt_dev_err(hdev, "Multiple cmd timeouts seen. Resetting usb device."); + /* This is not an unbalanced PM reference since the device will reset */ + err = usb_autopm_get_interface(data->intf); + if (!err) + usb_queue_reset_device(data->intf); + else + bt_dev_err(hdev, "Failed usb_autopm_get_interface with %d", err); +} + static inline void btusb_free_frags(struct btusb_data *data) { unsigned long flags; @@ -1666,14 +1687,15 @@ static void btusb_work(struct work_struct *work) new_alts = data->sco_num; } } else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) { - - data->usb_alt6_packet_flow = true; - /* Check if Alt 6 is supported for Transparent audio */ - if (btusb_find_altsetting(data, 6)) + if (btusb_find_altsetting(data, 6)) { + data->usb_alt6_packet_flow = true; new_alts = 6; - else + } else if (test_bit(BTUSB_USE_ALT1_FOR_WBS, &data->flags)) { + new_alts = 1; + } else { bt_dev_err(hdev, "Device does not support ALT setting 6"); + } } if (btusb_switch_alt_setting(hdev, new_alts) < 0) @@ -1720,6 +1742,7 @@ static int btusb_setup_csr(struct hci_dev *hdev) { struct hci_rp_read_local_version *rp; struct sk_buff *skb; + bool is_fake = false; BT_DBG("%s", hdev->name); @@ -1739,18 +1762,69 @@ static int btusb_setup_csr(struct hci_dev *hdev) rp = (struct hci_rp_read_local_version *)skb->data; - /* Detect controllers which aren't real CSR ones. */ + /* Detect a wide host of Chinese controllers that aren't CSR. + * + * Known fake bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891 + * + * The main thing they have in common is that these are really popular low-cost + * options that support newer Bluetooth versions but rely on heavy VID/PID + * squatting of this poor old Bluetooth 1.1 device. Even sold as such. + * + * We detect actual CSR devices by checking that the HCI manufacturer code + * is Cambridge Silicon Radio (10) and ensuring that LMP sub-version and + * HCI rev values always match. As they both store the firmware number. + */ if (le16_to_cpu(rp->manufacturer) != 10 || - le16_to_cpu(rp->lmp_subver) == 0x0c5c) { + le16_to_cpu(rp->hci_rev) != le16_to_cpu(rp->lmp_subver)) + is_fake = true; + + /* Known legit CSR firmware build numbers and their supported BT versions: + * - 1.1 (0x1) -> 0x0073, 0x020d, 0x033c, 0x034e + * - 1.2 (0x2) -> 0x04d9, 0x0529 + * - 2.0 (0x3) -> 0x07a6, 0x07ad, 0x0c5c + * - 2.1 (0x4) -> 0x149c, 0x1735, 0x1899 (0x1899 is a BlueCore4-External) + * - 4.0 (0x6) -> 0x1d86, 0x2031, 0x22bb + * + * e.g. Real CSR dongles with LMP subversion 0x73 are old enough that + * support BT 1.1 only; so it's a dead giveaway when some + * third-party BT 4.0 dongle reuses it. + */ + else if (le16_to_cpu(rp->lmp_subver) <= 0x034e && + le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_1_1) + is_fake = true; + + else if (le16_to_cpu(rp->lmp_subver) <= 0x0529 && + le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_1_2) + is_fake = true; + + else if (le16_to_cpu(rp->lmp_subver) <= 0x0c5c && + le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_2_0) + is_fake = true; + + else if (le16_to_cpu(rp->lmp_subver) <= 0x1899 && + le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_2_1) + is_fake = true; + + else if (le16_to_cpu(rp->lmp_subver) <= 0x22bb && + le16_to_cpu(rp->hci_ver) > BLUETOOTH_VER_4_0) + is_fake = true; + + if (is_fake) { + bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds..."); + + /* Generally these clones have big discrepancies between + * advertised features and what's actually supported. + * Probably will need to be expanded in the future; + * without these the controller will lock up. + */ + set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); + /* Clear the reset quirk since this is not an actual * early Bluetooth 1.1 device from CSR. */ clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); - - /* These fake CSR controllers have all a broken - * stored link key handling and so just disable it. - */ - set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); } kfree_skb(skb); @@ -2262,45 +2336,25 @@ static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver, return true; } -static int btusb_setup_intel_new(struct hci_dev *hdev) +static int btusb_intel_download_firmware(struct hci_dev *hdev, + struct intel_version *ver, + struct intel_boot_params *params) { - struct btusb_data *data = hci_get_drvdata(hdev); - struct intel_version ver; - struct intel_boot_params params; const struct firmware *fw; u32 boot_param; char fwname[64]; - ktime_t calltime, delta, rettime; - unsigned long long duration; int err; + struct btusb_data *data = hci_get_drvdata(hdev); - BT_DBG("%s", hdev->name); - - /* Set the default boot parameter to 0x0 and it is updated to - * SKU specific boot parameter after reading Intel_Write_Boot_Params - * command while downloading the firmware. - */ - boot_param = 0x00000000; - - calltime = ktime_get(); - - /* Read the Intel version information to determine if the device - * is in bootloader mode or if it already has operational firmware - * loaded. - */ - err = btintel_read_version(hdev, &ver); - if (err) { - bt_dev_err(hdev, "Intel Read version failed (%d)", err); - btintel_reset_to_bootloader(hdev); - return err; - } + if (!ver || !params) + return -EINVAL; /* The hardware platform number has a fixed value of 0x37 and * for now only accept this single value. */ - if (ver.hw_platform != 0x37) { + if (ver->hw_platform != 0x37) { bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)", - ver.hw_platform); + ver->hw_platform); return -EINVAL; } @@ -2310,7 +2364,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * This check has been put in place to ensure correct forward * compatibility options when newer hardware variants come along. */ - switch (ver.hw_variant) { + switch (ver->hw_variant) { case 0x0b: /* SfP */ case 0x0c: /* WsP */ case 0x11: /* JfP */ @@ -2320,11 +2374,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) break; default: bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", - ver.hw_variant); + ver->hw_variant); return -EINVAL; } - btintel_version_info(hdev, &ver); + btintel_version_info(hdev, ver); /* The firmware variant determines if the device is in bootloader * mode or is running operational firmware. The value 0x06 identifies @@ -2339,25 +2393,25 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * It is not possible to use the Secure Boot Parameters in this * case since that command is only available in bootloader mode. */ - if (ver.fw_variant == 0x23) { + if (ver->fw_variant == 0x23) { clear_bit(BTUSB_BOOTLOADER, &data->flags); btintel_check_bdaddr(hdev); - goto finish; + return 0; } /* If the device is not in bootloader mode, then the only possible * choice is to return an error and abort the device initialization. */ - if (ver.fw_variant != 0x06) { + if (ver->fw_variant != 0x06) { bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)", - ver.fw_variant); + ver->fw_variant); return -ENODEV; } /* Read the secure boot parameters to identify the operating * details of the bootloader. */ - err = btintel_read_boot_params(hdev, ¶ms); + err = btintel_read_boot_params(hdev, params); if (err) return err; @@ -2365,16 +2419,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * with a command complete event. If the boot parameters indicate * that this bootloader does not send them, then abort the setup. */ - if (params.limited_cce != 0x00) { + if (params->limited_cce != 0x00) { bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", - params.limited_cce); + params->limited_cce); return -EINVAL; } /* If the OTP has no valid Bluetooth device address, then there will * also be no valid address for the operational firmware. */ - if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) { + if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { bt_dev_info(hdev, "No device address configured"); set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); } @@ -2400,7 +2454,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi. * */ - err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, fwname, + err = btusb_setup_intel_new_get_fw_name(ver, params, fwname, sizeof(fwname), "sfi"); if (!err) { bt_dev_err(hdev, "Unsupported Intel firmware naming"); @@ -2415,16 +2469,6 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) bt_dev_info(hdev, "Found device firmware: %s", fwname); - /* Save the DDC file name for later use to apply once the firmware - * downloading is done. - */ - err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, fwname, - sizeof(fwname), "ddc"); - if (!err) { - bt_dev_err(hdev, "Unsupported Intel firmware naming"); - return -EINVAL; - } - if (fw->size < 644) { bt_dev_err(hdev, "Invalid size of firmware file (%zu)", fw->size); @@ -2479,18 +2523,58 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) goto done; } +done: + release_firmware(fw); + return err; +} + +static int btusb_setup_intel_new(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct intel_version ver; + struct intel_boot_params params; + u32 boot_param; + char ddcname[64]; + ktime_t calltime, delta, rettime; + unsigned long long duration; + int err; + struct intel_debug_features features; + + BT_DBG("%s", hdev->name); + + /* Set the default boot parameter to 0x0 and it is updated to + * SKU specific boot parameter after reading Intel_Write_Boot_Params + * command while downloading the firmware. + */ + boot_param = 0x00000000; + + calltime = ktime_get(); + + /* Read the Intel version information to determine if the device + * is in bootloader mode or if it already has operational firmware + * loaded. + */ + err = btintel_read_version(hdev, &ver); + if (err) { + bt_dev_err(hdev, "Intel Read version failed (%d)", err); + btintel_reset_to_bootloader(hdev); + return err; + } + + err = btusb_intel_download_firmware(hdev, &ver, ¶ms); + if (err) + return err; + + /* controller is already having an operational firmware */ + if (ver.fw_variant == 0x23) + goto finish; + rettime = ktime_get(); delta = ktime_sub(rettime, calltime); duration = (unsigned long long) ktime_to_ns(delta) >> 10; bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration); -done: - release_firmware(fw); - - if (err < 0) - return err; - calltime = ktime_get(); set_bit(BTUSB_BOOTING, &data->flags); @@ -2534,13 +2618,28 @@ done: clear_bit(BTUSB_BOOTLOADER, &data->flags); - /* Once the device is running in operational mode, it needs to apply - * the device configuration (DDC) parameters. - * - * The device can work without DDC parameters, so even if it fails - * to load the file, no need to fail the setup. + err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, ddcname, + sizeof(ddcname), "ddc"); + + if (!err) { + bt_dev_err(hdev, "Unsupported Intel firmware naming"); + } else { + /* Once the device is running in operational mode, it needs to + * apply the device configuration (DDC) parameters. + * + * The device can work without DDC parameters, so even if it + * fails to load the file, no need to fail the setup. + */ + btintel_load_ddc_config(hdev, ddcname); + } + + /* Read the Intel supported features and if new exception formats + * supported, need to load the additional DDC config to enable. */ - btintel_load_ddc_config(hdev, fwname); + btintel_read_debug_features(hdev, &features); + + /* Set DDC mask for available debug features */ + btintel_set_debug_features(hdev, &features); /* Read the Intel version information after loading the FW */ err = btintel_read_version(hdev, &ver); @@ -2925,7 +3024,7 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) const u8 *fw_ptr; size_t fw_size; int err, dlen; - u8 flag; + u8 flag, param; err = request_firmware(&fw, fwname, &hdev->dev); if (err < 0) { @@ -2933,6 +3032,20 @@ static int btusb_mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) return err; } + /* Power on data RAM the firmware relies on. */ + param = 1; + wmt_params.op = BTMTK_WMT_FUNC_CTRL; + wmt_params.flag = 3; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = NULL; + + err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to power on data RAM (%d)", err); + return err; + } + fw_ptr = fw->data; fw_size = fw->size; @@ -3704,6 +3817,9 @@ static bool btusb_prevent_wake(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); + if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags)) + return true; + return !device_may_wakeup(&data->udev->dev); } @@ -3941,10 +4057,20 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_QCA_ROME) { data->setup_on_usb = btusb_setup_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; + hdev->cmd_timeout = btusb_qca_cmd_timeout; set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); btusb_check_needs_reset_resume(intf); } + if (id->driver_info & BTUSB_AMP) { + /* AMP controllers do not support SCO packets */ + data->isoc = NULL; + } else { + /* Interface orders are hardcoded in the specification */ + data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1); + data->isoc_ifnum = ifnum_base + 1; + } + if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) && (id->driver_info & BTUSB_REALTEK)) { hdev->setup = btrtl_setup_realtek; @@ -3956,19 +4082,10 @@ static int btusb_probe(struct usb_interface *intf, * (DEVICE_REMOTE_WAKEUP) */ set_bit(BTUSB_WAKEUP_DISABLE, &data->flags); - - err = usb_autopm_get_interface(intf); - if (err < 0) - goto out_free_dev; - } - - if (id->driver_info & BTUSB_AMP) { - /* AMP controllers do not support SCO packets */ - data->isoc = NULL; - } else { - /* Interface orders are hardcoded in the specification */ - data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1); - data->isoc_ifnum = ifnum_base + 1; + if (btusb_find_altsetting(data, 1)) + set_bit(BTUSB_USE_ALT1_FOR_WBS, &data->flags); + else + bt_dev_err(hdev, "Device does not support ALT setting 1"); } if (!reset) @@ -4001,11 +4118,13 @@ static int btusb_probe(struct usb_interface *intf, if (bcdDevice < 0x117) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + /* This must be set first in case we disable it for fakes */ + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + /* Fake CSR devices with broken commands */ - if (bcdDevice <= 0x100 || bcdDevice == 0x134) + if (le16_to_cpu(udev->descriptor.idVendor) == 0x0a12 && + le16_to_cpu(udev->descriptor.idProduct) == 0x0001) hdev->setup = btusb_setup_csr; - - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); } if (id->driver_info & BTUSB_SNIFFER) { diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index e60b2e0773db..e41854e0d79a 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -793,7 +793,7 @@ static int h5_serdev_probe(struct serdev_device *serdev) if (!h5) return -ENOMEM; - set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.flags); + set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.hdev_flags); h5->hu = &h5->serdev_hu; h5->serdev_hu.serdev = serdev; diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index d9a4c6c691e0..8bfe024d1fcd 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -219,7 +219,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu) * perfectly safe to always send one. */ BT_DBG("dual wake-up-indication"); - /* fall through */ + fallthrough; case HCILL_ASLEEP: /* acknowledge device wake up */ if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) { diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 81c3c38baba1..20e1dedbc58c 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -46,7 +46,7 @@ #define HCI_MAX_IBS_SIZE 10 #define IBS_WAKE_RETRANS_TIMEOUT_MS 100 -#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS 40 +#define IBS_BTSOC_TX_IDLE_TIMEOUT_MS 200 #define IBS_HOST_TX_IDLE_TIMEOUT_MS 2000 #define CMD_TRANS_TIMEOUT_MS 100 #define MEMDUMP_TIMEOUT_MS 8000 @@ -72,7 +72,8 @@ enum qca_flags { QCA_DROP_VENDOR_EVENT, QCA_SUSPENDING, QCA_MEMDUMP_COLLECTION, - QCA_HW_ERROR_EVENT + QCA_HW_ERROR_EVENT, + QCA_SSR_TRIGGERED }; enum qca_capabilities { @@ -289,25 +290,21 @@ static void serial_clock_vote(unsigned long vote, struct hci_uart *hu) case HCI_IBS_TX_VOTE_CLOCK_ON: qca->tx_vote = true; qca->tx_votes_on++; - new_vote = true; break; case HCI_IBS_RX_VOTE_CLOCK_ON: qca->rx_vote = true; qca->rx_votes_on++; - new_vote = true; break; case HCI_IBS_TX_VOTE_CLOCK_OFF: qca->tx_vote = false; qca->tx_votes_off++; - new_vote = qca->rx_vote | qca->tx_vote; break; case HCI_IBS_RX_VOTE_CLOCK_OFF: qca->rx_vote = false; qca->rx_votes_off++; - new_vote = qca->rx_vote | qca->tx_vote; break; default: @@ -315,6 +312,8 @@ static void serial_clock_vote(unsigned long vote, struct hci_uart *hu) return; } + new_vote = qca->rx_vote | qca->tx_vote; + if (new_vote != old_vote) { if (new_vote) __serial_clock_on(hu->tty); @@ -474,8 +473,6 @@ static void hci_ibs_tx_idle_timeout(struct timer_list *t) case HCI_IBS_TX_ASLEEP: case HCI_IBS_TX_WAKING: - /* Fall through */ - default: BT_ERR("Spurious timeout tx state %d", qca->tx_ibs_state); break; @@ -518,8 +515,6 @@ static void hci_ibs_wake_retrans_timeout(struct timer_list *t) case HCI_IBS_TX_ASLEEP: case HCI_IBS_TX_AWAKE: - /* Fall through */ - default: BT_ERR("Spurious timeout tx state %d", qca->tx_ibs_state); break; @@ -837,8 +832,6 @@ static void device_woke_up(struct hci_uart *hu) break; case HCI_IBS_TX_ASLEEP: - /* Fall through */ - default: BT_ERR("Received HCI_IBS_WAKE_ACK in tx state %d", qca->tx_ibs_state); @@ -862,6 +855,13 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) BT_DBG("hu %p qca enq skb %p tx_ibs_state %d", hu, skb, qca->tx_ibs_state); + if (test_bit(QCA_SSR_TRIGGERED, &qca->flags)) { + /* As SSR is in progress, ignore the packets */ + bt_dev_dbg(hu->hdev, "SSR is in progress"); + kfree_skb(skb); + return 0; + } + /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); @@ -983,8 +983,11 @@ static void qca_controller_memdump(struct work_struct *work) while ((skb = skb_dequeue(&qca->rx_memdump_q))) { mutex_lock(&qca->hci_memdump_lock); - /* Skip processing the received packets if timeout detected. */ - if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT) { + /* Skip processing the received packets if timeout detected + * or memdump collection completed. + */ + if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT || + qca->memdump_state == QCA_MEMDUMP_COLLECTED) { mutex_unlock(&qca->hci_memdump_lock); return; } @@ -1128,6 +1131,7 @@ static int qca_controller_memdump_event(struct hci_dev *hdev, struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; + set_bit(QCA_SSR_TRIGGERED, &qca->flags); skb_queue_tail(&qca->rx_memdump_q, skb); queue_work(qca->workqueue, &qca->ctrl_memdump_evt); @@ -1485,9 +1489,8 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; - struct qca_memdump_data *qca_memdump = qca->qca_memdump; - char *memdump_buf = NULL; + set_bit(QCA_SSR_TRIGGERED, &qca->flags); set_bit(QCA_HW_ERROR_EVENT, &qca->flags); bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state); @@ -1509,19 +1512,23 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code) qca_wait_for_dump_collection(hdev); } + mutex_lock(&qca->hci_memdump_lock); if (qca->memdump_state != QCA_MEMDUMP_COLLECTED) { bt_dev_err(hu->hdev, "clearing allocated memory due to memdump timeout"); - mutex_lock(&qca->hci_memdump_lock); - if (qca_memdump) - memdump_buf = qca_memdump->memdump_buf_head; - vfree(memdump_buf); - kfree(qca_memdump); - qca->qca_memdump = NULL; + if (qca->qca_memdump) { + vfree(qca->qca_memdump->memdump_buf_head); + kfree(qca->qca_memdump); + qca->qca_memdump = NULL; + } qca->memdump_state = QCA_MEMDUMP_TIMEOUT; cancel_delayed_work(&qca->ctrl_memdump_timeout); - skb_queue_purge(&qca->rx_memdump_q); - mutex_unlock(&qca->hci_memdump_lock); + } + mutex_unlock(&qca->hci_memdump_lock); + + if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT || + qca->memdump_state == QCA_MEMDUMP_COLLECTED) { cancel_work_sync(&qca->ctrl_memdump_evt); + skb_queue_purge(&qca->rx_memdump_q); } clear_bit(QCA_HW_ERROR_EVENT, &qca->flags); @@ -1532,10 +1539,30 @@ static void qca_cmd_timeout(struct hci_dev *hdev) struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; - if (qca->memdump_state == QCA_MEMDUMP_IDLE) + set_bit(QCA_SSR_TRIGGERED, &qca->flags); + if (qca->memdump_state == QCA_MEMDUMP_IDLE) { + set_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); qca_send_crashbuffer(hu); - else - bt_dev_info(hdev, "Dump collection is in process"); + qca_wait_for_dump_collection(hdev); + } else if (qca->memdump_state == QCA_MEMDUMP_COLLECTING) { + /* Let us wait here until memory dump collected or + * memory dump timer expired. + */ + bt_dev_info(hdev, "waiting for dump to complete"); + qca_wait_for_dump_collection(hdev); + } + + mutex_lock(&qca->hci_memdump_lock); + if (qca->memdump_state != QCA_MEMDUMP_COLLECTED) { + qca->memdump_state = QCA_MEMDUMP_TIMEOUT; + if (!test_bit(QCA_HW_ERROR_EVENT, &qca->flags)) { + /* Inject hw error event to reset the device + * and driver. + */ + hci_reset_dev(hu->hdev); + } + } + mutex_unlock(&qca->hci_memdump_lock); } static int qca_wcn3990_init(struct hci_uart *hu) @@ -1641,11 +1668,15 @@ static int qca_setup(struct hci_uart *hu) bt_dev_info(hdev, "setting up %s", qca_is_wcn399x(soc_type) ? "wcn399x" : "ROME/QCA6390"); + qca->memdump_state = QCA_MEMDUMP_IDLE; + retry: ret = qca_power_on(hdev); if (ret) return ret; + clear_bit(QCA_SSR_TRIGGERED, &qca->flags); + if (qca_is_wcn399x(soc_type)) { set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); @@ -1788,9 +1819,6 @@ static void qca_power_shutdown(struct hci_uart *hu) qca_flush(hu); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); - hu->hdev->hw_error = NULL; - hu->hdev->cmd_timeout = NULL; - /* Non-serdev device usually is powered by external power * and don't need additional action in driver for power down */ @@ -1812,6 +1840,9 @@ static int qca_power_off(struct hci_dev *hdev) struct qca_data *qca = hu->priv; enum qca_btsoc_type soc_type = qca_soc_type(hu); + hu->hdev->hw_error = NULL; + hu->hdev->cmd_timeout = NULL; + /* Stop sending shutdown command if soc crashes. */ if (soc_type != QCA_ROME && qca->memdump_state == QCA_MEMDUMP_IDLE) { @@ -1819,7 +1850,6 @@ static int qca_power_off(struct hci_dev *hdev) usleep_range(8000, 10000); } - qca->memdump_state = QCA_MEMDUMP_IDLE; qca_power_shutdown(hu); return 0; } @@ -1962,17 +1992,17 @@ static int qca_serdev_probe(struct serdev_device *serdev) } qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); - if (!qcadev->susclk) { + if (IS_ERR(qcadev->susclk)) { dev_warn(&serdev->dev, "failed to acquire clk\n"); - } else { - err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ); - if (err) - return err; - - err = clk_prepare_enable(qcadev->susclk); - if (err) - return err; + return PTR_ERR(qcadev->susclk); } + err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ); + if (err) + return err; + + err = clk_prepare_enable(qcadev->susclk); + if (err) + return err; err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); if (err) { @@ -2050,6 +2080,7 @@ static int __maybe_unused qca_suspend(struct device *dev) struct hci_uart *hu = &qcadev->serdev_hu; struct qca_data *qca = hu->priv; unsigned long flags; + bool tx_pending = false; int ret = 0; u8 cmd; @@ -2068,7 +2099,7 @@ static int __maybe_unused qca_suspend(struct device *dev) switch (qca->tx_ibs_state) { case HCI_IBS_TX_WAKING: del_timer(&qca->wake_retrans_timer); - /* Fall through */ + fallthrough; case HCI_IBS_TX_AWAKE: del_timer(&qca->tx_idle_timer); @@ -2083,8 +2114,7 @@ static int __maybe_unused qca_suspend(struct device *dev) qca->tx_ibs_state = HCI_IBS_TX_ASLEEP; qca->ibs_sent_slps++; - - qca_wq_serial_tx_clock_vote_off(&qca->ws_tx_vote_off); + tx_pending = true; break; case HCI_IBS_TX_ASLEEP: @@ -2101,22 +2131,24 @@ static int __maybe_unused qca_suspend(struct device *dev) if (ret < 0) goto error; - serdev_device_wait_until_sent(hu->serdev, - msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); + if (tx_pending) { + serdev_device_wait_until_sent(hu->serdev, + msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); + serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu); + } /* Wait for HCI_IBS_SLEEP_IND sent by device to indicate its Tx is going * to sleep, so that the packet does not wake the system later. */ - ret = wait_event_interruptible_timeout(qca->suspend_wait_q, qca->rx_ibs_state == HCI_IBS_RX_ASLEEP, msecs_to_jiffies(IBS_BTSOC_TX_IDLE_TIMEOUT_MS)); - - if (ret > 0) - return 0; - - if (ret == 0) + if (ret == 0) { ret = -ETIMEDOUT; + goto error; + } + + return 0; error: clear_bit(QCA_SUSPENDING, &qca->flags); diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 599855e4c57c..7b233312e723 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -355,7 +355,8 @@ void hci_uart_unregister_device(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev; clear_bit(HCI_UART_PROTO_READY, &hu->flags); - hci_unregister_dev(hdev); + if (test_bit(HCI_UART_REGISTERED, &hu->flags)) + hci_unregister_dev(hdev); hci_free_dev(hdev); cancel_work_sync(&hu->write_work); |