Commit e61fbee7 authored by David S. Miller's avatar David S. Miller

Merge tag 'for-net-next-2021-08-19' of...

Merge tag 'for-net-next-2021-08-19' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Luiz Augusto von Dentz says:

====================
bluetooth-next pull request for net-next:

 - Add support for Foxconn Mediatek Chip
 - Add support for LG LGSBWAC92/TWCM-K505D
 - hci_h5 flow control fixes and suspend support
 - Switch to use lock_sock for SCO and RFCOMM
 - Various fixes for extended advertising
 - Reword Intel's setup on btusb unifying the supported generations
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 815cc21d 61969ef8
...@@ -387,6 +387,7 @@ struct bcm_subver_table { ...@@ -387,6 +387,7 @@ struct bcm_subver_table {
}; };
static const struct bcm_subver_table bcm_uart_subver_table[] = { static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x1111, "BCM4362A2" }, /* 000.017.017 */
{ 0x4103, "BCM4330B1" }, /* 002.001.003 */ { 0x4103, "BCM4330B1" }, /* 002.001.003 */
{ 0x410d, "BCM4334B0" }, /* 002.001.013 */ { 0x410d, "BCM4334B0" }, /* 002.001.013 */
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */ { 0x410e, "BCM43341B0" }, /* 002.001.014 */
......
This diff is collapsed.
...@@ -138,6 +138,49 @@ struct intel_debug_features { ...@@ -138,6 +138,49 @@ struct intel_debug_features {
#define INTEL_CNVX_TOP_STEP(cnvx_top) (((cnvx_top) & 0x0f000000) >> 24) #define INTEL_CNVX_TOP_STEP(cnvx_top) (((cnvx_top) & 0x0f000000) >> 24)
#define INTEL_CNVX_TOP_PACK_SWAB(t, s) __swab16(((__u16)(((t) << 4) | (s)))) #define INTEL_CNVX_TOP_PACK_SWAB(t, s) __swab16(((__u16)(((t) << 4) | (s))))
enum {
INTEL_BOOTLOADER,
INTEL_DOWNLOADING,
INTEL_FIRMWARE_LOADED,
INTEL_FIRMWARE_FAILED,
INTEL_BOOTING,
INTEL_BROKEN_INITIAL_NCMD,
INTEL_BROKEN_LED,
INTEL_ROM_LEGACY,
__INTEL_NUM_FLAGS,
};
struct btintel_data {
DECLARE_BITMAP(flags, __INTEL_NUM_FLAGS);
};
#define btintel_set_flag(hdev, nr) \
do { \
struct btintel_data *intel = hci_get_priv((hdev)); \
set_bit((nr), intel->flags); \
} while (0)
#define btintel_clear_flag(hdev, nr) \
do { \
struct btintel_data *intel = hci_get_priv((hdev)); \
clear_bit((nr), intel->flags); \
} while (0)
#define btintel_wake_up_flag(hdev, nr) \
do { \
struct btintel_data *intel = hci_get_priv((hdev)); \
wake_up_bit(intel->flags, (nr)); \
} while (0)
#define btintel_get_flag(hdev) \
(((struct btintel_data *)hci_get_priv(hdev))->flags)
#define btintel_test_flag(hdev, nr) test_bit((nr), btintel_get_flag(hdev))
#define btintel_test_and_clear_flag(hdev, nr) test_and_clear_bit((nr), btintel_get_flag(hdev))
#define btintel_wait_on_flag_timeout(hdev, nr, m, to) \
wait_on_bit_timeout(btintel_get_flag(hdev), (nr), m, to)
#if IS_ENABLED(CONFIG_BT_INTEL) #if IS_ENABLED(CONFIG_BT_INTEL)
int btintel_check_bdaddr(struct hci_dev *hdev); int btintel_check_bdaddr(struct hci_dev *hdev);
...@@ -145,19 +188,11 @@ int btintel_enter_mfg(struct hci_dev *hdev); ...@@ -145,19 +188,11 @@ int btintel_enter_mfg(struct hci_dev *hdev);
int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched); int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched);
int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int btintel_set_diag(struct hci_dev *hdev, bool enable); int btintel_set_diag(struct hci_dev *hdev, bool enable);
int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
void btintel_hw_error(struct hci_dev *hdev, u8 code);
int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver); int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver);
int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version);
int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name); int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
int btintel_set_event_mask(struct hci_dev *hdev, bool debug);
int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug); int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug);
int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver); int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write); u16 opcode_write);
int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param);
...@@ -165,16 +200,10 @@ int btintel_read_boot_params(struct hci_dev *hdev, ...@@ -165,16 +200,10 @@ int btintel_read_boot_params(struct hci_dev *hdev,
struct intel_boot_params *params); struct intel_boot_params *params);
int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver,
const struct firmware *fw, u32 *boot_param); const struct firmware *fw, u32 *boot_param);
int btintel_download_firmware_newgen(struct hci_dev *hdev, int btintel_configure_setup(struct hci_dev *hdev);
struct intel_version_tlv *ver, void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len);
const struct firmware *fw, void btintel_secure_send_result(struct hci_dev *hdev,
u32 *boot_param, u8 hw_variant, const void *ptr, unsigned int len);
u8 sbe_type);
void btintel_reset_to_bootloader(struct hci_dev *hdev);
int btintel_read_debug_features(struct hci_dev *hdev,
struct intel_debug_features *features);
int btintel_set_debug_features(struct hci_dev *hdev,
const struct intel_debug_features *features);
#else #else
static inline int btintel_check_bdaddr(struct hci_dev *hdev) static inline int btintel_check_bdaddr(struct hci_dev *hdev)
...@@ -202,44 +231,18 @@ static inline int btintel_set_diag(struct hci_dev *hdev, bool enable) ...@@ -202,44 +231,18 @@ static inline int btintel_set_diag(struct hci_dev *hdev, bool enable)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable)
{
return -EOPNOTSUPP;
}
static inline void btintel_hw_error(struct hci_dev *hdev, u8 code)
{
}
static inline int btintel_version_info(struct hci_dev *hdev, static inline int btintel_version_info(struct hci_dev *hdev,
struct intel_version *ver) struct intel_version *ver)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_version_info_tlv(struct hci_dev *hdev,
struct intel_version_tlv *version)
{
return -EOPNOTSUPP;
}
static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type,
u32 plen, const void *param)
{
return -EOPNOTSUPP;
}
static inline int btintel_load_ddc_config(struct hci_dev *hdev, static inline int btintel_load_ddc_config(struct hci_dev *hdev,
const char *ddc_name) const char *ddc_name)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_set_event_mask(struct hci_dev *hdev, bool debug)
{
return -EOPNOTSUPP;
}
static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -251,12 +254,6 @@ static inline int btintel_read_version(struct hci_dev *hdev, ...@@ -251,12 +254,6 @@ static inline int btintel_read_version(struct hci_dev *hdev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_read_version_tlv(struct hci_dev *hdev,
struct intel_version_tlv *ver)
{
return -EOPNOTSUPP;
}
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev, static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
u16 opcode_read, u16 opcode_read,
u16 opcode_write) u16 opcode_write)
...@@ -283,28 +280,18 @@ static inline int btintel_download_firmware(struct hci_dev *dev, ...@@ -283,28 +280,18 @@ static inline int btintel_download_firmware(struct hci_dev *dev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btintel_download_firmware_newgen(struct hci_dev *hdev, static inline int btintel_configure_setup(struct hci_dev *hdev)
const struct firmware *fw,
u32 *boot_param,
u8 hw_variant, u8 sbe_type)
{
return -EOPNOTSUPP;
}
static inline void btintel_reset_to_bootloader(struct hci_dev *hdev)
{ {
return -ENODEV;
} }
static inline int btintel_read_debug_features(struct hci_dev *hdev, static inline void btintel_bootup(struct hci_dev *hdev,
struct intel_debug_features *features) const void *ptr, unsigned int len)
{ {
return -EOPNOTSUPP;
} }
static inline int btintel_set_debug_features(struct hci_dev *hdev, static inline void btintel_secure_send_result(struct hci_dev *hdev,
const struct intel_debug_features *features) const void *ptr, unsigned int len)
{ {
return -EOPNOTSUPP;
} }
#endif #endif
...@@ -1350,6 +1350,7 @@ static void btmrvl_sdio_coredump(struct device *dev) ...@@ -1350,6 +1350,7 @@ static void btmrvl_sdio_coredump(struct device *dev)
u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr; u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
u8 dump_num = 0, idx, i, read_reg, doneflag = 0; u8 dump_num = 0, idx, i, read_reg, doneflag = 0;
u32 memory_size, fw_dump_len = 0; u32 memory_size, fw_dump_len = 0;
int size = 0;
card = sdio_get_drvdata(func); card = sdio_get_drvdata(func);
priv = card->priv; priv = card->priv;
...@@ -1478,7 +1479,7 @@ static void btmrvl_sdio_coredump(struct device *dev) ...@@ -1478,7 +1479,7 @@ static void btmrvl_sdio_coredump(struct device *dev)
if (fw_dump_len == 0) if (fw_dump_len == 0)
return; return;
fw_dump_data = vzalloc(fw_dump_len+1); fw_dump_data = vzalloc(fw_dump_len + 1);
if (!fw_dump_data) { if (!fw_dump_data) {
BT_ERR("Vzalloc fw_dump_data fail!"); BT_ERR("Vzalloc fw_dump_data fail!");
return; return;
...@@ -1493,20 +1494,18 @@ static void btmrvl_sdio_coredump(struct device *dev) ...@@ -1493,20 +1494,18 @@ static void btmrvl_sdio_coredump(struct device *dev)
struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
if (entry->mem_ptr) { if (entry->mem_ptr) {
strcpy(fw_dump_ptr, "========Start dump "); size += scnprintf(fw_dump_ptr + size,
fw_dump_ptr += strlen("========Start dump "); fw_dump_len + 1 - size,
"========Start dump %s========\n",
strcpy(fw_dump_ptr, entry->mem_name); entry->mem_name);
fw_dump_ptr += strlen(entry->mem_name);
memcpy(fw_dump_ptr + size, entry->mem_ptr,
strcpy(fw_dump_ptr, "========\n"); entry->mem_size);
fw_dump_ptr += strlen("========\n"); size += entry->mem_size;
memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size); size += scnprintf(fw_dump_ptr + size,
fw_dump_ptr += entry->mem_size; fw_dump_len + 1 - size,
"\n========End dump========\n");
strcpy(fw_dump_ptr, "\n========End dump========\n");
fw_dump_ptr += strlen("\n========End dump========\n");
vfree(mem_type_mapping_tbl[idx].mem_ptr); vfree(mem_type_mapping_tbl[idx].mem_ptr);
mem_type_mapping_tbl[idx].mem_ptr = NULL; mem_type_mapping_tbl[idx].mem_ptr = NULL;
......
/** /*
* Copyright (c) 2017 Redpine Signals Inc. * Copyright (c) 2017 Redpine Signals Inc.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
......
...@@ -681,11 +681,15 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, ...@@ -681,11 +681,15 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
} }
} }
/* RTL8822CE supports the Microsoft vendor extension and uses 0xFCF0 /* The following chips supports the Microsoft vendor extension,
* for VsMsftOpCode. * therefore set the corresponding VsMsftOpCode.
*/ */
if (lmp_subver == RTL_ROM_LMP_8822B) switch (lmp_subver) {
case RTL_ROM_LMP_8822B:
case RTL_ROM_LMP_8852A:
hci_set_msft_opcode(hdev, 0xFCF0); hci_set_msft_opcode(hdev, 0xFCF0);
break;
}
return btrtl_dev; return btrtl_dev;
......
This diff is collapsed.
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
/** /**
* struct bcm_device_data - device specific data * struct bcm_device_data - device specific data
* @no_early_set_baudrate: Disallow set baudrate before driver setup() * @no_early_set_baudrate: Disallow set baudrate before driver setup()
* @drive_rts_on_open: drive RTS signal on ->open() when platform requires it
*/ */
struct bcm_device_data { struct bcm_device_data {
bool no_early_set_baudrate; bool no_early_set_baudrate;
...@@ -77,6 +78,8 @@ struct bcm_device_data { ...@@ -77,6 +78,8 @@ struct bcm_device_data {
* @btlp: Apple ACPI method to toggle BT_WAKE pin ("Bluetooth Low Power") * @btlp: Apple ACPI method to toggle BT_WAKE pin ("Bluetooth Low Power")
* @btpu: Apple ACPI method to drive BT_REG_ON pin high ("Bluetooth Power Up") * @btpu: Apple ACPI method to drive BT_REG_ON pin high ("Bluetooth Power Up")
* @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down") * @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down")
* @gpio_count: internal counter for GPIO resources associated with ACPI device
* @gpio_int_idx: index in _CRS for GpioInt() resource
* @txco_clk: external reference frequency clock used by Bluetooth device * @txco_clk: external reference frequency clock used by Bluetooth device
* @lpo_clk: external LPO clock used by Bluetooth device * @lpo_clk: external LPO clock used by Bluetooth device
* @supplies: VBAT and VDDIO supplies used by Bluetooth device * @supplies: VBAT and VDDIO supplies used by Bluetooth device
...@@ -88,10 +91,13 @@ struct bcm_device_data { ...@@ -88,10 +91,13 @@ struct bcm_device_data {
* set to 0 if @init_speed is already the preferred baudrate * set to 0 if @init_speed is already the preferred baudrate
* @irq: interrupt triggered by HOST_WAKE_BT pin * @irq: interrupt triggered by HOST_WAKE_BT pin
* @irq_active_low: whether @irq is active low * @irq_active_low: whether @irq is active low
* @irq_acquired: flag to show if IRQ handler has been assigned
* @hu: pointer to HCI UART controller struct, * @hu: pointer to HCI UART controller struct,
* used to disable flow control during runtime suspend and system sleep * used to disable flow control during runtime suspend and system sleep
* @is_suspended: whether flow control is currently disabled * @is_suspended: whether flow control is currently disabled
* @no_early_set_baudrate: don't set_baudrate before setup() * @no_early_set_baudrate: don't set_baudrate before setup()
* @drive_rts_on_open: drive RTS signal on ->open() when platform requires it
* @pcm_int_params: keep the initial PCM configuration
*/ */
struct bcm_device { struct bcm_device {
/* Must be the first member, hci_serdev.c expects this. */ /* Must be the first member, hci_serdev.c expects this. */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/serdev.h> #include <linux/serdev.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -21,6 +22,8 @@ ...@@ -21,6 +22,8 @@
#include "btrtl.h" #include "btrtl.h"
#include "hci_uart.h" #include "hci_uart.h"
#define SUSPEND_TIMEOUT_MS 6000
#define HCI_3WIRE_ACK_PKT 0 #define HCI_3WIRE_ACK_PKT 0
#define HCI_3WIRE_LINK_PKT 15 #define HCI_3WIRE_LINK_PKT 15
...@@ -51,8 +54,10 @@ ...@@ -51,8 +54,10 @@
/* H5 state flags */ /* H5 state flags */
enum { enum {
H5_RX_ESC, /* SLIP escape mode */ H5_RX_ESC, /* SLIP escape mode */
H5_TX_ACK_REQ, /* Pending ack to send */ H5_TX_ACK_REQ, /* Pending ack to send */
H5_WAKEUP_DISABLE, /* Device cannot wake host */
H5_HW_FLOW_CONTROL, /* Use HW flow control */
}; };
struct h5 { struct h5 {
...@@ -97,6 +102,10 @@ struct h5 { ...@@ -97,6 +102,10 @@ struct h5 {
struct gpio_desc *device_wake_gpio; struct gpio_desc *device_wake_gpio;
}; };
enum h5_driver_info {
H5_INFO_WAKEUP_DISABLE = BIT(0),
};
struct h5_vnd { struct h5_vnd {
int (*setup)(struct h5 *h5); int (*setup)(struct h5 *h5);
void (*open)(struct h5 *h5); void (*open)(struct h5 *h5);
...@@ -106,6 +115,11 @@ struct h5_vnd { ...@@ -106,6 +115,11 @@ struct h5_vnd {
const struct acpi_gpio_mapping *acpi_gpio_map; const struct acpi_gpio_mapping *acpi_gpio_map;
}; };
struct h5_device_data {
uint32_t driver_info;
struct h5_vnd *vnd;
};
static void h5_reset_rx(struct h5 *h5); static void h5_reset_rx(struct h5 *h5);
static void h5_link_control(struct hci_uart *hu, const void *data, size_t len) static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
...@@ -573,6 +587,10 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count) ...@@ -573,6 +587,10 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count)
count -= processed; count -= processed;
} }
pm_runtime_get(&hu->serdev->dev);
pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
return 0; return 0;
} }
...@@ -609,6 +627,10 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -609,6 +627,10 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
break; break;
} }
pm_runtime_get_sync(&hu->serdev->dev);
pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
return 0; return 0;
} }
...@@ -791,6 +813,8 @@ static int h5_serdev_probe(struct serdev_device *serdev) ...@@ -791,6 +813,8 @@ static int h5_serdev_probe(struct serdev_device *serdev)
{ {
struct device *dev = &serdev->dev; struct device *dev = &serdev->dev;
struct h5 *h5; struct h5 *h5;
const struct h5_device_data *data;
int err;
h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL); h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
if (!h5) if (!h5)
...@@ -807,20 +831,19 @@ static int h5_serdev_probe(struct serdev_device *serdev) ...@@ -807,20 +831,19 @@ static int h5_serdev_probe(struct serdev_device *serdev)
if (!match) if (!match)
return -ENODEV; return -ENODEV;
h5->vnd = (const struct h5_vnd *)match->driver_data; data = (const struct h5_device_data *)match->driver_data;
h5->vnd = data->vnd;
h5->id = (char *)match->id; h5->id = (char *)match->id;
if (h5->vnd->acpi_gpio_map) if (h5->vnd->acpi_gpio_map)
devm_acpi_dev_add_driver_gpios(dev, devm_acpi_dev_add_driver_gpios(dev,
h5->vnd->acpi_gpio_map); h5->vnd->acpi_gpio_map);
} else { } else {
const void *data;
data = of_device_get_match_data(dev); data = of_device_get_match_data(dev);
if (!data) if (!data)
return -ENODEV; return -ENODEV;
h5->vnd = (const struct h5_vnd *)data; h5->vnd = data->vnd;
} }
...@@ -833,7 +856,14 @@ static int h5_serdev_probe(struct serdev_device *serdev) ...@@ -833,7 +856,14 @@ static int h5_serdev_probe(struct serdev_device *serdev)
if (IS_ERR(h5->device_wake_gpio)) if (IS_ERR(h5->device_wake_gpio))
return PTR_ERR(h5->device_wake_gpio); return PTR_ERR(h5->device_wake_gpio);
return hci_uart_register_device(&h5->serdev_hu, &h5p); err = hci_uart_register_device(&h5->serdev_hu, &h5p);
if (err)
return err;
if (data->driver_info & H5_INFO_WAKEUP_DISABLE)
set_bit(H5_WAKEUP_DISABLE, &h5->flags);
return 0;
} }
static void h5_serdev_remove(struct serdev_device *serdev) static void h5_serdev_remove(struct serdev_device *serdev)
...@@ -902,6 +932,9 @@ static int h5_btrtl_setup(struct h5 *h5) ...@@ -902,6 +932,9 @@ static int h5_btrtl_setup(struct h5 *h5)
serdev_device_set_baudrate(h5->hu->serdev, controller_baudrate); serdev_device_set_baudrate(h5->hu->serdev, controller_baudrate);
serdev_device_set_flow_control(h5->hu->serdev, flow_control); serdev_device_set_flow_control(h5->hu->serdev, flow_control);
if (flow_control)
set_bit(H5_HW_FLOW_CONTROL, &h5->flags);
err = btrtl_download_firmware(h5->hu->hdev, btrtl_dev); err = btrtl_download_firmware(h5->hu->hdev, btrtl_dev);
/* Give the device some time before the hci-core sends it a reset */ /* Give the device some time before the hci-core sends it a reset */
usleep_range(10000, 20000); usleep_range(10000, 20000);
...@@ -916,11 +949,25 @@ static int h5_btrtl_setup(struct h5 *h5) ...@@ -916,11 +949,25 @@ static int h5_btrtl_setup(struct h5 *h5)
static void h5_btrtl_open(struct h5 *h5) static void h5_btrtl_open(struct h5 *h5)
{ {
/*
* Since h5_btrtl_resume() does a device_reprobe() the suspend handling
* done by the hci_suspend_notifier is not necessary; it actually causes
* delays and a bunch of errors to get logged, so disable it.
*/
if (test_bit(H5_WAKEUP_DISABLE, &h5->flags))
set_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &h5->hu->flags);
/* Devices always start with these fixed parameters */ /* Devices always start with these fixed parameters */
serdev_device_set_flow_control(h5->hu->serdev, false); serdev_device_set_flow_control(h5->hu->serdev, false);
serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN); serdev_device_set_parity(h5->hu->serdev, SERDEV_PARITY_EVEN);
serdev_device_set_baudrate(h5->hu->serdev, 115200); serdev_device_set_baudrate(h5->hu->serdev, 115200);
pm_runtime_set_active(&h5->hu->serdev->dev);
pm_runtime_use_autosuspend(&h5->hu->serdev->dev);
pm_runtime_set_autosuspend_delay(&h5->hu->serdev->dev,
SUSPEND_TIMEOUT_MS);
pm_runtime_enable(&h5->hu->serdev->dev);
/* The controller needs up to 500ms to wakeup */ /* The controller needs up to 500ms to wakeup */
gpiod_set_value_cansleep(h5->enable_gpio, 1); gpiod_set_value_cansleep(h5->enable_gpio, 1);
gpiod_set_value_cansleep(h5->device_wake_gpio, 1); gpiod_set_value_cansleep(h5->device_wake_gpio, 1);
...@@ -929,21 +976,26 @@ static void h5_btrtl_open(struct h5 *h5) ...@@ -929,21 +976,26 @@ static void h5_btrtl_open(struct h5 *h5)
static void h5_btrtl_close(struct h5 *h5) static void h5_btrtl_close(struct h5 *h5)
{ {
pm_runtime_disable(&h5->hu->serdev->dev);
gpiod_set_value_cansleep(h5->device_wake_gpio, 0); gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
gpiod_set_value_cansleep(h5->enable_gpio, 0); gpiod_set_value_cansleep(h5->enable_gpio, 0);
} }
/* Suspend/resume support. On many devices the RTL BT device loses power during /* Suspend/resume support. On many devices the RTL BT device loses power during
* suspend/resume, causing it to lose its firmware and all state. So we simply * suspend/resume, causing it to lose its firmware and all state. So we simply
* turn it off on suspend and reprobe on resume. This mirrors how RTL devices * turn it off on suspend and reprobe on resume. This mirrors how RTL devices
* are handled in the USB driver, where the USB_QUIRK_RESET_RESUME is used which * are handled in the USB driver, where the BTUSB_WAKEUP_DISABLE is used which
* also causes a reprobe on resume. * also causes a reprobe on resume.
*/ */
static int h5_btrtl_suspend(struct h5 *h5) static int h5_btrtl_suspend(struct h5 *h5)
{ {
serdev_device_set_flow_control(h5->hu->serdev, false); serdev_device_set_flow_control(h5->hu->serdev, false);
gpiod_set_value_cansleep(h5->device_wake_gpio, 0); gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
gpiod_set_value_cansleep(h5->enable_gpio, 0);
if (test_bit(H5_WAKEUP_DISABLE, &h5->flags))
gpiod_set_value_cansleep(h5->enable_gpio, 0);
return 0; return 0;
} }
...@@ -969,17 +1021,25 @@ static void h5_btrtl_reprobe_worker(struct work_struct *work) ...@@ -969,17 +1021,25 @@ static void h5_btrtl_reprobe_worker(struct work_struct *work)
static int h5_btrtl_resume(struct h5 *h5) static int h5_btrtl_resume(struct h5 *h5)
{ {
struct h5_btrtl_reprobe *reprobe; if (test_bit(H5_WAKEUP_DISABLE, &h5->flags)) {
struct h5_btrtl_reprobe *reprobe;
reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL); reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL);
if (!reprobe) if (!reprobe)
return -ENOMEM; return -ENOMEM;
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
INIT_WORK(&reprobe->work, h5_btrtl_reprobe_worker);
reprobe->dev = get_device(&h5->hu->serdev->dev);
queue_work(system_long_wq, &reprobe->work);
} else {
gpiod_set_value_cansleep(h5->device_wake_gpio, 1);
if (test_bit(H5_HW_FLOW_CONTROL, &h5->flags))
serdev_device_set_flow_control(h5->hu->serdev, true);
}
INIT_WORK(&reprobe->work, h5_btrtl_reprobe_worker);
reprobe->dev = get_device(&h5->hu->serdev->dev);
queue_work(system_long_wq, &reprobe->work);
return 0; return 0;
} }
...@@ -1001,13 +1061,22 @@ static struct h5_vnd rtl_vnd = { ...@@ -1001,13 +1061,22 @@ static struct h5_vnd rtl_vnd = {
.resume = h5_btrtl_resume, .resume = h5_btrtl_resume,
.acpi_gpio_map = acpi_btrtl_gpios, .acpi_gpio_map = acpi_btrtl_gpios,
}; };
static const struct h5_device_data h5_data_rtl8822cs = {
.vnd = &rtl_vnd,
};
static const struct h5_device_data h5_data_rtl8723bs = {
.driver_info = H5_INFO_WAKEUP_DISABLE,
.vnd = &rtl_vnd,
};
#endif #endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id h5_acpi_match[] = { static const struct acpi_device_id h5_acpi_match[] = {
#ifdef CONFIG_BT_HCIUART_RTL #ifdef CONFIG_BT_HCIUART_RTL
{ "OBDA0623", (kernel_ulong_t)&rtl_vnd }, { "OBDA0623", (kernel_ulong_t)&h5_data_rtl8723bs },
{ "OBDA8723", (kernel_ulong_t)&rtl_vnd }, { "OBDA8723", (kernel_ulong_t)&h5_data_rtl8723bs },
#endif #endif
{ }, { },
}; };
...@@ -1016,16 +1085,17 @@ MODULE_DEVICE_TABLE(acpi, h5_acpi_match); ...@@ -1016,16 +1085,17 @@ MODULE_DEVICE_TABLE(acpi, h5_acpi_match);
static const struct dev_pm_ops h5_serdev_pm_ops = { static const struct dev_pm_ops h5_serdev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(h5_serdev_suspend, h5_serdev_resume) SET_SYSTEM_SLEEP_PM_OPS(h5_serdev_suspend, h5_serdev_resume)
SET_RUNTIME_PM_OPS(h5_serdev_suspend, h5_serdev_resume, NULL)
}; };
static const struct of_device_id rtl_bluetooth_of_match[] = { static const struct of_device_id rtl_bluetooth_of_match[] = {
#ifdef CONFIG_BT_HCIUART_RTL #ifdef CONFIG_BT_HCIUART_RTL
{ .compatible = "realtek,rtl8822cs-bt", { .compatible = "realtek,rtl8822cs-bt",
.data = (const void *)&rtl_vnd }, .data = (const void *)&h5_data_rtl8822cs },
{ .compatible = "realtek,rtl8723bs-bt", { .compatible = "realtek,rtl8723bs-bt",
.data = (const void *)&rtl_vnd }, .data = (const void *)&h5_data_rtl8723bs },
{ .compatible = "realtek,rtl8723ds-bt", { .compatible = "realtek,rtl8723ds-bt",
.data = (const void *)&rtl_vnd }, .data = (const void *)&h5_data_rtl8723bs },
#endif #endif
{ }, { },
}; };
......
...@@ -343,6 +343,9 @@ int hci_uart_register_device(struct hci_uart *hu, ...@@ -343,6 +343,9 @@ int hci_uart_register_device(struct hci_uart *hu,
hdev->setup = hci_uart_setup; hdev->setup = hci_uart_setup;
SET_HCIDEV_DEV(hdev, &hu->serdev->dev); SET_HCIDEV_DEV(hdev, &hu->serdev->dev);
if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags))
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
......
...@@ -86,9 +86,10 @@ struct hci_uart { ...@@ -86,9 +86,10 @@ struct hci_uart {
}; };
/* HCI_UART proto flag bits */ /* HCI_UART proto flag bits */
#define HCI_UART_PROTO_SET 0 #define HCI_UART_PROTO_SET 0
#define HCI_UART_REGISTERED 1 #define HCI_UART_REGISTERED 1
#define HCI_UART_PROTO_READY 2 #define HCI_UART_PROTO_READY 2
#define HCI_UART_NO_SUSPEND_NOTIFIER 3
/* TX states */ /* TX states */
#define HCI_UART_SENDING 1 #define HCI_UART_SENDING 1
......
...@@ -221,6 +221,7 @@ struct oob_data { ...@@ -221,6 +221,7 @@ struct oob_data {
struct adv_info { struct adv_info {
struct list_head list; struct list_head list;
bool enabled;
bool pending; bool pending;
__u8 instance; __u8 instance;
__u32 flags; __u32 flags;
...@@ -628,6 +629,7 @@ struct hci_conn { ...@@ -628,6 +629,7 @@ struct hci_conn {
__u8 init_addr_type; __u8 init_addr_type;
bdaddr_t resp_addr; bdaddr_t resp_addr;
__u8 resp_addr_type; __u8 resp_addr_type;
__u8 adv_instance;
__u16 handle; __u16 handle;
__u16 state; __u16 state;
__u8 mode; __u8 mode;
...@@ -1223,14 +1225,25 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) ...@@ -1223,14 +1225,25 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data)
dev_set_drvdata(&hdev->dev, data); dev_set_drvdata(&hdev->dev, data);
} }
static inline void *hci_get_priv(struct hci_dev *hdev)
{
return (char *)hdev + sizeof(*hdev);
}
struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_dev_get(int index);
struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, u8 src_type); struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, u8 src_type);
struct hci_dev *hci_alloc_dev(void); struct hci_dev *hci_alloc_dev_priv(int sizeof_priv);
static inline struct hci_dev *hci_alloc_dev(void)
{
return hci_alloc_dev_priv(0);
}
void hci_free_dev(struct hci_dev *hdev); void hci_free_dev(struct hci_dev *hdev);
int hci_register_dev(struct hci_dev *hdev); int hci_register_dev(struct hci_dev *hdev);
void hci_unregister_dev(struct hci_dev *hdev); void hci_unregister_dev(struct hci_dev *hdev);
void hci_cleanup_dev(struct hci_dev *hdev); void hci_release_dev(struct hci_dev *hdev);
int hci_suspend_dev(struct hci_dev *hdev); int hci_suspend_dev(struct hci_dev *hdev);
int hci_resume_dev(struct hci_dev *hdev); int hci_resume_dev(struct hci_dev *hdev);
int hci_reset_dev(struct hci_dev *hdev); int hci_reset_dev(struct hci_dev *hdev);
...@@ -1412,6 +1425,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ...@@ -1412,6 +1425,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
!hci_dev_test_flag(dev, HCI_AUTO_OFF)) !hci_dev_test_flag(dev, HCI_AUTO_OFF))
#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \ #define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \
hci_dev_test_flag(dev, HCI_SC_ENABLED)) hci_dev_test_flag(dev, HCI_SC_ENABLED))
#define rpa_valid(dev) (bacmp(&dev->rpa, BDADDR_ANY) && \
!hci_dev_test_flag(dev, HCI_RPA_EXPIRED))
#define adv_rpa_valid(adv) (bacmp(&adv->random_addr, BDADDR_ANY) && \
!adv->rpa_expired)
#define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \ #define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \
((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M)) ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M))
......
...@@ -170,7 +170,8 @@ static void lowpan_dev_debugfs_ctx_init(struct net_device *dev, ...@@ -170,7 +170,8 @@ static void lowpan_dev_debugfs_ctx_init(struct net_device *dev,
struct dentry *root; struct dentry *root;
char buf[32]; char buf[32];
WARN_ON_ONCE(id > LOWPAN_IPHC_CTX_TABLE_SIZE); if (WARN_ON_ONCE(id >= LOWPAN_IPHC_CTX_TABLE_SIZE))
return;
sprintf(buf, "%d", id); sprintf(buf, "%d", id);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#define BTNAMSIZ 18 #define BTNAMSIZ 21
/* CMTP ioctl defines */ /* CMTP ioctl defines */
#define CMTPCONNADD _IOW('C', 200, int) #define CMTPCONNADD _IOW('C', 200, int)
......
...@@ -1343,6 +1343,12 @@ int hci_inquiry(void __user *arg) ...@@ -1343,6 +1343,12 @@ int hci_inquiry(void __user *arg)
goto done; goto done;
} }
/* Restrict maximum inquiry length to 60 seconds */
if (ir.length > 60) {
err = -EINVAL;
goto done;
}
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
...@@ -1718,6 +1724,7 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) ...@@ -1718,6 +1724,7 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
int hci_dev_do_close(struct hci_dev *hdev) int hci_dev_do_close(struct hci_dev *hdev)
{ {
bool auto_off; bool auto_off;
int err = 0;
BT_DBG("%s %p", hdev->name, hdev); BT_DBG("%s %p", hdev->name, hdev);
...@@ -1727,10 +1734,18 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1727,10 +1734,18 @@ int hci_dev_do_close(struct hci_dev *hdev)
hci_request_cancel_all(hdev); hci_request_cancel_all(hdev);
hci_req_sync_lock(hdev); hci_req_sync_lock(hdev);
if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
test_bit(HCI_UP, &hdev->flags)) {
/* Execute vendor specific shutdown routine */
if (hdev->shutdown)
err = hdev->shutdown(hdev);
}
if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
cancel_delayed_work_sync(&hdev->cmd_timer); cancel_delayed_work_sync(&hdev->cmd_timer);
hci_req_sync_unlock(hdev); hci_req_sync_unlock(hdev);
return 0; return err;
} }
hci_leds_update_powered(hdev, false); hci_leds_update_powered(hdev, false);
...@@ -1798,14 +1813,6 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1798,14 +1813,6 @@ int hci_dev_do_close(struct hci_dev *hdev)
clear_bit(HCI_INIT, &hdev->flags); clear_bit(HCI_INIT, &hdev->flags);
} }
if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
test_bit(HCI_UP, &hdev->flags)) {
/* Execute vendor specific shutdown routine */
if (hdev->shutdown)
hdev->shutdown(hdev);
}
/* flush cmd work */ /* flush cmd work */
flush_work(&hdev->cmd_work); flush_work(&hdev->cmd_work);
...@@ -1845,7 +1852,7 @@ int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1845,7 +1852,7 @@ int hci_dev_do_close(struct hci_dev *hdev)
hci_req_sync_unlock(hdev); hci_req_sync_unlock(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
return 0; return err;
} }
int hci_dev_close(__u16 dev) int hci_dev_close(__u16 dev)
...@@ -3751,11 +3758,18 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action, ...@@ -3751,11 +3758,18 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
} }
/* Alloc HCI device */ /* Alloc HCI device */
struct hci_dev *hci_alloc_dev(void) struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
{ {
struct hci_dev *hdev; struct hci_dev *hdev;
unsigned int alloc_size;
alloc_size = sizeof(*hdev);
if (sizeof_priv) {
/* Fixme: May need ALIGN-ment? */
alloc_size += sizeof_priv;
}
hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); hdev = kzalloc(alloc_size, GFP_KERNEL);
if (!hdev) if (!hdev)
return NULL; return NULL;
...@@ -3869,7 +3883,7 @@ struct hci_dev *hci_alloc_dev(void) ...@@ -3869,7 +3883,7 @@ struct hci_dev *hci_alloc_dev(void)
return hdev; return hdev;
} }
EXPORT_SYMBOL(hci_alloc_dev); EXPORT_SYMBOL(hci_alloc_dev_priv);
/* Free HCI device */ /* Free HCI device */
void hci_free_dev(struct hci_dev *hdev) void hci_free_dev(struct hci_dev *hdev)
...@@ -4034,13 +4048,13 @@ void hci_unregister_dev(struct hci_dev *hdev) ...@@ -4034,13 +4048,13 @@ void hci_unregister_dev(struct hci_dev *hdev)
} }
device_del(&hdev->dev); device_del(&hdev->dev);
/* Actual cleanup is deferred until hci_cleanup_dev(). */ /* Actual cleanup is deferred until hci_release_dev(). */
hci_dev_put(hdev); hci_dev_put(hdev);
} }
EXPORT_SYMBOL(hci_unregister_dev); EXPORT_SYMBOL(hci_unregister_dev);
/* Cleanup HCI device */ /* Release HCI device */
void hci_cleanup_dev(struct hci_dev *hdev) void hci_release_dev(struct hci_dev *hdev)
{ {
debugfs_remove_recursive(hdev->debugfs); debugfs_remove_recursive(hdev->debugfs);
kfree_const(hdev->hw_info); kfree_const(hdev->hw_info);
...@@ -4067,7 +4081,9 @@ void hci_cleanup_dev(struct hci_dev *hdev) ...@@ -4067,7 +4081,9 @@ void hci_cleanup_dev(struct hci_dev *hdev)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
ida_simple_remove(&hci_index_ida, hdev->id); ida_simple_remove(&hci_index_ida, hdev->id);
kfree(hdev);
} }
EXPORT_SYMBOL(hci_release_dev);
/* Suspend HCI device */ /* Suspend HCI device */
int hci_suspend_dev(struct hci_dev *hdev) int hci_suspend_dev(struct hci_dev *hdev)
......
This diff is collapsed.
...@@ -2072,8 +2072,6 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, ...@@ -2072,8 +2072,6 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
* current RPA has expired then generate a new one. * current RPA has expired then generate a new one.
*/ */
if (use_rpa) { if (use_rpa) {
int to;
/* If Controller supports LL Privacy use own address type is /* If Controller supports LL Privacy use own address type is
* 0x03 * 0x03
*/ */
...@@ -2084,14 +2082,10 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, ...@@ -2084,14 +2082,10 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
*own_addr_type = ADDR_LE_DEV_RANDOM; *own_addr_type = ADDR_LE_DEV_RANDOM;
if (adv_instance) { if (adv_instance) {
if (!adv_instance->rpa_expired && if (adv_rpa_valid(adv_instance))
!bacmp(&adv_instance->random_addr, &hdev->rpa))
return 0; return 0;
adv_instance->rpa_expired = false;
} else { } else {
if (!hci_dev_test_and_clear_flag(hdev, HCI_RPA_EXPIRED) && if (rpa_valid(hdev))
!bacmp(&hdev->random_addr, &hdev->rpa))
return 0; return 0;
} }
...@@ -2103,14 +2097,6 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, ...@@ -2103,14 +2097,6 @@ int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
bacpy(rand_addr, &hdev->rpa); bacpy(rand_addr, &hdev->rpa);
to = msecs_to_jiffies(hdev->rpa_timeout * 1000);
if (adv_instance)
queue_delayed_work(hdev->workqueue,
&adv_instance->rpa_expired_cb, to);
else
queue_delayed_work(hdev->workqueue,
&hdev->rpa_expired, to);
return 0; return 0;
} }
...@@ -2153,6 +2139,30 @@ void __hci_req_clear_ext_adv_sets(struct hci_request *req) ...@@ -2153,6 +2139,30 @@ void __hci_req_clear_ext_adv_sets(struct hci_request *req)
hci_req_add(req, HCI_OP_LE_CLEAR_ADV_SETS, 0, NULL); hci_req_add(req, HCI_OP_LE_CLEAR_ADV_SETS, 0, NULL);
} }
static void set_random_addr(struct hci_request *req, bdaddr_t *rpa)
{
struct hci_dev *hdev = req->hdev;
/* If we're advertising or initiating an LE connection we can't
* go ahead and change the random address at this time. This is
* because the eventual initiator address used for the
* subsequently created connection will be undefined (some
* controllers use the new address and others the one we had
* when the operation started).
*
* In this kind of scenario skip the update and let the random
* address be updated at the next cycle.
*/
if (hci_dev_test_flag(hdev, HCI_LE_ADV) ||
hci_lookup_le_connect(hdev)) {
bt_dev_dbg(hdev, "Deferring random address update");
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
return;
}
hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, rpa);
}
int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance) int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
{ {
struct hci_cp_le_set_ext_adv_params cp; struct hci_cp_le_set_ext_adv_params cp;
...@@ -2255,6 +2265,13 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance) ...@@ -2255,6 +2265,13 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
} else { } else {
if (!bacmp(&random_addr, &hdev->random_addr)) if (!bacmp(&random_addr, &hdev->random_addr))
return 0; return 0;
/* Instance 0x00 doesn't have an adv_info, instead it
* uses hdev->random_addr to track its address so
* whenever it needs to be updated this also set the
* random address since hdev->random_addr is shared with
* scan state machine.
*/
set_random_addr(req, &random_addr);
} }
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
...@@ -2512,30 +2529,6 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk, ...@@ -2512,30 +2529,6 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
false); false);
} }
static void set_random_addr(struct hci_request *req, bdaddr_t *rpa)
{
struct hci_dev *hdev = req->hdev;
/* If we're advertising or initiating an LE connection we can't
* go ahead and change the random address at this time. This is
* because the eventual initiator address used for the
* subsequently created connection will be undefined (some
* controllers use the new address and others the one we had
* when the operation started).
*
* In this kind of scenario skip the update and let the random
* address be updated at the next cycle.
*/
if (hci_dev_test_flag(hdev, HCI_LE_ADV) ||
hci_lookup_le_connect(hdev)) {
bt_dev_dbg(hdev, "Deferring random address update");
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
return;
}
hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, rpa);
}
int hci_update_random_address(struct hci_request *req, bool require_privacy, int hci_update_random_address(struct hci_request *req, bool require_privacy,
bool use_rpa, u8 *own_addr_type) bool use_rpa, u8 *own_addr_type)
{ {
...@@ -2547,8 +2540,6 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, ...@@ -2547,8 +2540,6 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
* the current RPA in use, then generate a new one. * the current RPA in use, then generate a new one.
*/ */
if (use_rpa) { if (use_rpa) {
int to;
/* If Controller supports LL Privacy use own address type is /* If Controller supports LL Privacy use own address type is
* 0x03 * 0x03
*/ */
...@@ -2558,8 +2549,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, ...@@ -2558,8 +2549,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
else else
*own_addr_type = ADDR_LE_DEV_RANDOM; *own_addr_type = ADDR_LE_DEV_RANDOM;
if (!hci_dev_test_and_clear_flag(hdev, HCI_RPA_EXPIRED) && if (rpa_valid(hdev))
!bacmp(&hdev->random_addr, &hdev->rpa))
return 0; return 0;
err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa); err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
...@@ -2570,9 +2560,6 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, ...@@ -2570,9 +2560,6 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
set_random_addr(req, &hdev->rpa); set_random_addr(req, &hdev->rpa);
to = msecs_to_jiffies(hdev->rpa_timeout * 1000);
queue_delayed_work(hdev->workqueue, &hdev->rpa_expired, to);
return 0; return 0;
} }
......
...@@ -85,8 +85,7 @@ static void bt_host_release(struct device *dev) ...@@ -85,8 +85,7 @@ static void bt_host_release(struct device *dev)
struct hci_dev *hdev = to_hci_dev(dev); struct hci_dev *hdev = to_hci_dev(dev);
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
hci_cleanup_dev(hdev); hci_release_dev(hdev);
kfree(hdev);
module_put(THIS_MODULE); module_put(THIS_MODULE);
} }
......
...@@ -7204,7 +7204,7 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status, ...@@ -7204,7 +7204,7 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
if (!mgmt_rp) if (!mgmt_rp)
goto done; goto done;
if (status) if (eir_len == 0)
goto send_rsp; goto send_rsp;
eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV, eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
...@@ -7725,7 +7725,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, ...@@ -7725,7 +7725,7 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev,
* advertising. * advertising.
*/ */
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY)) if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_NOT_SUPPORTED); MGMT_STATUS_NOT_SUPPORTED);
if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets) if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets)
......
...@@ -70,7 +70,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) ...@@ -70,7 +70,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
BT_DBG("dlc %p state %ld err %d", d, d->state, err); BT_DBG("dlc %p state %ld err %d", d, d->state, err);
spin_lock_bh(&sk->sk_lock.slock); lock_sock(sk);
if (err) if (err)
sk->sk_err = err; sk->sk_err = err;
...@@ -91,7 +91,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) ...@@ -91,7 +91,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
sk->sk_state_change(sk); sk->sk_state_change(sk);
} }
spin_unlock_bh(&sk->sk_lock.slock); release_sock(sk);
if (parent && sock_flag(sk, SOCK_ZAPPED)) { if (parent && sock_flag(sk, SOCK_ZAPPED)) {
/* We have to drop DLC lock here, otherwise /* We have to drop DLC lock here, otherwise
...@@ -974,7 +974,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * ...@@ -974,7 +974,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
if (!parent) if (!parent)
return 0; return 0;
bh_lock_sock(parent); lock_sock(parent);
/* Check for backlog size */ /* Check for backlog size */
if (sk_acceptq_is_full(parent)) { if (sk_acceptq_is_full(parent)) {
...@@ -1001,7 +1001,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * ...@@ -1001,7 +1001,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
result = 1; result = 1;
done: done:
bh_unlock_sock(parent); release_sock(parent);
if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
parent->sk_state_change(parent); parent->sk_state_change(parent);
......
...@@ -48,6 +48,8 @@ struct sco_conn { ...@@ -48,6 +48,8 @@ struct sco_conn {
spinlock_t lock; spinlock_t lock;
struct sock *sk; struct sock *sk;
struct delayed_work timeout_work;
unsigned int mtu; unsigned int mtu;
}; };
...@@ -74,31 +76,47 @@ struct sco_pinfo { ...@@ -74,31 +76,47 @@ struct sco_pinfo {
#define SCO_CONN_TIMEOUT (HZ * 40) #define SCO_CONN_TIMEOUT (HZ * 40)
#define SCO_DISCONN_TIMEOUT (HZ * 2) #define SCO_DISCONN_TIMEOUT (HZ * 2)
static void sco_sock_timeout(struct timer_list *t) static void sco_sock_timeout(struct work_struct *work)
{ {
struct sock *sk = from_timer(sk, t, sk_timer); struct sco_conn *conn = container_of(work, struct sco_conn,
timeout_work.work);
struct sock *sk;
sco_conn_lock(conn);
sk = conn->sk;
if (sk)
sock_hold(sk);
sco_conn_unlock(conn);
if (!sk)
return;
BT_DBG("sock %p state %d", sk, sk->sk_state); BT_DBG("sock %p state %d", sk, sk->sk_state);
bh_lock_sock(sk); lock_sock(sk);
sk->sk_err = ETIMEDOUT; sk->sk_err = ETIMEDOUT;
sk->sk_state_change(sk); sk->sk_state_change(sk);
bh_unlock_sock(sk); release_sock(sk);
sco_sock_kill(sk);
sock_put(sk); sock_put(sk);
} }
static void sco_sock_set_timer(struct sock *sk, long timeout) static void sco_sock_set_timer(struct sock *sk, long timeout)
{ {
if (!sco_pi(sk)->conn)
return;
BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout); BT_DBG("sock %p state %d timeout %ld", sk, sk->sk_state, timeout);
sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); cancel_delayed_work(&sco_pi(sk)->conn->timeout_work);
schedule_delayed_work(&sco_pi(sk)->conn->timeout_work, timeout);
} }
static void sco_sock_clear_timer(struct sock *sk) static void sco_sock_clear_timer(struct sock *sk)
{ {
if (!sco_pi(sk)->conn)
return;
BT_DBG("sock %p state %d", sk, sk->sk_state); BT_DBG("sock %p state %d", sk, sk->sk_state);
sk_stop_timer(sk, &sk->sk_timer); cancel_delayed_work(&sco_pi(sk)->conn->timeout_work);
} }
/* ---- SCO connections ---- */ /* ---- SCO connections ---- */
...@@ -173,12 +191,14 @@ static void sco_conn_del(struct hci_conn *hcon, int err) ...@@ -173,12 +191,14 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
if (sk) { if (sk) {
sock_hold(sk); sock_hold(sk);
bh_lock_sock(sk); lock_sock(sk);
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
sco_chan_del(sk, err); sco_chan_del(sk, err);
bh_unlock_sock(sk); release_sock(sk);
sco_sock_kill(sk);
sock_put(sk); sock_put(sk);
/* Ensure no more work items will run before freeing conn. */
cancel_delayed_work_sync(&conn->timeout_work);
} }
hcon->sco_data = NULL; hcon->sco_data = NULL;
...@@ -193,6 +213,8 @@ static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, ...@@ -193,6 +213,8 @@ static void __sco_chan_add(struct sco_conn *conn, struct sock *sk,
sco_pi(sk)->conn = conn; sco_pi(sk)->conn = conn;
conn->sk = sk; conn->sk = sk;
INIT_DELAYED_WORK(&conn->timeout_work, sco_sock_timeout);
if (parent) if (parent)
bt_accept_enqueue(parent, sk, true); bt_accept_enqueue(parent, sk, true);
} }
...@@ -212,44 +234,32 @@ static int sco_chan_add(struct sco_conn *conn, struct sock *sk, ...@@ -212,44 +234,32 @@ static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
return err; return err;
} }
static int sco_connect(struct sock *sk) static int sco_connect(struct hci_dev *hdev, struct sock *sk)
{ {
struct sco_conn *conn; struct sco_conn *conn;
struct hci_conn *hcon; struct hci_conn *hcon;
struct hci_dev *hdev;
int err, type; int err, type;
BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst); BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
if (!hdev)
return -EHOSTUNREACH;
hci_dev_lock(hdev);
if (lmp_esco_capable(hdev) && !disable_esco) if (lmp_esco_capable(hdev) && !disable_esco)
type = ESCO_LINK; type = ESCO_LINK;
else else
type = SCO_LINK; type = SCO_LINK;
if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT && if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
(!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) { (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)))
err = -EOPNOTSUPP; return -EOPNOTSUPP;
goto done;
}
hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst, hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
sco_pi(sk)->setting); sco_pi(sk)->setting);
if (IS_ERR(hcon)) { if (IS_ERR(hcon))
err = PTR_ERR(hcon); return PTR_ERR(hcon);
goto done;
}
conn = sco_conn_add(hcon); conn = sco_conn_add(hcon);
if (!conn) { if (!conn) {
hci_conn_drop(hcon); hci_conn_drop(hcon);
err = -ENOMEM; return -ENOMEM;
goto done;
} }
/* Update source addr of the socket */ /* Update source addr of the socket */
...@@ -257,7 +267,7 @@ static int sco_connect(struct sock *sk) ...@@ -257,7 +267,7 @@ static int sco_connect(struct sock *sk)
err = sco_chan_add(conn, sk, NULL); err = sco_chan_add(conn, sk, NULL);
if (err) if (err)
goto done; return err;
if (hcon->state == BT_CONNECTED) { if (hcon->state == BT_CONNECTED) {
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
...@@ -267,9 +277,6 @@ static int sco_connect(struct sock *sk) ...@@ -267,9 +277,6 @@ static int sco_connect(struct sock *sk)
sco_sock_set_timer(sk, sk->sk_sndtimeo); sco_sock_set_timer(sk, sk->sk_sndtimeo);
} }
done:
hci_dev_unlock(hdev);
hci_dev_put(hdev);
return err; return err;
} }
...@@ -394,8 +401,7 @@ static void sco_sock_cleanup_listen(struct sock *parent) ...@@ -394,8 +401,7 @@ static void sco_sock_cleanup_listen(struct sock *parent)
*/ */
static void sco_sock_kill(struct sock *sk) static void sco_sock_kill(struct sock *sk)
{ {
if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket || if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
sock_flag(sk, SOCK_DEAD))
return; return;
BT_DBG("sk %p state %d", sk, sk->sk_state); BT_DBG("sk %p state %d", sk, sk->sk_state);
...@@ -443,11 +449,10 @@ static void __sco_sock_close(struct sock *sk) ...@@ -443,11 +449,10 @@ static void __sco_sock_close(struct sock *sk)
/* Must be called on unlocked socket. */ /* Must be called on unlocked socket. */
static void sco_sock_close(struct sock *sk) static void sco_sock_close(struct sock *sk)
{ {
sco_sock_clear_timer(sk);
lock_sock(sk); lock_sock(sk);
sco_sock_clear_timer(sk);
__sco_sock_close(sk); __sco_sock_close(sk);
release_sock(sk); release_sock(sk);
sco_sock_kill(sk);
} }
static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg, static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg,
...@@ -500,8 +505,6 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, ...@@ -500,8 +505,6 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock,
sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT; sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
timer_setup(&sk->sk_timer, sco_sock_timeout, 0);
bt_sock_link(&sco_sk_list, sk); bt_sock_link(&sco_sk_list, sk);
return sk; return sk;
} }
...@@ -566,6 +569,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen ...@@ -566,6 +569,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
{ {
struct sockaddr_sco *sa = (struct sockaddr_sco *) addr; struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct hci_dev *hdev;
int err; int err;
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
...@@ -580,12 +584,19 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen ...@@ -580,12 +584,19 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
if (sk->sk_type != SOCK_SEQPACKET) if (sk->sk_type != SOCK_SEQPACKET)
return -EINVAL; return -EINVAL;
hdev = hci_get_route(&sa->sco_bdaddr, &sco_pi(sk)->src, BDADDR_BREDR);
if (!hdev)
return -EHOSTUNREACH;
hci_dev_lock(hdev);
lock_sock(sk); lock_sock(sk);
/* Set destination address and psm */ /* Set destination address and psm */
bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr); bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
err = sco_connect(sk); err = sco_connect(hdev, sk);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
if (err) if (err)
goto done; goto done;
...@@ -773,6 +784,11 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) ...@@ -773,6 +784,11 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting)
cp.max_latency = cpu_to_le16(0xffff); cp.max_latency = cpu_to_le16(0xffff);
cp.retrans_effort = 0xff; cp.retrans_effort = 0xff;
break; break;
default:
/* use CVSD settings as fallback */
cp.max_latency = cpu_to_le16(0xffff);
cp.retrans_effort = 0xff;
break;
} }
hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
...@@ -1083,11 +1099,11 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -1083,11 +1099,11 @@ static void sco_conn_ready(struct sco_conn *conn)
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
if (sk) { if (sk) {
lock_sock(sk);
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
bh_lock_sock(sk);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
sk->sk_state_change(sk); sk->sk_state_change(sk);
bh_unlock_sock(sk); release_sock(sk);
} else { } else {
sco_conn_lock(conn); sco_conn_lock(conn);
...@@ -1102,12 +1118,12 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -1102,12 +1118,12 @@ static void sco_conn_ready(struct sco_conn *conn)
return; return;
} }
bh_lock_sock(parent); lock_sock(parent);
sk = sco_sock_alloc(sock_net(parent), NULL, sk = sco_sock_alloc(sock_net(parent), NULL,
BTPROTO_SCO, GFP_ATOMIC, 0); BTPROTO_SCO, GFP_ATOMIC, 0);
if (!sk) { if (!sk) {
bh_unlock_sock(parent); release_sock(parent);
sco_conn_unlock(conn); sco_conn_unlock(conn);
return; return;
} }
...@@ -1128,7 +1144,7 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -1128,7 +1144,7 @@ static void sco_conn_ready(struct sco_conn *conn)
/* Wake up parent */ /* Wake up parent */
parent->sk_data_ready(parent); parent->sk_data_ready(parent);
bh_unlock_sock(parent); release_sock(parent);
sco_conn_unlock(conn); sco_conn_unlock(conn);
} }
......
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