diff options
author | Jakub Kicinski <kuba@kernel.org> | 2023-08-26 03:30:59 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-08-26 03:30:59 +0200 |
commit | 3db34747631161b24241b2dae06d8e3e69cf7d8b (patch) | |
tree | 416ac852a7c22bf510a97b5dcb69465e6389a420 | |
parent | kunit: Fix checksum tests on big endian CPUs (diff) | |
parent | Bluetooth: btusb: Do not call kfree_skb() under spin_lock_irqsave() (diff) | |
download | linux-3db34747631161b24241b2dae06d8e3e69cf7d8b.tar.xz linux-3db34747631161b24241b2dae06d8e3e69cf7d8b.zip |
Merge tag 'for-net-next-2023-08-24' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Luiz Augusto von Dentz says:
====================
bluetooth-next pull request for net-next:
- Introduce HCI_QUIRK_BROKEN_LE_CODED
- Add support for PA/BIG sync
- Add support for NXP IW624 chipset
- Add support for Qualcomm WCN7850
* tag 'for-net-next-2023-08-24' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next:
Bluetooth: btusb: Do not call kfree_skb() under spin_lock_irqsave()
Bluetooth: btusb: Fix quirks table naming
Bluetooth: HCI: Introduce HCI_QUIRK_BROKEN_LE_CODED
Bluetooth: btintel: Send new command for PPAG
Bluetooth: ISO: Add support for periodic adv reports processing
Bluetooth: hci_conn: fail SCO/ISO via hci_conn_failed if ACL gone early
Bluetooth: hci_core: Fix missing instances using HCI_MAX_AD_LENGTH
Bluetooth: ISO: Use defer setup to separate PA sync and BIG sync
Bluetooth: qca: add support for WCN7850
Bluetooth: qca: use switch case for soc type behavior
dt-bindings: net: bluetooth: qualcomm: document WCN7850 chipset
Bluetooth: hci_conn: Fix sending BT_HCI_CMD_LE_CREATE_CONN_CANCEL
Bluetooth: hci_sync: Fix UAF in hci_disconnect_all_sync
Bluetooth: btnxpuart: Improve inband Independent Reset handling
Bluetooth: btnxpuart: Add support for IW624 chipset
Bluetooth: btnxpuart: Remove check for CTS low after FW download
====================
Link: https://lore.kernel.org/r/20230824201458.2577-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml | 23 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.c | 31 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.h | 7 | ||||
-rw-r--r-- | drivers/bluetooth/btnxpuart.c | 216 | ||||
-rw-r--r-- | drivers/bluetooth/btqca.c | 97 | ||||
-rw-r--r-- | drivers/bluetooth/btqca.h | 37 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 6 | ||||
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 264 | ||||
-rw-r--r-- | include/net/bluetooth/hci.h | 21 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 40 | ||||
-rw-r--r-- | net/bluetooth/eir.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 48 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 64 | ||||
-rw-r--r-- | net/bluetooth/hci_sync.c | 75 | ||||
-rw-r--r-- | net/bluetooth/iso.c | 188 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 6 |
16 files changed, 818 insertions, 307 deletions
diff --git a/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml b/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml index 2735c6a4f336..eba2f3026ab0 100644 --- a/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml +++ b/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml @@ -26,6 +26,7 @@ properties: - qcom,qca6390-bt - qcom,wcn6750-bt - qcom,wcn6855-bt + - qcom,wcn7850-bt enable-gpios: maxItems: 1 @@ -58,6 +59,9 @@ properties: vddaon-supply: description: VDD_AON supply regulator handle + vdddig-supply: + description: VDD_DIG supply regulator handle + vddbtcxmx-supply: description: VDD_BT_CXMX supply regulator handle @@ -73,6 +77,9 @@ properties: vddrfa1p2-supply: description: VDD_RFA_1P2 supply regulator handle + vddrfa1p9-supply: + description: VDD_RFA_1P9 supply regulator handle + vddrfa2p2-supply: description: VDD_RFA_2P2 supply regulator handle @@ -157,6 +164,22 @@ allOf: - vddrfa0p8-supply - vddrfa1p2-supply - vddrfa1p7-supply + - if: + properties: + compatible: + contains: + enum: + - qcom,wcn7850-bt + then: + required: + - enable-gpios + - swctrl-gpios + - vddio-supply + - vddaon-supply + - vdddig-supply + - vddrfa0p8-supply + - vddrfa1p2-supply + - vddrfa1p9-supply examples: - | diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 633e8d9bf58f..2462796a512a 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -2401,7 +2401,7 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver { struct btintel_ppag ppag; struct sk_buff *skb; - struct btintel_loc_aware_reg ppag_cmd; + struct hci_ppag_enable_cmd ppag_cmd; acpi_handle handle; /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ @@ -2409,6 +2409,8 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver case 0x504: /* Hrp2 */ case 0x202: /* Jfp2 */ case 0x201: /* Jfp1 */ + bt_dev_dbg(hdev, "PPAG not supported for Intel CNVr (0x%3x)", + ver->cnvr_top & 0xFFF); return; } @@ -2434,24 +2436,29 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver } if (ppag.domain != 0x12) { - bt_dev_warn(hdev, "PPAG-BT: domain is not bluetooth"); + bt_dev_dbg(hdev, "PPAG-BT: Bluetooth domain is disabled in ACPI firmware"); return; } - /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */ - if (!(ppag.mode & BIT(0))) { - bt_dev_dbg(hdev, "PPAG-BT: disabled"); + /* PPAG mode + * BIT 0 : 0 Disabled in EU + * 1 Enabled in EU + * BIT 1 : 0 Disabled in China + * 1 Enabled in China + */ + if ((ppag.mode & 0x01) != BIT(0) && (ppag.mode & 0x02) != BIT(1)) { + bt_dev_dbg(hdev, "PPAG-BT: EU, China mode are disabled in CB/BIOS"); return; } - ppag_cmd.mcc = cpu_to_le32(0); - ppag_cmd.sel = cpu_to_le32(0); /* 0 - Enable , 1 - Disable, 2 - Testing mode */ - ppag_cmd.delta = cpu_to_le32(0); - skb = __hci_cmd_sync(hdev, 0xfe19, sizeof(ppag_cmd), &ppag_cmd, HCI_CMD_TIMEOUT); + ppag_cmd.ppag_enable_flags = cpu_to_le32(ppag.mode); + + skb = __hci_cmd_sync(hdev, INTEL_OP_PPAG_CMD, sizeof(ppag_cmd), &ppag_cmd, HCI_CMD_TIMEOUT); if (IS_ERR(skb)) { bt_dev_warn(hdev, "Failed to send PPAG Enable (%ld)", PTR_ERR(skb)); return; } + bt_dev_info(hdev, "PPAG-BT: Enabled (Mode %d)", ppag.mode); kfree_skb(skb); } @@ -2780,6 +2787,9 @@ static int btintel_setup_combined(struct hci_dev *hdev) set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + /* These variants don't seem to support LE Coded PHY */ + set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); + /* Setup MSFT Extension support */ btintel_set_msft_opcode(hdev, ver.hw_variant); @@ -2851,6 +2861,9 @@ static int btintel_setup_combined(struct hci_dev *hdev) */ set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + /* These variants don't seem to support LE Coded PHY */ + set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); + /* Set Valid LE States quirk */ set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 2ed646609dee..3a2d5b4219dd 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -137,10 +137,9 @@ struct intel_offload_use_cases { __u8 preset[8]; } __packed; -struct btintel_loc_aware_reg { - __le32 mcc; - __le32 sel; - __le32 delta; +#define INTEL_OP_PPAG_CMD 0xFE0B +struct hci_ppag_enable_cmd { + __le32 ppag_enable_flags; } __packed; #define INTEL_TLV_TYPE_ID 0x01 diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index ee6f6c872a34..b7e66b7ac570 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -28,12 +28,18 @@ #define BTNXPUART_FW_DOWNLOADING 2 #define BTNXPUART_CHECK_BOOT_SIGNATURE 3 #define BTNXPUART_SERDEV_OPEN 4 +#define BTNXPUART_IR_IN_PROGRESS 5 + +/* NXP HW err codes */ +#define BTNXPUART_IR_HW_ERR 0xb0 #define FIRMWARE_W8987 "nxp/uartuart8987_bt.bin" #define FIRMWARE_W8997 "nxp/uartuart8997_bt_v4.bin" #define FIRMWARE_W9098 "nxp/uartuart9098_bt_v1.bin" #define FIRMWARE_IW416 "nxp/uartiw416_bt_v0.bin" #define FIRMWARE_IW612 "nxp/uartspi_n61x_v1.bin.se" +#define FIRMWARE_IW624 "nxp/uartiw624_bt.bin" +#define FIRMWARE_SECURE_IW624 "nxp/uartiw624_bt.bin.se" #define FIRMWARE_AW693 "nxp/uartaw693_bt.bin" #define FIRMWARE_SECURE_AW693 "nxp/uartaw693_bt.bin.se" #define FIRMWARE_HELPER "nxp/helper_uart_3000000.bin" @@ -41,6 +47,8 @@ #define CHIP_ID_W9098 0x5c03 #define CHIP_ID_IW416 0x7201 #define CHIP_ID_IW612 0x7601 +#define CHIP_ID_IW624a 0x8000 +#define CHIP_ID_IW624c 0x8001 #define CHIP_ID_AW693 0x8200 #define FW_SECURE_MASK 0xc0 @@ -152,6 +160,7 @@ struct btnxpuart_dev { u32 fw_v1_sent_bytes; u32 fw_v3_offset_correction; u32 fw_v1_expected_len; + u32 boot_reg_offset; wait_queue_head_t fw_dnld_done_wait_q; wait_queue_head_t check_boot_sign_wait_q; @@ -375,39 +384,13 @@ static void ps_timeout_func(struct timer_list *t) } } -static int ps_init_work(struct hci_dev *hdev) +static void ps_setup(struct hci_dev *hdev) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct ps_data *psdata = &nxpdev->psdata; - psdata->h2c_ps_interval = PS_DEFAULT_TIMEOUT_PERIOD_MS; - psdata->ps_state = PS_STATE_AWAKE; - psdata->target_ps_mode = DEFAULT_PS_MODE; psdata->hdev = hdev; - psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE; - psdata->c2h_wakeup_gpio = 0xff; - - switch (DEFAULT_H2C_WAKEUP_MODE) { - case WAKEUP_METHOD_DTR: - psdata->h2c_wakeupmode = WAKEUP_METHOD_DTR; - break; - case WAKEUP_METHOD_BREAK: - default: - psdata->h2c_wakeupmode = WAKEUP_METHOD_BREAK; - break; - } - psdata->cur_psmode = PS_MODE_DISABLE; - psdata->cur_h2c_wakeupmode = WAKEUP_METHOD_INVALID; INIT_WORK(&psdata->work, ps_work_func); - - return 0; -} - -static void ps_init_timer(struct hci_dev *hdev) -{ - struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); - struct ps_data *psdata = &nxpdev->psdata; - timer_setup(&psdata->ps_timer, ps_timeout_func, 0); } @@ -510,19 +493,31 @@ static void ps_init(struct hci_dev *hdev) serdev_device_set_tiocm(nxpdev->serdev, TIOCM_RTS, 0); usleep_range(5000, 10000); - switch (psdata->h2c_wakeupmode) { + psdata->ps_state = PS_STATE_AWAKE; + psdata->c2h_wakeupmode = BT_HOST_WAKEUP_METHOD_NONE; + psdata->c2h_wakeup_gpio = 0xff; + + psdata->cur_h2c_wakeupmode = WAKEUP_METHOD_INVALID; + psdata->h2c_ps_interval = PS_DEFAULT_TIMEOUT_PERIOD_MS; + switch (DEFAULT_H2C_WAKEUP_MODE) { case WAKEUP_METHOD_DTR: + psdata->h2c_wakeupmode = WAKEUP_METHOD_DTR; serdev_device_set_tiocm(nxpdev->serdev, 0, TIOCM_DTR); serdev_device_set_tiocm(nxpdev->serdev, TIOCM_DTR, 0); break; case WAKEUP_METHOD_BREAK: default: + psdata->h2c_wakeupmode = WAKEUP_METHOD_BREAK; serdev_device_break_ctl(nxpdev->serdev, -1); usleep_range(5000, 10000); serdev_device_break_ctl(nxpdev->serdev, 0); usleep_range(5000, 10000); break; } + + psdata->cur_psmode = PS_MODE_DISABLE; + psdata->target_ps_mode = DEFAULT_PS_MODE; + if (psdata->cur_h2c_wakeupmode != psdata->h2c_wakeupmode) hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL); if (psdata->cur_psmode != psdata->target_ps_mode) @@ -538,6 +533,7 @@ static int nxp_download_firmware(struct hci_dev *hdev) nxpdev->fw_dnld_v1_offset = 0; nxpdev->fw_v1_sent_bytes = 0; nxpdev->fw_v1_expected_len = HDR_LEN; + nxpdev->boot_reg_offset = 0; nxpdev->fw_v3_offset_correction = 0; nxpdev->baudrate_changed = false; nxpdev->timeout_changed = false; @@ -547,7 +543,7 @@ static int nxp_download_firmware(struct hci_dev *hdev) serdev_device_set_flow_control(nxpdev->serdev, false); nxpdev->current_baudrate = HCI_NXP_PRI_BAUDRATE; - /* Wait till FW is downloaded and CTS becomes low */ + /* Wait till FW is downloaded */ err = wait_event_interruptible_timeout(nxpdev->fw_dnld_done_wait_q, !test_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state), @@ -558,16 +554,11 @@ static int nxp_download_firmware(struct hci_dev *hdev) } serdev_device_set_flow_control(nxpdev->serdev, true); - err = serdev_device_wait_for_cts(nxpdev->serdev, 1, 60000); - if (err < 0) { - bt_dev_err(hdev, "CTS is still high. FW Download failed."); - return err; - } release_firmware(nxpdev->fw); memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name)); /* Allow the downloaded FW to initialize */ - usleep_range(800 * USEC_PER_MSEC, 1 * USEC_PER_SEC); + msleep(1200); return 0; } @@ -591,6 +582,12 @@ static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len) struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); struct nxp_bootloader_cmd nxp_cmd5; struct uart_config uart_config; + u32 clkdivaddr = CLKDIVADDR - nxpdev->boot_reg_offset; + u32 uartdivaddr = UARTDIVADDR - nxpdev->boot_reg_offset; + u32 uartmcraddr = UARTMCRADDR - nxpdev->boot_reg_offset; + u32 uartreinitaddr = UARTREINITADDR - nxpdev->boot_reg_offset; + u32 uarticraddr = UARTICRADDR - nxpdev->boot_reg_offset; + u32 uartfcraddr = UARTFCRADDR - nxpdev->boot_reg_offset; if (req_len == sizeof(nxp_cmd5)) { nxp_cmd5.header = __cpu_to_le32(5); @@ -603,17 +600,17 @@ static bool nxp_fw_change_baudrate(struct hci_dev *hdev, u16 req_len) serdev_device_write_buf(nxpdev->serdev, (u8 *)&nxp_cmd5, sizeof(nxp_cmd5)); nxpdev->fw_v3_offset_correction += req_len; } else if (req_len == sizeof(uart_config)) { - uart_config.clkdiv.address = __cpu_to_le32(CLKDIVADDR); + uart_config.clkdiv.address = __cpu_to_le32(clkdivaddr); uart_config.clkdiv.value = __cpu_to_le32(0x00c00000); - uart_config.uartdiv.address = __cpu_to_le32(UARTDIVADDR); + uart_config.uartdiv.address = __cpu_to_le32(uartdivaddr); uart_config.uartdiv.value = __cpu_to_le32(1); - uart_config.mcr.address = __cpu_to_le32(UARTMCRADDR); + uart_config.mcr.address = __cpu_to_le32(uartmcraddr); uart_config.mcr.value = __cpu_to_le32(MCR); - uart_config.re_init.address = __cpu_to_le32(UARTREINITADDR); + uart_config.re_init.address = __cpu_to_le32(uartreinitaddr); uart_config.re_init.value = __cpu_to_le32(INIT); - uart_config.icr.address = __cpu_to_le32(UARTICRADDR); + uart_config.icr.address = __cpu_to_le32(uarticraddr); uart_config.icr.value = __cpu_to_le32(ICR); - uart_config.fcr.address = __cpu_to_le32(UARTFCRADDR); + uart_config.fcr.address = __cpu_to_le32(uartfcraddr); uart_config.fcr.value = __cpu_to_le32(FCR); /* FW expects swapped CRC bytes */ uart_config.crc = __cpu_to_be32(crc32_be(0UL, (char *)&uart_config, @@ -702,7 +699,7 @@ static int nxp_recv_chip_ver_v1(struct hci_dev *hdev, struct sk_buff *skb) goto free_skb; chip_id = le16_to_cpu(req->chip_id ^ req->chip_id_comp); - if (chip_id == 0xffff) { + if (chip_id == 0xffff && nxpdev->fw_dnld_v1_offset) { nxpdev->fw_dnld_v1_offset = 0; nxpdev->fw_v1_sent_bytes = 0; nxpdev->fw_v1_expected_len = HDR_LEN; @@ -827,6 +824,7 @@ free_skb: static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid, u8 loader_ver) { + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); char *fw_name = NULL; switch (chipid) { @@ -839,6 +837,16 @@ static char *nxp_get_fw_name_from_chipid(struct hci_dev *hdev, u16 chipid, case CHIP_ID_IW612: fw_name = FIRMWARE_IW612; break; + case CHIP_ID_IW624a: + case CHIP_ID_IW624c: + nxpdev->boot_reg_offset = 1; + if ((loader_ver & FW_SECURE_MASK) == FW_OPEN) + fw_name = FIRMWARE_IW624; + else if ((loader_ver & FW_SECURE_MASK) != FW_AUTH_ILLEGAL) + fw_name = FIRMWARE_SECURE_IW624; + else + bt_dev_err(hdev, "Illegal loader version %02x", loader_ver); + break; case CHIP_ID_AW693: if ((loader_ver & FW_SECURE_MASK) == FW_OPEN) fw_name = FIRMWARE_AW693; @@ -969,45 +977,13 @@ static int nxp_set_baudrate_cmd(struct hci_dev *hdev, void *data) return 0; } -static int nxp_set_ind_reset(struct hci_dev *hdev, void *data) -{ - struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); - struct sk_buff *skb; - u8 *status; - u8 pcmd = 0; - int err = 0; - - skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1, &pcmd); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - status = skb_pull_data(skb, 1); - if (!status || *status) - goto free_skb; - - set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); - err = nxp_download_firmware(hdev); - if (err < 0) - goto free_skb; - serdev_device_set_baudrate(nxpdev->serdev, nxpdev->fw_init_baudrate); - nxpdev->current_baudrate = nxpdev->fw_init_baudrate; - if (nxpdev->current_baudrate != HCI_NXP_SEC_BAUDRATE) { - nxpdev->new_baudrate = HCI_NXP_SEC_BAUDRATE; - nxp_set_baudrate_cmd(hdev, NULL); - } - hci_cmd_sync_queue(hdev, send_wakeup_method_cmd, NULL, NULL); - hci_cmd_sync_queue(hdev, send_ps_cmd, NULL, NULL); - -free_skb: - kfree_skb(skb); - return err; -} - -/* NXP protocol */ static int nxp_check_boot_sign(struct btnxpuart_dev *nxpdev) { serdev_device_set_baudrate(nxpdev->serdev, HCI_NXP_PRI_BAUDRATE); - serdev_device_set_flow_control(nxpdev->serdev, true); + if (test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) + serdev_device_set_flow_control(nxpdev->serdev, false); + else + serdev_device_set_flow_control(nxpdev->serdev, true); set_bit(BTNXPUART_CHECK_BOOT_SIGNATURE, &nxpdev->tx_state); return wait_event_interruptible_timeout(nxpdev->check_boot_sign_wait_q, @@ -1016,15 +992,29 @@ static int nxp_check_boot_sign(struct btnxpuart_dev *nxpdev) msecs_to_jiffies(1000)); } +static int nxp_set_ind_reset(struct hci_dev *hdev, void *data) +{ + static const u8 ir_hw_err[] = { HCI_EV_HARDWARE_ERROR, + 0x01, BTNXPUART_IR_HW_ERR }; + struct sk_buff *skb; + + skb = bt_skb_alloc(3, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + hci_skb_pkt_type(skb) = HCI_EVENT_PKT; + skb_put_data(skb, ir_hw_err, 3); + + /* Inject Hardware Error to upper stack */ + return hci_recv_frame(hdev, skb); +} + +/* NXP protocol */ static int nxp_setup(struct hci_dev *hdev) { struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); int err = 0; - set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); - init_waitqueue_head(&nxpdev->fw_dnld_done_wait_q); - init_waitqueue_head(&nxpdev->check_boot_sign_wait_q); - if (nxp_check_boot_sign(nxpdev)) { bt_dev_dbg(hdev, "Need FW Download."); err = nxp_download_firmware(hdev); @@ -1035,10 +1025,6 @@ static int nxp_setup(struct hci_dev *hdev) clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); } - device_property_read_u32(&nxpdev->serdev->dev, "fw-init-baudrate", - &nxpdev->fw_init_baudrate); - if (!nxpdev->fw_init_baudrate) - nxpdev->fw_init_baudrate = FW_INIT_BAUDRATE; serdev_device_set_baudrate(nxpdev->serdev, nxpdev->fw_init_baudrate); nxpdev->current_baudrate = nxpdev->fw_init_baudrate; @@ -1049,6 +1035,46 @@ static int nxp_setup(struct hci_dev *hdev) ps_init(hdev); + if (test_and_clear_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) + hci_dev_clear_flag(hdev, HCI_SETUP); + + return 0; +} + +static void nxp_hw_err(struct hci_dev *hdev, u8 code) +{ + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); + + switch (code) { + case BTNXPUART_IR_HW_ERR: + set_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state); + hci_dev_set_flag(hdev, HCI_SETUP); + break; + default: + break; + } +} + +static int nxp_shutdown(struct hci_dev *hdev) +{ + struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev); + struct sk_buff *skb; + u8 *status; + u8 pcmd = 0; + + if (test_bit(BTNXPUART_IR_IN_PROGRESS, &nxpdev->tx_state)) { + skb = nxp_drv_send_cmd(hdev, HCI_NXP_IND_RESET, 1, &pcmd); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + status = skb_pull_data(skb, 1); + if (status) { + serdev_device_set_flow_control(nxpdev->serdev, false); + set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); + } + kfree_skb(skb); + } + return 0; } @@ -1256,7 +1282,8 @@ static int btnxpuart_receive_buf(struct serdev_device *serdev, const u8 *data, nxpdev->rx_skb = NULL; return err; } - nxpdev->hdev->stat.byte_rx += count; + if (!is_fw_downloading(nxpdev)) + nxpdev->hdev->stat.byte_rx += count; return count; } @@ -1289,6 +1316,16 @@ static int nxp_serdev_probe(struct serdev_device *serdev) INIT_WORK(&nxpdev->tx_work, btnxpuart_tx_work); skb_queue_head_init(&nxpdev->txq); + init_waitqueue_head(&nxpdev->fw_dnld_done_wait_q); + init_waitqueue_head(&nxpdev->check_boot_sign_wait_q); + + device_property_read_u32(&nxpdev->serdev->dev, "fw-init-baudrate", + &nxpdev->fw_init_baudrate); + if (!nxpdev->fw_init_baudrate) + nxpdev->fw_init_baudrate = FW_INIT_BAUDRATE; + + set_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state); + crc8_populate_msb(crc8_table, POLYNOMIAL8); /* Initialize and register HCI device */ @@ -1309,6 +1346,8 @@ static int nxp_serdev_probe(struct serdev_device *serdev) hdev->flush = btnxpuart_flush; hdev->setup = nxp_setup; hdev->send = nxp_enqueue; + hdev->hw_error = nxp_hw_err; + hdev->shutdown = nxp_shutdown; SET_HCIDEV_DEV(hdev, &serdev->dev); if (hci_register_dev(hdev) < 0) { @@ -1317,8 +1356,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev) return -ENODEV; } - ps_init_work(hdev); - ps_init_timer(hdev); + ps_setup(hdev); return 0; } diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 6f2187fab55f..5a35ac4138c6 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -604,26 +604,38 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, /* Download rampatch file */ config.type = TLV_TYPE_PATCH; - if (soc_type == QCA_WCN3988) { - snprintf(config.fwname, sizeof(config.fwname), - "qca/apbtfw%02x.tlv", rom_ver); - } else if (qca_is_wcn399x(soc_type)) { + switch (soc_type) { + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: snprintf(config.fwname, sizeof(config.fwname), "qca/crbtfw%02x.tlv", rom_ver); - } else if (soc_type == QCA_QCA6390) { + break; + case QCA_WCN3988: + snprintf(config.fwname, sizeof(config.fwname), + "qca/apbtfw%02x.tlv", rom_ver); + break; + case QCA_QCA6390: snprintf(config.fwname, sizeof(config.fwname), "qca/htbtfw%02x.tlv", rom_ver); - } else if (soc_type == QCA_WCN6750) { + break; + case QCA_WCN6750: /* Choose mbn file by default.If mbn file is not found * then choose tlv file */ config.type = ELF_TYPE_PATCH; snprintf(config.fwname, sizeof(config.fwname), "qca/msbtfw%02x.mbn", rom_ver); - } else if (soc_type == QCA_WCN6855) { + break; + case QCA_WCN6855: snprintf(config.fwname, sizeof(config.fwname), "qca/hpbtfw%02x.tlv", rom_ver); - } else { + break; + case QCA_WCN7850: + snprintf(config.fwname, sizeof(config.fwname), + "qca/hmtbtfw%02x.tlv", rom_ver); + break; + default: snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin", soc_ver); } @@ -639,33 +651,48 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, /* Download NVM configuration */ config.type = TLV_TYPE_NVM; - if (firmware_name) + if (firmware_name) { snprintf(config.fwname, sizeof(config.fwname), "qca/%s", firmware_name); - else if (soc_type == QCA_WCN3988) - snprintf(config.fwname, sizeof(config.fwname), - "qca/apnv%02x.bin", rom_ver); - else if (qca_is_wcn399x(soc_type)) { - if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { + } else { + switch (soc_type) { + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { + snprintf(config.fwname, sizeof(config.fwname), + "qca/crnv%02xu.bin", rom_ver); + } else { + snprintf(config.fwname, sizeof(config.fwname), + "qca/crnv%02x.bin", rom_ver); + } + break; + case QCA_WCN3988: snprintf(config.fwname, sizeof(config.fwname), - "qca/crnv%02xu.bin", rom_ver); - } else { + "qca/apnv%02x.bin", rom_ver); + break; + case QCA_QCA6390: + snprintf(config.fwname, sizeof(config.fwname), + "qca/htnv%02x.bin", rom_ver); + break; + case QCA_WCN6750: + snprintf(config.fwname, sizeof(config.fwname), + "qca/msnv%02x.bin", rom_ver); + break; + case QCA_WCN6855: + snprintf(config.fwname, sizeof(config.fwname), + "qca/hpnv%02x.bin", rom_ver); + break; + case QCA_WCN7850: snprintf(config.fwname, sizeof(config.fwname), - "qca/crnv%02x.bin", rom_ver); + "qca/hmtnv%02x.bin", rom_ver); + break; + + default: + snprintf(config.fwname, sizeof(config.fwname), + "qca/nvm_%08x.bin", soc_ver); } } - else if (soc_type == QCA_QCA6390) - snprintf(config.fwname, sizeof(config.fwname), - "qca/htnv%02x.bin", rom_ver); - else if (soc_type == QCA_WCN6750) - snprintf(config.fwname, sizeof(config.fwname), - "qca/msnv%02x.bin", rom_ver); - else if (soc_type == QCA_WCN6855) - snprintf(config.fwname, sizeof(config.fwname), - "qca/hpnv%02x.bin", rom_ver); - else - snprintf(config.fwname, sizeof(config.fwname), - "qca/nvm_%08x.bin", soc_ver); err = qca_download_firmware(hdev, &config, soc_type, rom_ver); if (err < 0) { @@ -673,16 +700,25 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, return err; } - if (soc_type >= QCA_WCN3991) { + switch (soc_type) { + case QCA_WCN3991: + case QCA_QCA6390: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: err = qca_disable_soc_logging(hdev); if (err < 0) return err; + break; + default: + break; } /* WCN399x and WCN6750 supports the Microsoft vendor extension with 0xFD70 as the * VsMsftOpCode. */ switch (soc_type) { + case QCA_WCN3988: case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: @@ -704,6 +740,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, case QCA_WCN3991: case QCA_WCN6750: case QCA_WCN6855: + case QCA_WCN7850: /* get fw build info */ err = qca_read_fw_build_info(hdev); if (err < 0) diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index fc6cf314eb0e..03bff5c0059d 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -149,6 +149,7 @@ enum qca_btsoc_type { QCA_QCA6390, QCA_WCN6750, QCA_WCN6855, + QCA_WCN7850, }; #if IS_ENABLED(CONFIG_BT_QCA) @@ -161,27 +162,6 @@ int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver, enum qca_btsoc_type); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_send_pre_shutdown_cmd(struct hci_dev *hdev); -static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) -{ - switch (soc_type) { - case QCA_WCN3988: - case QCA_WCN3990: - case QCA_WCN3991: - case QCA_WCN3998: - return true; - default: - return false; - } -} -static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type) -{ - return soc_type == QCA_WCN6750; -} -static inline bool qca_is_wcn6855(enum qca_btsoc_type soc_type) -{ - return soc_type == QCA_WCN6855; -} - #else static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) @@ -209,21 +189,6 @@ static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) return -EOPNOTSUPP; } -static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) -{ - return false; -} - -static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type) -{ - return false; -} - -static inline bool qca_is_wcn6855(enum qca_btsoc_type soc_type) -{ - return false; -} - static inline int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) { return -EOPNOTSUPP; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1bb3b09013b0..82597ab4f747 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -175,7 +175,7 @@ static const struct usb_device_id btusb_table[] = { MODULE_DEVICE_TABLE(usb, btusb_table); -static const struct usb_device_id blacklist_table[] = { +static const struct usb_device_id quirks_table[] = { /* CSR BlueCore devices */ { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR }, @@ -2162,7 +2162,7 @@ static int btusb_switch_alt_setting(struct hci_dev *hdev, int new_alts) * alternate setting. */ spin_lock_irqsave(&data->rxlock, flags); - kfree_skb(data->sco_skb); + dev_kfree_skb_irq(data->sco_skb); data->sco_skb = NULL; spin_unlock_irqrestore(&data->rxlock, flags); @@ -4194,7 +4194,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); + match = usb_match_id(intf, quirks_table); if (match) id = match; } diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 011822519602..4b57e15f9c7a 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -607,9 +607,18 @@ static int qca_open(struct hci_uart *hu) if (hu->serdev) { qcadev = serdev_device_get_drvdata(hu->serdev); - if (qca_is_wcn399x(qcadev->btsoc_type) || - qca_is_wcn6750(qcadev->btsoc_type)) + switch (qcadev->btsoc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: hu->init_speed = qcadev->init_speed; + break; + + default: + break; + } if (qcadev->oper_speed) hu->oper_speed = qcadev->oper_speed; @@ -1341,12 +1350,20 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); /* Give the controller time to process the request */ - if (qca_is_wcn399x(qca_soc_type(hu)) || - qca_is_wcn6750(qca_soc_type(hu)) || - qca_is_wcn6855(qca_soc_type(hu))) + switch (qca_soc_type(hu)) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: usleep_range(1000, 10000); - else + break; + + default: msleep(300); + } return 0; } @@ -1419,13 +1436,20 @@ static unsigned int qca_get_speed(struct hci_uart *hu, static int qca_check_speeds(struct hci_uart *hu) { - if (qca_is_wcn399x(qca_soc_type(hu)) || - qca_is_wcn6750(qca_soc_type(hu)) || - qca_is_wcn6855(qca_soc_type(hu))) { + switch (qca_soc_type(hu)) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: if (!qca_get_speed(hu, QCA_INIT_SPEED) && !qca_get_speed(hu, QCA_OPER_SPEED)) return -EINVAL; - } else { + break; + + default: if (!qca_get_speed(hu, QCA_INIT_SPEED) || !qca_get_speed(hu, QCA_OPER_SPEED)) return -EINVAL; @@ -1454,14 +1478,29 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) /* Disable flow control for wcn3990 to deassert RTS while * changing the baudrate of chip and host. */ - if (qca_is_wcn399x(soc_type) || - qca_is_wcn6750(soc_type) || - qca_is_wcn6855(soc_type)) + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: hci_uart_set_flow_control(hu, true); + break; + + default: + break; + } - if (soc_type == QCA_WCN3990) { + switch (soc_type) { + case QCA_WCN3990: reinit_completion(&qca->drop_ev_comp); set_bit(QCA_DROP_VENDOR_EVENT, &qca->flags); + break; + + default: + break; } qca_baudrate = qca_get_baudrate_value(speed); @@ -1473,12 +1512,23 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) host_set_baudrate(hu, speed); error: - if (qca_is_wcn399x(soc_type) || - qca_is_wcn6750(soc_type) || - qca_is_wcn6855(soc_type)) + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: hci_uart_set_flow_control(hu, false); + break; - if (soc_type == QCA_WCN3990) { + default: + break; + } + + switch (soc_type) { + case QCA_WCN3990: /* Wait for the controller to send the vendor event * for the baudrate change command. */ @@ -1490,6 +1540,10 @@ error: } clear_bit(QCA_DROP_VENDOR_EVENT, &qca->flags); + break; + + default: + break; } } @@ -1651,12 +1705,20 @@ static int qca_regulator_init(struct hci_uart *hu) } } - if (qca_is_wcn399x(soc_type)) { + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: /* Forcefully enable wcn399x to enter in to boot mode. */ host_set_baudrate(hu, 2400); ret = qca_send_power_pulse(hu, false); if (ret) return ret; + break; + + default: + break; } /* For wcn6750 need to enable gpio bt_en */ @@ -1673,10 +1735,18 @@ static int qca_regulator_init(struct hci_uart *hu) qca_set_speed(hu, QCA_INIT_SPEED); - if (qca_is_wcn399x(soc_type)) { + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: ret = qca_send_power_pulse(hu, true); if (ret) return ret; + break; + + default: + break; } /* Now the device is in ready state to communicate with host. @@ -1710,11 +1780,18 @@ static int qca_power_on(struct hci_dev *hdev) if (!hu->serdev) return 0; - if (qca_is_wcn399x(soc_type) || - qca_is_wcn6750(soc_type) || - qca_is_wcn6855(soc_type)) { + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: ret = qca_regulator_init(hu); - } else { + break; + + default: qcadev = serdev_device_get_drvdata(hu->serdev); if (qcadev->bt_en) { gpiod_set_value_cansleep(qcadev->bt_en, 1); @@ -1748,6 +1825,7 @@ static int qca_setup(struct hci_uart *hu) const char *firmware_name = qca_get_firmware_name(hu); int ret; struct qca_btsoc_version ver; + const char *soc_name; ret = qca_check_speeds(hu); if (ret) @@ -1762,10 +1840,30 @@ static int qca_setup(struct hci_uart *hu) */ set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - bt_dev_info(hdev, "setting up %s", - qca_is_wcn399x(soc_type) ? "wcn399x" : - (soc_type == QCA_WCN6750) ? "wcn6750" : - (soc_type == QCA_WCN6855) ? "wcn6855" : "ROME/QCA6390"); + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + soc_name = "wcn399x"; + break; + + case QCA_WCN6750: + soc_name = "wcn6750"; + break; + + case QCA_WCN6855: + soc_name = "wcn6855"; + break; + + case QCA_WCN7850: + soc_name = "wcn7850"; + break; + + default: + soc_name = "ROME/QCA6390"; + } + bt_dev_info(hdev, "setting up %s", soc_name); qca->memdump_state = QCA_MEMDUMP_IDLE; @@ -1776,16 +1874,23 @@ retry: clear_bit(QCA_SSR_TRIGGERED, &qca->flags); - if (qca_is_wcn399x(soc_type) || - qca_is_wcn6750(soc_type) || - qca_is_wcn6855(soc_type)) { + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); hci_set_aosp_capable(hdev); ret = qca_read_soc_version(hdev, &ver, soc_type); if (ret) goto out; - } else { + break; + + default: qca_set_speed(hu, QCA_INIT_SPEED); } @@ -1799,9 +1904,17 @@ retry: qca_baudrate = qca_get_baudrate_value(speed); } - if (!(qca_is_wcn399x(soc_type) || - qca_is_wcn6750(soc_type) || - qca_is_wcn6855(soc_type))) { + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: + break; + + default: /* Get QCA version information */ ret = qca_read_soc_version(hdev, &ver, soc_type); if (ret) @@ -1955,6 +2068,20 @@ static const struct qca_device_data qca_soc_data_wcn6855 __maybe_unused = { .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, }; +static const struct qca_device_data qca_soc_data_wcn7850 __maybe_unused = { + .soc_type = QCA_WCN7850, + .vregs = (struct qca_vreg []) { + { "vddio", 5000 }, + { "vddaon", 26000 }, + { "vdddig", 126000 }, + { "vddrfa0p8", 102000 }, + { "vddrfa1p2", 257000 }, + { "vddrfa1p9", 302000 }, + }, + .num_vregs = 6, + .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, +}; + static void qca_power_shutdown(struct hci_uart *hu) { struct qca_serdev *qcadev; @@ -1980,11 +2107,18 @@ static void qca_power_shutdown(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); - if (qca_is_wcn399x(soc_type)) { + switch (soc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, false); qca_regulator_disable(qcadev); - } else if (soc_type == QCA_WCN6750 || soc_type == QCA_WCN6855) { + break; + + case QCA_WCN6750: + case QCA_WCN6855: gpiod_set_value_cansleep(qcadev->bt_en, 0); msleep(100); qca_regulator_disable(qcadev); @@ -1992,7 +2126,9 @@ static void qca_power_shutdown(struct hci_uart *hu) sw_ctrl_state = gpiod_get_value_cansleep(qcadev->sw_ctrl); bt_dev_dbg(hu->hdev, "SW_CTRL is %d", sw_ctrl_state); } - } else if (qcadev->bt_en) { + break; + + default: gpiod_set_value_cansleep(qcadev->bt_en, 0); } @@ -2117,11 +2253,19 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->oper_speed) BT_DBG("UART will pick default operating speed"); - if (data && - (qca_is_wcn399x(data->soc_type) || - qca_is_wcn6750(data->soc_type) || - qca_is_wcn6855(data->soc_type))) { + if (data) qcadev->btsoc_type = data->soc_type; + else + qcadev->btsoc_type = QCA_ROME; + + switch (qcadev->btsoc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: qcadev->bt_power = devm_kzalloc(&serdev->dev, sizeof(struct qca_power), GFP_KERNEL); @@ -2151,7 +2295,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) GPIOD_IN); if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && (data->soc_type == QCA_WCN6750 || - data->soc_type == QCA_WCN6855)) + data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_WCN7850)) dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); @@ -2165,12 +2310,9 @@ static int qca_serdev_probe(struct serdev_device *serdev) BT_ERR("wcn3990 serdev registration failed"); return err; } - } else { - if (data) - qcadev->btsoc_type = data->soc_type; - else - qcadev->btsoc_type = QCA_ROME; + break; + default: qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR_OR_NULL(qcadev->bt_en)) { @@ -2226,13 +2368,24 @@ static void qca_serdev_remove(struct serdev_device *serdev) struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); struct qca_power *power = qcadev->bt_power; - if ((qca_is_wcn399x(qcadev->btsoc_type) || - qca_is_wcn6750(qcadev->btsoc_type) || - qca_is_wcn6855(qcadev->btsoc_type)) && - power->vregs_on) - qca_power_shutdown(&qcadev->serdev_hu); - else if (qcadev->susclk) - clk_disable_unprepare(qcadev->susclk); + switch (qcadev->btsoc_type) { + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: + if (power->vregs_on) { + qca_power_shutdown(&qcadev->serdev_hu); + break; + } + fallthrough; + + default: + if (qcadev->susclk) + clk_disable_unprepare(qcadev->susclk); + } hci_uart_unregister_device(&qcadev->serdev_hu); } @@ -2415,6 +2568,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, { .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750}, { .compatible = "qcom,wcn6855-bt", .data = &qca_soc_data_wcn6855}, + { .compatible = "qcom,wcn7850-bt", .data = &qca_soc_data_wcn7850}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 5723405b833e..87d92accc26e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -319,6 +319,16 @@ enum { * This quirk must be set before hci_register_dev is called. */ HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, + + /* + * When this quirk is set, LE Coded PHY shall not be used. This is + * required for some Intel controllers which erroneously claim to + * support it but it causes problems with extended scanning. + * + * This quirk can be set before hci_register_dev is called or + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_BROKEN_LE_CODED, }; /* HCI device flags */ @@ -2771,6 +2781,17 @@ struct hci_ev_le_enh_conn_complete { __u8 clk_accurancy; } __packed; +#define HCI_EV_LE_PER_ADV_REPORT 0x0f +struct hci_ev_le_per_adv_report { + __le16 sync_handle; + __u8 tx_power; + __u8 rssi; + __u8 cte_type; + __u8 data_status; + __u8 length; + __u8 data[]; +} __packed; + #define HCI_EV_LE_EXT_ADV_SET_TERM 0x12 struct hci_evt_le_ext_adv_set_term { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index c53d74236e3a..e6359f7346f1 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -83,7 +83,7 @@ struct discovery_state { u8 last_adv_addr_type; s8 last_adv_rssi; u32 last_adv_flags; - u8 last_adv_data[HCI_MAX_AD_LENGTH]; + u8 last_adv_data[HCI_MAX_EXT_AD_LENGTH]; u8 last_adv_data_len; bool report_invalid_rssi; bool result_filtering; @@ -290,7 +290,7 @@ struct adv_pattern { __u8 ad_type; __u8 offset; __u8 length; - __u8 value[HCI_MAX_AD_LENGTH]; + __u8 value[HCI_MAX_EXT_AD_LENGTH]; }; struct adv_rssi_thresholds { @@ -726,7 +726,7 @@ struct hci_conn { __u16 le_conn_interval; __u16 le_conn_latency; __u16 le_supv_timeout; - __u8 le_adv_data[HCI_MAX_AD_LENGTH]; + __u8 le_adv_data[HCI_MAX_EXT_AD_LENGTH]; __u8 le_adv_data_len; __u8 le_per_adv_data[HCI_MAX_PER_AD_LENGTH]; __u8 le_per_adv_data_len; @@ -978,6 +978,8 @@ enum { HCI_CONN_CREATE_CIS, HCI_CONN_BIG_SYNC, HCI_CONN_BIG_SYNC_FAILED, + HCI_CONN_PA_SYNC, + HCI_CONN_PA_SYNC_FAILED, }; static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) @@ -1300,7 +1302,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_big_any_dst(struct hci_dev * if (c->type != ISO_LINK) continue; - if (handle == c->iso_qos.bcast.big) { + if (handle != BT_ISO_QOS_BIG_UNSET && handle == c->iso_qos.bcast.big) { rcu_read_unlock(); return c; } @@ -1311,6 +1313,29 @@ static inline struct hci_conn *hci_conn_hash_lookup_big_any_dst(struct hci_dev * return NULL; } +static inline struct hci_conn * +hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big) +{ + struct hci_conn_hash *h = &hdev->conn_hash; + struct hci_conn *c; + + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { + if (c->type != ISO_LINK || + !test_bit(HCI_CONN_PA_SYNC, &c->flags)) + continue; + + if (c->iso_qos.bcast.big == big) { + rcu_read_unlock(); + return c; + } + } + rcu_read_unlock(); + + return NULL; +} + static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, __u8 type, __u16 state) { @@ -1435,7 +1460,8 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 data_len, __u8 *data); int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, __u8 sid, struct bt_iso_qos *qos); -int hci_le_big_create_sync(struct hci_dev *hdev, struct bt_iso_qos *qos, +int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, + struct bt_iso_qos *qos, __u16 sync_handle, __u8 num_bis, __u8 bis[]); int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); @@ -1791,7 +1817,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define scan_2m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_2M) || \ ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_2M)) -#define le_coded_capable(dev) (((dev)->le_features[1] & HCI_LE_PHY_CODED)) +#define le_coded_capable(dev) (((dev)->le_features[1] & HCI_LE_PHY_CODED) && \ + !test_bit(HCI_QUIRK_BROKEN_LE_CODED, \ + &(dev)->quirks)) #define scan_coded(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_CODED) || \ ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED)) diff --git a/net/bluetooth/eir.c b/net/bluetooth/eir.c index 8a85f6cdfbc1..9214189279e8 100644 --- a/net/bluetooth/eir.c +++ b/net/bluetooth/eir.c @@ -33,7 +33,7 @@ u8 eir_append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len) size_t complete_len; /* no space left for name (+ NULL + type + len) */ - if ((HCI_MAX_AD_LENGTH - ad_len) < HCI_MAX_SHORT_NAME_LENGTH + 3) + if ((max_adv_len(hdev) - ad_len) < HCI_MAX_SHORT_NAME_LENGTH + 3) return ad_len; /* use complete name if present and fits */ diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 234746721047..9d5057cef30a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -734,6 +734,7 @@ struct iso_list_data { }; int count; bool big_term; + bool pa_sync_term; bool big_sync_term; }; @@ -807,7 +808,10 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data) if (d->big_sync_term) hci_le_big_terminate_sync(hdev, d->big); - return hci_le_pa_terminate_sync(hdev, d->sync_handle); + if (d->pa_sync_term) + return hci_le_pa_terminate_sync(hdev, d->sync_handle); + + return 0; } static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn) @@ -823,6 +827,7 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c d->big = big; d->sync_handle = conn->sync_handle; + d->pa_sync_term = test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags); d->big_sync_term = test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags); ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d, @@ -1039,6 +1044,29 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, return conn; } +static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason) +{ + if (!reason) + reason = HCI_ERROR_REMOTE_USER_TERM; + + /* Due to race, SCO/ISO conn might be not established yet at this point, + * and nothing else will clean it up. In other cases it is done via HCI + * events. + */ + switch (conn->type) { + case SCO_LINK: + case ESCO_LINK: + if (HCI_CONN_HANDLE_UNSET(conn->handle)) + hci_conn_failed(conn, reason); + break; + case ISO_LINK: + if (conn->state != BT_CONNECTED && + !test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) + hci_conn_failed(conn, reason); + break; + } +} + static void hci_conn_unlink(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; @@ -1061,14 +1089,7 @@ static void hci_conn_unlink(struct hci_conn *conn) if (!test_bit(HCI_UP, &hdev->flags)) continue; - /* Due to race, SCO connection might be not established - * yet at this point. Delete it now, otherwise it is - * possible for it to be stuck and can't be deleted. - */ - if ((child->type == SCO_LINK || - child->type == ESCO_LINK) && - HCI_CONN_HANDLE_UNSET(child->handle)) - hci_conn_del(child); + hci_conn_cleanup_child(child, conn->abort_reason); } return; @@ -1299,6 +1320,7 @@ static int hci_connect_le_sync(struct hci_dev *hdev, void *data) bt_dev_dbg(hdev, "conn %p", conn); + clear_bit(HCI_CONN_SCANNING, &conn->flags); conn->state = BT_CONNECT; return hci_le_create_conn_sync(hdev, conn); @@ -1370,8 +1392,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->sec_level = BT_SECURITY_LOW; conn->conn_timeout = conn_timeout; - clear_bit(HCI_CONN_SCANNING, &conn->flags); - err = hci_cmd_sync_queue(hdev, hci_connect_le_sync, UINT_PTR(conn->handle), create_le_conn_complete); @@ -2100,7 +2120,8 @@ int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, return hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete); } -int hci_le_big_create_sync(struct hci_dev *hdev, struct bt_iso_qos *qos, +int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon, + struct bt_iso_qos *qos, __u16 sync_handle, __u8 num_bis, __u8 bis[]) { struct _packed { @@ -2116,6 +2137,9 @@ int hci_le_big_create_sync(struct hci_dev *hdev, struct bt_iso_qos *qos, if (err) return err; + if (hcon) + hcon->iso_qos.bcast.big = qos->bcast.big; + memset(&pdu, 0, sizeof(pdu)); pdu.cp.handle = qos->bcast.big; pdu.cp.sync_handle = cpu_to_le16(sync_handle); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 559b6080706c..35f251041eeb 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6581,19 +6581,56 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, struct hci_ev_le_pa_sync_established *ev = data; int mask = hdev->link_mode; __u8 flags = 0; + struct hci_conn *bis; bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); - if (ev->status) - return; - hci_dev_lock(hdev); hci_dev_clear_flag(hdev, HCI_PA_SYNC); mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ISO_LINK, &flags); - if (!(mask & HCI_LM_ACCEPT)) + if (!(mask & HCI_LM_ACCEPT)) { hci_le_pa_term_sync(hdev, ev->handle); + goto unlock; + } + + if (!(flags & HCI_PROTO_DEFER)) + goto unlock; + + /* Add connection to indicate the PA sync event */ + bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY, + HCI_ROLE_SLAVE); + + if (!bis) + goto unlock; + + if (ev->status) + set_bit(HCI_CONN_PA_SYNC_FAILED, &bis->flags); + else + set_bit(HCI_CONN_PA_SYNC, &bis->flags); + + /* Notify connection to iso layer */ + hci_connect_cfm(bis, ev->status); + +unlock: + hci_dev_unlock(hdev); +} + +static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) +{ + struct hci_ev_le_per_adv_report *ev = data; + int mask = hdev->link_mode; + __u8 flags = 0; + + bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle)); + + hci_dev_lock(hdev); + + mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags); + if (!(mask & HCI_LM_ACCEPT)) + hci_le_pa_term_sync(hdev, ev->sync_handle); hci_dev_unlock(hdev); } @@ -7045,6 +7082,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, { struct hci_evt_le_big_sync_estabilished *ev = data; struct hci_conn *bis; + struct hci_conn *pa_sync; int i; bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); @@ -7055,6 +7093,15 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, hci_dev_lock(hdev); + if (!ev->status) { + pa_sync = hci_conn_hash_lookup_pa_sync(hdev, ev->handle); + if (pa_sync) + /* Also mark the BIG sync established event on the + * associated PA sync hcon + */ + set_bit(HCI_CONN_BIG_SYNC, &pa_sync->flags); + } + for (i = 0; i < ev->num_bis; i++) { u16 handle = le16_to_cpu(ev->bis[i]); __le32 interval; @@ -7068,6 +7115,10 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, bis->handle = handle; } + if (ev->status != 0x42) + /* Mark PA sync as established */ + set_bit(HCI_CONN_PA_SYNC, &bis->flags); + bis->iso_qos.bcast.big = ev->handle; memset(&interval, 0, sizeof(interval)); memcpy(&interval, ev->latency, sizeof(ev->latency)); @@ -7180,6 +7231,11 @@ static const struct hci_le_ev { HCI_LE_EV(HCI_EV_LE_PA_SYNC_ESTABLISHED, hci_le_pa_sync_estabilished_evt, sizeof(struct hci_ev_le_pa_sync_established)), + /* [0x0f = HCI_EV_LE_PER_ADV_REPORT] */ + HCI_LE_EV_VL(HCI_EV_LE_PER_ADV_REPORT, + hci_le_per_adv_report_evt, + sizeof(struct hci_ev_le_per_adv_report), + HCI_MAX_EVENT_SIZE), /* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */ HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt, sizeof(struct hci_evt_le_ext_adv_set_term)), diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 5eb30ba21370..9b93653c6197 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -4668,7 +4668,10 @@ static const struct { "advertised, but not supported."), HCI_QUIRK_BROKEN(SET_RPA_TIMEOUT, "HCI LE Set Random Private Address Timeout command is " - "advertised, but not supported.") + "advertised, but not supported."), + HCI_QUIRK_BROKEN(LE_CODED, + "HCI LE Coded PHY feature bit is set, " + "but its usage is not supported.") }; /* This function handles hdev setup stage: @@ -5370,6 +5373,7 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason) { int err = 0; u16 handle = conn->handle; + struct hci_conn *c; switch (conn->state) { case BT_CONNECTED: @@ -5383,49 +5387,78 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason) err = hci_reject_conn_sync(hdev, conn, reason); break; case BT_OPEN: + hci_dev_lock(hdev); + + /* Cleanup bis or pa sync connections */ + if (test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn->flags) || + test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn->flags)) { + hci_conn_failed(conn, reason); + } else if (test_bit(HCI_CONN_PA_SYNC, &conn->flags) || + test_bit(HCI_CONN_BIG_SYNC, &conn->flags)) { + conn->state = BT_CLOSED; + hci_disconn_cfm(conn, reason); + hci_conn_del(conn); + } + + hci_dev_unlock(hdev); + return 0; case BT_BOUND: hci_dev_lock(hdev); hci_conn_failed(conn, reason); hci_dev_unlock(hdev); return 0; default: + hci_dev_lock(hdev); conn->state = BT_CLOSED; + hci_disconn_cfm(conn, reason); + hci_conn_del(conn); + hci_dev_unlock(hdev); return 0; } + hci_dev_lock(hdev); + + /* Check if the connection hasn't been cleanup while waiting + * commands to complete. + */ + c = hci_conn_hash_lookup_handle(hdev, handle); + if (!c || c != conn) { + err = 0; + goto unlock; + } + /* Cleanup hci_conn object if it cannot be cancelled as it * likelly means the controller and host stack are out of sync * or in case of LE it was still scanning so it can be cleanup * safely. */ - if (err) { - struct hci_conn *c; - - /* Check if the connection hasn't been cleanup while waiting - * commands to complete. - */ - c = hci_conn_hash_lookup_handle(hdev, handle); - if (!c || c != conn) - return 0; - - hci_dev_lock(hdev); - hci_conn_failed(conn, err); - hci_dev_unlock(hdev); - } + hci_conn_failed(conn, reason); +unlock: + hci_dev_unlock(hdev); return err; } static int hci_disconnect_all_sync(struct hci_dev *hdev, u8 reason) { - struct hci_conn *conn, *tmp; - int err; + struct list_head *head = &hdev->conn_hash.list; + struct hci_conn *conn; - list_for_each_entry_safe(conn, tmp, &hdev->conn_hash.list, list) { - err = hci_abort_conn_sync(hdev, conn, reason); - if (err) - return err; + rcu_read_lock(); + while ((conn = list_first_or_null_rcu(head, struct hci_conn, list))) { + /* Make sure the connection is not freed while unlocking */ + conn = hci_conn_get(conn); + rcu_read_unlock(); + /* Disregard possible errors since hci_conn_del shall have been + * called even in case of errors had occurred since it would + * then cause hci_conn_failed to be called which calls + * hci_conn_del internally. + */ + hci_abort_conn_sync(hdev, conn, reason); + hci_conn_put(conn); + rcu_read_lock(); } + rcu_read_unlock(); return 0; } diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 3c03e49422c7..16da946f5881 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -51,6 +51,7 @@ static void iso_sock_kill(struct sock *sk); /* iso_pinfo flags values */ enum { BT_SK_BIG_SYNC, + BT_SK_PA_SYNC, }; struct iso_pinfo { @@ -75,6 +76,8 @@ static struct bt_iso_qos default_qos; static bool check_ucast_qos(struct bt_iso_qos *qos); static bool check_bcast_qos(struct bt_iso_qos *qos); +static bool iso_match_sid(struct sock *sk, void *data); +static void iso_sock_disconn(struct sock *sk); /* ---- ISO timers ---- */ #define ISO_CONN_TIMEOUT (HZ * 40) @@ -598,6 +601,15 @@ static void iso_sock_cleanup_listen(struct sock *parent) iso_sock_kill(sk); } + /* If listening socket stands for a PA sync connection, + * properly disconnect the hcon and socket. + */ + if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon && + test_bit(HCI_CONN_PA_SYNC, &iso_pi(parent)->conn->hcon->flags)) { + iso_sock_disconn(parent); + return; + } + parent->sk_state = BT_CLOSED; sock_set_flag(parent, SOCK_ZAPPED); } @@ -619,6 +631,16 @@ static void iso_sock_kill(struct sock *sk) sock_put(sk); } +static void iso_sock_disconn(struct sock *sk) +{ + sk->sk_state = BT_DISCONN; + iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT); + iso_conn_lock(iso_pi(sk)->conn); + hci_conn_drop(iso_pi(sk)->conn->hcon); + iso_pi(sk)->conn->hcon = NULL; + iso_conn_unlock(iso_pi(sk)->conn); +} + static void __iso_sock_close(struct sock *sk) { BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); @@ -631,20 +653,19 @@ static void __iso_sock_close(struct sock *sk) case BT_CONNECT: case BT_CONNECTED: case BT_CONFIG: - if (iso_pi(sk)->conn->hcon) { - sk->sk_state = BT_DISCONN; - iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT); - iso_conn_lock(iso_pi(sk)->conn); - hci_conn_drop(iso_pi(sk)->conn->hcon); - iso_pi(sk)->conn->hcon = NULL; - iso_conn_unlock(iso_pi(sk)->conn); - } else { + if (iso_pi(sk)->conn->hcon) + iso_sock_disconn(sk); + else iso_chan_del(sk, ECONNRESET); - } break; case BT_CONNECT2: - iso_chan_del(sk, ECONNRESET); + if (iso_pi(sk)->conn->hcon && + (test_bit(HCI_CONN_PA_SYNC, &iso_pi(sk)->conn->hcon->flags) || + test_bit(HCI_CONN_PA_SYNC_FAILED, &iso_pi(sk)->conn->hcon->flags))) + iso_sock_disconn(sk); + else + iso_chan_del(sk, ECONNRESET); break; case BT_DISCONN: iso_chan_del(sk, ECONNRESET); @@ -1139,6 +1160,29 @@ static void iso_conn_defer_accept(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_LE_ACCEPT_CIS, sizeof(cp), &cp); } +static void iso_conn_big_sync(struct sock *sk) +{ + int err; + struct hci_dev *hdev; + + hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src, + iso_pi(sk)->src_type); + + if (!hdev) + return; + + if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) { + err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon, + &iso_pi(sk)->qos, + iso_pi(sk)->sync_handle, + iso_pi(sk)->bc_num_bis, + iso_pi(sk)->bc_bis); + if (err) + bt_dev_err(hdev, "hci_le_big_create_sync: %d", + err); + } +} + static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags) { @@ -1151,8 +1195,15 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg, lock_sock(sk); switch (sk->sk_state) { case BT_CONNECT2: - iso_conn_defer_accept(pi->conn->hcon); - sk->sk_state = BT_CONFIG; + if (pi->conn->hcon && + test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) { + iso_conn_big_sync(sk); + sk->sk_state = BT_LISTEN; + set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags); + } else { + iso_conn_defer_accept(pi->conn->hcon); + sk->sk_state = BT_CONFIG; + } release_sock(sk); return 0; case BT_CONNECT: @@ -1395,7 +1446,8 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname, break; case BT_ISO_BASE: - if (sk->sk_state == BT_CONNECTED) { + if (sk->sk_state == BT_CONNECTED && + !bacmp(&iso_pi(sk)->dst, BDADDR_ANY)) { base_len = iso_pi(sk)->conn->hcon->le_per_adv_data_len; base = iso_pi(sk)->conn->hcon->le_per_adv_data; } else { @@ -1513,11 +1565,17 @@ static bool iso_match_big(struct sock *sk, void *data) return ev->handle == iso_pi(sk)->qos.bcast.big; } +static bool iso_match_pa_sync_flag(struct sock *sk, void *data) +{ + return test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags); +} + static void iso_conn_ready(struct iso_conn *conn) { - struct sock *parent; + struct sock *parent = NULL; struct sock *sk = conn->sk; - struct hci_ev_le_big_sync_estabilished *ev; + struct hci_ev_le_big_sync_estabilished *ev = NULL; + struct hci_ev_le_pa_sync_established *ev2 = NULL; struct hci_conn *hcon; BT_DBG("conn %p", conn); @@ -1529,15 +1587,32 @@ static void iso_conn_ready(struct iso_conn *conn) if (!hcon) return; - ev = hci_recv_event_data(hcon->hdev, - HCI_EVT_LE_BIG_SYNC_ESTABILISHED); - if (ev) + if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags) || + test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) { + ev = hci_recv_event_data(hcon->hdev, + HCI_EVT_LE_BIG_SYNC_ESTABILISHED); + + /* Get reference to PA sync parent socket, if it exists */ parent = iso_get_sock_listen(&hcon->src, &hcon->dst, - iso_match_big, ev); - else + iso_match_pa_sync_flag, NULL); + if (!parent && ev) + parent = iso_get_sock_listen(&hcon->src, + &hcon->dst, + iso_match_big, ev); + } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags) || + test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) { + ev2 = hci_recv_event_data(hcon->hdev, + HCI_EV_LE_PA_SYNC_ESTABLISHED); + if (ev2) + parent = iso_get_sock_listen(&hcon->src, + &hcon->dst, + iso_match_sid, ev2); + } + + if (!parent) parent = iso_get_sock_listen(&hcon->src, - BDADDR_ANY, NULL, NULL); + BDADDR_ANY, NULL, NULL); if (!parent) return; @@ -1554,11 +1629,17 @@ static void iso_conn_ready(struct iso_conn *conn) iso_sock_init(sk, parent); bacpy(&iso_pi(sk)->src, &hcon->src); - iso_pi(sk)->src_type = hcon->src_type; + + /* Convert from HCI to three-value type */ + if (hcon->src_type == ADDR_LE_DEV_PUBLIC) + iso_pi(sk)->src_type = BDADDR_LE_PUBLIC; + else + iso_pi(sk)->src_type = BDADDR_LE_RANDOM; /* If hcon has no destination address (BDADDR_ANY) it means it - * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we need to - * initialize using the parent socket destination address. + * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED or + * HCI_EV_LE_PA_SYNC_ESTABLISHED so we need to initialize using + * the parent socket destination address. */ if (!bacmp(&hcon->dst, BDADDR_ANY)) { bacpy(&hcon->dst, &iso_pi(parent)->dst); @@ -1566,13 +1647,24 @@ static void iso_conn_ready(struct iso_conn *conn) hcon->sync_handle = iso_pi(parent)->sync_handle; } + if (ev2 && !ev2->status) { + iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle; + iso_pi(sk)->qos = iso_pi(parent)->qos; + iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis; + memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS); + } + bacpy(&iso_pi(sk)->dst, &hcon->dst); iso_pi(sk)->dst_type = hcon->dst_type; + iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle; + memcpy(iso_pi(sk)->base, iso_pi(parent)->base, iso_pi(parent)->base_len); + iso_pi(sk)->base_len = iso_pi(parent)->base_len; hci_conn_hold(hcon); iso_chan_add(conn, sk, parent); - if (ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) { + if ((ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) || + (ev2 && ev2->status)) { /* Trigger error signal on child socket */ sk->sk_err = ECONNREFUSED; sk->sk_error_report(sk); @@ -1604,12 +1696,20 @@ static bool iso_match_sync_handle(struct sock *sk, void *data) return le16_to_cpu(ev->sync_handle) == iso_pi(sk)->sync_handle; } +static bool iso_match_sync_handle_pa_report(struct sock *sk, void *data) +{ + struct hci_ev_le_per_adv_report *ev = data; + + return le16_to_cpu(ev->sync_handle) == iso_pi(sk)->sync_handle; +} + /* ----- ISO interface with lower layer (HCI) ----- */ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) { struct hci_ev_le_pa_sync_established *ev1; struct hci_evt_le_big_info_adv_report *ev2; + struct hci_ev_le_per_adv_report *ev3; struct sock *sk; int lm = 0; @@ -1625,12 +1725,15 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) * 2. HCI_EVT_LE_BIG_INFO_ADV_REPORT: When connect_ind is triggered by a * a BIG Info it attempts to check if there any listening socket with * the same sync_handle and if it does then attempt to create a sync. + * 3. HCI_EV_LE_PER_ADV_REPORT: When a PA report is received, it is stored + * in iso_pi(sk)->base so it can be passed up to user, in the case of a + * broadcast sink. */ ev1 = hci_recv_event_data(hdev, HCI_EV_LE_PA_SYNC_ESTABLISHED); if (ev1) { sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, iso_match_sid, ev1); - if (sk) + if (sk && !ev1->status) iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle); goto done; @@ -1638,16 +1741,21 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT); if (ev2) { + /* Try to get PA sync listening socket, if it exists */ sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, - iso_match_sync_handle, ev2); + iso_match_pa_sync_flag, NULL); + if (!sk) + sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, + iso_match_sync_handle, ev2); if (sk) { int err; if (ev2->num_bis < iso_pi(sk)->bc_num_bis) iso_pi(sk)->bc_num_bis = ev2->num_bis; - if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) { - err = hci_le_big_create_sync(hdev, + if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) && + !test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) { + err = hci_le_big_create_sync(hdev, NULL, &iso_pi(sk)->qos, iso_pi(sk)->sync_handle, iso_pi(sk)->bc_num_bis, @@ -1659,6 +1767,17 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) } } } + } + + ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT); + if (ev3) { + sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, + iso_match_sync_handle_pa_report, ev3); + + if (sk) { + memcpy(iso_pi(sk)->base, ev3->data, ev3->length); + iso_pi(sk)->base_len = ev3->length; + } } else { sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL); } @@ -1699,12 +1818,13 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); - /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED is set, - * queue the failed bis connection into the accept queue of the - * listening socket and wake up userspace, to inform the user about - * the BIG sync failed event. + /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED or + * HCI_CONN_PA_SYNC_FAILED is set, queue the failed connection + * into the accept queue of the listening socket and wake up + * userspace, to inform the user about the event. */ - if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) { + if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags) || + test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) { struct iso_conn *conn; conn = iso_conn_add(hcon); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index d6c9b7bc8592..ba2e00646e8e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5381,9 +5381,9 @@ static u8 parse_adv_monitor_pattern(struct adv_monitor *m, u8 pattern_count, for (i = 0; i < pattern_count; i++) { offset = patterns[i].offset; length = patterns[i].length; - if (offset >= HCI_MAX_AD_LENGTH || - length > HCI_MAX_AD_LENGTH || - (offset + length) > HCI_MAX_AD_LENGTH) + if (offset >= HCI_MAX_EXT_AD_LENGTH || + length > HCI_MAX_EXT_AD_LENGTH || + (offset + length) > HCI_MAX_EXT_AD_LENGTH) return MGMT_STATUS_INVALID_PARAMS; p = kmalloc(sizeof(*p), GFP_KERNEL); |