From ad4a6795e0cfd7f2954ff004e83f00e0aa097f4c Mon Sep 17 00:00:00 2001 From: Spoorthi Ravishankar Koppad Date: Mon, 15 Jul 2019 17:05:22 +0530 Subject: [PATCH 01/19] Bluetooth: Add support for utilizing Fast Advertising Interval Changes made to add support for fast advertising interval as per core 4.1 specification, section 9.3.11.2. A peripheral device entering any of the following GAP modes and sending either non-connectable advertising events or scannable undirected advertising events should use adv_fast_interval2 (100ms - 150ms) for adv_fast_period(30s). - Non-Discoverable Mode - Non-Connectable Mode - Limited Discoverable Mode - General Discoverable Mode Signed-off-by: Spoorthi Ravishankar Koppad Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_request.c | 29 ++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ffc95b382eb5..b689aceb636b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1517,6 +1517,8 @@ void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); #define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04 #define DISCOV_BREDR_INQUIRY_LEN 0x08 #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ +#define DISCOV_LE_FAST_ADV_INT_MIN 100 /* msec */ +#define DISCOV_LE_FAST_ADV_INT_MAX 150 /* msec */ void mgmt_fill_version_info(void *ver); int mgmt_new_settings(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 621f1a97d803..7f6a581b5b7e 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1054,6 +1054,7 @@ void __hci_req_enable_advertising(struct hci_request *req) struct hci_cp_le_set_adv_param cp; u8 own_addr_type, enable = 0x01; bool connectable; + u16 adv_min_interval, adv_max_interval; u32 flags; flags = get_adv_instance_flags(hdev, hdev->cur_adv_instance); @@ -1087,16 +1088,30 @@ void __hci_req_enable_advertising(struct hci_request *req) return; memset(&cp, 0, sizeof(cp)); - cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval); - cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval); - if (connectable) + if (connectable) { cp.type = LE_ADV_IND; - else if (get_cur_adv_instance_scan_rsp_len(hdev)) - cp.type = LE_ADV_SCAN_IND; - else - cp.type = LE_ADV_NONCONN_IND; + adv_min_interval = hdev->le_adv_min_interval; + adv_max_interval = hdev->le_adv_max_interval; + } else { + if (get_cur_adv_instance_scan_rsp_len(hdev)) + cp.type = LE_ADV_SCAN_IND; + else + cp.type = LE_ADV_NONCONN_IND; + + if (!hci_dev_test_flag(hdev, HCI_DISCOVERABLE) || + hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) { + adv_min_interval = DISCOV_LE_FAST_ADV_INT_MIN; + adv_max_interval = DISCOV_LE_FAST_ADV_INT_MAX; + } else { + adv_min_interval = hdev->le_adv_min_interval; + adv_max_interval = hdev->le_adv_max_interval; + } + } + + cp.min_interval = cpu_to_le16(adv_min_interval); + cp.max_interval = cpu_to_le16(adv_max_interval); cp.own_address_type = own_addr_type; cp.channel_map = hdev->le_adv_channel_map; From 9c81f2b7e7835a2a1fb1c4e96e36f710fc4b0728 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 7 Aug 2019 11:58:49 -0700 Subject: [PATCH 02/19] Bluetooth: hci_qca: Remove redundant initializations to zero The qca_data structure is allocated with kzalloc() and hence zero-initialized. Remove a bunch of unnecessary explicit initializations of struct members to zero. Signed-off-by: Matthias Kaehlcke Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 9a970fd1975a..f4142d195e03 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -502,26 +502,7 @@ static int qca_open(struct hci_uart *hu) qca->tx_ibs_state = HCI_IBS_TX_ASLEEP; qca->rx_ibs_state = HCI_IBS_RX_ASLEEP; - /* clocks actually on, but we start votes off */ - qca->tx_vote = false; - qca->rx_vote = false; - qca->flags = 0; - - qca->ibs_sent_wacks = 0; - qca->ibs_sent_slps = 0; - qca->ibs_sent_wakes = 0; - qca->ibs_recv_wacks = 0; - qca->ibs_recv_slps = 0; - qca->ibs_recv_wakes = 0; qca->vote_last_jif = jiffies; - qca->vote_on_ms = 0; - qca->vote_off_ms = 0; - qca->votes_on = 0; - qca->votes_off = 0; - qca->tx_votes_on = 0; - qca->tx_votes_off = 0; - qca->rx_votes_on = 0; - qca->rx_votes_off = 0; hu->priv = qca; From ff7c8380c9d36252a6b977cf9c7f8b75abfb8719 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 12 Aug 2019 14:22:11 +0800 Subject: [PATCH 03/19] Bluetooth: hci_bcm: Fix -Wunused-const-variable warnings If CONFIG_ACPI is not set, gcc warn this: drivers/bluetooth/hci_bcm.c:831:39: warning: acpi_bcm_int_last_gpios defined but not used [-Wunused-const-variable=] drivers/bluetooth/hci_bcm.c:838:39: warning: acpi_bcm_int_first_gpios defined but not used [-Wunused-const-variable=] move them to #ifdef CONFIG_ACPI block. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index ae2624fce913..4d9de20bab7b 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -824,6 +824,21 @@ unlock: } #endif +/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */ +static const struct dmi_system_id bcm_broken_irq_dmi_table[] = { + { + .ident = "Meegopad T08", + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, + "To be filled by OEM."), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"), + DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"), + }, + }, + { } +}; + +#ifdef CONFIG_ACPI static const struct acpi_gpio_params first_gpio = { 0, 0, false }; static const struct acpi_gpio_params second_gpio = { 1, 0, false }; static const struct acpi_gpio_params third_gpio = { 2, 0, false }; @@ -842,21 +857,6 @@ static const struct acpi_gpio_mapping acpi_bcm_int_first_gpios[] = { { }, }; -/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */ -static const struct dmi_system_id bcm_broken_irq_dmi_table[] = { - { - .ident = "Meegopad T08", - .matches = { - DMI_EXACT_MATCH(DMI_BOARD_VENDOR, - "To be filled by OEM."), - DMI_EXACT_MATCH(DMI_BOARD_NAME, "T3 MRD"), - DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V1.1"), - }, - }, - { } -}; - -#ifdef CONFIG_ACPI static int bcm_resource(struct acpi_resource *ares, void *data) { struct bcm_device *dev = data; From 9e45524a011107a73bc2cdde8370c61e82e93a4d Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Wed, 14 Aug 2019 20:02:52 +0800 Subject: [PATCH 04/19] Bluetooth: btusb: Fix suspend issue for Realtek devices From the perspective of controller, global suspend means there is no SET_FEATURE (DEVICE_REMOTE_WAKEUP) and controller would drop the firmware. It would consume less power. So we should not send this kind of SET_FEATURE when host goes to suspend state. Otherwise, when making device enter selective suspend, host should send SET_FEATURE to make sure the firmware remains. Signed-off-by: Alex Lu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5cf0734eb31b..31d3febed187 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -435,6 +435,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = { #define BTUSB_OOB_WAKE_ENABLED 11 #define BTUSB_HW_RESET_ACTIVE 12 #define BTUSB_TX_WAIT_VND_EVT 13 +#define BTUSB_WAKEUP_DISABLE 14 struct btusb_data { struct hci_dev *hdev; @@ -1175,6 +1176,13 @@ static int btusb_open(struct hci_dev *hdev) */ device_wakeup_enable(&data->udev->dev); + /* Disable device remote wakeup when host is suspended + * For Realtek chips, global suspend without + * SET_FEATURE (DEVICE_REMOTE_WAKEUP) can save more power in device. + */ + if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags)) + device_wakeup_disable(&data->udev->dev); + if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) goto done; @@ -1238,6 +1246,11 @@ static int btusb_close(struct hci_dev *hdev) goto failed; data->intf->needs_remote_wakeup = 0; + + /* Enable remote wake up for auto-suspend */ + if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags)) + data->intf->needs_remote_wakeup = 1; + device_wakeup_disable(&data->udev->dev); usb_autopm_put_interface(data->intf); @@ -3771,11 +3784,11 @@ static int btusb_probe(struct usb_interface *intf, hdev->setup = btrtl_setup_realtek; hdev->shutdown = btrtl_shutdown_realtek; - /* Realtek devices lose their updated firmware over suspend, - * but the USB hub doesn't notice any status change. - * Explicitly request a device reset on resume. + /* Realtek devices lose their updated firmware over global + * suspend that means host doesn't send SET_FEATURE + * (DEVICE_REMOTE_WAKEUP) */ - interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME; + set_bit(BTUSB_WAKEUP_DISABLE, &data->flags); } #endif @@ -3949,6 +3962,19 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message) enable_irq(data->oob_wake_irq); } + /* For global suspend, Realtek devices lose the loaded fw + * in them. But for autosuspend, firmware should remain. + * Actually, it depends on whether the usb host sends + * set feature (enable wakeup) or not. + */ + if (test_bit(BTUSB_WAKEUP_DISABLE, &data->flags)) { + if (PMSG_IS_AUTO(message) && + device_can_wakeup(&data->udev->dev)) + data->udev->do_remote_wakeup = 1; + else if (!PMSG_IS_AUTO(message)) + data->udev->reset_resume = 1; + } + return 0; } From 569428dabc3e2523ca2b357e7d86412df1dd1e6a Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 15 Aug 2019 11:22:55 +0530 Subject: [PATCH 05/19] Bluetooth: 6lowpan: Make variable header_ops constant Static variable header_ops, of type header_ops, is used only once, when it is assigned to field header_ops of a variable having type net_device. This corresponding field is declared as const in the definition of net_device. Hence make header_ops constant as well to protect it from unnecessary modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Marcel Holtmann --- net/bluetooth/6lowpan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 9d41de1ec90f..bb55d92691b0 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -583,7 +583,7 @@ static const struct net_device_ops netdev_ops = { .ndo_start_xmit = bt_xmit, }; -static struct header_ops header_ops = { +static const struct header_ops header_ops = { .create = header_create, }; From 2edc9c5cca7ac87e99c0eddf398ddcf92c4b36de Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 15 Aug 2019 11:21:49 +0530 Subject: [PATCH 06/19] Bluetooth: hci_qca: Make structure qca_proto constant Static structure qca_proto, of type hci_uart_proto, is used four times: as the last argument in function hci_uart_register_device(), and as the only argument to functions hci_uart_register_proto() and hci_uart_unregister_proto(). In all three of these functions, the parameter corresponding to qca_proto is declared as constant. Therefore, make qca_proto itself constant as well in order to protect it from unintended modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index f4142d195e03..0cf532071664 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1307,7 +1307,7 @@ static int qca_setup(struct hci_uart *hu) return ret; } -static struct hci_uart_proto qca_proto = { +static const struct hci_uart_proto qca_proto = { .id = HCI_UART_QCA, .name = "QCA", .manufacturer = 29, From e14c167a58b80803f35edf575a33562411f9170d Mon Sep 17 00:00:00 2001 From: Rocky Liao Date: Wed, 21 Aug 2019 14:23:39 +0800 Subject: [PATCH 07/19] Bluetooth: hci_qca: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for QCA UART Radio QCA UART Bluetooth controllers can do both LE scan and BR/EDR inquiry at once, need to set HCI_QUIRK_SIMULTANEOUS_DISCOVERY quirk. Signed-off-by: Rocky Liao Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 0cf532071664..15753f6bce80 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1242,6 +1242,11 @@ static int qca_setup(struct hci_uart *hu) /* Patch downloading has to be done without IBS mode */ clear_bit(QCA_IBS_ENABLED, &qca->flags); + /* Enable controller to do both LE scan and BR/EDR inquiry + * simultaneously. + */ + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + if (qca_is_wcn399x(soc_type)) { bt_dev_info(hdev, "setting up wcn3990"); From dd656296c67fe4b0743aea59fcb5ab7220626c78 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Fri, 23 Aug 2019 12:31:35 +0200 Subject: [PATCH 08/19] dt-bindings: net: Add compatible for BCM4345C5 bluetooth device This is present in the AP6526 WiFi/Bluetooth 5.0 module. Signed-off-by: Ondrej Jirman Acked-by: Rob Herring Signed-off-by: Marcel Holtmann --- Documentation/devicetree/bindings/net/broadcom-bluetooth.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt index c26f4e11037c..4fa00e2eafcf 100644 --- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt +++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt @@ -13,6 +13,7 @@ Required properties: * "brcm,bcm20702a1" * "brcm,bcm4330-bt" * "brcm,bcm43438-bt" + * "brcm,bcm4345c5" Optional properties: From 52c8c7a766ecc49ff2e4c1db30b0a24a019e31d4 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Fri, 23 Aug 2019 12:31:36 +0200 Subject: [PATCH 09/19] bluetooth: bcm: Add support for loading firmware for BCM4345C5 Detect BCM4345C5 and load a corresponding firmware file. Signed-off-by: Ondrej Jirman Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btbcm.c | 3 +++ drivers/bluetooth/hci_bcm.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 124ef0a3e1dd..2d2e6d862068 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -23,6 +23,7 @@ #define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}}) #define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}}) #define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}}) +#define BDADDR_BCM4345C5 (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0xc5, 0x45, 0x43}}) #define BDADDR_BCM43341B (&(bdaddr_t) {{0xac, 0x1f, 0x00, 0x1b, 0x34, 0x43}}) int btbcm_check_bdaddr(struct hci_dev *hdev) @@ -73,6 +74,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev) !bacmp(&bda->bdaddr, BDADDR_BCM2076B1) || !bacmp(&bda->bdaddr, BDADDR_BCM4324B3) || !bacmp(&bda->bdaddr, BDADDR_BCM4330B1) || + !bacmp(&bda->bdaddr, BDADDR_BCM4345C5) || !bacmp(&bda->bdaddr, BDADDR_BCM43430A0) || !bacmp(&bda->bdaddr, BDADDR_BCM43341B)) { bt_dev_info(hdev, "BCM: Using default device address (%pMR)", @@ -332,6 +334,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x2122, "BCM4343A0" }, /* 001.001.034 */ { 0x2209, "BCM43430A1" }, /* 001.002.009 */ { 0x6119, "BCM4345C0" }, /* 003.001.025 */ + { 0x6606, "BCM4345C5" }, /* 003.006.006 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */ { 0x4217, "BCM4329B1" }, /* 002.002.023 */ diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 4d9de20bab7b..95c312ae94cf 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1419,6 +1419,7 @@ static void bcm_serdev_remove(struct serdev_device *serdev) #ifdef CONFIG_OF static const struct of_device_id bcm_bluetooth_of_match[] = { { .compatible = "brcm,bcm20702a1" }, + { .compatible = "brcm,bcm4345c5" }, { .compatible = "brcm,bcm4330-bt" }, { .compatible = "brcm,bcm43438-bt" }, { }, From 16946de5905fff243c1e4415c4565803945e8c47 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Fri, 23 Aug 2019 12:31:37 +0200 Subject: [PATCH 10/19] bluetooth: hci_bcm: Give more time to come out of reset Some supported devices need more time to come out of reset (eg. BCM4345C5 in AP6256). I don't have/found a datasheet, so the value was arrive at experimentally with the Oprange Pi 3 board. Without increased delay, I got intermittent failures during probe. This is a Bluetooth 5.0 device, so maybe that's why it takes longer to initialize than the others. Signed-off-by: Ondrej Jirman Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 95c312ae94cf..7646636f2d18 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -260,7 +260,7 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered) } /* wait for device to power on and come out of reset */ - usleep_range(10000, 20000); + usleep_range(100000, 120000); dev->res_enabled = powered; From 010376ab7fd788a0eddb86b6de5869b3045b97e3 Mon Sep 17 00:00:00 2001 From: Harish Bandi Date: Fri, 30 Aug 2019 17:58:36 +0530 Subject: [PATCH 11/19] Bluetooth: hci_qca: wait for Pre shutdown complete event before sending the Power off pulse When SoC receives pre shut down command, it share the same with other COEX shared clients. So SoC needs a short time after sending VS pre shutdown command before turning off the regulators and sending the power off pulse. Along with short delay, needs to wait for command complete event for Pre shutdown VS command Signed-off-by: Harish Bandi Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 5 +++-- drivers/bluetooth/hci_qca.c | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 0875470a7806..8cc21ad7cf29 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -106,8 +106,9 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) bt_dev_dbg(hdev, "QCA pre shutdown cmd"); - skb = __hci_cmd_sync(hdev, QCA_PRE_SHUTDOWN_CMD, 0, - NULL, HCI_INIT_TIMEOUT); + skb = __hci_cmd_sync_ev(hdev, QCA_PRE_SHUTDOWN_CMD, 0, + NULL, HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { err = PTR_ERR(skb); bt_dev_err(hdev, "QCA preshutdown_cmd failed (%d)", err); diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 15753f6bce80..d33828fef89f 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1375,6 +1375,8 @@ static int qca_power_off(struct hci_dev *hdev) /* Perform pre shutdown command */ qca_send_pre_shutdown_cmd(hdev); + usleep_range(8000, 10000); + qca_power_shutdown(hu); return 0; } From 65251e2e0ad379d89f5784626b8c40ff62220d8b Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Fri, 30 Aug 2019 20:02:14 +0800 Subject: [PATCH 12/19] Bluetooth: btrtl: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY Realtek Bluetooth controllers can do both LE scan and BR/EDR inquiry at once, need to set HCI_QUIRK_SIMULTANEOUS_DISCOVERY quirk. Signed-off-by: Alex Lu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 4f75a9b61d09..b7487ab99eed 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -641,6 +641,11 @@ int btrtl_setup_realtek(struct hci_dev *hdev) btrtl_free(btrtl_dev); + /* Enable controller to do both LE scan and BR/EDR inquiry + * simultaneously. + */ + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); + return ret; } EXPORT_SYMBOL_GPL(btrtl_setup_realtek); From 240b64a83165dde816664b50900aa12f1db92359 Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Sat, 31 Aug 2019 16:36:02 +0800 Subject: [PATCH 13/19] Bluetooth: btrtl: Add firmware version print This patch is used to print fw version for debug convenience Signed-off-by: Alex Lu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 56 ++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index b7487ab99eed..adb8ba0fcd59 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -178,6 +178,27 @@ static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev, return &ic_id_table[i]; } +static struct sk_buff *btrtl_read_local_version(struct hci_dev *hdev) +{ + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION failed (%ld)", + PTR_ERR(skb)); + return skb; + } + + if (skb->len != sizeof(struct hci_rp_read_local_version)) { + rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION event length mismatch"); + kfree_skb(skb); + return ERR_PTR(-EIO); + } + + return skb; +} + static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) { struct rtl_rom_version_evt *rom_version; @@ -368,6 +389,8 @@ static int rtl_download_firmware(struct hci_dev *hdev, int frag_len = RTL_FRAG_LEN; int ret = 0; int i; + struct sk_buff *skb; + struct hci_rp_read_local_version *rp; dl_cmd = kmalloc(sizeof(struct rtl_download_cmd), GFP_KERNEL); if (!dl_cmd) @@ -406,6 +429,18 @@ static int rtl_download_firmware(struct hci_dev *hdev, data += RTL_FRAG_LEN; } + skb = btrtl_read_local_version(hdev); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); + rtl_dev_err(hdev, "read local version failed"); + goto out; + } + + rp = (struct hci_rp_read_local_version *)skb->data; + rtl_dev_info(hdev, "fw version 0x%04x%04x", + __le16_to_cpu(rp->hci_rev), __le16_to_cpu(rp->lmp_subver)); + kfree_skb(skb); + out: kfree(dl_cmd); return ret; @@ -484,27 +519,6 @@ out: return ret; } -static struct sk_buff *btrtl_read_local_version(struct hci_dev *hdev) -{ - struct sk_buff *skb; - - skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, - HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION failed (%ld)\n", - PTR_ERR(skb)); - return skb; - } - - if (skb->len != sizeof(struct hci_rp_read_local_version)) { - rtl_dev_err(hdev, "HCI_OP_READ_LOCAL_VERSION event length mismatch\n"); - kfree_skb(skb); - return ERR_PTR(-EIO); - } - - return skb; -} - void btrtl_free(struct btrtl_device_info *btrtl_dev) { kfree(btrtl_dev->fw_data); From d182215d2fb9e58a7637efc937fa11dc15cf7a84 Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Sat, 31 Aug 2019 16:41:13 +0800 Subject: [PATCH 14/19] Bluetooth: btrtl: Remove redundant prefix from calls to rtl_dev macros the rtl: or RTL: prefix in the string is pointless. The rtl_dev_* macros already does that. Signed-off-by: Alex Lu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index adb8ba0fcd59..20aeed3c1ee7 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -213,7 +213,7 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) } if (skb->len != sizeof(*rom_version)) { - rtl_dev_err(hdev, "RTL version event length mismatch\n"); + rtl_dev_err(hdev, "version event length mismatch\n"); kfree_skb(skb); return -EIO; } @@ -451,7 +451,7 @@ static int rtl_load_file(struct hci_dev *hdev, const char *name, u8 **buff) const struct firmware *fw; int ret; - rtl_dev_info(hdev, "rtl: loading %s\n", name); + rtl_dev_info(hdev, "loading %s\n", name); ret = request_firmware(&fw, name, &hdev->dev); if (ret < 0) return ret; @@ -551,7 +551,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, } resp = (struct hci_rp_read_local_version *)skb->data; - rtl_dev_info(hdev, "rtl: examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x\n", + rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x\n", resp->hci_ver, resp->hci_rev, resp->lmp_ver, resp->lmp_subver); @@ -564,7 +564,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, hdev->bus); if (!btrtl_dev->ic_info) { - rtl_dev_info(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x", + rtl_dev_info(hdev, "unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x", lmp_subver, hci_rev, hci_ver); return btrtl_dev; } @@ -622,7 +622,7 @@ int btrtl_download_firmware(struct hci_dev *hdev, * to a different value. */ if (!btrtl_dev->ic_info) { - rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n"); + rtl_dev_info(hdev, "assuming no firmware upload needed\n"); return 0; } @@ -636,7 +636,7 @@ int btrtl_download_firmware(struct hci_dev *hdev, case RTL_ROM_LMP_8822B: return btrtl_setup_rtl8723b(hdev, btrtl_dev); default: - rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n"); + rtl_dev_info(hdev, "assuming no firmware upload needed\n"); return 0; } } From f1300c0340872d7d02617f439433d70c6f47700f Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Sat, 31 Aug 2019 16:46:11 +0800 Subject: [PATCH 15/19] Bluetooth: btrtl: Remove trailing newline from calls to rtl_dev macros These printing macros already add a trailing newline, so drop these unnecessary additional newlines. Signed-off-by: Alex Lu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 20aeed3c1ee7..0354e93e7a7c 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -207,19 +207,19 @@ static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version) /* Read RTL ROM version command */ skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { - rtl_dev_err(hdev, "Read ROM version failed (%ld)\n", + rtl_dev_err(hdev, "Read ROM version failed (%ld)", PTR_ERR(skb)); return PTR_ERR(skb); } if (skb->len != sizeof(*rom_version)) { - rtl_dev_err(hdev, "version event length mismatch\n"); + rtl_dev_err(hdev, "version event length mismatch"); kfree_skb(skb); return -EIO; } rom_version = (struct rtl_rom_version_evt *)skb->data; - rtl_dev_info(hdev, "rom_version status=%x version=%x\n", + rtl_dev_info(hdev, "rom_version status=%x version=%x", rom_version->status, rom_version->version); *version = rom_version->version; @@ -263,7 +263,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, fwptr = btrtl_dev->fw_data + btrtl_dev->fw_len - sizeof(extension_sig); if (memcmp(fwptr, extension_sig, sizeof(extension_sig)) != 0) { - rtl_dev_err(hdev, "extension section signature mismatch\n"); + rtl_dev_err(hdev, "extension section signature mismatch"); return -EINVAL; } @@ -284,7 +284,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, break; if (length == 0) { - rtl_dev_err(hdev, "found instruction with length 0\n"); + rtl_dev_err(hdev, "found instruction with length 0"); return -EINVAL; } @@ -297,7 +297,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, } if (project_id < 0) { - rtl_dev_err(hdev, "failed to find version instruction\n"); + rtl_dev_err(hdev, "failed to find version instruction"); return -EINVAL; } @@ -308,13 +308,13 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, } if (i >= ARRAY_SIZE(project_id_to_lmp_subver)) { - rtl_dev_err(hdev, "unknown project id %d\n", project_id); + rtl_dev_err(hdev, "unknown project id %d", project_id); return -EINVAL; } if (btrtl_dev->ic_info->lmp_subver != project_id_to_lmp_subver[i].lmp_subver) { - rtl_dev_err(hdev, "firmware is for %x but this is a %x\n", + rtl_dev_err(hdev, "firmware is for %x but this is a %x", project_id_to_lmp_subver[i].lmp_subver, btrtl_dev->ic_info->lmp_subver); return -EINVAL; @@ -322,7 +322,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, epatch_info = (struct rtl_epatch_header *)btrtl_dev->fw_data; if (memcmp(epatch_info->signature, RTL_EPATCH_SIGNATURE, 8) != 0) { - rtl_dev_err(hdev, "bad EPATCH signature\n"); + rtl_dev_err(hdev, "bad EPATCH signature"); return -EINVAL; } @@ -412,14 +412,14 @@ static int rtl_download_firmware(struct hci_dev *hdev, skb = __hci_cmd_sync(hdev, 0xfc20, frag_len + 1, dl_cmd, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { - rtl_dev_err(hdev, "download fw command failed (%ld)\n", + rtl_dev_err(hdev, "download fw command failed (%ld)", PTR_ERR(skb)); ret = -PTR_ERR(skb); goto out; } if (skb->len != sizeof(struct rtl_download_response)) { - rtl_dev_err(hdev, "download fw event length mismatch\n"); + rtl_dev_err(hdev, "download fw event length mismatch"); kfree_skb(skb); ret = -EIO; goto out; @@ -451,7 +451,7 @@ static int rtl_load_file(struct hci_dev *hdev, const char *name, u8 **buff) const struct firmware *fw; int ret; - rtl_dev_info(hdev, "loading %s\n", name); + rtl_dev_info(hdev, "loading %s", name); ret = request_firmware(&fw, name, &hdev->dev); if (ret < 0) return ret; @@ -475,7 +475,7 @@ static int btrtl_setup_rtl8723a(struct hci_dev *hdev, * (which is only for RTL8723B and newer). */ if (!memcmp(btrtl_dev->fw_data, RTL_EPATCH_SIGNATURE, 8)) { - rtl_dev_err(hdev, "unexpected EPATCH signature!\n"); + rtl_dev_err(hdev, "unexpected EPATCH signature!"); return -EINVAL; } @@ -510,7 +510,7 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev, fw_data = tbuff; } - rtl_dev_info(hdev, "cfg_sz %d, total sz %d\n", btrtl_dev->cfg_len, ret); + rtl_dev_info(hdev, "cfg_sz %d, total sz %d", btrtl_dev->cfg_len, ret); ret = rtl_download_firmware(hdev, fw_data, ret); @@ -551,7 +551,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, } resp = (struct hci_rp_read_local_version *)skb->data; - rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x\n", + rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x", resp->hci_ver, resp->hci_rev, resp->lmp_ver, resp->lmp_subver); @@ -578,7 +578,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, btrtl_dev->fw_len = rtl_load_file(hdev, btrtl_dev->ic_info->fw_name, &btrtl_dev->fw_data); if (btrtl_dev->fw_len < 0) { - rtl_dev_err(hdev, "firmware file %s not found\n", + rtl_dev_err(hdev, "firmware file %s not found", btrtl_dev->ic_info->fw_name); ret = btrtl_dev->fw_len; goto err_free; @@ -596,7 +596,7 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, &btrtl_dev->cfg_data); if (btrtl_dev->ic_info->config_needed && btrtl_dev->cfg_len <= 0) { - rtl_dev_err(hdev, "mandatory config file %s not found\n", + rtl_dev_err(hdev, "mandatory config file %s not found", btrtl_dev->ic_info->cfg_name); ret = btrtl_dev->cfg_len; goto err_free; @@ -622,7 +622,7 @@ int btrtl_download_firmware(struct hci_dev *hdev, * to a different value. */ if (!btrtl_dev->ic_info) { - rtl_dev_info(hdev, "assuming no firmware upload needed\n"); + rtl_dev_info(hdev, "assuming no firmware upload needed"); return 0; } @@ -636,7 +636,7 @@ int btrtl_download_firmware(struct hci_dev *hdev, case RTL_ROM_LMP_8822B: return btrtl_setup_rtl8723b(hdev, btrtl_dev); default: - rtl_dev_info(hdev, "assuming no firmware upload needed\n"); + rtl_dev_info(hdev, "assuming no firmware upload needed"); return 0; } } @@ -733,18 +733,18 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, total_data_len = btrtl_dev->cfg_len - sizeof(*config); if (total_data_len <= 0) { - rtl_dev_warn(hdev, "no config loaded\n"); + rtl_dev_warn(hdev, "no config loaded"); return -EINVAL; } config = (struct rtl_vendor_config *)btrtl_dev->cfg_data; if (le32_to_cpu(config->signature) != RTL_CONFIG_MAGIC) { - rtl_dev_err(hdev, "invalid config magic\n"); + rtl_dev_err(hdev, "invalid config magic"); return -EINVAL; } if (total_data_len < le16_to_cpu(config->total_len)) { - rtl_dev_err(hdev, "config is too short\n"); + rtl_dev_err(hdev, "config is too short"); return -EINVAL; } @@ -754,7 +754,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, switch (le16_to_cpu(entry->offset)) { case 0xc: if (entry->len < sizeof(*device_baudrate)) { - rtl_dev_err(hdev, "invalid UART config entry\n"); + rtl_dev_err(hdev, "invalid UART config entry"); return -EINVAL; } @@ -771,7 +771,7 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, break; default: - rtl_dev_dbg(hdev, "skipping config entry 0x%x (len %u)\n", + rtl_dev_dbg(hdev, "skipping config entry 0x%x (len %u)", le16_to_cpu(entry->offset), entry->len); break; }; @@ -780,13 +780,13 @@ int btrtl_get_uart_settings(struct hci_dev *hdev, } if (!found) { - rtl_dev_err(hdev, "no UART config entry found\n"); + rtl_dev_err(hdev, "no UART config entry found"); return -ENOENT; } - rtl_dev_dbg(hdev, "device baudrate = 0x%08x\n", *device_baudrate); - rtl_dev_dbg(hdev, "controller baudrate = %u\n", *controller_baudrate); - rtl_dev_dbg(hdev, "flow control %d\n", *flow_control); + rtl_dev_dbg(hdev, "device baudrate = 0x%08x", *device_baudrate); + rtl_dev_dbg(hdev, "controller baudrate = %u", *controller_baudrate); + rtl_dev_dbg(hdev, "flow control %d", *flow_control); return 0; } From 72bb169e024a20203e6044a81d5e41ae6ee0645b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 29 Aug 2019 20:12:11 -0500 Subject: [PATCH 16/19] Bluetooth: mgmt: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct mgmt_rp_get_connections { ... struct mgmt_addr_info addr[0]; } __packed; Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes. So, replace the following form: sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); with: struct_size(rp, addr, i) Also, notice that, in this case, variable rp_len is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 150114e33b20..acb7c6d5643f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2588,7 +2588,6 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, { struct mgmt_rp_get_connections *rp; struct hci_conn *c; - size_t rp_len; int err; u16 i; @@ -2608,8 +2607,7 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, i++; } - rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); - rp = kmalloc(rp_len, GFP_KERNEL); + rp = kmalloc(struct_size(rp, addr, i), GFP_KERNEL); if (!rp) { err = -ENOMEM; goto unlock; @@ -2629,10 +2627,8 @@ static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data, rp->conn_count = cpu_to_le16(i); /* Recalculate length in case of filtered SCO connections, etc */ - rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info)); - err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp, - rp_len); + struct_size(rp, addr, i)); kfree(rp); From cf0d9a705d81a0f581865cefe0880f29589dd06f Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 5 Sep 2019 13:21:57 +0800 Subject: [PATCH 17/19] Bluetooth: btrtl: Fix an issue that failing to download the FW which size is over 32K bytes Fix the issue that when the FW size is 32K+, it will fail for the download process because of the incorrect index. When firmware patch length is over 32K, "dl_cmd->index" may >= 0x80. It will be thought as "data end" that download process will not complete. However, driver should recount the index from 1. Signed-off-by: Max Chou Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 0354e93e7a7c..bf3c02be6930 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -401,7 +401,11 @@ static int rtl_download_firmware(struct hci_dev *hdev, BT_DBG("download fw (%d/%d)", i, frag_num); - dl_cmd->index = i; + if (i > 0x7f) + dl_cmd->index = (i & 0x7f) + 1; + else + dl_cmd->index = i; + if (i == (frag_num - 1)) { dl_cmd->index |= 0x80; /* data end */ frag_len = fw_len % RTL_FRAG_LEN; From d7ef0d1e39685b38c97b30daa6de0d50df004839 Mon Sep 17 00:00:00 2001 From: Alex Lu Date: Thu, 5 Sep 2019 10:36:31 +0800 Subject: [PATCH 18/19] Bluetooth: btusb: Use cmd_timeout to reset Realtek device Realtek Bluetooth controller provides a BT_DIS reset pin for hardware reset of it. The cmd_timeout is helpful on Realtek bluetooth controller where the firmware gets stuck. Signed-off-by: Alex Lu Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 31d3febed187..ed455de598ea 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -524,6 +524,36 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev) gpiod_set_value_cansleep(reset_gpio, 0); } +static void btusb_rtl_cmd_timeout(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct gpio_desc *reset_gpio = data->reset_gpio; + + if (++data->cmd_timeout_cnt < 5) + return; + + if (!reset_gpio) { + bt_dev_err(hdev, "No gpio to reset Realtek device, ignoring"); + return; + } + + /* Toggle the hard reset line. The Realtek device is going to + * yank itself off the USB and then replug. The cleanup is handled + * correctly on the way out (standard USB disconnect), and the new + * device is detected cleanly and bound to the driver again like + * it should be. + */ + if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { + bt_dev_err(hdev, "last reset failed? Not resetting again"); + return; + } + + bt_dev_err(hdev, "Reset Realtek device via gpio"); + gpiod_set_value_cansleep(reset_gpio, 0); + msleep(200); + gpiod_set_value_cansleep(reset_gpio, 1); +} + static inline void btusb_free_frags(struct btusb_data *data) { unsigned long flags; @@ -3783,6 +3813,7 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_REALTEK) { hdev->setup = btrtl_setup_realtek; hdev->shutdown = btrtl_shutdown_realtek; + hdev->cmd_timeout = btusb_rtl_cmd_timeout; /* Realtek devices lose their updated firmware over global * suspend that means host doesn't send SET_FEATURE From 8bb3537095f107ed55ad51f6241165b397aaafac Mon Sep 17 00:00:00 2001 From: Dan Elkouby Date: Fri, 6 Sep 2019 14:06:44 +0300 Subject: [PATCH 19/19] Bluetooth: hidp: Fix assumptions on the return value of hidp_send_message hidp_send_message was changed to return non-zero values on success, which some other bits did not expect. This caused spurious errors to be propagated through the stack, breaking some drivers, such as hid-sony for the Dualshock 4 in Bluetooth mode. As pointed out by Dan Carpenter, hid-microsoft directly relied on that assumption as well. Fixes: 48d9cc9d85dd ("Bluetooth: hidp: Let hidp_send_message return number of queued bytes") Signed-off-by: Dan Elkouby Reviewed-by: Dan Carpenter Reviewed-by: Jiri Kosina Signed-off-by: Marcel Holtmann --- drivers/hid/hid-microsoft.c | 2 +- net/bluetooth/hidp/core.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 8b3a922bdad3..2cf83856f2e4 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -303,7 +303,7 @@ static void ms_ff_worker(struct work_struct *work) r->magnitude[MAGNITUDE_WEAK] = ms->weak; /* right actuator */ ret = hid_hw_output_report(hdev, (__u8 *)r, sizeof(*r)); - if (ret) + if (ret < 0) hid_warn(hdev, "failed to send FF report\n"); } diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 8d889969ae7e..bef84b95e2c4 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -267,7 +267,7 @@ static int hidp_get_raw_report(struct hid_device *hid, set_bit(HIDP_WAITING_FOR_RETURN, &session->flags); data[0] = report_number; ret = hidp_send_ctrl_message(session, report_type, data, 1); - if (ret) + if (ret < 0) goto err; /* Wait for the return of the report. The returned report @@ -343,7 +343,7 @@ static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum, data[0] = reportnum; set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags); ret = hidp_send_ctrl_message(session, report_type, data, count); - if (ret) + if (ret < 0) goto err; /* Wait for the ACK from the device. */