From e5d6468fe9d8dced9af0c548a359a7dbeb31c931 Mon Sep 17 00:00:00 2001 From: Rocky Liao Date: Wed, 25 Mar 2020 10:26:37 +0800 Subject: Bluetooth: hci_qca: Add support for Qualcomm Bluetooth SoC QCA6390 This patch adds support for QCA6390, including the devicetree and acpi compatible hwid matching, and patch/nvm downloading. Signed-off-by: Rocky Liao Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 18 +++++++++++++----- drivers/bluetooth/btqca.h | 3 ++- drivers/bluetooth/hci_qca.c | 40 +++++++++++++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 13 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index a16845c0751d..3ea866d44568 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -32,7 +32,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version, * VSE event. WCN3991 sends version command response as a payload to * command complete event. */ - if (soc_type == QCA_WCN3991) { + if (soc_type >= QCA_WCN3991) { event_type = 0; rlen += 1; rtype = EDL_PATCH_VER_REQ_CMD; @@ -69,7 +69,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version, goto out; } - if (soc_type == QCA_WCN3991) + if (soc_type >= QCA_WCN3991) memmove(&edl->data, &edl->data[1], sizeof(*ver)); ver = (struct qca_btsoc_version *)(edl->data); @@ -217,7 +217,7 @@ static void qca_tlv_check_data(struct qca_fw_config *config, tlv_nvm->data[0] |= 0x80; /* UART Baud Rate */ - if (soc_type == QCA_WCN3991) + if (soc_type >= QCA_WCN3991) tlv_nvm->data[1] = nvm_baud_rate; else tlv_nvm->data[2] = nvm_baud_rate; @@ -268,7 +268,7 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, * VSE event. WCN3991 sends version command response as a payload to * command complete event. */ - if (soc_type == QCA_WCN3991) { + if (soc_type >= QCA_WCN3991) { event_type = 0; rlen = sizeof(*edl); rtype = EDL_PATCH_TLV_REQ_CMD; @@ -301,7 +301,7 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, err = -EIO; } - if (soc_type == QCA_WCN3991) + if (soc_type >= QCA_WCN3991) goto out; tlv_resp = (struct tlv_seg_resp *)(edl->data); @@ -442,6 +442,11 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, (soc_ver & 0x0000000f); snprintf(config.fwname, sizeof(config.fwname), "qca/crbtfw%02x.tlv", rom_ver); + } else if (soc_type == QCA_QCA6390) { + rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | + (soc_ver & 0x0000000f); + snprintf(config.fwname, sizeof(config.fwname), + "qca/htbtfw%02x.tlv", rom_ver); } else { snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin", soc_ver); @@ -464,6 +469,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, else if (qca_is_wcn399x(soc_type)) snprintf(config.fwname, sizeof(config.fwname), "qca/crnv%02x.bin", rom_ver); + else if (soc_type == QCA_QCA6390) + snprintf(config.fwname, sizeof(config.fwname), + "qca/htnv%02x.bin", rom_ver); else snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin", soc_ver); diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index e16a4d650597..6e1e62dd4b95 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -125,8 +125,9 @@ enum qca_btsoc_type { QCA_AR3002, QCA_ROME, QCA_WCN3990, - QCA_WCN3991, QCA_WCN3998, + QCA_WCN3991, + QCA_QCA6390, }; #if IS_ENABLED(CONFIG_BT_QCA) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 439392b1c043..d0ac554584a4 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1596,7 +1597,7 @@ 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" : "ROME"); + qca_is_wcn399x(soc_type) ? "wcn399x" : "ROME/QCA6390"); retry: ret = qca_power_on(hdev); @@ -1665,10 +1666,10 @@ retry: } /* Setup bdaddr */ - if (qca_is_wcn399x(soc_type)) - hu->hdev->set_bdaddr = qca_set_bdaddr; - else + if (soc_type == QCA_ROME) hu->hdev->set_bdaddr = qca_set_bdaddr_rome; + else + hu->hdev->set_bdaddr = qca_set_bdaddr; return ret; } @@ -1721,6 +1722,11 @@ static const struct qca_vreg_data qca_soc_data_wcn3998 = { .num_vregs = 4, }; +static const struct qca_vreg_data qca_soc_data_qca6390 = { + .soc_type = QCA_QCA6390, + .num_vregs = 0, +}; + static void qca_power_shutdown(struct hci_uart *hu) { struct qca_serdev *qcadev; @@ -1764,7 +1770,7 @@ static int qca_power_off(struct hci_dev *hdev) enum qca_btsoc_type soc_type = qca_soc_type(hu); /* Stop sending shutdown command if soc crashes. */ - if (qca_is_wcn399x(soc_type) + if (soc_type != QCA_ROME && qca->memdump_state == QCA_MEMDUMP_IDLE) { qca_send_pre_shutdown_cmd(hdev); usleep_range(8000, 10000); @@ -1900,7 +1906,11 @@ static int qca_serdev_probe(struct serdev_device *serdev) return err; } } else { - qcadev->btsoc_type = QCA_ROME; + if (data) + qcadev->btsoc_type = data->soc_type; + else + qcadev->btsoc_type = QCA_ROME; + qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); if (!qcadev->bt_en) { @@ -2044,21 +2054,37 @@ static int __maybe_unused qca_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume); +#ifdef CONFIG_OF static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, + { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390}, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id qca_bluetooth_acpi_match[] = { + { "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 }, + { "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 }, + { "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 }, + { "DLB26390", (kernel_ulong_t)&qca_soc_data_qca6390 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, qca_bluetooth_acpi_match); +#endif + static struct serdev_device_driver qca_serdev_driver = { .probe = qca_serdev_probe, .remove = qca_serdev_remove, .driver = { .name = "hci_uart_qca", - .of_match_table = qca_bluetooth_of_match, + .of_match_table = of_match_ptr(qca_bluetooth_of_match), + .acpi_match_table = ACPI_PTR(qca_bluetooth_acpi_match), .pm = &qca_pm_ops, }, }; -- cgit v1.2.3-59-g8ed1b From b25e4df4a83e516efbdeeefb5b2d3e259639a56e Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 2 Apr 2020 14:55:18 +0200 Subject: Bluetooth: hci_bcm: respect IRQ polarity from DT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IRQ polarity is be configured in bcm_setup_sleep(). Make the configured value match what is in the DeviceTree. Cc: stable@vger.kernel.org Fixes: f25a96c8eb46 ("Bluetooth: hci_bcm: enable IRQ capability from devicetree") Signed-off-by: Michał Mirosław Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index b236cb11c0dc..36b7f0d00c4b 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1153,7 +1153,8 @@ static int bcm_of_probe(struct bcm_device *bdev) device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params", bdev->pcm_int_params, 5); bdev->irq = of_irq_get_byname(bdev->dev->of_node, "host-wakeup"); - + bdev->irq_active_low = irq_get_trigger_type(bdev->irq) + & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW); return 0; } -- cgit v1.2.3-59-g8ed1b From 81bd5d0c62437c02caac6b3f942fcda874063cb0 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Thu, 2 Apr 2020 14:55:20 +0200 Subject: Bluetooth: hci_bcm: fix freeing not-requested IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When BT module can't be initialized, but it has an IRQ, unloading the driver WARNs when trying to free not-yet-requested IRQ. Fix it by noting whether the IRQ was requested. WARNING: CPU: 2 PID: 214 at kernel/irq/devres.c:144 devm_free_irq+0x49/0x4ca [...] WARNING: CPU: 2 PID: 214 at kernel/irq/manage.c:1746 __free_irq+0x8b/0x27c Trying to free already-free IRQ 264 Modules linked in: hci_uart(-) btbcm bluetooth ecdh_generic ecc libaes CPU: 2 PID: 214 Comm: rmmod Tainted: G W 5.6.1mq-00044-ga5f9ea098318-dirty #928 [...] [] (devm_free_irq) from [] (bcm_close+0x97/0x118 [hci_uart]) [] (bcm_close [hci_uart]) from [] (hci_uart_unregister_device+0x33/0x3c [hci_uart]) [] (hci_uart_unregister_device [hci_uart]) from [] (serdev_drv_remove+0x13/0x20) [] (serdev_drv_remove) from [] (device_release_driver_internal+0x97/0x118) [] (device_release_driver_internal) from [] (driver_detach+0x2f/0x58) [] (driver_detach) from [] (bus_remove_driver+0x41/0x94) [] (bus_remove_driver) from [] (bcm_deinit+0x1b/0x740 [hci_uart]) [] (bcm_deinit [hci_uart]) from [] (hci_uart_exit+0x13/0x30 [hci_uart]) [] (hci_uart_exit [hci_uart]) from [] (sys_delete_module+0x109/0x1d0) [] (sys_delete_module) from [] (ret_fast_syscall+0x1/0x5a) [...] Cc: stable@vger.kernel.org Fixes: 6cc4396c8829 ("Bluetooth: hci_bcm: Add wake-up capability") Signed-off-by: Michał Mirosław Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 36b7f0d00c4b..19e4587f366c 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -118,6 +118,7 @@ struct bcm_device { u32 oper_speed; int irq; bool irq_active_low; + bool irq_acquired; #ifdef CONFIG_PM struct hci_uart *hu; @@ -333,6 +334,8 @@ static int bcm_request_irq(struct bcm_data *bcm) goto unlock; } + bdev->irq_acquired = true; + device_init_wakeup(bdev->dev, true); pm_runtime_set_autosuspend_delay(bdev->dev, @@ -514,7 +517,7 @@ static int bcm_close(struct hci_uart *hu) } if (bdev) { - if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) { + if (IS_ENABLED(CONFIG_PM) && bdev->irq_acquired) { devm_free_irq(bdev->dev, bdev->irq, bdev); device_init_wakeup(bdev->dev, false); pm_runtime_disable(bdev->dev); -- cgit v1.2.3-59-g8ed1b From baac6276c0a9f36f1fe1f00590ef00d2ba5ba626 Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Fri, 3 Apr 2020 21:43:59 +0200 Subject: Bluetooth: btusb: handle mSBC audio over USB Endpoints For mSBC encoded audio stream over usb transport, btusb driver to be set to alternate settings 6 as per BT core spec 5.0. The type of air mode is used to differenting which alt setting to be used. The changes are made considering some discussion over the similar patch submitted earlier from Kuba Pawlak (link below) https://www.spinics.net/lists/linux-bluetooth/msg64577.html Reported-by: kbuild test robot Signed-off-by: Sathish Narasimman Signed-off-by: Chethan T N Signed-off-by: Hsin-Yu Chao Signed-off-by: Amit K Bag Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 156 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 37 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3bdec42c9612..110e96b245e5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -492,6 +492,8 @@ struct btusb_data { __u8 cmdreq; unsigned int sco_num; + unsigned int air_mode; + bool usb_alt6_packet_flow; int isoc_altsetting; int suspend_count; @@ -983,6 +985,42 @@ static void btusb_isoc_complete(struct urb *urb) } } +static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len, + int mtu, struct btusb_data *data) +{ + int i, offset = 0; + unsigned int interval; + + BT_DBG("len %d mtu %d", len, mtu); + + /* For mSBC ALT 6 setting the host will send the packet at continuous + * flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting + * 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets. + * To maintain the rate we send 63bytes of usb packets alternatively for + * 7ms and 8ms to maintain the rate as 7.5ms. + */ + if (data->usb_alt6_packet_flow) { + interval = 7; + data->usb_alt6_packet_flow = false; + } else { + interval = 6; + data->usb_alt6_packet_flow = true; + } + + for (i = 0; i < interval; i++) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = offset; + } + + if (len && i < BTUSB_MAX_ISOC_FRAMES) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = len; + i++; + } + + urb->number_of_packets = i; +} + static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu) { int i, offset = 0; @@ -1386,9 +1424,13 @@ static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb) urb->transfer_flags = URB_ISO_ASAP; - __fill_isoc_descriptor(urb, skb->len, - le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); - + if (data->isoc_altsetting == 6) + __fill_isoc_descriptor_msbc(urb, skb->len, + le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize), + data); + else + __fill_isoc_descriptor(urb, skb->len, + le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); skb->dev = (void *)hdev; return urb; @@ -1484,6 +1526,7 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt) if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) { data->sco_num = hci_conn_num(hdev, SCO_LINK); + data->air_mode = evt; schedule_work(&data->work); } } @@ -1531,11 +1574,67 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting) return 0; } +static int btusb_switch_alt_setting(struct hci_dev *hdev, int new_alts) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + int err; + + if (data->isoc_altsetting != new_alts) { + unsigned long flags; + + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->isoc_anchor); + + /* When isochronous alternate setting needs to be + * changed, because SCO connection has been added + * or removed, a packet fragment may be left in the + * reassembling state. This could lead to wrongly + * assembled fragments. + * + * Clear outstanding fragment when selecting a new + * alternate setting. + */ + spin_lock_irqsave(&data->rxlock, flags); + kfree_skb(data->sco_skb); + data->sco_skb = NULL; + spin_unlock_irqrestore(&data->rxlock, flags); + + err = __set_isoc_interface(hdev, new_alts); + if (err < 0) + return err; + } + + if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { + if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0) + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + else + btusb_submit_isoc_urb(hdev, GFP_KERNEL); + } + + return 0; +} + +static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data, + int alt) +{ + struct usb_interface *intf = data->isoc; + int i; + + BT_DBG("Looking for Alt no :%d", alt); + + for (i = 0; i < intf->num_altsetting; i++) { + if (intf->altsetting[i].desc.bAlternateSetting == alt) + return &intf->altsetting[i]; + } + + return NULL; +} + static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; - int new_alts; + int new_alts = 0; int err; if (data->sco_num > 0) { @@ -1550,44 +1649,27 @@ static void btusb_work(struct work_struct *work) set_bit(BTUSB_DID_ISO_RESUME, &data->flags); } - if (hdev->voice_setting & 0x0020) { - static const int alts[3] = { 2, 4, 5 }; - - new_alts = alts[data->sco_num - 1]; - } else { - new_alts = data->sco_num; - } - - if (data->isoc_altsetting != new_alts) { - unsigned long flags; + if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) { + if (hdev->voice_setting & 0x0020) { + static const int alts[3] = { 2, 4, 5 }; - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); - usb_kill_anchored_urbs(&data->isoc_anchor); - - /* When isochronous alternate setting needs to be - * changed, because SCO connection has been added - * or removed, a packet fragment may be left in the - * reassembling state. This could lead to wrongly - * assembled fragments. - * - * Clear outstanding fragment when selecting a new - * alternate setting. - */ - spin_lock_irqsave(&data->rxlock, flags); - kfree_skb(data->sco_skb); - data->sco_skb = NULL; - spin_unlock_irqrestore(&data->rxlock, flags); + new_alts = alts[data->sco_num - 1]; + } else { + new_alts = data->sco_num; + } + } else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) { - if (__set_isoc_interface(hdev, new_alts) < 0) - return; - } + data->usb_alt6_packet_flow = true; - if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { - if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0) - clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + /* Check if Alt 6 is supported for Transparent audio */ + if (btusb_find_altsetting(data, 6)) + new_alts = 6; else - btusb_submit_isoc_urb(hdev, GFP_KERNEL); + bt_dev_err(hdev, "Device does not support ALT setting 6"); } + + if (btusb_switch_alt_setting(hdev, new_alts) < 0) + bt_dev_err(hdev, "set USB alt:(%d) failed!", new_alts); } else { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->isoc_anchor); -- cgit v1.2.3-59-g8ed1b From 7fd673bcdacc8528c7d9489d31f040eac7cca164 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 3 Apr 2020 21:44:02 +0200 Subject: Bluetooth: btusb: Enable Intel events even if already in operational mode In case the controller is already in operation mode, the Intel specific events will not be enabled. Fix this by jumping to a common finish section that will allow setting final details for the controller. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 110e96b245e5..43925bdeaa81 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2334,7 +2334,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) if (ver.fw_variant == 0x23) { clear_bit(BTUSB_BOOTLOADER, &data->flags); btintel_check_bdaddr(hdev); - return 0; + goto finish; } /* If the device is not in bootloader mode, then the only possible @@ -2534,6 +2534,14 @@ done: */ btintel_load_ddc_config(hdev, fwname); + /* Read the Intel version information after loading the FW */ + err = btintel_read_version(hdev, &ver); + if (err) + return err; + + btintel_version_info(hdev, &ver); + +finish: /* Set the event mask for Intel specific vendor events. This enables * a few extra events that are useful during general operation. It * does not enable any debugging related events. @@ -2543,13 +2551,6 @@ done: */ btintel_set_event_mask(hdev, false); - /* Read the Intel version information after loading the FW */ - err = btintel_read_version(hdev, &ver); - if (err) - return err; - - btintel_version_info(hdev, &ver); - return 0; } -- cgit v1.2.3-59-g8ed1b From fc04590e3d39213a22b7afd46c4bd5d95a6cab1f Mon Sep 17 00:00:00 2001 From: Miao-chen Chou Date: Fri, 3 Apr 2020 21:44:03 +0200 Subject: Bluetooth: btusb: Enable MSFT extension for Intel ThunderPeak devices The Intel ThundePeak BT controllers support the Microsoft vendor extension and they are using 0xFC1E for VsMsftOpCode. < HCI Command: Vendor (0x3f|0x001e) plen 1 00 > HCI Event: Command Complete (0x0e) plen 15 Vendor (0x3f|0x001e) ncmd 1 Status: Success (0x00) 00 3f 00 00 00 00 00 00 00 01 50 Signed-off-by: Miao-chen Chou Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 43925bdeaa81..09913cadd1ca 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2542,6 +2542,15 @@ done: btintel_version_info(hdev, &ver); finish: + /* All Intel controllers that support the Microsoft vendor + * extension are using 0xFC1E for VsMsftOpCode. + */ + switch (ver.hw_variant) { + case 0x12: /* ThP */ + hci_set_msft_opcode(hdev, 0xFC1E); + break; + } + /* Set the event mask for Intel specific vendor events. This enables * a few extra events that are useful during general operation. It * does not enable any debugging related events. -- cgit v1.2.3-59-g8ed1b From fcd156ee8bc6a989dbf7e5efbccdc9cdb831fd27 Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Wed, 8 Apr 2020 10:57:03 +0530 Subject: Bluetooth: btusb: check for NULL in btusb_find_altsetting() The new btusb_find_altsetting() dereferences it without checking the check is added in this patch Signed-off-by: Sathish Narasimman Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 09913cadd1ca..871162790a0e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1622,6 +1622,9 @@ static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data, BT_DBG("Looking for Alt no :%d", alt); + if (!intf) + return NULL; + for (i = 0; i < intf->num_altsetting; i++) { if (intf->altsetting[i].desc.bAlternateSetting == alt) return &intf->altsetting[i]; -- cgit v1.2.3-59-g8ed1b From 04896832c94aae4842100cafb8d3a73e1bed3a45 Mon Sep 17 00:00:00 2001 From: "Ziqian SUN (Zamir)" Date: Sat, 11 Apr 2020 09:34:27 +0800 Subject: Bluetooth: btrtl: Add support for RTL8761B Add new compatible device RTL8761B. RTL8761B is a USB Bluetooth device, with support of BLE and BR/EDR. The USB info is T: Bus=03 Lev=04 Prnt=04 Port=00 Cnt=01 Dev#= 29 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=8771 Rev= 2.00 S: Manufacturer=Realtek S: Product=Bluetooth Radio S: SerialNumber=XXXXXXXXXXXX C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Ziqian SUN (Zamir) Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 67f4bc21e7c5..3a9afc905f24 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -130,12 +130,19 @@ static const struct id_table ic_id_table[] = { .cfg_name = "rtl_bt/rtl8821c_config" }, /* 8761A */ - { IC_MATCH_FL_LMPSUBV, RTL_ROM_LMP_8761A, 0x0, + { IC_INFO(RTL_ROM_LMP_8761A, 0xa), .config_needed = false, .has_rom_version = true, .fw_name = "rtl_bt/rtl8761a_fw.bin", .cfg_name = "rtl_bt/rtl8761a_config" }, + /* 8761B */ + { IC_INFO(RTL_ROM_LMP_8761A, 0xb), + .config_needed = false, + .has_rom_version = true, + .fw_name = "rtl_bt/rtl8761b_fw.bin", + .cfg_name = "rtl_bt/rtl8761b_config" }, + /* 8822C with UART interface */ { .match_flags = IC_MATCH_FL_LMPSUBV | IC_MATCH_FL_HCIREV | IC_MATCH_FL_HCIBUS, @@ -267,6 +274,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, { RTL_ROM_LMP_8723B, 9 }, /* 8723D */ { RTL_ROM_LMP_8821A, 10 }, /* 8821C */ { RTL_ROM_LMP_8822B, 13 }, /* 8822C */ + { RTL_ROM_LMP_8761A, 14 }, /* 8761B */ }; min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3; -- cgit v1.2.3-59-g8ed1b From 3fef10ec321ced8e75cd0a28616402401cbbcaf4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:25 +0200 Subject: Bluetooth: btbcm: Drop upper nibble version check from btbcm_initialize() btbcm_initialize() must either return an error; or fill the passed in fw_name, otherwise we end up passing uninitialized stack memory to request_firmware(). Since we have a fallback hw_name of "BCM" not having a known version in the subver field does not matter, drop the check so that we always fill the passed in fw_name. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 1f498f358f60..b9e1fe052148 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -440,10 +440,6 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, return err; } - /* Upper nibble of rev should be between 0 and 3? */ - if (((rev & 0xf000) >> 12) > 3) - return 0; - bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : bcm_uart_subver_table; -- cgit v1.2.3-59-g8ed1b From f8c51d28e9d13f20c33f4f2f46f8e7d0b8476b9c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:26 +0200 Subject: Bluetooth: btbcm: Move setting of USE_BDADDR_PROPERTY quirk to hci_bcm.c btbcm_finalize() is currently only used by UART attached BCM devices. Move the setting of the USE_BDADDR_PROPERTY quirk, which we only want for UART attached devices to hci_bcm in preparation for using btbcm_finalize() for USB attached devices too. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 6 ------ drivers/bluetooth/hci_bcm.c | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index b9e1fe052148..8052a0e8dbfb 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -488,12 +488,6 @@ int btbcm_finalize(struct hci_dev *hdev) set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - /* Some devices ship with the controller default address. - * Allow the bootloader to set a valid address through the - * device tree. - */ - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); - return 0; } EXPORT_SYMBOL_GPL(btbcm_finalize); diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 19e4587f366c..c42bf791a61b 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -623,6 +623,12 @@ finalize: if (err) return err; + /* Some devices ship with the controller default address. + * Allow the bootloader to set a valid address through the + * device tree. + */ + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); + if (!bcm_request_irq(bcm)) err = bcm_setup_sleep(hu); -- cgit v1.2.3-59-g8ed1b From 0287c5d84f5c0cde6c39362d56c7002dc4acedb3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:27 +0200 Subject: Bluetooth: btbcm: Fold Patch loading + applying into btbcm_initialize() Instead of having btbcm_initialize() fill a passed in fw_name buffer and then have its callers use that to request the firmware + load it into the HCI, make btbcm_initialize() do this itself the first time it is called (its get called a second time to reset the HCI after the firmware has been loaded). This removes some code duplication and makes it easier for further patches in this series to try more then 1 firmware filename. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 50 +++++++++++++++++++++++++++------------------ drivers/bluetooth/btbcm.h | 6 ++---- drivers/bluetooth/hci_bcm.c | 19 +++-------------- 3 files changed, 35 insertions(+), 40 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 8052a0e8dbfb..c22e90a5e288 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -27,6 +27,8 @@ #define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}}) #define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) +#define BCM_FW_NAME_LEN 64 + int btbcm_check_bdaddr(struct hci_dev *hdev) { struct hci_rp_read_bd_addr *bda; @@ -408,14 +410,15 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = { { } }; -int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, - bool reinit) +int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) { u16 subver, rev, pid, vid; const char *hw_name = "BCM"; struct sk_buff *skb; struct hci_rp_read_local_version *ver; const struct bcm_subver_table *bcm_subver_table; + char fw_name[BCM_FW_NAME_LEN]; + const struct firmware *fw; int i, err; /* Reset */ @@ -434,7 +437,7 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, kfree_skb(skb); /* Read controller information */ - if (!reinit) { + if (!(*fw_load_done)) { err = btbcm_read_info(hdev); if (err) return err; @@ -460,27 +463,42 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, pid = get_unaligned_le16(skb->data + 3); kfree_skb(skb); - snprintf(fw_name, len, "brcm/%s-%4.4x-%4.4x.hcd", + snprintf(fw_name, BCM_FW_NAME_LEN, "brcm/%s-%4.4x-%4.4x.hcd", hw_name, vid, pid); } else { - snprintf(fw_name, len, "brcm/%s.hcd", hw_name); + snprintf(fw_name, BCM_FW_NAME_LEN, "brcm/%s.hcd", hw_name); } bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", hw_name, (subver & 0xe000) >> 13, (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); + if (*fw_load_done) + return 0; + + err = request_firmware(&fw, fw_name, &hdev->dev); + if (err) { + bt_dev_info(hdev, "BCM: Patch %s not found", fw_name); + return 0; + } + + err = btbcm_patchram(hdev, fw); + if (err) + bt_dev_info(hdev, "BCM: Patch failed (%d)", err); + + release_firmware(fw); + *fw_load_done = true; return 0; } EXPORT_SYMBOL_GPL(btbcm_initialize); int btbcm_finalize(struct hci_dev *hdev) { - char fw_name[64]; + bool fw_load_done = true; int err; /* Re-initialize */ - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true); + err = btbcm_initialize(hdev, &fw_load_done); if (err) return err; @@ -494,28 +512,20 @@ EXPORT_SYMBOL_GPL(btbcm_finalize); int btbcm_setup_patchram(struct hci_dev *hdev) { - char fw_name[64]; - const struct firmware *fw; + bool fw_load_done = false; struct sk_buff *skb; int err; /* Initialize */ - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), false); + err = btbcm_initialize(hdev, &fw_load_done); if (err) return err; - err = request_firmware(&fw, fw_name, &hdev->dev); - if (err < 0) { - bt_dev_info(hdev, "BCM: Patch %s not found", fw_name); + if (!fw_load_done) goto done; - } - btbcm_patchram(hdev, fw); - - release_firmware(fw); - - /* Re-initialize */ - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true); + /* Re-initialize after loading Patch */ + err = btbcm_initialize(hdev, &fw_load_done); if (err) return err; diff --git a/drivers/bluetooth/btbcm.h b/drivers/bluetooth/btbcm.h index 014ef847a486..8437caba421d 100644 --- a/drivers/bluetooth/btbcm.h +++ b/drivers/bluetooth/btbcm.h @@ -62,8 +62,7 @@ int btbcm_write_pcm_int_params(struct hci_dev *hdev, int btbcm_setup_patchram(struct hci_dev *hdev); int btbcm_setup_apple(struct hci_dev *hdev); -int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, - bool reinit); +int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done); int btbcm_finalize(struct hci_dev *hdev); #else @@ -105,8 +104,7 @@ static inline int btbcm_setup_apple(struct hci_dev *hdev) return 0; } -static inline int btbcm_initialize(struct hci_dev *hdev, char *fw_name, - size_t len, bool reinit) +static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) { return 0; } diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index c42bf791a61b..61731cb451cb 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -553,8 +553,7 @@ static int bcm_flush(struct hci_uart *hu) static int bcm_setup(struct hci_uart *hu) { struct bcm_data *bcm = hu->priv; - char fw_name[64]; - const struct firmware *fw; + bool fw_load_done = false; unsigned int speed; int err; @@ -563,21 +562,12 @@ static int bcm_setup(struct hci_uart *hu) hu->hdev->set_diag = bcm_set_diag; hu->hdev->set_bdaddr = btbcm_set_bdaddr; - err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name), false); + err = btbcm_initialize(hu->hdev, &fw_load_done); if (err) return err; - err = request_firmware(&fw, fw_name, &hu->hdev->dev); - if (err < 0) { - bt_dev_info(hu->hdev, "BCM: Patch %s not found", fw_name); + if (!fw_load_done) return 0; - } - - err = btbcm_patchram(hu->hdev, fw); - if (err) { - bt_dev_info(hu->hdev, "BCM: Patch failed (%d)", err); - goto finalize; - } /* Init speed if any */ if (hu->init_speed) @@ -616,9 +606,6 @@ static int bcm_setup(struct hci_uart *hu) btbcm_write_pcm_int_params(hu->hdev, ¶ms); } -finalize: - release_firmware(fw); - err = btbcm_finalize(hu->hdev); if (err) return err; -- cgit v1.2.3-59-g8ed1b From 2fcdd562b91bdc29dddd406f7278102e4d90b1fa Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:28 +0200 Subject: Bluetooth: btbcm: Make btbcm_initialize() print local-name on re-init too Make btbcm_initialize() get and print the device's local-name on re-init too, this will make us also print the local-name after loading the Patch on UART attached devices making things more consistent. This also removes some code duplication from btbcm_setup_patchram() and allows more code duplication removal there in a follow-up patch. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index c22e90a5e288..3404021b10bd 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -360,6 +360,13 @@ static int btbcm_read_info(struct hci_dev *hdev) bt_dev_info(hdev, "BCM: features 0x%2.2x", skb->data[1]); kfree_skb(skb); + return 0; +} + +static int btbcm_print_local_name(struct hci_dev *hdev) +{ + struct sk_buff *skb; + /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (IS_ERR(skb)) @@ -442,6 +449,9 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) if (err) return err; } + err = btbcm_print_local_name(hdev); + if (err) + return err; bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : bcm_uart_subver_table; @@ -513,7 +523,6 @@ EXPORT_SYMBOL_GPL(btbcm_finalize); int btbcm_setup_patchram(struct hci_dev *hdev) { bool fw_load_done = false; - struct sk_buff *skb; int err; /* Initialize */ @@ -529,14 +538,6 @@ int btbcm_setup_patchram(struct hci_dev *hdev) if (err) return err; - /* Read Local Name */ - skb = btbcm_read_local_name(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - bt_dev_info(hdev, "%s", (char *)(skb->data + 1)); - kfree_skb(skb); - done: btbcm_check_bdaddr(hdev); -- cgit v1.2.3-59-g8ed1b From 0383f16a87c4dec6840cdbb80c2a30ecfdc2ffb0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:29 +0200 Subject: Bluetooth: btbcm: Make btbcm_setup_patchram use btbcm_finalize On UART attached devices we do: 1. btbcm_initialize() 2. Setup UART baudrate, etc. 3. btbcm_finalize() After our previous changes we can now also use btbcm_finalize() from the btbcm_setup_patchram() function used on USB devices without any functional changes. This completes unifying the USB and UART paths as much as possible. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 27 ++++++++------------------- drivers/bluetooth/btbcm.h | 4 ++-- drivers/bluetooth/hci_bcm.c | 2 +- 3 files changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 3404021b10bd..cc3628cace35 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -502,15 +502,16 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) } EXPORT_SYMBOL_GPL(btbcm_initialize); -int btbcm_finalize(struct hci_dev *hdev) +int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) { - bool fw_load_done = true; int err; - /* Re-initialize */ - err = btbcm_initialize(hdev, &fw_load_done); - if (err) - return err; + /* Re-initialize if necessary */ + if (*fw_load_done) { + err = btbcm_initialize(hdev, fw_load_done); + if (err) + return err; + } btbcm_check_bdaddr(hdev); @@ -530,20 +531,8 @@ int btbcm_setup_patchram(struct hci_dev *hdev) if (err) return err; - if (!fw_load_done) - goto done; - /* Re-initialize after loading Patch */ - err = btbcm_initialize(hdev, &fw_load_done); - if (err) - return err; - -done: - btbcm_check_bdaddr(hdev); - - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - - return 0; + return btbcm_finalize(hdev, &fw_load_done); } EXPORT_SYMBOL_GPL(btbcm_setup_patchram); diff --git a/drivers/bluetooth/btbcm.h b/drivers/bluetooth/btbcm.h index 8437caba421d..8bf01565fdfc 100644 --- a/drivers/bluetooth/btbcm.h +++ b/drivers/bluetooth/btbcm.h @@ -63,7 +63,7 @@ int btbcm_setup_patchram(struct hci_dev *hdev); int btbcm_setup_apple(struct hci_dev *hdev); int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done); -int btbcm_finalize(struct hci_dev *hdev); +int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done); #else @@ -109,7 +109,7 @@ static inline int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) return 0; } -static inline int btbcm_finalize(struct hci_dev *hdev) +static inline int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) { return 0; } diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 61731cb451cb..8ea5ca8d71d6 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -606,7 +606,7 @@ static int bcm_setup(struct hci_uart *hu) btbcm_write_pcm_int_params(hu->hdev, ¶ms); } - err = btbcm_finalize(hu->hdev); + err = btbcm_finalize(hu->hdev, &fw_load_done); if (err) return err; -- cgit v1.2.3-59-g8ed1b From f53b975cf113fa0dca9c7bba067c3d749682cc82 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:30 +0200 Subject: Bluetooth: btbcm: Bail sooner from btbcm_initialize() when not loading fw If we have already loaded the firmware/patchram and btbcm_initialize() is called to re-init the HCI after this then there is no need to get the USB device-ids and build a firmware-filename out of these. Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index cc3628cace35..9fa153b35825 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -463,6 +463,13 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) } } + bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", + hw_name, (subver & 0xe000) >> 13, + (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); + + if (*fw_load_done) + return 0; + if (hdev->bus == HCI_USB) { /* Read USB Product Info */ skb = btbcm_read_usb_product(hdev); @@ -479,13 +486,6 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) snprintf(fw_name, BCM_FW_NAME_LEN, "brcm/%s.hcd", hw_name); } - bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", - hw_name, (subver & 0xe000) >> 13, - (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); - - if (*fw_load_done) - return 0; - err = request_firmware(&fw, fw_name, &hdev->dev); if (err) { bt_dev_info(hdev, "BCM: Patch %s not found", fw_name); -- cgit v1.2.3-59-g8ed1b From 74530a639adfa2b2162df6a688c6367ecae6a3ca Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:31 +0200 Subject: Bluetooth: btbcm: Try multiple Patch filenames when loading the Patch firmware Currently the bcm_uart_subver_ and bcm_usb_subver_table-s lack entries for various newer chipsets. This makes the code use just "BCM" as prefix for the filename to pass to request-firmware, making it harder for users to figure out which firmware they need. This especially a problem with UART attached devices where this leads to the filename being "BCM.hcd". If we add new entries to the subver-tables now, then this will change what firmware file the kernel looks for, e.g. currently linux-firmware contains a brcm/BCM-0bb4-0306.hcd file. If we add the info for the BCM20703A1 to the subver table, then this will change to brcm/BCM20703A1-0bb4-0306.hcd. This will cause the file to no longer get loaded breaking Bluetooth for existing users, going against the no regressions policy. To avoid this regression make the btbcm code try multiple filenames, first try the fullname, e.g. BCM20703A1-0bb4-0306.hcd and if that is not found, then fallback to the name with just BCM as prefix. This commit also adds an info message which filename was used, this makes the output look like this for example: [ 57.387867] Bluetooth: hci0: BCM20703A1 [ 57.387870] Bluetooth: hci0: BCM20703A1 (001.001.005) build 0000 [ 57.389438] Bluetooth: hci0: BCM20703A1 'brcm/BCM20703A1-0a5c-6410.hcd' Patch [ 58.681769] Bluetooth: hci0: BCM20703A1 Generic USB 20Mhz fcbga_BU [ 58.681772] Bluetooth: hci0: BCM20703A1 (001.001.005) build 0481 Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 59 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 16 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 9fa153b35825..739ba1200f5d 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -28,6 +28,9 @@ #define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) #define BCM_FW_NAME_LEN 64 +#define BCM_FW_NAME_COUNT_MAX 2 +/* For kmalloc-ing the fw-name array instead of putting it on the stack */ +typedef char bcm_fw_name[BCM_FW_NAME_LEN]; int btbcm_check_bdaddr(struct hci_dev *hdev) { @@ -420,11 +423,13 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = { int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) { u16 subver, rev, pid, vid; - const char *hw_name = "BCM"; struct sk_buff *skb; struct hci_rp_read_local_version *ver; const struct bcm_subver_table *bcm_subver_table; - char fw_name[BCM_FW_NAME_LEN]; + const char *hw_name = NULL; + char postfix[16] = ""; + int fw_name_count = 0; + bcm_fw_name *fw_name; const struct firmware *fw; int i, err; @@ -464,7 +469,7 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) } bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", - hw_name, (subver & 0xe000) >> 13, + hw_name ? hw_name : "BCM", (subver & 0xe000) >> 13, (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); if (*fw_load_done) @@ -480,24 +485,46 @@ int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done) pid = get_unaligned_le16(skb->data + 3); kfree_skb(skb); - snprintf(fw_name, BCM_FW_NAME_LEN, "brcm/%s-%4.4x-%4.4x.hcd", - hw_name, vid, pid); - } else { - snprintf(fw_name, BCM_FW_NAME_LEN, "brcm/%s.hcd", hw_name); + snprintf(postfix, sizeof(postfix), "-%4.4x-%4.4x", vid, pid); } - err = request_firmware(&fw, fw_name, &hdev->dev); - if (err) { - bt_dev_info(hdev, "BCM: Patch %s not found", fw_name); - return 0; + fw_name = kmalloc(BCM_FW_NAME_COUNT_MAX * BCM_FW_NAME_LEN, GFP_KERNEL); + if (!fw_name) + return -ENOMEM; + + if (hw_name) { + snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN, + "brcm/%s%s.hcd", hw_name, postfix); + fw_name_count++; } - err = btbcm_patchram(hdev, fw); - if (err) - bt_dev_info(hdev, "BCM: Patch failed (%d)", err); + snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN, + "brcm/BCM%s.hcd", postfix); + fw_name_count++; + + for (i = 0; i < fw_name_count; i++) { + err = firmware_request_nowarn(&fw, fw_name[i], &hdev->dev); + if (err == 0) { + bt_dev_info(hdev, "%s '%s' Patch", + hw_name ? hw_name : "BCM", fw_name[i]); + *fw_load_done = true; + break; + } + } + + if (*fw_load_done) { + err = btbcm_patchram(hdev, fw); + if (err) + bt_dev_info(hdev, "BCM: Patch failed (%d)", err); + + release_firmware(fw); + } else { + bt_dev_err(hdev, "BCM: firmware Patch file not found, tried:"); + for (i = 0; i < fw_name_count; i++) + bt_dev_err(hdev, "BCM: '%s'", fw_name[i]); + } - release_firmware(fw); - *fw_load_done = true; + kfree(fw_name); return 0; } EXPORT_SYMBOL_GPL(btbcm_initialize); -- cgit v1.2.3-59-g8ed1b From c03ee9af4e07112bd3fc688daca9e654f41eca93 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 17 Apr 2020 19:15:32 +0200 Subject: Bluetooth: btbcm: Add 2 missing models to subver tables Currently the bcm_uart_subver_ and bcm_usb_subver_table-s lack entries for the BCM4324B5 and BCM20703A1 chipsets. This makes the code use just "BCM" as prefix for the filename to pass to request-firmware, making it harder for users to figure out which firmware they need. This especially is problematic with the UART attached BCM4324B5 where this leads to the filename being just "BCM.hcd". Add the 2 missing devices to subver tables. This has been tested on: 1. A Dell XPS15 9550 where this makes btbcm.c try to load "BCM20703A1-0a5c-6410.hcd" before it tries to load "BCM-0a5c-6410.hcd". 2. A Thinkpad 8 where this makes btbcm.c try to load "BCM4324B5.hcd" before it tries to load "BCM.hcd" Signed-off-by: Hans de Goede Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 739ba1200f5d..df7a8a22e53c 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -392,6 +392,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x410e, "BCM43341B0" }, /* 002.001.014 */ { 0x4204, "BCM2076B1" }, /* 002.002.004 */ { 0x4406, "BCM4324B3" }, /* 002.004.006 */ + { 0x4606, "BCM4324B5" }, /* 002.006.006 */ { 0x6109, "BCM4335C0" }, /* 003.001.009 */ { 0x610c, "BCM4354" }, /* 003.001.012 */ { 0x2122, "BCM4343A0" }, /* 001.001.034 */ @@ -407,6 +408,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { }; static const struct bcm_subver_table bcm_usb_subver_table[] = { + { 0x2105, "BCM20703A1" }, /* 001.001.005 */ { 0x210b, "BCM43142A0" }, /* 001.001.011 */ { 0x2112, "BCM4314A0" }, /* 001.001.018 */ { 0x2118, "BCM20702A0" }, /* 001.001.024 */ -- cgit v1.2.3-59-g8ed1b From 220915857e29795ae5ba4222806268b4a99c19c1 Mon Sep 17 00:00:00 2001 From: Alain Michaud Date: Thu, 23 Apr 2020 14:43:27 +0000 Subject: Bluetooth: Adding driver and quirk defs for multi-role LE This change adds the relevant driver and quirk to allow drivers to report the le_states as being trustworthy. This has historically been disabled as controllers did not reliably support this. In particular, this will be used to relax this condition for controllers that have been well tested and reliable. /* Most controller will fail if we try to create new connections * while we have an existing one in slave role. */ if (hdev->conn_hash.le_num_slave > 0) return NULL; Signed-off-by: Alain Michaud Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + include/net/bluetooth/hci.h | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 871162790a0e..9a0ac333c886 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -58,6 +58,7 @@ static struct usb_driver btusb_driver; #define BTUSB_CW6622 0x100000 #define BTUSB_MEDIATEK 0x200000 #define BTUSB_WIDEBAND_SPEECH 0x400000 +#define BTUSB_VALID_LE_STATES 0x800000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 1da8cec8e210..e5bc1dfe809a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -218,6 +218,15 @@ enum { * This quirk must be set before hci_register_dev is called. */ HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + + /* When this quirk is set, the controller has validated that + * LE states reported through the HCI_LE_READ_SUPPORTED_STATES are + * valid. This mechanism is necessary as many controllers have + * been seen has having trouble initiating a connectable + * advertisement despite the state combination being reported as + * supported. + */ + HCI_QUIRK_VALID_LE_STATES, }; /* HCI device flags */ -- cgit v1.2.3-59-g8ed1b From aff8c489256ea1e32b35a007906a16dce7c6b4db Mon Sep 17 00:00:00 2001 From: Alain Michaud Date: Thu, 23 Apr 2020 14:43:31 +0000 Subject: Bluetooth: btusb: Adding support for LE scatternet to Jfp and ThP This change adds support for LE scatternet connections to Intel's JfP and ThP controllers. Signed-off-by: Alain Michaud Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9a0ac333c886..8ae3ad7a6013 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -336,7 +336,8 @@ static const struct usb_device_id blacklist_table[] = { /* Intel Bluetooth devices */ { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW | - BTUSB_WIDEBAND_SPEECH }, + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW | @@ -349,7 +350,8 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW | - BTUSB_WIDEBAND_SPEECH }, + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, /* Other Intel Bluetooth devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01), @@ -3973,6 +3975,9 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_WIDEBAND_SPEECH) set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + if (id->driver_info & BTUSB_VALID_LE_STATES) + set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); + if (id->driver_info & BTUSB_DIGIANSWER) { data->cmdreq_type = USB_TYPE_VENDOR; set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -- cgit v1.2.3-59-g8ed1b From 31d4ab856e2d57a8877d90012b42d029f1fe0fe9 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 23 Apr 2020 01:34:29 +0000 Subject: Bluetooth: hci_qca: add compatible for QCA9377 Add a compatible so QCA9377 devices can be defined in device-tree. Signed-off-by: Christian Hewitt Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index d0ac554584a4..072983dc07e3 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2058,6 +2058,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume); static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390}, + { .compatible = "qcom,qca9377-bt" }, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, -- cgit v1.2.3-59-g8ed1b From 37aee136f8c4e4989099e7d4972d617ea7ad3e5c Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Thu, 23 Apr 2020 01:34:30 +0000 Subject: Bluetooth: hci_qca: allow max-speed to be set for QCA9377 devices Move the read of max-speed from device-tree out of the qca_is_wcn399x if block so oper_speed can be set for QCA9377 devices as well. Suggested-by: Abhishek Pandit-Subedi Signed-off-by: Christian Hewitt Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 072983dc07e3..b3fd07a6f812 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -597,10 +597,12 @@ 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)) { + + if (qca_is_wcn399x(qcadev->btsoc_type)) hu->init_speed = qcadev->init_speed; + + if (qcadev->oper_speed) hu->oper_speed = qcadev->oper_speed; - } } timer_setup(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, 0); @@ -1871,6 +1873,11 @@ static int qca_serdev_probe(struct serdev_device *serdev) serdev_device_set_drvdata(serdev, qcadev); device_property_read_string(&serdev->dev, "firmware-name", &qcadev->firmware_name); + device_property_read_u32(&serdev->dev, "max-speed", + &qcadev->oper_speed); + if (!qcadev->oper_speed) + BT_DBG("UART will pick default operating speed"); + if (data && qca_is_wcn399x(data->soc_type)) { qcadev->btsoc_type = data->soc_type; qcadev->bt_power = devm_kzalloc(&serdev->dev, @@ -1895,11 +1902,6 @@ static int qca_serdev_probe(struct serdev_device *serdev) return PTR_ERR(qcadev->susclk); } - device_property_read_u32(&serdev->dev, "max-speed", - &qcadev->oper_speed); - if (!qcadev->oper_speed) - BT_DBG("UART will pick default operating speed"); - err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); if (err) { BT_ERR("wcn3990 serdev registration failed"); -- cgit v1.2.3-59-g8ed1b From 4765db373ea34c7262e3467f8aaf4167dd1cdafa Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 25 Apr 2020 08:55:30 -0700 Subject: Bluetooth: hci_h5: Add support for binding RTL8723BS with device tree RTL8723BS is often used in ARM boards, so add ability to bind it using device tree. Signed-off-by: Vasily Khoruzhick Signed-off-by: Alistair Francis Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_h5.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 106c110efe56..e60b2e0773db 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -1018,6 +1018,8 @@ static const struct of_device_id rtl_bluetooth_of_match[] = { #ifdef CONFIG_BT_HCIUART_RTL { .compatible = "realtek,rtl8822cs-bt", .data = (const void *)&rtl_vnd }, + { .compatible = "realtek,rtl8723bs-bt", + .data = (const void *)&rtl_vnd }, #endif { }, }; -- cgit v1.2.3-59-g8ed1b From b7d0bf11a7ad0e97721a5c4a209ba749649f8b9e Mon Sep 17 00:00:00 2001 From: Abhishek Pandit-Subedi Date: Tue, 12 May 2020 19:19:27 -0700 Subject: Bluetooth: btusb: Implement hdev->prevent_wake Implement the prevent_wake hook by checking device_may_wakeup on the usb interface. This prevents the Bluetooth core from enabling scanning when the device isn't expected to wake from suspend. Signed-off-by: Abhishek Pandit-Subedi Reviewed-by: Alain Michaud Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 8ae3ad7a6013..c17359c0e320 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3698,6 +3698,13 @@ static void btusb_check_needs_reset_resume(struct usb_interface *intf) interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; } +static bool btusb_prevent_wake(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + + return !device_may_wakeup(&data->udev->dev); +} + static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -3831,6 +3838,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->flush = btusb_flush; hdev->send = btusb_send_frame; hdev->notify = btusb_notify; + hdev->prevent_wake = btusb_prevent_wake; #ifdef CONFIG_PM err = btusb_config_oob_wake(hdev); -- cgit v1.2.3-59-g8ed1b From 875e16759005e3bdaa84eb2741281f37ba35b886 Mon Sep 17 00:00:00 2001 From: Raghuram Hegde Date: Mon, 11 May 2020 16:40:40 +0530 Subject: Bluetooth: btusb: Add support for Intel Bluetooth Device Typhoon Peak (8087:0032) Device from /sys/kernel/debug/usb/devices: T: Bus=01 Lev=01 Prnt=01 Port=13 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=8087 ProdID=0032 Rev= 0.00 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms Signed-off-by: Raghuram Hegde Signed-off-by: Chethan T N Signed-off-by: Amit K Bag Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c17359c0e320..5f022e9cf667 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -342,6 +342,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_NEW | + BTUSB_WIDEBAND_SPEECH}, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, -- cgit v1.2.3-59-g8ed1b From 608c39f4308cefde9d1f24b661261de2b3f3fef4 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sat, 9 May 2020 15:17:19 +0200 Subject: Bluetooth: serdev: Constify serdev_device_ops serdev_device_ops is not modified and can be const. Also, remove the unneeded declaration of it. Output from the file command before and after: Before: text data bss dec hex filename 7192 2408 192 9792 2640 drivers/bluetooth/hci_serdev.o After: text data bss dec hex filename 7256 2344 192 9792 2640 drivers/bluetooth/hci_serdev.o Signed-off-by: Rikard Falkeborn Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_serdev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 4652896d4990..599855e4c57c 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -21,8 +21,6 @@ #include "hci_uart.h" -static struct serdev_device_ops hci_serdev_client_ops; - static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) { struct hci_dev *hdev = hu->hdev; @@ -260,7 +258,7 @@ static int hci_uart_receive_buf(struct serdev_device *serdev, const u8 *data, return count; } -static struct serdev_device_ops hci_serdev_client_ops = { +static const struct serdev_device_ops hci_serdev_client_ops = { .receive_buf = hci_uart_receive_buf, .write_wakeup = hci_uart_write_wakeup, }; -- cgit v1.2.3-59-g8ed1b From a228f7a410290d836f3a9f9b1ed5aef1aab25cc7 Mon Sep 17 00:00:00 2001 From: Abhishek Pandit-Subedi Date: Thu, 14 May 2020 13:14:04 -0700 Subject: Bluetooth: hci_qca: Enable WBS support for wcn3991 WCN3991 supports transparent WBS (host encoded mSBC). Add a flag to the device match data to show WBS is supported. This requires the matching firmware for WCN3991 in linux-firmware: 1a8b0dc00f77 (qca: Enable transparent WBS for WCN3991) Signed-off-by: Abhishek Pandit-Subedi Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index b3fd07a6f812..26efe822f6e5 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -75,6 +75,9 @@ enum qca_flags { QCA_HW_ERROR_EVENT }; +enum qca_capabilities { + QCA_CAP_WIDEBAND_SPEECH = BIT(0), +}; /* HCI_IBS transmit side sleep protocol states */ enum tx_ibs_states { @@ -187,10 +190,11 @@ struct qca_vreg { unsigned int load_uA; }; -struct qca_vreg_data { +struct qca_device_data { enum qca_btsoc_type soc_type; struct qca_vreg *vregs; size_t num_vregs; + uint32_t capabilities; }; /* @@ -1691,7 +1695,7 @@ static const struct hci_uart_proto qca_proto = { .dequeue = qca_dequeue, }; -static const struct qca_vreg_data qca_soc_data_wcn3990 = { +static const struct qca_device_data qca_soc_data_wcn3990 = { .soc_type = QCA_WCN3990, .vregs = (struct qca_vreg []) { { "vddio", 15000 }, @@ -1702,7 +1706,7 @@ static const struct qca_vreg_data qca_soc_data_wcn3990 = { .num_vregs = 4, }; -static const struct qca_vreg_data qca_soc_data_wcn3991 = { +static const struct qca_device_data qca_soc_data_wcn3991 = { .soc_type = QCA_WCN3991, .vregs = (struct qca_vreg []) { { "vddio", 15000 }, @@ -1711,9 +1715,10 @@ static const struct qca_vreg_data qca_soc_data_wcn3991 = { { "vddch0", 450000 }, }, .num_vregs = 4, + .capabilities = QCA_CAP_WIDEBAND_SPEECH, }; -static const struct qca_vreg_data qca_soc_data_wcn3998 = { +static const struct qca_device_data qca_soc_data_wcn3998 = { .soc_type = QCA_WCN3998, .vregs = (struct qca_vreg []) { { "vddio", 10000 }, @@ -1724,7 +1729,7 @@ static const struct qca_vreg_data qca_soc_data_wcn3998 = { .num_vregs = 4, }; -static const struct qca_vreg_data qca_soc_data_qca6390 = { +static const struct qca_device_data qca_soc_data_qca6390 = { .soc_type = QCA_QCA6390, .num_vregs = 0, }; @@ -1860,7 +1865,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) { struct qca_serdev *qcadev; struct hci_dev *hdev; - const struct qca_vreg_data *data; + const struct qca_device_data *data; int err; bool power_ctrl_enabled = true; @@ -1948,6 +1953,12 @@ static int qca_serdev_probe(struct serdev_device *serdev) hdev->shutdown = qca_power_off; } + /* Wideband speech support must be set per driver since it can't be + * queried via hci. + */ + if (data && (data->capabilities & QCA_CAP_WIDEBAND_SPEECH)) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + return 0; } -- cgit v1.2.3-59-g8ed1b From 85e90d9391f57436b6f7f00503de370a657420ba Mon Sep 17 00:00:00 2001 From: Abhishek Pandit-Subedi Date: Wed, 20 May 2020 09:32:28 -0700 Subject: Bluetooth: hci_qca: Fix uninitialized access to hdev hdev is always allocated and not only when power control is required. Reported-by: Dan Carpenter Signed-off-by: Abhishek Pandit-Subedi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 26efe822f6e5..e4a68238fcb9 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1947,8 +1947,9 @@ static int qca_serdev_probe(struct serdev_device *serdev) } } + hdev = qcadev->serdev_hu.hdev; + if (power_ctrl_enabled) { - hdev = qcadev->serdev_hu.hdev; set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); hdev->shutdown = qca_power_off; } -- cgit v1.2.3-59-g8ed1b From bf0ddd104167bfc08a5a169b3669f06c9052c1b0 Mon Sep 17 00:00:00 2001 From: "Azamat H. Hackimov" Date: Sun, 24 May 2020 20:41:29 +0300 Subject: Bluetooth: btbcm: Added 003.006.007, changed 001.003.015 Added new Broadcom device BCM4350C5, changed BCM4354A2 to BCM4356A2. Based on Broadcom Windows drivers 001.003.015 should be BCM4356A2. I have user report that firmware name is misplaced (https://github.com/winterheart/broadcom-bt-firmware/issues/3). Signed-off-by: Azamat H. Hackimov Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index df7a8a22e53c..1b9743b7f2ef 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -414,11 +414,12 @@ static const struct bcm_subver_table bcm_usb_subver_table[] = { { 0x2118, "BCM20702A0" }, /* 001.001.024 */ { 0x2126, "BCM4335A0" }, /* 001.001.038 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */ - { 0x230f, "BCM4354A2" }, /* 001.003.015 */ + { 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x4106, "BCM4335B0" }, /* 002.001.006 */ { 0x410e, "BCM20702B0" }, /* 002.001.014 */ { 0x6109, "BCM4335C0" }, /* 003.001.009 */ { 0x610c, "BCM4354" }, /* 003.001.012 */ + { 0x6607, "BCM4350C5" }, /* 003.006.007 */ { } }; -- cgit v1.2.3-59-g8ed1b From feac90d756c03b03b83fabe83571bd88ecc96b78 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Fri, 29 May 2020 04:31:07 +0800 Subject: Bluetooth: hci_qca: Fix suspend/resume functionality failure @dev parameter of qca_suspend()/qca_resume() represents serdev_device, but it is mistook for hci_dev and causes succedent unexpected memory access. Fix by taking @dev as serdev_device. Fixes: 41d5b25fed0 ("Bluetooth: hci_qca: add PM support") Signed-off-by: Zijun Hu Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e4a68238fcb9..adcbe00a2275 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1977,8 +1977,9 @@ static void qca_serdev_remove(struct serdev_device *serdev) static int __maybe_unused qca_suspend(struct device *dev) { - struct hci_dev *hdev = container_of(dev, struct hci_dev, dev); - struct hci_uart *hu = hci_get_drvdata(hdev); + struct serdev_device *serdev = to_serdev_device(dev); + struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + struct hci_uart *hu = &qcadev->serdev_hu; struct qca_data *qca = hu->priv; unsigned long flags; int ret = 0; @@ -2057,8 +2058,9 @@ error: static int __maybe_unused qca_resume(struct device *dev) { - struct hci_dev *hdev = container_of(dev, struct hci_dev, dev); - struct hci_uart *hu = hci_get_drvdata(hdev); + struct serdev_device *serdev = to_serdev_device(dev); + struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + struct hci_uart *hu = &qcadev->serdev_hu; struct qca_data *qca = hu->priv; clear_bit(QCA_SUSPENDING, &qca->flags); -- cgit v1.2.3-59-g8ed1b From 4803c54ca24923a30664bea2a7772db6e7303c51 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 29 May 2020 10:27:26 +0800 Subject: Bluetooth: btmtkuart: Improve exception handling in btmtuart_probe() Calls of the functions clk_disable_unprepare() and hci_free_dev() were missing for the exception handling. Thus add the missed function calls together with corresponding jump targets. Fixes: 055825614c6b ("Bluetooth: btmtkuart: add an implementation for clock osc property") Signed-off-by: Chuhong Yuan Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index e11169ad8247..8a81fbca5c9d 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -1015,7 +1015,7 @@ static int btmtkuart_probe(struct serdev_device *serdev) if (btmtkuart_is_standalone(bdev)) { err = clk_prepare_enable(bdev->osc); if (err < 0) - return err; + goto err_hci_free_dev; if (bdev->boot) { gpiod_set_value_cansleep(bdev->boot, 1); @@ -1028,10 +1028,8 @@ static int btmtkuart_probe(struct serdev_device *serdev) /* Power on */ err = regulator_enable(bdev->vcc); - if (err < 0) { - clk_disable_unprepare(bdev->osc); - return err; - } + if (err < 0) + goto err_clk_disable_unprepare; /* Reset if the reset-gpios is available otherwise the board * -level design should be guaranteed. @@ -1063,7 +1061,6 @@ static int btmtkuart_probe(struct serdev_device *serdev) err = hci_register_dev(hdev); if (err < 0) { dev_err(&serdev->dev, "Can't register HCI device\n"); - hci_free_dev(hdev); goto err_regulator_disable; } @@ -1072,6 +1069,11 @@ static int btmtkuart_probe(struct serdev_device *serdev) err_regulator_disable: if (btmtkuart_is_standalone(bdev)) regulator_disable(bdev->vcc); +err_clk_disable_unprepare: + if (btmtkuart_is_standalone(bdev)) + clk_disable_unprepare(bdev->osc); +err_hci_free_dev: + hci_free_dev(hdev); return err; } -- cgit v1.2.3-59-g8ed1b From 7e7bbddd029b644f00f0ffbfbc485ed71977d0d5 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Fri, 29 May 2020 21:56:57 +0800 Subject: Bluetooth: hci_qca: Fix qca6390 enable failure after warm reboot Warm reboot can not reset controller qca6390 due to lack of controllable power supply, so causes firmware download failure during enable. Fixed by sending VSC EDL_SOC_RESET to reset qca6390 within added device shutdown implementation. Signed-off-by: Zijun Hu Tested-by: Zijun Hu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index adcbe00a2275..aa957d749d6f 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1975,6 +1975,38 @@ static void qca_serdev_remove(struct serdev_device *serdev) hci_uart_unregister_device(&qcadev->serdev_hu); } +static void qca_serdev_shutdown(struct device *dev) +{ + int ret; + int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); + struct serdev_device *serdev = to_serdev_device(dev); + struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); + const u8 ibs_wake_cmd[] = { 0xFD }; + const u8 edl_reset_soc_cmd[] = { 0x01, 0x00, 0xFC, 0x01, 0x05 }; + + if (qcadev->btsoc_type == QCA_QCA6390) { + serdev_device_write_flush(serdev); + ret = serdev_device_write_buf(serdev, ibs_wake_cmd, + sizeof(ibs_wake_cmd)); + if (ret < 0) { + BT_ERR("QCA send IBS_WAKE_IND error: %d", ret); + return; + } + serdev_device_wait_until_sent(serdev, timeout); + usleep_range(8000, 10000); + + serdev_device_write_flush(serdev); + ret = serdev_device_write_buf(serdev, edl_reset_soc_cmd, + sizeof(edl_reset_soc_cmd)); + if (ret < 0) { + BT_ERR("QCA send EDL_RESET_REQ error: %d", ret); + return; + } + serdev_device_wait_until_sent(serdev, timeout); + usleep_range(8000, 10000); + } +} + static int __maybe_unused qca_suspend(struct device *dev) { struct serdev_device *serdev = to_serdev_device(dev); @@ -2102,6 +2134,7 @@ static struct serdev_device_driver qca_serdev_driver = { .name = "hci_uart_qca", .of_match_table = of_match_ptr(qca_bluetooth_of_match), .acpi_match_table = ACPI_PTR(qca_bluetooth_acpi_match), + .shutdown = qca_serdev_shutdown, .pm = &qca_pm_ops, }, }; -- cgit v1.2.3-59-g8ed1b From 4942857b015ede4fab8b262931244a3c1006a2a6 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Fri, 29 May 2020 22:46:13 +0800 Subject: Bluetooth: hci_qca: Improve controller ID info log level Controller ID info got by VSC EDL_PATCH_GETVER is very important, so improve its log level from DEBUG to INFO. Signed-off-by: Zijun Hu Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 3ea866d44568..c5984966f315 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -74,17 +74,21 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version, ver = (struct qca_btsoc_version *)(edl->data); - BT_DBG("%s: Product:0x%08x", hdev->name, le32_to_cpu(ver->product_id)); - BT_DBG("%s: Patch :0x%08x", hdev->name, le16_to_cpu(ver->patch_ver)); - BT_DBG("%s: ROM :0x%08x", hdev->name, le16_to_cpu(ver->rom_ver)); - BT_DBG("%s: SOC :0x%08x", hdev->name, le32_to_cpu(ver->soc_id)); + bt_dev_info(hdev, "QCA Product ID :0x%08x", + le32_to_cpu(ver->product_id)); + bt_dev_info(hdev, "QCA SOC Version :0x%08x", + le32_to_cpu(ver->soc_id)); + bt_dev_info(hdev, "QCA ROM Version :0x%08x", + le16_to_cpu(ver->rom_ver)); + bt_dev_info(hdev, "QCA Patch Version:0x%08x", + le16_to_cpu(ver->patch_ver)); /* QCA chipset version can be decided by patch and SoC * version, combination with upper 2 bytes from SoC * and lower 2 bytes from patch will be used. */ *soc_version = (le32_to_cpu(ver->soc_id) << 16) | - (le16_to_cpu(ver->rom_ver) & 0x0000ffff); + (le16_to_cpu(ver->rom_ver) & 0x0000ffff); if (*soc_version == 0) err = -EILSEQ; -- cgit v1.2.3-59-g8ed1b From d3a0fe6b0988241c64ef4f6a1045423cc79a612a Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Fri, 29 May 2020 23:58:56 +0800 Subject: Bluetooth: btmtkuart: Use serdev_device_write_buf() instead of serdev_device_write() serdev_device_write() is not appropriate at here because serdev_device_write_wakeup() is not used to release completion hold by the former at @write_wakeup member of struct serdev_device_ops. Fix by using serdev_device_write_buf() instead of serdev_device_write(). Signed-off-by: Zijun Hu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index 8a81fbca5c9d..6c40bc75fb5b 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -695,8 +695,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev) /* Send a dummy byte 0xff to activate the new baudrate */ param = 0xff; - err = serdev_device_write(bdev->serdev, ¶m, sizeof(param), - MAX_SCHEDULE_TIMEOUT); + err = serdev_device_write_buf(bdev->serdev, ¶m, sizeof(param)); if (err < 0 || err < sizeof(param)) return err; -- cgit v1.2.3-59-g8ed1b From e5aeebddfc312ea7bb55dfe6c7264e71a3b43992 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Fri, 29 May 2020 22:38:31 +0800 Subject: Bluetooth: hci_qca: Fix QCA6390 memdump failure QCA6390 memdump VSE sometimes come to bluetooth driver with wrong sequence number as illustrated as follows: frame # in dec: frame data in hex 1396: ff fd 01 08 74 05 00 37 8f 14 1397: ff fd 01 08 75 05 00 ff bf 38 1414: ff fd 01 08 86 05 00 fb 5e 4b 1399: ff fd 01 08 77 05 00 f3 44 0a 1400: ff fd 01 08 78 05 00 ca f7 41 it is mistook for controller missing packets, so results in page fault after overwriting memdump buffer allocated. Fixed by ignoring QCA6390 sequence number check and checking buffer space before writing. Signed-off-by: Zijun Hu Tested-by: Zijun Hu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 54 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) (limited to 'drivers/bluetooth') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index aa957d749d6f..81c3c38baba1 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -114,6 +114,7 @@ struct qca_memdump_data { char *memdump_buf_tail; u32 current_seq_no; u32 received_dump; + u32 ram_dump_size; }; struct qca_memdump_event_hdr { @@ -976,6 +977,8 @@ static void qca_controller_memdump(struct work_struct *work) char nullBuff[QCA_DUMP_PACKET_SIZE] = { 0 }; u16 seq_no; u32 dump_size; + u32 rx_size; + enum qca_btsoc_type soc_type = qca_soc_type(hu); while ((skb = skb_dequeue(&qca->rx_memdump_q))) { @@ -1025,10 +1028,12 @@ static void qca_controller_memdump(struct work_struct *work) dump_size); queue_delayed_work(qca->workqueue, &qca->ctrl_memdump_timeout, - msecs_to_jiffies(MEMDUMP_TIMEOUT_MS)); + msecs_to_jiffies(MEMDUMP_TIMEOUT_MS) + ); skb_pull(skb, sizeof(dump_size)); memdump_buf = vmalloc(dump_size); + qca_memdump->ram_dump_size = dump_size; qca_memdump->memdump_buf_head = memdump_buf; qca_memdump->memdump_buf_tail = memdump_buf; } @@ -1051,26 +1056,57 @@ static void qca_controller_memdump(struct work_struct *work) * the controller. In such cases let us store the dummy * packets in the buffer. */ + /* For QCA6390, controller does not lost packets but + * sequence number field of packat sometimes has error + * bits, so skip this checking for missing packet. + */ while ((seq_no > qca_memdump->current_seq_no + 1) && - seq_no != QCA_LAST_SEQUENCE_NUM) { + (soc_type != QCA_QCA6390) && + seq_no != QCA_LAST_SEQUENCE_NUM) { bt_dev_err(hu->hdev, "QCA controller missed packet:%d", qca_memdump->current_seq_no); + rx_size = qca_memdump->received_dump; + rx_size += QCA_DUMP_PACKET_SIZE; + if (rx_size > qca_memdump->ram_dump_size) { + bt_dev_err(hu->hdev, + "QCA memdump received %d, no space for missed packet", + qca_memdump->received_dump); + break; + } memcpy(memdump_buf, nullBuff, QCA_DUMP_PACKET_SIZE); memdump_buf = memdump_buf + QCA_DUMP_PACKET_SIZE; qca_memdump->received_dump += QCA_DUMP_PACKET_SIZE; qca_memdump->current_seq_no++; } - memcpy(memdump_buf, (unsigned char *) skb->data, skb->len); - memdump_buf = memdump_buf + skb->len; - qca_memdump->memdump_buf_tail = memdump_buf; - qca_memdump->current_seq_no = seq_no + 1; - qca_memdump->received_dump += skb->len; + rx_size = qca_memdump->received_dump + skb->len; + if (rx_size <= qca_memdump->ram_dump_size) { + if ((seq_no != QCA_LAST_SEQUENCE_NUM) && + (seq_no != qca_memdump->current_seq_no)) + bt_dev_err(hu->hdev, + "QCA memdump unexpected packet %d", + seq_no); + bt_dev_dbg(hu->hdev, + "QCA memdump packet %d with length %d", + seq_no, skb->len); + memcpy(memdump_buf, (unsigned char *)skb->data, + skb->len); + memdump_buf = memdump_buf + skb->len; + qca_memdump->memdump_buf_tail = memdump_buf; + qca_memdump->current_seq_no = seq_no + 1; + qca_memdump->received_dump += skb->len; + } else { + bt_dev_err(hu->hdev, + "QCA memdump received %d, no space for packet %d", + qca_memdump->received_dump, seq_no); + } qca->qca_memdump = qca_memdump; kfree_skb(skb); if (seq_no == QCA_LAST_SEQUENCE_NUM) { - bt_dev_info(hu->hdev, "QCA writing crash dump of size %d bytes", - qca_memdump->received_dump); + bt_dev_info(hu->hdev, + "QCA memdump Done, received %d, total %d", + qca_memdump->received_dump, + qca_memdump->ram_dump_size); memdump_buf = qca_memdump->memdump_buf_head; dev_coredumpv(&hu->serdev->dev, memdump_buf, qca_memdump->received_dump, GFP_KERNEL); -- cgit v1.2.3-59-g8ed1b