diff options
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/btbcm.c | 12 | ||||
-rw-r--r-- | drivers/bluetooth/btintel.c | 114 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 9 | ||||
-rw-r--r-- | drivers/bluetooth/btmtkuart.c | 4 | ||||
-rw-r--r-- | drivers/bluetooth/btnxpuart.c | 28 | ||||
-rw-r--r-- | drivers/bluetooth/btqca.c | 4 | ||||
-rw-r--r-- | drivers/bluetooth/btrsi.c | 1 | ||||
-rw-r--r-- | drivers/bluetooth/btrtl.c | 14 | ||||
-rw-r--r-- | drivers/bluetooth/btsdio.c | 8 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 25 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcm4377.c | 1 | ||||
-rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 6 | ||||
-rw-r--r-- | drivers/bluetooth/hci_serdev.c | 9 | ||||
-rw-r--r-- | drivers/bluetooth/hci_uart.h | 1 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 10 | ||||
-rw-r--r-- | drivers/bluetooth/virtio_bt.c | 2 |
16 files changed, 225 insertions, 23 deletions
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 0a5445ac5e..f9a7c790d7 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -11,6 +11,7 @@ #include <linux/firmware.h> #include <linux/dmi.h> #include <linux/of.h> +#include <linux/string.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -543,8 +544,6 @@ static const char *btbcm_get_board_name(struct device *dev) struct device_node *root; char *board_type; const char *tmp; - int len; - int i; root = of_find_node_by_path("/"); if (!root) @@ -554,13 +553,8 @@ static const char *btbcm_get_board_name(struct device *dev) return NULL; /* get rid of any '/' in the compatible string */ - len = strlen(tmp) + 1; - board_type = devm_kzalloc(dev, len, GFP_KERNEL); - strscpy(board_type, tmp, len); - for (i = 0; i < len; i++) { - if (board_type[i] == '/') - board_type[i] = '-'; - } + board_type = devm_kstrdup(dev, tmp, GFP_KERNEL); + strreplace(board_type, '/', '-'); of_node_put(root); return board_type; diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index e532e2be17..6ba7f5d1b8 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -2670,6 +2670,119 @@ static void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant) } } +static void btintel_print_fseq_info(struct hci_dev *hdev) +{ + struct sk_buff *skb; + u8 *p; + u32 val; + const char *str; + + skb = __hci_cmd_sync(hdev, 0xfcb3, 0, NULL, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_dbg(hdev, "Reading fseq status command failed (%ld)", + PTR_ERR(skb)); + return; + } + + if (skb->len < (sizeof(u32) * 16 + 2)) { + bt_dev_dbg(hdev, "Malformed packet of length %u received", + skb->len); + kfree_skb(skb); + return; + } + + p = skb_pull_data(skb, 1); + if (*p) { + bt_dev_dbg(hdev, "Failed to get fseq status (0x%2.2x)", *p); + kfree_skb(skb); + return; + } + + p = skb_pull_data(skb, 1); + switch (*p) { + case 0: + str = "Success"; + break; + case 1: + str = "Fatal error"; + break; + case 2: + str = "Semaphore acquire error"; + break; + default: + str = "Unknown error"; + break; + } + + if (*p) { + bt_dev_err(hdev, "Fseq status: %s (0x%2.2x)", str, *p); + kfree_skb(skb); + return; + } + + bt_dev_info(hdev, "Fseq status: %s (0x%2.2x)", str, *p); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Reason: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Global version: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Installed version: 0x%8.8x", val); + + p = skb->data; + skb_pull_data(skb, 4); + bt_dev_info(hdev, "Fseq executed: %2.2u.%2.2u.%2.2u.%2.2u", p[0], p[1], + p[2], p[3]); + + p = skb->data; + skb_pull_data(skb, 4); + bt_dev_info(hdev, "Fseq BT Top: %2.2u.%2.2u.%2.2u.%2.2u", p[0], p[1], + p[2], p[3]); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq Top init version: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq Cnvio init version: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq MBX Wifi file version: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq BT version: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq Top reset address: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq MBX timeout: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq MBX ack: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq CNVi id: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq CNVr id: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq Error handle: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq Magic noalive indication: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq OTP version: 0x%8.8x", val); + + val = get_unaligned_le32(skb_pull_data(skb, 4)); + bt_dev_dbg(hdev, "Fseq MBX otp version: 0x%8.8x", val); + + kfree_skb(skb); +} + static int btintel_setup_combined(struct hci_dev *hdev) { const u8 param[1] = { 0xFF }; @@ -2902,6 +3015,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); btintel_register_devcoredump_support(hdev); + btintel_print_fseq_info(hdev); break; default: bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 18f34998a1..9658b33c82 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -121,6 +121,13 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) ((event->data[2] == MODULE_BROUGHT_UP) || (event->data[2] == MODULE_ALREADY_UP)) ? "Bring-up succeed" : "Bring-up failed"); + + if (event->length > 3 && event->data[3]) + priv->btmrvl_dev.dev_type = HCI_AMP; + else + priv->btmrvl_dev.dev_type = HCI_PRIMARY; + + BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type); } else if (priv->btmrvl_dev.sendcmdflag && event->data[1] == MODULE_SHUTDOWN_REQ) { BT_DBG("EVENT:%s", (event->data[2]) ? @@ -679,6 +686,8 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) hdev->wakeup = btmrvl_wakeup; SET_HCIDEV_DEV(hdev, &card->func->dev); + hdev->dev_type = priv->btmrvl_dev.dev_type; + ret = hci_register_dev(hdev); if (ret < 0) { BT_ERR("Can not register HCI device"); diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index 3c84fcbda0..e6bc4a73c9 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -383,8 +383,8 @@ static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count) } } -static ssize_t btmtkuart_receive_buf(struct serdev_device *serdev, - const u8 *data, size_t count) +static size_t btmtkuart_receive_buf(struct serdev_device *serdev, + const u8 *data, size_t count) { struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index c19dc8a298..9d0c7e2781 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -126,6 +126,7 @@ struct ps_data { struct hci_dev *hdev; struct work_struct work; struct timer_list ps_timer; + struct mutex ps_lock; }; struct wakeup_cmd_payload { @@ -317,6 +318,9 @@ static void ps_start_timer(struct btnxpuart_dev *nxpdev) if (psdata->cur_psmode == PS_MODE_ENABLE) mod_timer(&psdata->ps_timer, jiffies + msecs_to_jiffies(psdata->h2c_ps_interval)); + + if (psdata->ps_state == PS_STATE_AWAKE && psdata->ps_cmd == PS_CMD_ENTER_PS) + cancel_work_sync(&psdata->work); } static void ps_cancel_timer(struct btnxpuart_dev *nxpdev) @@ -337,6 +341,7 @@ static void ps_control(struct hci_dev *hdev, u8 ps_state) !test_bit(BTNXPUART_SERDEV_OPEN, &nxpdev->tx_state)) return; + mutex_lock(&psdata->ps_lock); switch (psdata->cur_h2c_wakeupmode) { case WAKEUP_METHOD_DTR: if (ps_state == PS_STATE_AWAKE) @@ -350,12 +355,15 @@ static void ps_control(struct hci_dev *hdev, u8 ps_state) status = serdev_device_break_ctl(nxpdev->serdev, 0); else status = serdev_device_break_ctl(nxpdev->serdev, -1); + msleep(20); /* Allow chip to detect UART-break and enter sleep */ bt_dev_dbg(hdev, "Set UART break: %s, status=%d", str_on_off(ps_state == PS_STATE_SLEEP), status); break; } if (!status) psdata->ps_state = ps_state; + mutex_unlock(&psdata->ps_lock); + if (ps_state == PS_STATE_AWAKE) btnxpuart_tx_wakeup(nxpdev); } @@ -391,17 +399,25 @@ static void ps_setup(struct hci_dev *hdev) psdata->hdev = hdev; INIT_WORK(&psdata->work, ps_work_func); + mutex_init(&psdata->ps_lock); timer_setup(&psdata->ps_timer, ps_timeout_func, 0); } -static void ps_wakeup(struct btnxpuart_dev *nxpdev) +static bool ps_wakeup(struct btnxpuart_dev *nxpdev) { struct ps_data *psdata = &nxpdev->psdata; + u8 ps_state; - if (psdata->ps_state != PS_STATE_AWAKE) { + mutex_lock(&psdata->ps_lock); + ps_state = psdata->ps_state; + mutex_unlock(&psdata->ps_lock); + + if (ps_state != PS_STATE_AWAKE) { psdata->ps_cmd = PS_CMD_EXIT_PS; schedule_work(&psdata->work); + return true; } + return false; } static int send_ps_cmd(struct hci_dev *hdev, void *data) @@ -1171,7 +1187,6 @@ static struct sk_buff *nxp_dequeue(void *data) { struct btnxpuart_dev *nxpdev = (struct btnxpuart_dev *)data; - ps_wakeup(nxpdev); ps_start_timer(nxpdev); return skb_dequeue(&nxpdev->txq); } @@ -1186,6 +1201,9 @@ static void btnxpuart_tx_work(struct work_struct *work) struct sk_buff *skb; int len; + if (ps_wakeup(nxpdev)) + return; + while ((skb = nxp_dequeue(nxpdev))) { len = serdev_device_write_buf(serdev, skb->data, skb->len); hdev->stat.byte_tx += len; @@ -1267,8 +1285,8 @@ static const struct h4_recv_pkt nxp_recv_pkts[] = { { NXP_RECV_FW_REQ_V3, .recv = nxp_recv_fw_req_v3 }, }; -static ssize_t btnxpuart_receive_buf(struct serdev_device *serdev, - const u8 *data, size_t count) +static size_t btnxpuart_receive_buf(struct serdev_device *serdev, + const u8 *data, size_t count) { struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev); diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 35fb26cbf2..638074992c 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -148,10 +148,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev) } build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL); - if (!build_label) { - err = -ENOMEM; + if (!build_label) goto out; - } hci_set_fw_info(hdev, "%s", build_label); diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c index 0c91d7635a..634cf8f5ed 100644 --- a/drivers/bluetooth/btrsi.c +++ b/drivers/bluetooth/btrsi.c @@ -134,6 +134,7 @@ static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops) hdev->bus = HCI_USB; hci_set_drvdata(hdev, h_adapter); + hdev->dev_type = HCI_PRIMARY; hdev->open = rsi_hci_open; hdev->close = rsi_hci_close; hdev->flush = rsi_hci_flush; diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 277d039ecb..cc50de69e8 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -69,6 +69,7 @@ enum btrtl_chip_id { CHIP_ID_8852B = 20, CHIP_ID_8852C = 25, CHIP_ID_8851B = 36, + CHIP_ID_8852BT = 47, }; struct id_table { @@ -307,6 +308,15 @@ static const struct id_table ic_id_table[] = { .fw_name = "rtl_bt/rtl8851bu_fw", .cfg_name = "rtl_bt/rtl8851bu_config", .hw_info = "rtl8851bu" }, + + /* 8852BT/8852BE-VT */ + { IC_INFO(RTL_ROM_LMP_8852A, 0x87, 0xc, HCI_USB), + .config_needed = false, + .has_rom_version = true, + .has_msft_ext = true, + .fw_name = "rtl_bt/rtl8852btu_fw", + .cfg_name = "rtl_bt/rtl8852btu_config", + .hw_info = "rtl8852btu" }, }; static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev, @@ -645,6 +655,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, { RTL_ROM_LMP_8852A, 20 }, /* 8852B */ { RTL_ROM_LMP_8852A, 25 }, /* 8852C */ { RTL_ROM_LMP_8851B, 36 }, /* 8851B */ + { RTL_ROM_LMP_8852A, 47 }, /* 8852BT */ }; if (btrtl_dev->fw_len <= 8) @@ -1275,6 +1286,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) case CHIP_ID_8852B: case CHIP_ID_8852C: case CHIP_ID_8851B: + case CHIP_ID_8852BT: set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); @@ -1505,6 +1517,8 @@ MODULE_FIRMWARE("rtl_bt/rtl8852bs_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bs_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8852btu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8852btu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw_v2.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_config.bin"); diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index fdcfe9c503..f19d31ee37 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -32,6 +32,9 @@ static const struct sdio_device_id btsdio_table[] = { /* Generic Bluetooth Type-B SDIO device */ { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) }, + /* Generic Bluetooth AMP controller */ + { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) }, + { } /* Terminating entry */ }; @@ -316,6 +319,11 @@ static int btsdio_probe(struct sdio_func *func, hdev->bus = HCI_SDIO; hci_set_drvdata(hdev, data); + if (id->class == SDIO_CLASS_BT_AMP) + hdev->dev_type = HCI_AMP; + else + hdev->dev_type = HCI_PRIMARY; + data->hdev = hdev; SET_HCIDEV_DEV(hdev, &func->dev); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a1b82abe06..01b99471d1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -555,6 +555,9 @@ static const struct usb_device_id quirks_table[] = { { USB_DEVICE(0x13d3, 0x3572), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + /* Realtek 8852BT/8852BE-VT Bluetooth devices */ + { USB_DEVICE(0x0bda, 0x8520), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, /* Realtek Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01), .driver_info = BTUSB_REALTEK }, @@ -657,6 +660,11 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, + /* Additional MediaTek MT7925 Bluetooth devices */ + { USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, + /* Additional Realtek 8723AE Bluetooth devices */ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK }, @@ -3082,7 +3090,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev) int err, status; u32 dev_id = 0; char fw_bin_name[64]; - u32 fw_version = 0; + u32 fw_version = 0, fw_flavor = 0; u8 param; struct btmediatek_data *mediatek; @@ -3105,6 +3113,12 @@ static int btusb_mtk_setup(struct hci_dev *hdev) bt_dev_err(hdev, "Failed to get fw version (%d)", err); return err; } + err = btusb_mtk_id_get(data, 0x70010020, &fw_flavor); + if (err < 0) { + bt_dev_err(hdev, "Failed to get fw flavor (%d)", err); + return err; + } + fw_flavor = (fw_flavor & 0x00000080) >> 7; } mediatek = hci_get_priv(hdev); @@ -3129,6 +3143,10 @@ static int btusb_mtk_setup(struct hci_dev *hdev) snprintf(fw_bin_name, sizeof(fw_bin_name), "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", dev_id & 0xffff, dev_id & 0xffff, (fw_version & 0xff) + 1); + else if (dev_id == 0x7961 && fw_flavor) + snprintf(fw_bin_name, sizeof(fw_bin_name), + "mediatek/BT_RAM_CODE_MT%04x_1a_%x_hdr.bin", + dev_id & 0xffff, (fw_version & 0xff) + 1); else snprintf(fw_bin_name, sizeof(fw_bin_name), "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin", @@ -4314,6 +4332,11 @@ static int btusb_probe(struct usb_interface *intf, hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); + if (id->driver_info & BTUSB_AMP) + hdev->dev_type = HCI_AMP; + else + hdev->dev_type = HCI_PRIMARY; + data->hdev = hdev; SET_HCIDEV_DEV(hdev, &intf->dev); diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c index 0c2f15235b..9a7243d5db 100644 --- a/drivers/bluetooth/hci_bcm4377.c +++ b/drivers/bluetooth/hci_bcm4377.c @@ -2361,6 +2361,7 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id) bcm4377->hdev = hdev; hdev->bus = HCI_PCI; + hdev->dev_type = HCI_PRIMARY; hdev->open = bcm4377_hci_open; hdev->close = bcm4377_hci_close; hdev->send = bcm4377_hci_send_frame; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 17a2f158a0..a26367e9fb 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -667,6 +667,11 @@ static int hci_uart_register_dev(struct hci_uart *hu) if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) + hdev->dev_type = HCI_AMP; + else + hdev->dev_type = HCI_PRIMARY; + /* Only call open() for the protocol after hdev is fully initialized as * open() (or a timer/workqueue it starts) may attempt to reference it. */ @@ -717,6 +722,7 @@ static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags) { unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) | BIT(HCI_UART_RESET_ON_INIT) | + BIT(HCI_UART_CREATE_AMP) | BIT(HCI_UART_INIT_PENDING) | BIT(HCI_UART_EXT_CONFIG) | BIT(HCI_UART_VND_DETECT); diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 0eaec878fa..85c0d9b68f 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -271,8 +271,8 @@ static void hci_uart_write_wakeup(struct serdev_device *serdev) * * Return: number of processed bytes */ -static ssize_t hci_uart_receive_buf(struct serdev_device *serdev, - const u8 *data, size_t count) +static size_t hci_uart_receive_buf(struct serdev_device *serdev, + const u8 *data, size_t count) { struct hci_uart *hu = serdev_device_get_drvdata(serdev); @@ -366,6 +366,11 @@ int hci_uart_register_device_priv(struct hci_uart *hu, if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); + if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) + hdev->dev_type = HCI_AMP; + else + hdev->dev_type = HCI_PRIMARY; + if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) return 0; diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 00bf7ae82c..68c8c7e95d 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -37,6 +37,7 @@ #define HCI_UART_RAW_DEVICE 0 #define HCI_UART_RESET_ON_INIT 1 +#define HCI_UART_CREATE_AMP 2 #define HCI_UART_INIT_PENDING 3 #define HCI_UART_EXT_CONFIG 4 #define HCI_UART_VND_DETECT 5 diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 28750a40f0..572d68d529 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -384,10 +384,17 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) { struct hci_dev *hdev; struct sk_buff *skb; + __u8 dev_type; if (data->hdev) return -EBADFD; + /* bits 0-1 are dev_type (Primary or AMP) */ + dev_type = opcode & 0x03; + + if (dev_type != HCI_PRIMARY && dev_type != HCI_AMP) + return -EINVAL; + /* bits 2-5 are reserved (must be zero) */ if (opcode & 0x3c) return -EINVAL; @@ -405,6 +412,7 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) data->hdev = hdev; hdev->bus = HCI_VIRTUAL; + hdev->dev_type = dev_type; hci_set_drvdata(hdev, data); hdev->open = vhci_open_dev; @@ -626,7 +634,7 @@ static void vhci_open_timeout(struct work_struct *work) struct vhci_data *data = container_of(work, struct vhci_data, open_timeout.work); - vhci_create_device(data, 0x00); + vhci_create_device(data, amp ? HCI_AMP : HCI_PRIMARY); } static int vhci_open(struct inode *inode, struct file *file) diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index 18208e152a..2ac70b560c 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -274,6 +274,7 @@ static int virtbt_probe(struct virtio_device *vdev) switch (type) { case VIRTIO_BT_CONFIG_TYPE_PRIMARY: + case VIRTIO_BT_CONFIG_TYPE_AMP: break; default: return -EINVAL; @@ -302,6 +303,7 @@ static int virtbt_probe(struct virtio_device *vdev) vbt->hdev = hdev; hdev->bus = HCI_VIRTIO; + hdev->dev_type = type; hci_set_drvdata(hdev, vbt); hdev->open = virtbt_open; |