Skip to content

Commit

Permalink
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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>
  • Loading branch information
David S. Miller committed May 13, 2020
2 parents b41dc4a + 5b44067 commit 6cd3588
Show file tree
Hide file tree
Showing 23 changed files with 618 additions and 258 deletions.
5 changes: 5 additions & 0 deletions Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ device the slave device is attached to.
Required properties:
- compatible: should contain one of the following:
* "qcom,qca6174-bt"
* "qcom,qca9377-bt"
* "qcom,wcn3990-bt"
* "qcom,wcn3991-bt"
* "qcom,wcn3998-bt"
Expand All @@ -21,6 +22,10 @@ Optional properties for compatible string qcom,qca6174-bt:
- clocks: clock provided to the controller (SUSCLK_32KHZ)
- firmware-name: specify the name of nvm firmware to load

Optional properties for compatible string qcom,qca9377-bt:

- max-speed: see Documentation/devicetree/bindings/serial/serial.yaml

Required properties for compatible string qcom,wcn399x-bt:

- vddio-supply: VDD_IO supply regulator handle.
Expand Down
54 changes: 54 additions & 0 deletions Documentation/devicetree/bindings/net/realtek-bluetooth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/realtek-bluetooth.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: RTL8723BS/RTL8723CS/RTL8822CS Bluetooth Device Tree Bindings

maintainers:
- Vasily Khoruzhick <anarsoul@gmail.com>
- Alistair Francis <alistair@alistair23.me>

description:
RTL8723CS/RTL8723CS/RTL8822CS is WiFi + BT chip. WiFi part is connected over
SDIO, while BT is connected over serial. It speaks H5 protocol with few
extra commands to upload firmware and change module speed.

properties:
compatible:
oneOf:
- const: "realtek,rtl8723bs-bt"
- const: "realtek,rtl8723cs-bt"
- const: "realtek,rtl8822cs-bt"

device-wake-gpios:
maxItems: 1
description: GPIO specifier, used to wakeup the BT module

enable-gpios:
maxItems: 1
description: GPIO specifier, used to enable the BT module

host-wake-gpios:
maxItems: 1
description: GPIO specifier, used to wakeup the host processor

required:
- compatible

examples:
- |
#include <dt-bindings/gpio/gpio.h>
uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
uart-has-rtscts = <1>;
bluetooth {
compatible = "realtek,rtl8723bs-bt";
device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_HIGH>; /* PL5 */
host-wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
};
};
139 changes: 79 additions & 60 deletions drivers/bluetooth/btbcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand All @@ -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 */
Expand All @@ -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 */
Expand All @@ -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 */
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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);

Expand Down
10 changes: 4 additions & 6 deletions drivers/bluetooth/btbcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
}
Expand Down
20 changes: 18 additions & 2 deletions drivers/bluetooth/btusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 },
Expand All @@ -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),
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6cd3588

Please sign in to comment.