diff options
author | David S. Miller <davem@davemloft.net> | 2020-05-13 21:20:12 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-05-13 21:20:12 +0200 |
commit | 6cd35888a0db4b18a5796fe5d5863f004f8eef0f (patch) | |
tree | e21b4eb06573358cf53ecd2a8fce88857189f92b /drivers | |
parent | Merge branch 'net-dsa-felix-tc-taprio-and-CBS-offload-support' (diff) | |
parent | Bluetooth: L2CAP: add support for waiting disconnection resp (diff) | |
download | linux-6cd35888a0db4b18a5796fe5d5863f004f8eef0f.tar.xz linux-6cd35888a0db4b18a5796fe5d5863f004f8eef0f.zip |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says:
====================
pull request: bluetooth-next 2020-05-13
Here's a second attempt at a bluetooth-next pull request which
supercedes the one dated 2020-05-09. This should have the issues
discovered by Jakub fixed.
- Add support for Intel Typhoon Peak device (8087:0032)
- Add device tree bindings for Realtek RTL8723BS device
- Add device tree bindings for Qualcomm QCA9377 device
- Add support for experimental features configuration through mgmt
- Add driver hook to prevent wake from suspend
- Add support for waiting for L2CAP disconnection response
- Multiple fixes & cleanups to the btbcm driver
- Add support for LE scatternet topology for selected devices
- A few other smaller fixes & cleanups
Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bluetooth/btbcm.c | 139 | ||||
-rw-r--r-- | drivers/bluetooth/btbcm.h | 10 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 20 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcm.c | 27 | ||||
-rw-r--r-- | drivers/bluetooth/hci_h5.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 17 | ||||
-rw-r--r-- | drivers/bluetooth/hci_serdev.c | 4 |
7 files changed, 124 insertions, 95 deletions
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 1f498f358f60..df7a8a22e53c 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -27,6 +27,11 @@ #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 +#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) { struct hci_rp_read_bd_addr *bda; @@ -358,6 +363,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)) @@ -380,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 */ @@ -395,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 */ @@ -408,14 +422,17 @@ 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; + 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; /* Reset */ @@ -434,15 +451,14 @@ 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; } - - /* Upper nibble of rev should be between 0 and 3? */ - if (((rev & 0xf000) >> 12) > 3) - return 0; + 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; @@ -454,6 +470,13 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len, } } + bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", + hw_name ? hw_name : "BCM", (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); @@ -464,85 +487,81 @@ 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", - hw_name, vid, pid); - } else { - snprintf(fw_name, len, "brcm/%s.hcd", hw_name); + snprintf(postfix, sizeof(postfix), "-%4.4x-%4.4x", vid, pid); } - 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); + 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++; + } + + 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]); + } + kfree(fw_name); return 0; } EXPORT_SYMBOL_GPL(btbcm_initialize); -int btbcm_finalize(struct hci_dev *hdev) +int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done) { - char fw_name[64]; int err; - /* Re-initialize */ - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true); - 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); 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); int btbcm_setup_patchram(struct hci_dev *hdev) { - char fw_name[64]; - const struct firmware *fw; - struct sk_buff *skb; + bool fw_load_done = false; 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); - goto done; - } - - btbcm_patchram(hdev, fw); - - release_firmware(fw); - - /* Re-initialize */ - err = btbcm_initialize(hdev, fw_name, sizeof(fw_name), true); - 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); - - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - - return 0; + /* Re-initialize after loading Patch */ + 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 014ef847a486..8bf01565fdfc 100644 --- a/drivers/bluetooth/btbcm.h +++ b/drivers/bluetooth/btbcm.h @@ -62,9 +62,8 @@ 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_finalize(struct hci_dev *hdev); +int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done); +int btbcm_finalize(struct hci_dev *hdev, bool *fw_load_done); #else @@ -105,13 +104,12 @@ 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; } -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/btusb.c b/drivers/bluetooth/btusb.c index 871162790a0e..5f022e9cf667 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 */ @@ -335,11 +336,14 @@ 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 | 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 }, @@ -348,7 +352,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), @@ -3695,6 +3700,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) { @@ -3828,6 +3840,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); @@ -3972,6 +3985,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); diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 19e4587f366c..8ea5ca8d71d6 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,13 +606,16 @@ 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); + err = btbcm_finalize(hu->hdev, &fw_load_done); 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); 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 { }, }; diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index d0ac554584a4..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"); @@ -2058,6 +2060,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}, 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, }; |