Commit 6cd35888 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

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: default avatarDavid S. Miller <davem@davemloft.net>
parents b41dc4ae 5b440676
......@@ -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"
......@@ -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.
......
# 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 */
};
};
......@@ -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);
/* 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);
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);
err = btbcm_initialize(hdev, &fw_load_done);
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);
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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, &params);
}
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);
......
......@@ -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
{ },
};
......
......@@ -597,11 +597,13 @@ 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);
qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS;
......@@ -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},
......
......@@ -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,
};
......
......@@ -153,6 +153,12 @@ __printf(1, 2)
void bt_warn(const char *fmt, ...);
__printf(1, 2)
void bt_err(const char *fmt, ...);
#if IS_ENABLED(CONFIG_BT_FEATURE_DEBUG)
void bt_dbg_set(bool enable);
bool bt_dbg_get(void);
__printf(1, 2)
void bt_dbg(const char *fmt, ...);
#endif
__printf(1, 2)
void bt_warn_ratelimited(const char *fmt, ...);
__printf(1, 2)
......@@ -161,7 +167,12 @@ void bt_err_ratelimited(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
#define BT_WARN(fmt, ...) bt_warn(fmt "\n", ##__VA_ARGS__)
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
#if IS_ENABLED(CONFIG_BT_FEATURE_DEBUG)
#define BT_DBG(fmt, ...) bt_dbg(fmt "\n", ##__VA_ARGS__)
#else
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
#endif
#define bt_dev_info(hdev, fmt, ...) \
BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
......
......@@ -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 */
......@@ -249,6 +258,7 @@ enum {
HCI_MGMT_DEV_CLASS_EVENTS,
HCI_MGMT_LOCAL_NAME_EVENTS,
HCI_MGMT_OOB_DATA_EVENTS,
HCI_MGMT_EXP_FEATURE_EVENTS,
};
/*
......
......@@ -110,7 +110,7 @@ enum suspend_tasks {
enum suspended_state {
BT_RUNNING = 0,
BT_SUSPEND_DISCONNECT,
BT_SUSPEND_COMPLETE,
BT_SUSPEND_CONFIGURE_WAKE,
};
struct hci_conn_hash {
......@@ -503,6 +503,7 @@ struct hci_dev {
int (*set_diag)(struct hci_dev *hdev, bool enable);
int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
void (*cmd_timeout)(struct hci_dev *hdev);
bool (*prevent_wake)(struct hci_dev *hdev);
};
#define HCI_PHY_HANDLE(handle) (handle & 0xff)
......@@ -1554,6 +1555,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
#define HCI_MGMT_NO_HDEV BIT(1)
#define HCI_MGMT_UNTRUSTED BIT(2)
#define HCI_MGMT_UNCONFIGURED BIT(3)
#define HCI_MGMT_HDEV_OPTIONAL BIT(4)
struct hci_mgmt_handler {
int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
......
......@@ -70,14 +70,14 @@ struct mgmt_rp_read_version {
struct mgmt_rp_read_commands {
__le16 num_commands;
__le16 num_events;
__le16 opcodes[0];
__le16 opcodes[];
} __packed;
#define MGMT_OP_READ_INDEX_LIST 0x0003
#define MGMT_READ_INDEX_LIST_SIZE 0
struct mgmt_rp_read_index_list {
__le16 num_controllers;
__le16 index[0];
__le16 index[];
} __packed;
/* Reserve one extra byte for names in management messages so that they
......@@ -183,7 +183,7 @@ struct mgmt_link_key_info {
struct mgmt_cp_load_link_keys {
__u8 debug_keys;
__le16 key_count;
struct mgmt_link_key_info keys[0];
struct mgmt_link_key_info keys[];
} __packed;
#define MGMT_LOAD_LINK_KEYS_SIZE 3
......@@ -206,7 +206,7 @@ struct mgmt_ltk_info {
#define MGMT_OP_LOAD_LONG_TERM_KEYS 0x0013
struct mgmt_cp_load_long_term_keys {
__le16 key_count;
struct mgmt_ltk_info keys[0];
struct mgmt_ltk_info keys[];
} __packed;
#define MGMT_LOAD_LONG_TERM_KEYS_SIZE 2
......@@ -223,7 +223,7 @@ struct mgmt_rp_disconnect {
#define MGMT_GET_CONNECTIONS_SIZE 0
struct mgmt_rp_get_connections {
__le16 conn_count;
struct mgmt_addr_info addr[0];
struct mgmt_addr_info addr[];
} __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0016
......@@ -413,7 +413,7 @@ struct mgmt_irk_info {
#define MGMT_OP_LOAD_IRKS 0x0030
struct mgmt_cp_load_irks {
__le16 irk_count;
struct mgmt_irk_info irks[0];
struct mgmt_irk_info irks[];
} __packed;
#define MGMT_LOAD_IRKS_SIZE 2
......@@ -465,7 +465,7 @@ struct mgmt_conn_param {
#define MGMT_OP_LOAD_CONN_PARAM 0x0035
struct mgmt_cp_load_conn_param {
__le16 param_count;
struct mgmt_conn_param params[0];
struct mgmt_conn_param params[];
} __packed;
#define MGMT_LOAD_CONN_PARAM_SIZE 2
......@@ -473,7 +473,7 @@ struct mgmt_cp_load_conn_param {
#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0
struct mgmt_rp_read_unconf_index_list {
__le16 num_controllers;
__le16 index[0];
__le16 index[];
} __packed;
#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001
......@@ -504,7 +504,7 @@ struct mgmt_cp_start_service_discovery {
__u8 type;
__s8 rssi;
__le16 uuid_count;
__u8 uuids[0][16];
__u8 uuids[][16];
} __packed;
#define MGMT_START_SERVICE_DISCOVERY_SIZE 4
......@@ -516,7 +516,7 @@ struct mgmt_cp_read_local_oob_ext_data {
struct mgmt_rp_read_local_oob_ext_data {
__u8 type;
__le16 eir_len;
__u8 eir[0];
__u8 eir[];
} __packed;
#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C
......@@ -527,7 +527,7 @@ struct mgmt_rp_read_ext_index_list {
__le16 index;
__u8 type;
__u8 bus;
} entry[0];
} entry[];
} __packed;
#define MGMT_OP_READ_ADV_FEATURES 0x0003D
......@@ -538,7 +538,7 @@ struct mgmt_rp_read_adv_features {
__u8 max_scan_rsp_len;
__u8 max_instances;
__u8 num_instances;
__u8 instance[0];
__u8 instance[];
} __packed;
#define MGMT_OP_ADD_ADVERTISING 0x003E
......@@ -549,7 +549,7 @@ struct mgmt_cp_add_advertising {
__le16 timeout;
__u8 adv_data_len;
__u8 scan_rsp_len;
__u8 data[0];
__u8 data[];
} __packed;
#define MGMT_ADD_ADVERTISING_SIZE 11
struct mgmt_rp_add_advertising {
......@@ -603,7 +603,7 @@ struct mgmt_rp_read_ext_info {
__le32 supported_settings;
__le32 current_settings;
__le16 eir_len;
__u8 eir[0];
__u8 eir[];
} __packed;
#define MGMT_OP_SET_APPEARANCE 0x0043
......@@ -668,7 +668,7 @@ struct mgmt_blocked_key_info {
struct mgmt_cp_set_blocked_keys {
__le16 key_count;
struct mgmt_blocked_key_info keys[0];
struct mgmt_blocked_key_info keys[];
} __packed;
#define MGMT_OP_SET_BLOCKED_KEYS_SIZE 2
......@@ -678,14 +678,35 @@ struct mgmt_cp_set_blocked_keys {
#define MGMT_READ_SECURITY_INFO_SIZE 0
struct mgmt_rp_read_security_info {
__le16 sec_len;
__u8 sec[0];
__u8 sec[];
} __packed;
#define MGMT_OP_READ_EXP_FEATURES_INFO 0x0049
#define MGMT_READ_EXP_FEATURES_INFO_SIZE 0
struct mgmt_rp_read_exp_features_info {
__le16 feature_count;
struct {
__u8 uuid[16];
__le32 flags;
} features[];
} __packed;
#define MGMT_OP_SET_EXP_FEATURE 0x004a
struct mgmt_cp_set_exp_feature {
__u8 uuid[16];
__u8 param[];
} __packed;
#define MGMT_SET_EXP_FEATURE_SIZE 16
struct mgmt_rp_set_exp_feature {
__u8 uuid[16];
__le32 flags;
} __packed;
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
__u8 status;
__u8 data[0];
__u8 data[];
} __packed;
#define MGMT_EV_CMD_STATUS 0x0002
......@@ -733,7 +754,7 @@ struct mgmt_ev_device_connected {
struct mgmt_addr_info addr;
__le32 flags;
__le16 eir_len;
__u8 eir[0];
__u8 eir[];
} __packed;
#define MGMT_DEV_DISCONN_UNKNOWN 0x00
......@@ -788,7 +809,7 @@ struct mgmt_ev_device_found {
__s8 rssi;
__le32 flags;
__le16 eir_len;
__u8 eir[0];
__u8 eir[];
} __packed;
#define MGMT_EV_DISCOVERING 0x0013
......@@ -883,7 +904,7 @@ struct mgmt_ev_ext_index {
struct mgmt_ev_local_oob_data_updated {
__u8 type;
__le16 eir_len;
__u8 eir[0];
__u8 eir[];
} __packed;
#define MGMT_EV_ADVERTISING_ADDED 0x0023
......@@ -899,10 +920,16 @@ struct mgmt_ev_advertising_removed {
#define MGMT_EV_EXT_INFO_CHANGED 0x0025
struct mgmt_ev_ext_info_changed {
__le16 eir_len;
__u8 eir[0];
__u8 eir[];
} __packed;
#define MGMT_EV_PHY_CONFIGURATION_CHANGED 0x0026
struct mgmt_ev_phy_configuration_changed {
__le32 selected_phys;
} __packed;
#define MGMT_EV_EXP_FEATURE_CHANGED 0x0027
struct mgmt_ev_exp_feature_changed {
__u8 uuid[16];
__le32 flags;
} __packed;
......@@ -135,4 +135,11 @@ config BT_SELFTEST_SMP
Run test cases for SMP cryptographic functionality, including both
legacy SMP as well as the Secure Connections features.
config BT_FEATURE_DEBUG
bool "Enable runtime option for debugging statements"
depends on BT && !DYNAMIC_DEBUG
help
This provides an option to enable/disable debugging statements
at runtime via the experimental features interface.
source "drivers/bluetooth/Kconfig"
......@@ -3350,10 +3350,12 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
*/
ret = hci_change_suspend_state(hdev, BT_SUSPEND_DISCONNECT);
/* Only configure whitelist if disconnect succeeded */
if (!ret)
/* Only configure whitelist if disconnect succeeded and wake
* isn't being prevented.
*/
if (!ret && !(hdev->prevent_wake && hdev->prevent_wake(hdev)))
ret = hci_change_suspend_state(hdev,
BT_SUSPEND_COMPLETE);
BT_SUSPEND_CONFIGURE_WAKE);
} else if (action == PM_POST_SUSPEND) {
ret = hci_change_suspend_state(hdev, BT_RUNNING);
}
......
......@@ -42,12 +42,27 @@
/* Handle HCI Event packets */
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
u8 *new_status)
{
__u8 status = *((__u8 *) skb->data);
BT_DBG("%s status 0x%2.2x", hdev->name, status);
/* It is possible that we receive Inquiry Complete event right
* before we receive Inquiry Cancel Command Complete event, in
* which case the latter event should have status of Command
* Disallowed (0x0c). This should not be treated as error, since
* we actually achieve what Inquiry Cancel wants to achieve,
* which is to end the last Inquiry session.
*/
if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
status = 0x00;
}
*new_status = status;
if (status)
return;
......@@ -3233,7 +3248,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
switch (*opcode) {
case HCI_OP_INQUIRY_CANCEL:
hci_cc_inquiry_cancel(hdev, skb);
hci_cc_inquiry_cancel(hdev, skb, status);
break;
case HCI_OP_PERIODIC_INQ:
......@@ -5288,7 +5303,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
/* 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)
if (hdev->conn_hash.le_num_slave > 0 &&
(!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) ||
!(hdev->le_states[3] & 0x10)))
return NULL;
/* If we're not connectable only connect devices that we have in
......
......@@ -35,7 +35,7 @@
#define HCI_REQ_CANCELED 2
#define LE_SUSPEND_SCAN_WINDOW 0x0012
#define LE_SUSPEND_SCAN_INTERVAL 0x0060
#define LE_SUSPEND_SCAN_INTERVAL 0x0400
void hci_req_init(struct hci_request *req, struct hci_dev *hdev)
{
......@@ -890,7 +890,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
struct hci_dev *hdev = req->hdev;
u8 own_addr_type;
u8 filter_policy;
u8 window, interval;
u16 window, interval;
if (hdev->scanning_paused) {
bt_dev_dbg(hdev, "Scanning is paused for suspend");
......@@ -1090,7 +1090,7 @@ void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next)
disconnect_counter);
set_bit(SUSPEND_DISCONNECTING, hdev->suspend_tasks);
}
} else if (next == BT_SUSPEND_COMPLETE) {
} else if (next == BT_SUSPEND_CONFIGURE_WAKE) {
/* Unpause to take care of updating scanning params */
hdev->scanning_paused = false;
/* Enable event filter for paired devices */
......@@ -1447,7 +1447,7 @@ void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
hdev->scan_rsp_data_len = len;
cp.handle = 0;
cp.handle = instance;
cp.length = len;
cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
......@@ -1591,7 +1591,7 @@ void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
hdev->adv_data_len = len;
cp.length = len;
cp.handle = 0;
cp.handle = instance;
cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
......@@ -1876,7 +1876,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
memset(&cp, 0, sizeof(cp));
cp.handle = 0;
cp.handle = instance;
bacpy(&cp.bdaddr, &random_addr);
hci_req_add(req,
......
......@@ -1579,12 +1579,14 @@ static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk,
}
}
if (!(handler->flags & HCI_MGMT_HDEV_OPTIONAL)) {
no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
if (no_hdev != !hdev) {
err = mgmt_cmd_status(sk, index, opcode,
MGMT_STATUS_INVALID_INDEX);
goto done;
}
}
var_len = (handler->flags & HCI_MGMT_VAR_LEN);
if ((var_len && len < handler->data_len) ||
......
......@@ -5927,7 +5927,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
if (!enable_ecred)
return -EINVAL;
if (cmd_len < sizeof(*req) || cmd_len - sizeof(*req) % sizeof(u16)) {
if (cmd_len < sizeof(*req) || (cmd_len - sizeof(*req)) % sizeof(u16)) {
result = L2CAP_CR_LE_INVALID_PARAMS;
goto response;
}
......@@ -5964,7 +5964,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
}
result = L2CAP_CR_LE_SUCCESS;
cmd_len -= sizeof(req);
cmd_len -= sizeof(*req);
num_scid = cmd_len / sizeof(u16);
for (i = 0; i < num_scid; i++) {
......
......@@ -1271,14 +1271,21 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
struct l2cap_conn *conn;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
/* 'how' parameter is mapped to sk_shutdown as follows:
* SHUT_RD (0) --> RCV_SHUTDOWN (1)
* SHUT_WR (1) --> SEND_SHUTDOWN (2)
* SHUT_RDWR (2) --> SHUTDOWN_MASK (3)
*/
how++;
if (!sk)
return 0;
lock_sock(sk);
if (sk->sk_shutdown)
if ((sk->sk_shutdown & how) == how)
goto shutdown_already;
BT_DBG("Handling sock shutdown");
......@@ -1301,11 +1308,20 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
* has already been actioned to close the L2CAP
* link such as by l2cap_disconnection_req().
*/
if (sk->sk_shutdown)
goto has_shutdown;
if ((sk->sk_shutdown & how) == how)
goto shutdown_matched;
}
sk->sk_shutdown = SHUTDOWN_MASK;
/* Try setting the RCV_SHUTDOWN bit, return early if SEND_SHUTDOWN
* is already set
*/
if ((how & RCV_SHUTDOWN) && !(sk->sk_shutdown & RCV_SHUTDOWN)) {
sk->sk_shutdown |= RCV_SHUTDOWN;
if ((sk->sk_shutdown & how) == how)
goto shutdown_matched;
}
sk->sk_shutdown |= SEND_SHUTDOWN;
release_sock(sk);
l2cap_chan_lock(chan);
......@@ -1335,7 +1351,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
has_shutdown:
shutdown_matched:
l2cap_chan_put(chan);
sock_put(sk);
......@@ -1363,7 +1379,7 @@ static int l2cap_sock_release(struct socket *sock)
bt_sock_unlink(&l2cap_sk_list, sk);
err = l2cap_sock_shutdown(sock, 2);
err = l2cap_sock_shutdown(sock, SHUT_RDWR);
chan = l2cap_pi(sk)->chan;
l2cap_chan_hold(chan);
......
......@@ -183,6 +183,39 @@ void bt_err(const char *format, ...)
}
EXPORT_SYMBOL(bt_err);
#ifdef CONFIG_BT_FEATURE_DEBUG
static bool debug_enable;
void bt_dbg_set(bool enable)
{
debug_enable = enable;
}
bool bt_dbg_get(void)
{
return debug_enable;
}
void bt_dbg(const char *format, ...)
{
struct va_format vaf;
va_list args;
if (likely(!debug_enable))
return;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
printk(KERN_DEBUG pr_fmt("%pV"), &vaf);
va_end(args);
}
EXPORT_SYMBOL(bt_dbg);
#endif
void bt_warn_ratelimited(const char *format, ...)
{
struct va_format vaf;
......
This diff is collapsed.
......@@ -508,7 +508,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
if (!chan || !chan->data)
return false;
BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
bt_dev_dbg(hdev, "RPA %pMR IRK %*phN", bdaddr, 16, irk);
err = smp_ah(irk, &bdaddr->b[3], hash);
if (err)
......@@ -534,7 +534,7 @@ int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
if (err < 0)
return err;
BT_DBG("RPA %pMR", rpa);
bt_dev_dbg(hdev, "RPA %pMR", rpa);
return 0;
}
......@@ -551,7 +551,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
smp = chan->data;
if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS)) {
BT_DBG("Using debug keys");
bt_dev_dbg(hdev, "Using debug keys");
err = set_ecdh_privkey(smp->tfm_ecdh, debug_sk);
if (err)
return err;
......@@ -1867,7 +1867,7 @@ static u8 sc_send_public_key(struct smp_chan *smp)
{
struct hci_dev *hdev = smp->conn->hcon->hdev;
BT_DBG("");
bt_dev_dbg(hdev, "");
if (test_bit(SMP_FLAG_LOCAL_OOB, &smp->flags)) {
struct l2cap_chan *chan = hdev->smp_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment