diff options
| -rw-r--r-- | drivers/bluetooth/btbcm.c | 11 | ||||
| -rw-r--r-- | drivers/bluetooth/btintel.c | 109 | ||||
| -rw-r--r-- | drivers/bluetooth/btintel.h | 20 | ||||
| -rw-r--r-- | drivers/bluetooth/btintel_pcie.c | 122 | ||||
| -rw-r--r-- | drivers/bluetooth/btintel_pcie.h | 3 | ||||
| -rw-r--r-- | drivers/bluetooth/btmtk.c | 115 | ||||
| -rw-r--r-- | drivers/bluetooth/btmtk.h | 9 | ||||
| -rw-r--r-- | drivers/bluetooth/btmtksdio.c | 44 | ||||
| -rw-r--r-- | drivers/bluetooth/btqca.c | 37 | ||||
| -rw-r--r-- | drivers/bluetooth/btusb.c | 84 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 3 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_ll.c | 10 | ||||
| -rw-r--r-- | drivers/bluetooth/hci_qca.c | 84 | ||||
| -rw-r--r-- | include/linux/mmc/sdio_ids.h | 1 | ||||
| -rw-r--r-- | include/net/bluetooth/hci.h | 16 | ||||
| -rw-r--r-- | net/bluetooth/hci_conn.c | 4 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 4 | ||||
| -rw-r--r-- | net/bluetooth/hci_event.c | 21 | ||||
| -rw-r--r-- | net/bluetooth/hci_sync.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/l2cap_core.c | 15 | ||||
| -rw-r--r-- | net/bluetooth/sco.c | 3 |
21 files changed, 476 insertions, 241 deletions
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index d33cc70eec66..463d59890bef 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -223,7 +223,7 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) err = PTR_ERR(skb); bt_dev_err(hdev, "BCM: Download Minidrv command failed (%d)", err); - goto done; + return err; } kfree_skb(skb); @@ -242,8 +242,7 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) if (fw_size < cmd->plen) { bt_dev_err(hdev, "BCM: Patch is corrupted"); - err = -EINVAL; - goto done; + return -EINVAL; } cmd_param = fw_ptr; @@ -258,7 +257,7 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) err = PTR_ERR(skb); bt_dev_err(hdev, "BCM: Patch command %04x failed (%d)", opcode, err); - goto done; + return err; } kfree_skb(skb); } @@ -266,8 +265,7 @@ int btbcm_patchram(struct hci_dev *hdev, const struct firmware *fw) /* 250 msec delay after Launch Ram completes */ msleep(250); -done: - return err; + return 0; } EXPORT_SYMBOL(btbcm_patchram); @@ -507,6 +505,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x6119, "BCM4345C0" }, /* 003.001.025 */ { 0x6606, "BCM4345C5" }, /* 003.006.006 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */ + { 0x2310, "BCM4343A2" }, /* 001.003.016 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */ { 0x420d, "BCM4349B1" }, /* 002.002.013 */ { 0x420e, "BCM4349B1" }, /* 002.002.014 */ diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index ab146894ba4e..dcaaa4ca02b9 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -35,6 +35,19 @@ enum { DSM_SET_RESET_METHOD = 3, }; +/* Hybrid ECDSA + LMS */ +#define BTINTEL_RSA_HEADER_VER 0x00010000 +#define BTINTEL_ECDSA_HEADER_VER 0x00020000 +#define BTINTEL_HYBRID_HEADER_VER 0x00069700 +#define BTINTEL_ECDSA_OFFSET 128 +#define BTINTEL_CSS_HEADER_SIZE 128 +#define BTINTEL_ECDSA_PUB_KEY_SIZE 96 +#define BTINTEL_ECDSA_SIG_SIZE 96 +#define BTINTEL_LMS_OFFSET 320 +#define BTINTEL_LMS_PUB_KEY_SIZE 52 +#define BTINTEL_LMS_SIG_SIZE 1744 +#define BTINTEL_CMD_BUFFER_OFFSET 2116 + #define BTINTEL_BT_DOMAIN 0x12 #define BTINTEL_SAR_LEGACY 0 #define BTINTEL_SAR_INC_PWR 1 @@ -489,6 +502,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev, case 0x1d: /* BlazarU (BzrU) */ case 0x1e: /* BlazarI (Bzr) */ case 0x1f: /* Scorpious Peak */ + case 0x20: /* Scorpious Peak2 */ + case 0x21: /* Scorpious Peak2 F */ case 0x22: /* BlazarIW (BzrIW) */ break; default: @@ -510,8 +525,8 @@ int btintel_version_info_tlv(struct hci_dev *hdev, return -EINVAL; } - /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */ - if (version->sbe_type > 0x01) { + /* Secure boot engine type can be 0 (RSA), 1 (ECDSA), 2 (LMS), 3 (ECDSA + LMS) */ + if (version->sbe_type > 0x03) { bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)", version->sbe_type); return -EINVAL; @@ -1030,6 +1045,48 @@ static int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev, return 0; } +static int btintel_sfi_hybrid_header_secure_send(struct hci_dev *hdev, + const struct firmware *fw) +{ + int err; + + err = btintel_secure_send(hdev, 0x00, BTINTEL_CSS_HEADER_SIZE, fw->data); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware CSS header (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x03, BTINTEL_ECDSA_PUB_KEY_SIZE, + fw->data + BTINTEL_ECDSA_OFFSET); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware ECDSA pkey (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x02, BTINTEL_ECDSA_SIG_SIZE, + fw->data + BTINTEL_ECDSA_OFFSET + BTINTEL_ECDSA_PUB_KEY_SIZE); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware ECDSA signature (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x05, BTINTEL_LMS_PUB_KEY_SIZE, + fw->data + BTINTEL_LMS_OFFSET); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware LMS pkey (%d)", err); + return err; + } + + err = btintel_secure_send(hdev, 0x04, BTINTEL_LMS_SIG_SIZE, + fw->data + BTINTEL_LMS_OFFSET + BTINTEL_LMS_PUB_KEY_SIZE); + if (err < 0) { + bt_dev_err(hdev, "Failed to send firmware LMS signature (%d)", err); + return err; + } + + return 0; +} + static int btintel_download_firmware_payload(struct hci_dev *hdev, const struct firmware *fw, size_t offset) @@ -1203,11 +1260,12 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, * Command Buffer. * * CSS Header byte positions 0x08 to 0x0B represent the CSS Header - * version: RSA(0x00010000) , ECDSA (0x00020000) + * version: RSA(0x00010000) , ECDSA (0x00020000) , HYBRID (0x00069700) */ css_header_ver = get_unaligned_le32(fw->data + CSS_HEADER_OFFSET); - if (css_header_ver != 0x00010000) { - bt_dev_err(hdev, "Invalid CSS Header version"); + if (css_header_ver != BTINTEL_RSA_HEADER_VER && + css_header_ver != BTINTEL_HYBRID_HEADER_VER) { + bt_dev_err(hdev, "Invalid CSS Header version: 0x%8.8x", css_header_ver); return -EINVAL; } @@ -1225,15 +1283,15 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); if (err) return err; - } else if (hw_variant >= 0x17) { + } else if (hw_variant >= 0x17 && css_header_ver == BTINTEL_RSA_HEADER_VER) { /* Check if CSS header for ECDSA follows the RSA header */ if (fw->data[ECDSA_OFFSET] != 0x06) return -EINVAL; /* Check if the CSS Header version is ECDSA(0x00020000) */ css_header_ver = get_unaligned_le32(fw->data + ECDSA_OFFSET + CSS_HEADER_OFFSET); - if (css_header_ver != 0x00020000) { - bt_dev_err(hdev, "Invalid CSS Header version"); + if (css_header_ver != BTINTEL_ECDSA_HEADER_VER) { + bt_dev_err(hdev, "Invalid CSS Header version: 0x%8.8x", css_header_ver); return -EINVAL; } @@ -1256,6 +1314,14 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, if (err) return err; } + } else if (hw_variant >= 0x20 && css_header_ver == BTINTEL_HYBRID_HEADER_VER) { + err = btintel_sfi_hybrid_header_secure_send(hdev, fw); + if (err) + return err; + + err = btintel_download_firmware_payload(hdev, fw, BTINTEL_CMD_BUFFER_OFFSET); + if (err) + return err; } return 0; } @@ -2754,35 +2820,40 @@ static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver) struct btintel_dsbr_cmd cmd; struct sk_buff *skb; - u32 dsbr, cnvi; - u8 status; + u32 dsbr; + u8 status, hw_variant; int err; - cnvi = ver->cnvi_top & 0xfff; + hw_variant = INTEL_HW_VARIANT(ver->cnvi_bt); /* DSBR command needs to be sent for, * 1. BlazarI or BlazarIW + B0 step product in IML image. * 2. Gale Peak2 or BlazarU in OP image. * 3. Scorpious Peak in IML image. + * 4. Scorpious Peak2 onwards + PCIe transport in IML image. */ - switch (cnvi) { - case BTINTEL_CNVI_BLAZARI: - case BTINTEL_CNVI_BLAZARIW: + switch (hw_variant) { + case BTINTEL_HWID_BZRI: + case BTINTEL_HWID_BZRIW: if (ver->img_type == BTINTEL_IMG_IML && INTEL_CNVX_TOP_STEP(ver->cnvi_top) == 0x01) break; return 0; - case BTINTEL_CNVI_GAP: - case BTINTEL_CNVI_BLAZARU: + case BTINTEL_HWID_GAP: + case BTINTEL_HWID_BZRU: if (ver->img_type == BTINTEL_IMG_OP && hdev->bus == HCI_USB) break; return 0; - case BTINTEL_CNVI_SCP: + case BTINTEL_HWID_SCP: if (ver->img_type == BTINTEL_IMG_IML) break; return 0; default: + /* Scorpius Peak2 onwards */ + if (hw_variant >= BTINTEL_HWID_SCP2 && hdev->bus == HCI_PCI + && ver->img_type == BTINTEL_IMG_IML) + break; return 0; } @@ -3259,6 +3330,8 @@ void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant) case 0x1d: case 0x1e: case 0x1f: + case 0x20: + case 0x21: case 0x22: hci_set_msft_opcode(hdev, 0xFC1E); break; @@ -3600,6 +3673,8 @@ static int btintel_setup_combined(struct hci_dev *hdev) case 0x1d: case 0x1e: case 0x1f: + case 0x20: + case 0x21: case 0x22: /* Display version information of TLV type */ btintel_version_info_tlv(hdev, &ver_tlv); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 431998049e68..0e9ca99aaaae 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -54,11 +54,13 @@ struct intel_tlv { #define BTINTEL_HCI_OP_RESET 0xfc01 -#define BTINTEL_CNVI_BLAZARI 0x900 -#define BTINTEL_CNVI_BLAZARIW 0x901 -#define BTINTEL_CNVI_GAP 0x910 -#define BTINTEL_CNVI_BLAZARU 0x930 -#define BTINTEL_CNVI_SCP 0xA00 +#define BTINTEL_CNVI_BLAZARI 0x900 /* BlazarI - Lunar Lake */ +#define BTINTEL_CNVI_BLAZARIW 0x901 /* BlazarIW - Wildcat Lake */ +#define BTINTEL_CNVI_GAP 0x910 /* Gale Peak2 - Meteor Lake */ +#define BTINTEL_CNVI_BLAZARU 0x930 /* BlazarU - Meteor Lake */ +#define BTINTEL_CNVI_SCP 0xA00 /* Scorpius Peak - Panther Lake */ +#define BTINTEL_CNVI_SCP2 0xA10 /* Scorpius Peak2 - Nova Lake */ +#define BTINTEL_CNVI_SCP2F 0xA20 /* Scorpius Peak2F - Nova Lake */ /* CNVR */ #define BTINTEL_CNVR_FMP2 0x910 @@ -69,6 +71,14 @@ struct intel_tlv { #define BTINTEL_FWID_MAXLEN 64 +/* CNVi Hardware variant */ +#define BTINTEL_HWID_GAP 0x1c /* Gale Peak2 - Meteor Lake */ +#define BTINTEL_HWID_BZRI 0x1e /* BlazarI - Lunar Lake */ +#define BTINTEL_HWID_BZRU 0x1d /* BlazarU - Meteor Lake */ +#define BTINTEL_HWID_SCP 0x1f /* Scorpius Peak - Panther Lake */ +#define BTINTEL_HWID_SCP2 0x20 /* Scorpius Peak2 - Nova Lake */ +#define BTINTEL_HWID_BZRIW 0x22 /* BlazarIW - Wildcat Lake */ + struct intel_version_tlv { u32 cnvi_top; u32 cnvr_top; diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 37b744e35bc4..2f59c0d6f9ec 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -9,7 +9,9 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/firmware.h> +#include <linux/overflow.h> #include <linux/pci.h> +#include <linux/string.h> #include <linux/wait.h> #include <linux/delay.h> #include <linux/interrupt.h> @@ -35,6 +37,8 @@ #define POLL_INTERVAL_US 10 +#define BTINTEL_PCIE_DMA_ALIGN_128B 128 /* 128 byte aligned */ + /* Intel Bluetooth PCIe device id table */ static const struct pci_device_id btintel_pcie_table[] = { /* BlazarI, Wildcat Lake */ @@ -45,6 +49,10 @@ static const struct pci_device_id btintel_pcie_table[] = { { BTINTEL_PCI_DEVICE(0xE376, PCI_ANY_ID) }, /* Scorpious, Panther Lake-H404 */ { BTINTEL_PCI_DEVICE(0xE476, PCI_ANY_ID) }, + /* Scorpious2, Nova Lake-PCD-H */ + { BTINTEL_PCI_DEVICE(0xD346, PCI_ANY_ID) }, + /* Scorpious2, Nova Lake-PCD-S */ + { BTINTEL_PCI_DEVICE(0x6E74, PCI_ANY_ID) }, { 0 } }; MODULE_DEVICE_TABLE(pci, btintel_pcie_table); @@ -72,6 +80,9 @@ struct btintel_pcie_dev_recovery { #define BTINTEL_PCIE_SCP_HWEXP_SIZE 4096 #define BTINTEL_PCIE_SCP_HWEXP_DMP_ADDR 0xB030F800 +#define BTINTEL_PCIE_SCP2_HWEXP_SIZE 4096 +#define BTINTEL_PCIE_SCP2_HWEXP_DMP_ADDR 0xB031D000 + #define BTINTEL_PCIE_MAGIC_NUM 0xA5A5A5A5 #define BTINTEL_PCIE_TRIGGER_REASON_USER_TRIGGER 0x17A2 @@ -268,7 +279,7 @@ static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev) if (!skb) return; - snprintf(buf, sizeof(buf), "%s", "---- Dump of debug registers ---"); + strscpy(buf, "---- Dump of debug registers ---"); bt_dev_dbg(hdev, "%s", buf); skb_put_data(skb, buf, strlen(buf)); @@ -340,7 +351,7 @@ static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev) snprintf(buf, sizeof(buf), "txq: cr_tia: %u cr_hia: %u", cr_tia, cr_hia); skb_put_data(skb, buf, strlen(buf)); bt_dev_dbg(hdev, "%s", buf); - snprintf(buf, sizeof(buf), "--------------------------------"); + strscpy(buf, "--------------------------------"); bt_dev_dbg(hdev, "%s", buf); hci_recv_diag(hdev, skb); @@ -650,7 +661,7 @@ static int btintel_pcie_read_dram_buffers(struct btintel_pcie_data *data) else return -EINVAL; - snprintf(vendor, sizeof(vendor), "Vendor: Intel\n"); + strscpy(vendor, "Vendor: Intel\n"); snprintf(driver, sizeof(driver), "Driver: %s\n", data->dmp_hdr.driver_name); @@ -1224,11 +1235,16 @@ static void btintel_pcie_read_hwexp(struct btintel_pcie_data *data) return; len = BTINTEL_PCIE_BLZR_HWEXP_SIZE; /* exception data length */ addr = BTINTEL_PCIE_BLZR_HWEXP_DMP_ADDR; - break; + break; case BTINTEL_CNVI_SCP: len = BTINTEL_PCIE_SCP_HWEXP_SIZE; addr = BTINTEL_PCIE_SCP_HWEXP_DMP_ADDR; - break; + break; + case BTINTEL_CNVI_SCP2: + case BTINTEL_CNVI_SCP2F: + len = BTINTEL_PCIE_SCP2_HWEXP_SIZE; + addr = BTINTEL_PCIE_SCP2_HWEXP_DMP_ADDR; + break; default: bt_dev_err(data->hdev, "Unsupported cnvi 0x%8.8x", data->dmp_hdr.cnvi_top); return; @@ -1737,27 +1753,6 @@ static int btintel_pcie_setup_rxq_bufs(struct btintel_pcie_data *data, return 0; } -static void btintel_pcie_setup_ia(struct btintel_pcie_data *data, - dma_addr_t p_addr, void *v_addr, - struct ia *ia) -{ - /* TR Head Index Array */ - ia->tr_hia_p_addr = p_addr; - ia->tr_hia = v_addr; - - /* TR Tail Index Array */ - ia->tr_tia_p_addr = p_addr + sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES; - ia->tr_tia = v_addr + sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES; - - /* CR Head index Array */ - ia->cr_hia_p_addr = p_addr + (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 2); - ia->cr_hia = v_addr + (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 2); - - /* CR Tail Index Array */ - ia->cr_tia_p_addr = p_addr + (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 3); - ia->cr_tia = v_addr + (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 3); -} - static void btintel_pcie_free(struct btintel_pcie_data *data) { btintel_pcie_free_rxq_bufs(data, &data->rxq); @@ -1775,13 +1770,16 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) size_t total; dma_addr_t p_addr; void *v_addr; + size_t tfd_size, frbd_size, ctx_size, ci_size, urbd0_size, urbd1_size; /* Allocate the chunk of DMA memory for descriptors, index array, and * context information, instead of allocating individually. * The DMA memory for data buffer is allocated while setting up the * each queue. * - * Total size is sum of the following + * Total size is sum of the following and each of the individual sizes + * are aligned to 128 bytes before adding up. + * * + size of TFD * Number of descriptors in queue * + size of URBD0 * Number of descriptors in queue * + size of FRBD * Number of descriptors in queue @@ -1789,15 +1787,25 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) * + size of index * Number of queues(2) * type of index array(4) * + size of context information */ - total = (sizeof(struct tfd) + sizeof(struct urbd0)) * BTINTEL_PCIE_TX_DESCS_COUNT; - total += (sizeof(struct frbd) + sizeof(struct urbd1)) * BTINTEL_PCIE_RX_DESCS_COUNT; + tfd_size = ALIGN(sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT, + BTINTEL_PCIE_DMA_ALIGN_128B); + urbd0_size = ALIGN(sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT, + BTINTEL_PCIE_DMA_ALIGN_128B); + + frbd_size = ALIGN(sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT, + BTINTEL_PCIE_DMA_ALIGN_128B); + urbd1_size = ALIGN(sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT, + BTINTEL_PCIE_DMA_ALIGN_128B); + + ci_size = ALIGN(sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES, + BTINTEL_PCIE_DMA_ALIGN_128B); - /* Add the sum of size of index array and size of ci struct */ - total += (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4) + sizeof(struct ctx_info); + ctx_size = ALIGN(sizeof(struct ctx_info), BTINTEL_PCIE_DMA_ALIGN_128B); + + total = tfd_size + urbd0_size + frbd_size + urbd1_size + ctx_size + ci_size * 4; - /* Allocate DMA Pool */ data->dma_pool = dma_pool_create(KBUILD_MODNAME, &data->pdev->dev, - total, BTINTEL_PCIE_DMA_POOL_ALIGNMENT, 0); + total, BTINTEL_PCIE_DMA_ALIGN_128B, 0); if (!data->dma_pool) { err = -ENOMEM; goto exit_error; @@ -1822,29 +1830,29 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) data->txq.tfds_p_addr = p_addr; data->txq.tfds = v_addr; - p_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); - v_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); + p_addr += tfd_size; + v_addr += tfd_size; /* Setup urbd0 */ data->txq.urbd0s_p_addr = p_addr; data->txq.urbd0s = v_addr; - p_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); - v_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); + p_addr += urbd0_size; + v_addr += urbd0_size; /* Setup FRBD*/ data->rxq.frbds_p_addr = p_addr; data->rxq.frbds = v_addr; - p_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); - v_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); + p_addr += frbd_size; + v_addr += frbd_size; /* Setup urbd1 */ data->rxq.urbd1s_p_addr = p_addr; data->rxq.urbd1s = v_addr; - p_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); - v_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); + p_addr += urbd1_size; + v_addr += urbd1_size; /* Setup data buffers for txq */ err = btintel_pcie_setup_txq_bufs(data, &data->txq); @@ -1856,8 +1864,29 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) if (err) goto exit_error_txq; - /* Setup Index Array */ - btintel_pcie_setup_ia(data, p_addr, v_addr, &data->ia); + /* TR Head Index Array */ + data->ia.tr_hia_p_addr = p_addr; + data->ia.tr_hia = v_addr; + p_addr += ci_size; + v_addr += ci_size; + + /* TR Tail Index Array */ + data->ia.tr_tia_p_addr = p_addr; + data->ia.tr_tia = v_addr; + p_addr += ci_size; + v_addr += ci_size; + + /* CR Head index Array */ + data->ia.cr_hia_p_addr = p_addr; + data->ia.cr_hia = v_addr; + p_addr += ci_size; + v_addr += ci_size; + + /* CR Tail Index Array */ + data->ia.cr_tia_p_addr = p_addr; + data->ia.cr_tia = v_addr; + p_addr += ci_size; + v_addr += ci_size; /* Setup data buffers for dbgc */ err = btintel_pcie_setup_dbgc(data); @@ -1865,9 +1894,6 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) goto exit_error_txq; /* Setup Context Information */ - p_addr += sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4; - v_addr += sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4; - data->ci = v_addr; data->ci_p_addr = p_addr; @@ -2093,6 +2119,8 @@ static int btintel_pcie_setup_internal(struct hci_dev *hdev) switch (INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) { case 0x1e: /* BzrI */ case 0x1f: /* ScP */ + case 0x20: /* ScP2 */ + case 0x21: /* ScP2 F */ case 0x22: /* BzrIW */ /* Display version information of TLV type */ btintel_version_info_tlv(hdev, &ver_tlv); @@ -2372,7 +2400,7 @@ static int btintel_pcie_hci_drv_read_info(struct hci_dev *hdev, void *data, u16 opcode, num_supported_commands = ARRAY_SIZE(btintel_pcie_hci_drv_supported_commands); - rp_size = sizeof(*rp) + num_supported_commands * 2; + rp_size = struct_size(rp, supported_commands, num_supported_commands); rp = kmalloc(rp_size, GFP_KERNEL); if (!rp) diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h index e3d941ffef4a..3c7bb708362d 100644 --- a/drivers/bluetooth/btintel_pcie.h +++ b/drivers/bluetooth/btintel_pcie.h @@ -178,9 +178,6 @@ enum { /* The size of DMA buffer for TX and RX in bytes */ #define BTINTEL_PCIE_BUFFER_SIZE 4096 -/* DMA allocation alignment */ -#define BTINTEL_PCIE_DMA_POOL_ALIGNMENT 256 - #define BTINTEL_PCIE_TX_WAIT_TIMEOUT_MS 500 /* Doorbell vector for TFD */ diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index fa7533578f85..6fb6ca274808 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -112,7 +112,11 @@ static void btmtk_coredump_notify(struct hci_dev *hdev, int state) void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver, u32 fw_flavor) { - if (dev_id == 0x7925) + if (dev_id == 0x6639) + snprintf(buf, size, + "mediatek/mt7927/BT_RAM_CODE_MT%04x_2_%x_hdr.bin", + dev_id & 0xffff, (fw_ver & 0xff) + 1); + else if (dev_id == 0x7925) snprintf(buf, size, "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", dev_id & 0xffff, dev_id & 0xffff, (fw_ver & 0xff) + 1); @@ -128,7 +132,8 @@ void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver, EXPORT_SYMBOL_GPL(btmtk_fw_get_filename); int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, - wmt_cmd_sync_func_t wmt_cmd_sync) + wmt_cmd_sync_func_t wmt_cmd_sync, + u32 dev_id) { struct btmtk_hci_wmt_params wmt_params; struct btmtk_patch_header *hdr; @@ -166,6 +171,14 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, section_offset = le32_to_cpu(sectionmap->secoffset); dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize); + /* MT6639: only download sections where dlmode byte0 == 0x01, + * matching the Windows driver behavior which skips WiFi/other + * sections that would cause the chip to hang. + */ + if (dev_id == 0x6639 && dl_size > 0 && + (le32_to_cpu(sectionmap->bin_info_spec.dlmodecrctype) & 0xff) != 0x01) + continue; + if (dl_size > 0) { retry = 20; while (retry > 0) { @@ -205,9 +218,14 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, } } + /* If retry exhausted goto err_release_fw */ + if (retry == 0) { + err = -EIO; + goto err_release_fw; + } + fw_ptr += section_offset; wmt_params.op = BTMTK_WMT_PATCH_DWNLD; - wmt_params.status = NULL; while (dl_size > 0) { dlen = min_t(int, 250, dl_size); @@ -225,7 +243,14 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, wmt_params.data = fw_ptr; err = wmt_cmd_sync(hdev, &wmt_params); - if (err < 0) { + /* Status BTMTK_WMT_PATCH_PROGRESS indicates firmware is + * in process of being downloaded, which is not expected to + * occur here. + */ + if (status == BTMTK_WMT_PATCH_PROGRESS) { + err = -EIO; + goto err_release_fw; + } else if (err < 0) { bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", err); goto err_release_fw; @@ -442,6 +467,22 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) EXPORT_SYMBOL_GPL(btmtk_process_coredump); #if IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) +/* Known MT6639 (MT7927) Bluetooth USB devices. + * Used to scope the zero-CHIPID workaround to real MT6639 hardware, + * since some boards return 0x0000 from the MMIO chip ID register. + */ +static const struct { + u16 vendor; + u16 product; +} btmtk_mt6639_devs[] = { + { 0x0489, 0xe13a }, /* ASUS ROG Crosshair X870E Hero */ + { 0x0489, 0xe0fa }, /* Lenovo Legion Pro 7 16ARX9 */ + { 0x0489, 0xe10f }, /* Gigabyte Z790 AORUS MASTER X */ + { 0x0489, 0xe110 }, /* MSI X870E Ace Max */ + { 0x0489, 0xe116 }, /* TP-Link Archer TBE550E */ + { 0x13d3, 0x3588 }, /* ASUS ROG STRIX X870E-E */ +}; + static void btmtk_usb_wmt_recv(struct urb *urb) { struct hci_dev *hdev = urb->context; @@ -840,7 +881,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) if (err < 0) return err; msleep(100); - } else if (dev_id == 0x7925) { + } else if (dev_id == 0x7925 || dev_id == 0x6639) { err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val); if (err < 0) return err; @@ -926,7 +967,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id) } err = btmtk_usb_id_get(hdev, 0x70010200, &val); - if (err < 0 || !val) + if (err < 0 || (!val && dev_id != 0x6639)) bt_dev_err(hdev, "Can't get device id, subsys reset fail."); return err; @@ -983,40 +1024,22 @@ static int __set_mtk_intr_interface(struct hci_dev *hdev) { struct btmtk_data *btmtk_data = hci_get_priv(hdev); struct usb_interface *intf = btmtk_data->isopkt_intf; - int i, err; + int err; if (!btmtk_data->isopkt_intf) return -ENODEV; - err = usb_set_interface(btmtk_data->udev, MTK_ISO_IFNUM, 1); + err = usb_set_interface(btmtk_data->udev, MTK_ISO_IFNUM, + (intf->num_altsetting > 1) ? 1 : 0); if (err < 0) { bt_dev_err(hdev, "setting interface failed (%d)", -err); return err; } - btmtk_data->isopkt_tx_ep = NULL; - btmtk_data->isopkt_rx_ep = NULL; - - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { - struct usb_endpoint_descriptor *ep_desc; - - ep_desc = &intf->cur_altsetting->endpoint[i].desc; - - if (!btmtk_data->isopkt_tx_ep && - usb_endpoint_is_int_out(ep_desc)) { - btmtk_data->isopkt_tx_ep = ep_desc; - continue; - } - - if (!btmtk_data->isopkt_rx_ep && - usb_endpoint_is_int_in(ep_desc)) { - btmtk_data->isopkt_rx_ep = ep_desc; - continue; - } - } - - if (!btmtk_data->isopkt_tx_ep || - !btmtk_data->isopkt_rx_ep) { + err = usb_find_common_endpoints(intf->cur_altsetting, NULL, NULL, + &btmtk_data->isopkt_rx_ep, + &btmtk_data->isopkt_tx_ep); + if (err) { bt_dev_err(hdev, "invalid interrupt descriptors"); return -ENODEV; } @@ -1310,6 +1333,24 @@ int btmtk_usb_setup(struct hci_dev *hdev) fw_flavor = (fw_flavor & 0x00000080) >> 7; } + if (!dev_id) { + u16 vid = le16_to_cpu(btmtk_data->udev->descriptor.idVendor); + u16 pid = le16_to_cpu(btmtk_data->udev->descriptor.idProduct); + int i; + + for (i = 0; i < ARRAY_SIZE(btmtk_mt6639_devs); i++) { + if (vid == btmtk_mt6639_devs[i].vendor && + pid == btmtk_mt6639_devs[i].product) { + dev_id = 0x6639; + break; + } + } + + if (dev_id) + bt_dev_info(hdev, "MT6639: CHIPID=0x0000 with VID=%04x PID=%04x, using 0x6639", + vid, pid); + } + btmtk_data->dev_id = dev_id; err = btmtk_register_coredump(hdev, btmtk_data->drv_name, fw_version); @@ -1326,12 +1367,18 @@ int btmtk_usb_setup(struct hci_dev *hdev) case 0x7922: case 0x7925: case 0x7961: + case 0x7902: + case 0x6639: btmtk_fw_get_filename(fw_bin_name, sizeof(fw_bin_name), dev_id, fw_version, fw_flavor); err = btmtk_setup_firmware_79xx(hdev, fw_bin_name, - btmtk_usb_hci_wmt_sync); + btmtk_usb_hci_wmt_sync, + dev_id); if (err < 0) { + /* retry once if setup firmware error */ + if (!test_and_set_bit(BTMTK_FIRMWARE_DL_RETRY, &btmtk_data->flags)) + btmtk_reset_sync(hdev); bt_dev_err(hdev, "Failed to set up firmware (%d)", err); return err; } @@ -1359,6 +1406,9 @@ int btmtk_usb_setup(struct hci_dev *hdev) hci_set_msft_opcode(hdev, 0xFD30); hci_set_aosp_capable(hdev); + /* Clear BTMTK_FIRMWARE_DL_RETRY if setup successfully */ + test_and_clear_bit(BTMTK_FIRMWARE_DL_RETRY, &btmtk_data->flags); + /* Set up ISO interface after protocol enabled */ if (test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) { if (!btmtk_usb_isointf_init(hdev)) @@ -1497,3 +1547,4 @@ MODULE_FIRMWARE(FIRMWARE_MT7668); MODULE_FIRMWARE(FIRMWARE_MT7922); MODULE_FIRMWARE(FIRMWARE_MT7961); MODULE_FIRMWARE(FIRMWARE_MT7925); +MODULE_FIRMWARE(FIRMWARE_MT7927); diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h index 5df7c3296624..c564aedc0ce0 100644 --- a/drivers/bluetooth/btmtk.h +++ b/drivers/bluetooth/btmtk.h @@ -5,8 +5,10 @@ #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" #define FIRMWARE_MT7922 "mediatek/BT_RAM_CODE_MT7922_1_1_hdr.bin" +#define FIRMWARE_MT7902 "mediatek/BT_RAM_CODE_MT7902_1_1_hdr.bin" #define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin" #define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin" +#define FIRMWARE_MT7927 "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin" #define HCI_EV_WMT 0xe4 #define HCI_WMT_MAX_EVENT_SIZE 64 @@ -147,6 +149,7 @@ enum { BTMTK_HW_RESET_ACTIVE, BTMTK_ISOPKT_OVER_INTR, BTMTK_ISOPKT_RUNNING, + BTMTK_FIRMWARE_DL_RETRY, }; typedef int (*btmtk_reset_sync_func_t)(struct hci_dev *, void *); @@ -187,7 +190,8 @@ typedef int (*wmt_cmd_sync_func_t)(struct hci_dev *, int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, - wmt_cmd_sync_func_t wmt_cmd_sync); + wmt_cmd_sync_func_t wmt_cmd_sync, + u32 dev_id); int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname, wmt_cmd_sync_func_t wmt_cmd_sync); @@ -226,7 +230,8 @@ static inline int btmtk_set_bdaddr(struct hci_dev *hdev, static inline int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname, - wmt_cmd_sync_func_t wmt_cmd_sync) + wmt_cmd_sync_func_t wmt_cmd_sync, + u32 dev_id) { return -EOPNOTSUPP; } diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index e986e5af51ae..5b0fab7b89b5 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -42,24 +42,35 @@ struct btmtksdio_data { const char *fwname; u16 chipid; bool lp_mbox_supported; + bool pm_runtime_supported; }; static const struct btmtksdio_data mt7663_data = { .fwname = FIRMWARE_MT7663, .chipid = 0x7663, .lp_mbox_supported = false, + .pm_runtime_supported = true, }; static const struct btmtksdio_data mt7668_data = { .fwname = FIRMWARE_MT7668, .chipid = 0x7668, .lp_mbox_supported = false, + .pm_runtime_supported = true, }; static const struct btmtksdio_data mt7921_data = { .fwname = FIRMWARE_MT7961, .chipid = 0x7921, .lp_mbox_supported = true, + .pm_runtime_supported = true, +}; + +static const struct btmtksdio_data mt7902_data = { + .fwname = FIRMWARE_MT7902, + .chipid = 0x7902, + .lp_mbox_supported = false, + .pm_runtime_supported = false, }; static const struct sdio_device_id btmtksdio_table[] = { @@ -69,6 +80,8 @@ static const struct sdio_device_id btmtksdio_table[] = { .driver_data = (kernel_ulong_t)&mt7668_data }, {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7961), .driver_data = (kernel_ulong_t)&mt7921_data }, + {SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7902), + .driver_data = (kernel_ulong_t)&mt7902_data }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(sdio, btmtksdio_table); @@ -870,7 +883,7 @@ static int mt79xx_setup(struct hci_dev *hdev, const char *fwname) u8 param = 0x1; int err; - err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync); + err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync, 0); if (err < 0) { bt_dev_err(hdev, "Failed to setup 79xx firmware (%d)", err); return err; @@ -1090,6 +1103,7 @@ static int btmtksdio_setup(struct hci_dev *hdev) set_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state); switch (bdev->data->chipid) { + case 0x7902: case 0x7921: if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state)) { err = btmtksdio_mtk_reg_read(hdev, MT7921_DLSTATUS, @@ -1167,22 +1181,24 @@ static int btmtksdio_setup(struct hci_dev *hdev) delta = ktime_sub(rettime, calltime); duration = (unsigned long long)ktime_to_ns(delta) >> 10; - pm_runtime_set_autosuspend_delay(bdev->dev, - MTKBTSDIO_AUTOSUSPEND_DELAY); - pm_runtime_use_autosuspend(bdev->dev); + if (bdev->data->pm_runtime_supported) { + pm_runtime_set_autosuspend_delay(bdev->dev, + MTKBTSDIO_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(bdev->dev); - err = pm_runtime_set_active(bdev->dev); - if (err < 0) - return err; + err = pm_runtime_set_active(bdev->dev); + if (err < 0) + return err; - /* Default forbid runtime auto suspend, that can be allowed by - * enable_autosuspend flag or the PM runtime entry under sysfs. - */ - pm_runtime_forbid(bdev->dev); - pm_runtime_enable(bdev->dev); + /* Default forbid runtime auto suspend, that can be allowed by + * enable_autosuspend flag or the PM runtime entry under sysfs. + */ + pm_runtime_forbid(bdev->dev); + pm_runtime_enable(bdev->dev); - if (enable_autosuspend) - pm_runtime_allow(bdev->dev); + if (enable_autosuspend) + pm_runtime_allow(bdev->dev); + } bt_dev_info(hdev, "Device setup in %llu usecs", duration); diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 3b0626920193..dda76365726f 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -801,6 +801,14 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/%s", rampatch_name); } else { switch (soc_type) { + case QCA_QCA2066: + snprintf(config.fwname, sizeof(config.fwname), + "qca/hpbtfw%02x.tlv", rom_ver); + break; + case QCA_QCA6390: + snprintf(config.fwname, sizeof(config.fwname), + "qca/htbtfw%02x.tlv", rom_ver); + break; case QCA_WCN3950: snprintf(config.fwname, sizeof(config.fwname), "qca/cmbtfw%02x.tlv", rom_ver); @@ -815,14 +823,6 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/apbtfw%02x.tlv", rom_ver); break; - case QCA_QCA2066: - snprintf(config.fwname, sizeof(config.fwname), - "qca/hpbtfw%02x.tlv", rom_ver); - break; - case QCA_QCA6390: - snprintf(config.fwname, sizeof(config.fwname), - "qca/htbtfw%02x.tlv", rom_ver); - break; case QCA_WCN6750: /* Choose mbn file by default.If mbn file is not found * then choose tlv file @@ -892,6 +892,16 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, } } else { switch (soc_type) { + case QCA_QCA2066: + qca_get_nvm_name_by_board(config.fwname, + sizeof(config.fwname), + "hpnv", soc_type, ver, + rom_ver, boardid); + break; + case QCA_QCA6390: + snprintf(config.fwname, sizeof(config.fwname), + "qca/htnv%02x.bin", rom_ver); + break; case QCA_WCN3950: if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_T) variant = "t"; @@ -914,15 +924,6 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/apnv%02x.bin", rom_ver); break; - case QCA_QCA2066: - qca_get_nvm_name_by_board(config.fwname, - sizeof(config.fwname), "hpnv", soc_type, ver, - rom_ver, boardid); - 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); @@ -956,9 +957,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, } switch (soc_type) { - case QCA_WCN3991: case QCA_QCA2066: case QCA_QCA6390: + case QCA_WCN3991: case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5c535f3ab722..7f5fce93d984 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -671,7 +671,17 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, - + /* MediaTek MT7902 Bluetooth devices */ + { USB_DEVICE(0x0e8d, 0x1ede), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3579), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3580), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3594), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3596), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, /* MediaTek MT7922 Bluetooth devices */ { USB_DEVICE(0x13d3, 0x3585), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, @@ -697,14 +707,20 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe11d), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe152), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe153), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe170), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe174), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x04ca, 0x3807), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | @@ -737,6 +753,18 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe139), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe13a), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe0fa), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe10f), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe110), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe116), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3588), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe14e), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe14f), .driver_info = BTUSB_MEDIATEK | @@ -789,7 +817,7 @@ static const struct usb_device_id quirks_table[] = { { USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK | - BTUSB_WIDEBAND_SPEECH }, + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK | @@ -2471,6 +2499,7 @@ static int btusb_setup_csr(struct hci_dev *hdev) HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { int err = PTR_ERR(skb); + bt_dev_err(hdev, "CSR: Local version failed (%d)", err); return err; } @@ -3674,31 +3703,14 @@ static inline int __set_diag_interface(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); struct usb_interface *intf = data->diag; - int i; + int ret; if (!data->diag) return -ENODEV; - data->diag_tx_ep = NULL; - data->diag_rx_ep = NULL; - - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { - struct usb_endpoint_descriptor *ep_desc; - - ep_desc = &intf->cur_altsetting->endpoint[i].desc; - - if (!data->diag_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) { - data->diag_tx_ep = ep_desc; - continue; - } - - if (!data->diag_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) { - data->diag_rx_ep = ep_desc; - continue; - } - } - - if (!data->diag_tx_ep || !data->diag_rx_ep) { + ret = usb_find_common_endpoints(intf->cur_altsetting, &data->diag_rx_ep, + &data->diag_tx_ep, NULL, NULL); + if (ret) { bt_dev_err(hdev, "invalid diagnostic descriptors"); return -ENODEV; } @@ -4024,12 +4036,11 @@ static struct hci_drv btusb_hci_drv = { static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_endpoint_descriptor *ep_desc; struct gpio_desc *reset_gpio; struct btusb_data *data; struct hci_dev *hdev; unsigned ifnum_base; - int i, err, priv_size; + int err, priv_size; BT_DBG("intf %p id %p", intf, id); @@ -4066,26 +4077,9 @@ static int btusb_probe(struct usb_interface *intf, if (!data) return -ENOMEM; - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { - ep_desc = &intf->cur_altsetting->endpoint[i].desc; - - if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) { - data->intr_ep = ep_desc; - continue; - } - - if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) { - data->bulk_tx_ep = ep_desc; - continue; - } - - if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) { - data->bulk_rx_ep = ep_desc; - continue; - } - } - - if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) { + err = usb_find_common_endpoints(intf->cur_altsetting, &data->bulk_rx_ep, + &data->bulk_tx_ep, &data->intr_ep, NULL); + if (err) { kfree(data); return -ENODEV; } diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 71c1997a0f73..275ea865bc29 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -692,6 +692,9 @@ static int hci_uart_register_dev(struct hci_uart *hu) if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); + percpu_down_write(&hu->proto_lock); + clear_bit(HCI_UART_PROTO_INIT, &hu->flags); + percpu_up_write(&hu->proto_lock); hu->proto->close(hu); hu->hdev = NULL; hci_free_dev(hdev); diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 91c96ad12342..ab744001dafc 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -68,6 +68,7 @@ struct ll_device { struct gpio_desc *enable_gpio; struct clk *ext_clk; bdaddr_t bdaddr; + bool broken_enhanced_setup; }; struct ll_struct { @@ -658,6 +659,10 @@ static int ll_setup(struct hci_uart *hu) hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); } + if (lldev->broken_enhanced_setup) + hci_set_quirk(hu->hdev, + HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN); + /* Operational speed if any */ if (hu->oper_speed) speed = hu->oper_speed; @@ -712,6 +717,11 @@ static int hci_ti_probe(struct serdev_device *serdev) of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed); hci_uart_set_speeds(hu, 115200, max_speed); + if (of_device_is_compatible(serdev->dev.of_node, "ti,wl1831-st") || + of_device_is_compatible(serdev->dev.of_node, "ti,wl1835-st") || + of_device_is_compatible(serdev->dev.of_node, "ti,wl1837-st")) + lldev->broken_enhanced_setup = true; + /* optional BD address from nvram */ bdaddr_cell = nvmem_cell_get(&serdev->dev, "bd-address"); if (IS_ERR(bdaddr_cell)) { diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index bb9f002aa85e..cd1834246b47 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -236,8 +236,7 @@ struct qca_serdev { static int qca_regulator_enable(struct qca_serdev *qcadev); static void qca_regulator_disable(struct qca_serdev *qcadev); -static void qca_power_shutdown(struct hci_uart *hu); -static int qca_power_off(struct hci_dev *hdev); +static void qca_power_off(struct hci_uart *hu); static void qca_controller_memdump(struct work_struct *work); static void qca_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb); @@ -723,6 +722,10 @@ static int qca_close(struct hci_uart *hu) BT_DBG("hu %p qca close", hu); + /* BT core skips qca_hci_shutdown() which calls qca_power_off() on rmmod */ + if (!test_bit(QCA_BT_OFF, &qca->flags)) + qca_power_off(hu); + serial_clock_vote(HCI_IBS_VOTE_STATS_UPDATE, hu); skb_queue_purge(&qca->tx_wait_q); @@ -1105,7 +1108,7 @@ static void qca_controller_memdump(struct work_struct *work) qca->qca_memdump = NULL; qca->memdump_state = QCA_MEMDUMP_COLLECTED; cancel_delayed_work(&qca->ctrl_memdump_timeout); - clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); + clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); clear_bit(QCA_IBS_DISABLED, &qca->flags); mutex_unlock(&qca->hci_memdump_lock); return; @@ -1183,7 +1186,7 @@ static void qca_controller_memdump(struct work_struct *work) kfree(qca->qca_memdump); qca->qca_memdump = NULL; qca->memdump_state = QCA_MEMDUMP_COLLECTED; - clear_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); + clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags); } mutex_unlock(&qca->hci_memdump_lock); @@ -1850,6 +1853,7 @@ static int qca_power_on(struct hci_dev *hdev) return 0; switch (soc_type) { + case QCA_QCA6390: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -1858,7 +1862,6 @@ static int qca_power_on(struct hci_dev *hdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - case QCA_QCA6390: ret = qca_regulator_init(hu); break; @@ -2047,7 +2050,7 @@ retry: out: if (ret) { - qca_power_shutdown(hu); + qca_power_off(hu); if (retries < MAX_INIT_RETRIES) { bt_dev_warn(hdev, "Retry BT power ON:%d", retries); @@ -2096,6 +2099,18 @@ static const struct hci_uart_proto qca_proto = { .dequeue = qca_dequeue, }; +static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = { + .soc_type = QCA_QCA2066, + .num_vregs = 0, + .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES | + QCA_CAP_HFP_HW_OFFLOAD, +}; + +static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = { + .soc_type = QCA_QCA6390, + .num_vregs = 0, +}; + static const struct qca_device_data qca_soc_data_wcn3950 __maybe_unused = { .soc_type = QCA_WCN3950, .vregs = (struct qca_vreg []) { @@ -2152,18 +2167,6 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = { .num_vregs = 4, }; -static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = { - .soc_type = QCA_QCA2066, - .num_vregs = 0, - .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES | - QCA_CAP_HFP_HW_OFFLOAD, -}; - -static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = { - .soc_type = QCA_QCA6390, - .num_vregs = 0, -}; - static const struct qca_device_data qca_soc_data_wcn6750 __maybe_unused = { .soc_type = QCA_WCN6750, .vregs = (struct qca_vreg []) { @@ -2211,7 +2214,7 @@ static const struct qca_device_data qca_soc_data_wcn7850 __maybe_unused = { QCA_CAP_HFP_HW_OFFLOAD, }; -static void qca_power_shutdown(struct hci_uart *hu) +static void qca_power_off(struct hci_uart *hu) { struct qca_serdev *qcadev; struct qca_data *qca = hu->priv; @@ -2238,6 +2241,18 @@ static void qca_power_shutdown(struct hci_uart *hu) qcadev = serdev_device_get_drvdata(hu->serdev); power = qcadev->bt_power; + 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); + break; + default: + break; + } + if (power && power->pwrseq) { pwrseq_power_off(power->pwrseq); set_bit(QCA_BT_OFF, &qca->flags); @@ -2249,8 +2264,6 @@ static void qca_power_shutdown(struct hci_uart *hu) case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - host_set_baudrate(hu, 2400); - qca_send_power_pulse(hu, false); qca_regulator_disable(qcadev); break; @@ -2261,7 +2274,7 @@ static void qca_power_shutdown(struct hci_uart *hu) qca_regulator_disable(qcadev); if (qcadev->sw_ctrl) { sw_ctrl_state = gpiod_get_value_cansleep(qcadev->sw_ctrl); - bt_dev_dbg(hu->hdev, "SW_CTRL is %d", sw_ctrl_state); + BT_DBG("SW_CTRL is %d", sw_ctrl_state); } break; @@ -2272,7 +2285,7 @@ static void qca_power_shutdown(struct hci_uart *hu) set_bit(QCA_BT_OFF, &qca->flags); } -static int qca_power_off(struct hci_dev *hdev) +static int qca_hci_shutdown(struct hci_dev *hdev) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; @@ -2291,7 +2304,7 @@ static int qca_power_off(struct hci_dev *hdev) usleep_range(8000, 10000); } - qca_power_shutdown(hu); + qca_power_off(hu); return 0; } @@ -2402,6 +2415,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->btsoc_type = QCA_ROME; switch (qcadev->btsoc_type) { + case QCA_QCA6390: case QCA_WCN3950: case QCA_WCN3988: case QCA_WCN3990: @@ -2410,7 +2424,6 @@ static int qca_serdev_probe(struct serdev_device *serdev) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - case QCA_QCA6390: qcadev->bt_power = devm_kzalloc(&serdev->dev, sizeof(struct qca_power), GFP_KERNEL); @@ -2422,9 +2435,14 @@ static int qca_serdev_probe(struct serdev_device *serdev) } switch (qcadev->btsoc_type) { + case QCA_WCN3950: + case QCA_WCN3988: + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - case QCA_WCN6750: if (!device_property_present(&serdev->dev, "enable-gpios")) { /* * Backward compatibility with old DT sources. If the @@ -2446,12 +2464,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) else break; } - fallthrough; - case QCA_WCN3950: - case QCA_WCN3988: - case QCA_WCN3990: - case QCA_WCN3991: - case QCA_WCN3998: + qcadev->bt_power->dev = &serdev->dev; err = qca_init_regulators(qcadev->bt_power, data->vregs, data->num_vregs); @@ -2471,7 +2484,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->bt_en && (data->soc_type == QCA_WCN6750 || - data->soc_type == QCA_WCN6855)) + data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_WCN7850)) power_ctrl_enabled = false; qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", @@ -2530,7 +2544,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (power_ctrl_enabled) { hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); - hdev->shutdown = qca_power_off; + hdev->shutdown = qca_hci_shutdown; } if (data) { @@ -2565,7 +2579,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) case QCA_WCN6855: case QCA_WCN7850: if (power->vregs_on) - qca_power_shutdown(&qcadev->serdev_hu); + qca_power_off(&qcadev->serdev_hu); break; default: break; diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index 673cbdf43453..dce89c110691 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -111,6 +111,7 @@ #define SDIO_VENDOR_ID_MEDIATEK 0x037a #define SDIO_DEVICE_ID_MEDIATEK_MT7663 0x7663 #define SDIO_DEVICE_ID_MEDIATEK_MT7668 0x7668 +#define SDIO_DEVICE_ID_MEDIATEK_MT7902 0x790a #define SDIO_DEVICE_ID_MEDIATEK_MT7961 0x7961 #define SDIO_VENDOR_ID_MICROCHIP_WILC 0x0296 diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 89ad9470fa71..572b1c620c5d 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1468,8 +1468,12 @@ struct hci_rp_read_data_block_size { } __packed; #define HCI_OP_READ_LOCAL_CODECS 0x100b -struct hci_std_codecs { +struct hci_std_codecs_hdr { __u8 num; +} __packed; + +struct hci_std_codecs { + struct hci_std_codecs_hdr; __u8 codec[]; } __packed; @@ -1487,7 +1491,7 @@ struct hci_vnd_codecs { struct hci_rp_read_local_supported_codecs { __u8 status; - struct hci_std_codecs std_codecs; + struct hci_std_codecs_hdr std_codecs; struct hci_vnd_codecs vnd_codecs; } __packed; @@ -1504,8 +1508,12 @@ struct hci_std_codec_v2 { __u8 transport; } __packed; -struct hci_std_codecs_v2 { +struct hci_std_codecs_v2_hdr { __u8 num; +} __packed; + +struct hci_std_codecs_v2 { + struct hci_std_codecs_v2_hdr; struct hci_std_codec_v2 codec[]; } __packed; @@ -1522,7 +1530,7 @@ struct hci_vnd_codecs_v2 { struct hci_rp_read_local_supported_codecs_v2 { __u8 status; - struct hci_std_codecs_v2 std_codecs; + struct hci_std_codecs_v2_hdr std_codecs; struct hci_vnd_codecs_v2 vendor_codecs; } __packed; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 11d3ad8d2551..3a0592599086 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -3083,6 +3083,7 @@ static int abort_conn_sync(struct hci_dev *hdev, void *data) int hci_abort_conn(struct hci_conn *conn, u8 reason) { struct hci_dev *hdev = conn->hdev; + int err; /* If abort_reason has already been set it means the connection is * already being aborted so don't attempt to overwrite it. @@ -3119,7 +3120,8 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason) * as a result to MGMT_OP_DISCONNECT/MGMT_OP_UNPAIR which does * already queue its callback on cmd_sync_work. */ - return hci_cmd_sync_run_once(hdev, abort_conn_sync, conn, NULL); + err = hci_cmd_sync_run_once(hdev, abort_conn_sync, conn, NULL); + return (err == -EEXIST) ? 0 : err; } void hci_setup_tx_timestamp(struct sk_buff *skb, size_t key_offset, diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 01f8ceeb1c0c..c46c1236ebfa 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3917,8 +3917,8 @@ static void hci_isodata_packet(struct hci_dev *hdev, struct sk_buff *skb) err = iso_recv(hdev, handle, skb, flags); if (err == -ENOENT) - bt_dev_err(hdev, "ISO packet for unknown connection handle %d", - handle); + bt_dev_err_ratelimited(hdev, "ISO packet for unknown connection handle %d", + handle); else if (err) bt_dev_dbg(hdev, "ISO packet recv for handle %d failed: %d", handle, err); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3ebc5e6d45d9..b2ee6b6a0f56 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3340,8 +3340,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, memcpy(conn->dev_class, ev->dev_class, 3); - hci_dev_unlock(hdev); - if (ev->link_type == ACL_LINK || (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { struct hci_cp_accept_conn_req cp; @@ -3375,7 +3373,6 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, hci_connect_cfm(conn, 0); } - return; unlock: hci_dev_unlock(hdev); } @@ -5498,9 +5495,11 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data, bt_dev_dbg(hdev, ""); + hci_dev_lock(hdev); + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (!conn) - return; + goto unlock; conn->passkey_notify = __le32_to_cpu(ev->passkey); conn->passkey_entered = 0; @@ -5509,6 +5508,9 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data, mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, conn->dst_type, conn->passkey_notify, conn->passkey_entered); + +unlock: + hci_dev_unlock(hdev); } static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, @@ -5519,14 +5521,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, bt_dev_dbg(hdev, ""); + hci_dev_lock(hdev); + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (!conn) - return; + goto unlock; switch (ev->type) { case HCI_KEYPRESS_STARTED: conn->passkey_entered = 0; - return; + goto unlock; case HCI_KEYPRESS_ENTERED: conn->passkey_entered++; @@ -5541,13 +5545,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, break; case HCI_KEYPRESS_COMPLETED: - return; + goto unlock; } if (hci_dev_test_flag(hdev, HCI_MGMT)) mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, conn->dst_type, conn->passkey_notify, conn->passkey_entered); + +unlock: + hci_dev_unlock(hdev); } static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data, diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 919ec275dd23..fd3aacdea512 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -825,7 +825,7 @@ int hci_cmd_sync_run_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func, void *data, hci_cmd_sync_work_destroy_t destroy) { if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy)) - return 0; + return -EEXIST; return hci_cmd_sync_run(hdev, func, data, destroy); } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 95c65fece39b..77dec104a9c3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -5473,7 +5473,13 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, if (chan->ident != cmd->ident) continue; + l2cap_chan_hold(chan); + l2cap_chan_lock(chan); + l2cap_chan_del(chan, ECONNRESET); + + l2cap_chan_unlock(chan); + l2cap_chan_put(chan); } return 0; @@ -6705,6 +6711,13 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) return -ENOBUFS; } + if (skb->len > chan->mps) { + BT_ERR("Too big LE L2CAP MPS: len %u > %u", skb->len, + chan->mps); + l2cap_send_disconn_req(chan, ECONNRESET); + return -ENOBUFS; + } + chan->rx_credits--; BT_DBG("chan %p: rx_credits %u -> %u", chan, chan->rx_credits + 1, chan->rx_credits); @@ -6733,7 +6746,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) if (sdu_len > chan->imtu) { BT_ERR("Too big LE L2CAP SDU length: len %u > %u", - skb->len, sdu_len); + sdu_len, chan->imtu); l2cap_send_disconn_req(chan, ECONNRESET); err = -EMSGSIZE; goto failed; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index b84587811ef4..18826d4b9c0b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1045,7 +1045,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, codecs = (void *)buffer; - if (codecs->num_codecs > 1) { + if (codecs->num_codecs != 1 || + optlen < struct_size(codecs, codecs, codecs->num_codecs)) { hci_dev_put(hdev); err = -EINVAL; break; |
