Commit f7623d34 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 2019-07-07

Here's the main bluetooth-next pull request for 5.3:

 - Added support for new devices from Qualcomm, Realtek and Broadcom and
   MediaTek
 - Various fixes to 6LoWPAN
 - Fix L2CAP PSM namespace separation for LE & BR/EDR
 - Fix behavior with Microsoft Surface Precision Mouse
 - Added support for LE Ping feature
 - Fix L2CAP Disconnect response handling if received in wrong state

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 437fde6c 9ce67c32
Marvell Bluetooth Chips
-----------------------
This documents the binding structure and common properties for serial
attached Marvell Bluetooth devices. The following chips are included in
this binding:
* Marvell 88W8897 Bluetooth devices
Required properties:
- compatible: should be:
"mrvl,88w8897"
Optional properties:
None so far
Example:
&serial0 {
compatible = "ns16550a";
...
bluetooth {
compatible = "mrvl,88w8897";
};
};
...@@ -50,16 +50,33 @@ Required properties: ...@@ -50,16 +50,33 @@ Required properties:
"mediatek,mt7663u-bluetooth": for MT7663U device "mediatek,mt7663u-bluetooth": for MT7663U device
"mediatek,mt7668u-bluetooth": for MT7668U device "mediatek,mt7668u-bluetooth": for MT7668U device
- vcc-supply: Main voltage regulator - vcc-supply: Main voltage regulator
If the pin controller on the platform can support both pinmux and GPIO
control such as the most of MediaTek platform. Please use below properties.
- pinctrl-names: Should be "default", "runtime" - pinctrl-names: Should be "default", "runtime"
- pinctrl-0: Should contain UART RXD low when the device is powered up to - pinctrl-0: Should contain UART RXD low when the device is powered up to
enter proper bootstrap mode. enter proper bootstrap mode.
- pinctrl-1: Should contain UART mode pin ctrl - pinctrl-1: Should contain UART mode pin ctrl
Else, the pin controller on the platform only can support pinmux control and
the GPIO control still has to rely on the dedicated GPIO controller such as
a legacy MediaTek SoC, MT7621. Please use the below properties.
- boot-gpios: GPIO same to the pin as UART RXD and used to keep LOW when
the device is powered up to enter proper bootstrap mode when
- pinctrl-names: Should be "default"
- pinctrl-0: Should contain UART mode pin ctrl
Optional properties: Optional properties:
- reset-gpios: GPIO used to reset the device whose initial state keeps low, - reset-gpios: GPIO used to reset the device whose initial state keeps low,
if the GPIO is missing, then board-level design should be if the GPIO is missing, then board-level design should be
guaranteed. guaranteed.
- clocks: Should be the clock specifiers corresponding to the entry in
clock-names property. If the clock is missing, then board-level
design should be guaranteed.
- clock-names: Should contain "osc" entry for the external oscillator.
- current-speed: Current baud rate of the device whose defaults to 921600 - current-speed: Current baud rate of the device whose defaults to 921600
Example: Example:
......
...@@ -17,6 +17,7 @@ Optional properties for compatible string qcom,qca6174-bt: ...@@ -17,6 +17,7 @@ Optional properties for compatible string qcom,qca6174-bt:
- enable-gpios: gpio specifier used to enable chip - enable-gpios: gpio specifier used to enable chip
- clocks: clock provided to the controller (SUSCLK_32KHZ) - clocks: clock provided to the controller (SUSCLK_32KHZ)
- firmware-name: specify the name of nvm firmware to load
Required properties for compatible string qcom,wcn399x-bt: Required properties for compatible string qcom,wcn399x-bt:
...@@ -28,6 +29,7 @@ Required properties for compatible string qcom,wcn399x-bt: ...@@ -28,6 +29,7 @@ Required properties for compatible string qcom,wcn399x-bt:
Optional properties for compatible string qcom,wcn399x-bt: Optional properties for compatible string qcom,wcn399x-bt:
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt - max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
- firmware-name: specify the name of nvm firmware to load
Examples: Examples:
...@@ -40,6 +42,7 @@ serial@7570000 { ...@@ -40,6 +42,7 @@ serial@7570000 {
enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>; enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>;
clocks = <&divclk4>; clocks = <&divclk4>;
firmware-name = "nvm_00440302.bin";
}; };
}; };
...@@ -52,5 +55,6 @@ serial@898000 { ...@@ -52,5 +55,6 @@ serial@898000 {
vddrf-supply = <&vreg_l17a_1p3>; vddrf-supply = <&vreg_l17a_1p3>;
vddch0-supply = <&vreg_l25a_3p3>; vddch0-supply = <&vreg_l25a_3p3>;
max-speed = <3200000>; max-speed = <3200000>;
firmware-name = "crnv21.bin";
}; };
}; };
...@@ -52,6 +52,17 @@ config BT_HCIBTUSB_BCM ...@@ -52,6 +52,17 @@ config BT_HCIBTUSB_BCM
Say Y here to compile support for Broadcom protocol. Say Y here to compile support for Broadcom protocol.
config BT_HCIBTUSB_MTK
bool "MediaTek protocol support"
depends on BT_HCIBTUSB
default n
help
The MediaTek protocol support enables firmware download
support and chip initialization for MediaTek Bluetooth
USB controllers.
Say Y here to compile support for MediaTek protocol.
config BT_HCIBTUSB_RTL config BT_HCIBTUSB_RTL
bool "Realtek protocol support" bool "Realtek protocol support"
depends on BT_HCIBTUSB depends on BT_HCIBTUSB
...@@ -237,6 +248,7 @@ config BT_HCIUART_AG6XX ...@@ -237,6 +248,7 @@ config BT_HCIUART_AG6XX
config BT_HCIUART_MRVL config BT_HCIUART_MRVL
bool "Marvell protocol support" bool "Marvell protocol support"
depends on BT_HCIUART depends on BT_HCIUART
depends on BT_HCIUART_SERDEV
select BT_HCIUART_H4 select BT_HCIUART_H4
help help
Marvell is serial protocol for communication between Bluetooth Marvell is serial protocol for communication between Bluetooth
......
...@@ -359,7 +359,8 @@ static int bpa10x_set_diag(struct hci_dev *hdev, bool enable) ...@@ -359,7 +359,8 @@ static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
return 0; return 0;
} }
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id) static int bpa10x_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{ {
struct bpa10x_data *data; struct bpa10x_data *data;
struct hci_dev *hdev; struct hci_dev *hdev;
......
...@@ -335,6 +335,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { ...@@ -335,6 +335,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */
{ 0x4217, "BCM4329B1" }, /* 002.002.023 */ { 0x4217, "BCM4329B1" }, /* 002.002.023 */
{ 0x6106, "BCM4359C0" }, /* 003.001.006 */
{ } { }
}; };
......
...@@ -115,10 +115,12 @@ struct btmtk_hci_wmt_params { ...@@ -115,10 +115,12 @@ struct btmtk_hci_wmt_params {
struct btmtkuart_dev { struct btmtkuart_dev {
struct hci_dev *hdev; struct hci_dev *hdev;
struct serdev_device *serdev; struct serdev_device *serdev;
struct clk *clk;
struct clk *clk;
struct clk *osc;
struct regulator *vcc; struct regulator *vcc;
struct gpio_desc *reset; struct gpio_desc *reset;
struct gpio_desc *boot;
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
struct pinctrl_state *pins_runtime; struct pinctrl_state *pins_runtime;
struct pinctrl_state *pins_boot; struct pinctrl_state *pins_boot;
...@@ -911,6 +913,19 @@ static int btmtkuart_parse_dt(struct serdev_device *serdev) ...@@ -911,6 +913,19 @@ static int btmtkuart_parse_dt(struct serdev_device *serdev)
return err; return err;
} }
bdev->osc = devm_clk_get_optional(&serdev->dev, "osc");
if (IS_ERR(bdev->osc)) {
err = PTR_ERR(bdev->osc);
return err;
}
bdev->boot = devm_gpiod_get_optional(&serdev->dev, "boot",
GPIOD_OUT_LOW);
if (IS_ERR(bdev->boot)) {
err = PTR_ERR(bdev->boot);
return err;
}
bdev->pinctrl = devm_pinctrl_get(&serdev->dev); bdev->pinctrl = devm_pinctrl_get(&serdev->dev);
if (IS_ERR(bdev->pinctrl)) { if (IS_ERR(bdev->pinctrl)) {
err = PTR_ERR(bdev->pinctrl); err = PTR_ERR(bdev->pinctrl);
...@@ -919,8 +934,10 @@ static int btmtkuart_parse_dt(struct serdev_device *serdev) ...@@ -919,8 +934,10 @@ static int btmtkuart_parse_dt(struct serdev_device *serdev)
bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl, bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl,
"default"); "default");
if (IS_ERR(bdev->pins_boot)) { if (IS_ERR(bdev->pins_boot) && !bdev->boot) {
err = PTR_ERR(bdev->pins_boot); err = PTR_ERR(bdev->pins_boot);
dev_err(&serdev->dev,
"Should assign RXD to LOW at boot stage\n");
return err; return err;
} }
...@@ -996,13 +1013,25 @@ static int btmtkuart_probe(struct serdev_device *serdev) ...@@ -996,13 +1013,25 @@ static int btmtkuart_probe(struct serdev_device *serdev)
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
if (btmtkuart_is_standalone(bdev)) { if (btmtkuart_is_standalone(bdev)) {
/* Switch to the specific pin state for the booting requires */ err = clk_prepare_enable(bdev->osc);
pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); if (err < 0)
return err;
if (bdev->boot) {
gpiod_set_value_cansleep(bdev->boot, 1);
} else {
/* Switch to the specific pin state for the booting
* requires.
*/
pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
}
/* Power on */ /* Power on */
err = regulator_enable(bdev->vcc); err = regulator_enable(bdev->vcc);
if (err < 0) if (err < 0) {
clk_disable_unprepare(bdev->osc);
return err; return err;
}
/* Reset if the reset-gpios is available otherwise the board /* Reset if the reset-gpios is available otherwise the board
* -level design should be guaranteed. * -level design should be guaranteed.
...@@ -1017,6 +1046,10 @@ static int btmtkuart_probe(struct serdev_device *serdev) ...@@ -1017,6 +1046,10 @@ static int btmtkuart_probe(struct serdev_device *serdev)
* mode the device requires for UART transfers. * mode the device requires for UART transfers.
*/ */
msleep(50); msleep(50);
if (bdev->boot)
devm_gpiod_put(&serdev->dev, bdev->boot);
pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime); pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime);
/* A standalone device doesn't depends on power domain on SoC, /* A standalone device doesn't depends on power domain on SoC,
...@@ -1037,10 +1070,8 @@ static int btmtkuart_probe(struct serdev_device *serdev) ...@@ -1037,10 +1070,8 @@ static int btmtkuart_probe(struct serdev_device *serdev)
return 0; return 0;
err_regulator_disable: err_regulator_disable:
if (btmtkuart_is_standalone(bdev)) { if (btmtkuart_is_standalone(bdev))
pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
regulator_disable(bdev->vcc); regulator_disable(bdev->vcc);
}
return err; return err;
} }
...@@ -1050,9 +1081,9 @@ static void btmtkuart_remove(struct serdev_device *serdev) ...@@ -1050,9 +1081,9 @@ static void btmtkuart_remove(struct serdev_device *serdev)
struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
struct hci_dev *hdev = bdev->hdev; struct hci_dev *hdev = bdev->hdev;
if (btmtkuart_is_standalone(bdev)) { if (btmtkuart_is_standalone(bdev)) {
pinctrl_select_state(bdev->pinctrl, bdev->pins_boot);
regulator_disable(bdev->vcc); regulator_disable(bdev->vcc);
clk_disable_unprepare(bdev->osc);
} }
hci_unregister_dev(hdev); hci_unregister_dev(hdev);
......
...@@ -131,6 +131,7 @@ static void qca_tlv_check_data(struct rome_config *config, ...@@ -131,6 +131,7 @@ static void qca_tlv_check_data(struct rome_config *config,
* In case VSE is skipped, only the last segment is acked. * In case VSE is skipped, only the last segment is acked.
*/ */
config->dnld_mode = tlv_patch->download_mode; config->dnld_mode = tlv_patch->download_mode;
config->dnld_type = config->dnld_mode;
BT_DBG("Total Length : %d bytes", BT_DBG("Total Length : %d bytes",
le32_to_cpu(tlv_patch->total_size)); le32_to_cpu(tlv_patch->total_size));
...@@ -251,6 +252,31 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, ...@@ -251,6 +252,31 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
return err; return err;
} }
static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
{
struct hci_event_hdr *hdr;
struct hci_ev_cmd_complete *evt;
struct sk_buff *skb;
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
if (!skb)
return -ENOMEM;
hdr = skb_put(skb, sizeof(*hdr));
hdr->evt = HCI_EV_CMD_COMPLETE;
hdr->plen = sizeof(*evt) + 1;
evt = skb_put(skb, sizeof(*evt));
evt->ncmd = 1;
evt->opcode = QCA_HCI_CC_OPCODE;
skb_put_u8(skb, QCA_HCI_CC_SUCCESS);
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
return hci_recv_frame(hdev, skb);
}
static int qca_download_firmware(struct hci_dev *hdev, static int qca_download_firmware(struct hci_dev *hdev,
struct rome_config *config) struct rome_config *config)
{ {
...@@ -284,11 +310,22 @@ static int qca_download_firmware(struct hci_dev *hdev, ...@@ -284,11 +310,22 @@ static int qca_download_firmware(struct hci_dev *hdev,
ret = qca_tlv_send_segment(hdev, segsize, segment, ret = qca_tlv_send_segment(hdev, segsize, segment,
config->dnld_mode); config->dnld_mode);
if (ret) if (ret)
break; goto out;
segment += segsize; segment += segsize;
} }
/* Latest qualcomm chipsets are not sending a command complete event
* for every fw packet sent. They only respond with a vendor specific
* event for the last packet. This optimization in the chip will
* decrease the BT in initialization time. Here we will inject a command
* complete event to avoid a command timeout error message.
*/
if (config->dnld_type == ROME_SKIP_EVT_VSE_CC ||
config->dnld_type == ROME_SKIP_EVT_VSE)
return qca_inject_cmd_complete_event(hdev);
out:
release_firmware(fw); release_firmware(fw);
return ret; return ret;
...@@ -319,7 +356,8 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) ...@@ -319,7 +356,8 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome); EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, u32 soc_ver) enum qca_btsoc_type soc_type, u32 soc_ver,
const char *firmware_name)
{ {
struct rome_config config; struct rome_config config;
int err; int err;
...@@ -352,7 +390,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, ...@@ -352,7 +390,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
/* Download NVM configuration */ /* Download NVM configuration */
config.type = TLV_TYPE_NVM; config.type = TLV_TYPE_NVM;
if (qca_is_wcn399x(soc_type)) if (firmware_name)
snprintf(config.fwname, sizeof(config.fwname),
"qca/%s", firmware_name);
else if (qca_is_wcn399x(soc_type))
snprintf(config.fwname, sizeof(config.fwname), snprintf(config.fwname, sizeof(config.fwname),
"qca/crnv%02x.bin", rom_ver); "qca/crnv%02x.bin", rom_ver);
else else
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#define QCA_WCN3990_POWERON_PULSE 0xFC #define QCA_WCN3990_POWERON_PULSE 0xFC
#define QCA_WCN3990_POWEROFF_PULSE 0xC0 #define QCA_WCN3990_POWEROFF_PULSE 0xC0
#define QCA_HCI_CC_OPCODE 0xFC00
#define QCA_HCI_CC_SUCCESS 0x00
enum qca_baudrate { enum qca_baudrate {
QCA_BAUDRATE_115200 = 0, QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600, QCA_BAUDRATE_57600,
...@@ -69,6 +72,7 @@ struct rome_config { ...@@ -69,6 +72,7 @@ struct rome_config {
char fwname[64]; char fwname[64];
uint8_t user_baud_rate; uint8_t user_baud_rate;
enum rome_tlv_dnld_mode dnld_mode; enum rome_tlv_dnld_mode dnld_mode;
enum rome_tlv_dnld_mode dnld_type;
}; };
struct edl_event_hdr { struct edl_event_hdr {
...@@ -127,7 +131,8 @@ enum qca_btsoc_type { ...@@ -127,7 +131,8 @@ enum qca_btsoc_type {
int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, u32 soc_ver); enum qca_btsoc_type soc_type, u32 soc_ver,
const char *firmware_name);
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
...@@ -142,7 +147,8 @@ static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdad ...@@ -142,7 +147,8 @@ static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdad
} }
static inline int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, static inline int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, u32 soc_ver) enum qca_btsoc_type soc_type, u32 soc_ver,
const char *firmware_name)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define RTL_ROM_LMP_3499 0x3499 #define RTL_ROM_LMP_3499 0x3499
#define RTL_ROM_LMP_8723A 0x1200 #define RTL_ROM_LMP_8723A 0x1200
#define RTL_ROM_LMP_8723B 0x8723 #define RTL_ROM_LMP_8723B 0x8723
#define RTL_ROM_LMP_8723D 0x8873
#define RTL_ROM_LMP_8821A 0x8821 #define RTL_ROM_LMP_8821A 0x8821
#define RTL_ROM_LMP_8761A 0x8761 #define RTL_ROM_LMP_8761A 0x8761
#define RTL_ROM_LMP_8822B 0x8822 #define RTL_ROM_LMP_8822B 0x8822
...@@ -107,6 +108,13 @@ static const struct id_table ic_id_table[] = { ...@@ -107,6 +108,13 @@ static const struct id_table ic_id_table[] = {
.fw_name = "rtl_bt/rtl8723ds_fw.bin", .fw_name = "rtl_bt/rtl8723ds_fw.bin",
.cfg_name = "rtl_bt/rtl8723ds_config" }, .cfg_name = "rtl_bt/rtl8723ds_config" },
/* 8723DU */
{ IC_INFO(RTL_ROM_LMP_8723D, 0x826C),
.config_needed = true,
.has_rom_version = true,
.fw_name = "rtl_bt/rtl8723d_fw.bin",
.cfg_name = "rtl_bt/rtl8723d_config" },
/* 8821A */ /* 8821A */
{ IC_INFO(RTL_ROM_LMP_8821A, 0xa), { IC_INFO(RTL_ROM_LMP_8821A, 0xa),
.config_needed = false, .config_needed = false,
...@@ -637,6 +645,26 @@ int btrtl_setup_realtek(struct hci_dev *hdev) ...@@ -637,6 +645,26 @@ int btrtl_setup_realtek(struct hci_dev *hdev)
} }
EXPORT_SYMBOL_GPL(btrtl_setup_realtek); EXPORT_SYMBOL_GPL(btrtl_setup_realtek);
int btrtl_shutdown_realtek(struct hci_dev *hdev)
{
struct sk_buff *skb;
int ret;
/* According to the vendor driver, BT must be reset on close to avoid
* firmware crash.
*/
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
bt_dev_err(hdev, "HCI reset during shutdown failed");
return ret;
}
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btrtl_shutdown_realtek);
static unsigned int btrtl_convert_baudrate(u32 device_baudrate) static unsigned int btrtl_convert_baudrate(u32 device_baudrate)
{ {
switch (device_baudrate) { switch (device_baudrate) {
......
...@@ -55,6 +55,7 @@ void btrtl_free(struct btrtl_device_info *btrtl_dev); ...@@ -55,6 +55,7 @@ void btrtl_free(struct btrtl_device_info *btrtl_dev);
int btrtl_download_firmware(struct hci_dev *hdev, int btrtl_download_firmware(struct hci_dev *hdev,
struct btrtl_device_info *btrtl_dev); struct btrtl_device_info *btrtl_dev);
int btrtl_setup_realtek(struct hci_dev *hdev); int btrtl_setup_realtek(struct hci_dev *hdev);
int btrtl_shutdown_realtek(struct hci_dev *hdev);
int btrtl_get_uart_settings(struct hci_dev *hdev, int btrtl_get_uart_settings(struct hci_dev *hdev,
struct btrtl_device_info *btrtl_dev, struct btrtl_device_info *btrtl_dev,
unsigned int *controller_baudrate, unsigned int *controller_baudrate,
...@@ -83,6 +84,11 @@ static inline int btrtl_setup_realtek(struct hci_dev *hdev) ...@@ -83,6 +84,11 @@ static inline int btrtl_setup_realtek(struct hci_dev *hdev)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int btrtl_shutdown_realtek(struct hci_dev *hdev)
{
return -EOPNOTSUPP;
}
static inline int btrtl_get_uart_settings(struct hci_dev *hdev, static inline int btrtl_get_uart_settings(struct hci_dev *hdev,
struct btrtl_device_info *btrtl_dev, struct btrtl_device_info *btrtl_dev,
unsigned int *controller_baudrate, unsigned int *controller_baudrate,
......
...@@ -286,6 +286,7 @@ static int btsdio_probe(struct sdio_func *func, ...@@ -286,6 +286,7 @@ static int btsdio_probe(struct sdio_func *func,
switch (func->device) { switch (func->device) {
case SDIO_DEVICE_ID_BROADCOM_43341: case SDIO_DEVICE_ID_BROADCOM_43341:
case SDIO_DEVICE_ID_BROADCOM_43430: case SDIO_DEVICE_ID_BROADCOM_43430:
case SDIO_DEVICE_ID_BROADCOM_4356:
return -ENODEV; return -ENODEV;
} }
} }
......
This diff is collapsed.
...@@ -744,6 +744,11 @@ static int bcsp_close(struct hci_uart *hu) ...@@ -744,6 +744,11 @@ static int bcsp_close(struct hci_uart *hu)
skb_queue_purge(&bcsp->rel); skb_queue_purge(&bcsp->rel);
skb_queue_purge(&bcsp->unrel); skb_queue_purge(&bcsp->unrel);
if (bcsp->rx_skb) {
kfree_skb(bcsp->rx_skb);
bcsp->rx_skb = NULL;
}
kfree(bcsp); kfree(bcsp);
return 0; return 0;
} }
......
...@@ -178,6 +178,7 @@ static void hci_uart_write_work(struct work_struct *work) ...@@ -178,6 +178,7 @@ static void hci_uart_write_work(struct work_struct *work)
goto restart; goto restart;
clear_bit(HCI_UART_SENDING, &hu->tx_state); clear_bit(HCI_UART_SENDING, &hu->tx_state);
wake_up_bit(&hu->tx_state, HCI_UART_SENDING);
} }
void hci_uart_init_work(struct work_struct *work) void hci_uart_init_work(struct work_struct *work)
...@@ -213,6 +214,13 @@ int hci_uart_init_ready(struct hci_uart *hu) ...@@ -213,6 +214,13 @@ int hci_uart_init_ready(struct hci_uart *hu)
return 0; return 0;
} }
int hci_uart_wait_until_sent(struct hci_uart *hu)
{
return wait_on_bit_timeout(&hu->tx_state, HCI_UART_SENDING,
TASK_INTERRUPTIBLE,
msecs_to_jiffies(2000));
}
/* ------- Interface to HCI layer ------ */ /* ------- Interface to HCI layer ------ */
/* Reset device */ /* Reset device */
static int hci_uart_flush(struct hci_dev *hdev) static int hci_uart_flush(struct hci_dev *hdev)
......
...@@ -128,6 +128,7 @@ static int ll_open(struct hci_uart *hu) ...@@ -128,6 +128,7 @@ static int ll_open(struct hci_uart *hu)
if (hu->serdev) { if (hu->serdev) {
struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
if (!IS_ERR(lldev->ext_clk)) if (!IS_ERR(lldev->ext_clk))
clk_prepare_enable(lldev->ext_clk); clk_prepare_enable(lldev->ext_clk);
} }
...@@ -162,6 +163,7 @@ static int ll_close(struct hci_uart *hu) ...@@ -162,6 +163,7 @@ static int ll_close(struct hci_uart *hu)
if (hu->serdev) { if (hu->serdev) {
struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
gpiod_set_value_cansleep(lldev->enable_gpio, 0); gpiod_set_value_cansleep(lldev->enable_gpio, 0);
clk_disable_unprepare(lldev->ext_clk); clk_disable_unprepare(lldev->ext_clk);
...@@ -227,7 +229,8 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu) ...@@ -227,7 +229,8 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu)
break; break;
default: default:
/* any other state is illegal */ /* any other state is illegal */
BT_ERR("received HCILL_WAKE_UP_IND in state %ld", ll->hcill_state); BT_ERR("received HCILL_WAKE_UP_IND in state %ld",
ll->hcill_state);
break; break;
} }
...@@ -256,7 +259,8 @@ static void ll_device_want_to_sleep(struct hci_uart *hu) ...@@ -256,7 +259,8 @@ static void ll_device_want_to_sleep(struct hci_uart *hu)
/* sanity check */ /* sanity check */
if (ll->hcill_state != HCILL_AWAKE) if (ll->hcill_state != HCILL_AWAKE)
BT_ERR("ERR: HCILL_GO_TO_SLEEP_IND in state %ld", ll->hcill_state); BT_ERR("ERR: HCILL_GO_TO_SLEEP_IND in state %ld",
ll->hcill_state);
/* acknowledge device sleep */ /* acknowledge device sleep */
if (send_hcill_cmd(HCILL_GO_TO_SLEEP_ACK, hu) < 0) { if (send_hcill_cmd(HCILL_GO_TO_SLEEP_ACK, hu) < 0) {
...@@ -289,7 +293,8 @@ static void ll_device_woke_up(struct hci_uart *hu) ...@@ -289,7 +293,8 @@ static void ll_device_woke_up(struct hci_uart *hu)
/* sanity check */ /* sanity check */
if (ll->hcill_state != HCILL_ASLEEP_TO_AWAKE) if (ll->hcill_state != HCILL_ASLEEP_TO_AWAKE)
BT_ERR("received HCILL_WAKE_UP_ACK in state %ld", ll->hcill_state); BT_ERR("received HCILL_WAKE_UP_ACK in state %ld",
ll->hcill_state);
/* send pending packets and change state to HCILL_AWAKE */ /* send pending packets and change state to HCILL_AWAKE */
__ll_do_awake(ll); __ll_do_awake(ll);
...@@ -338,7 +343,8 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -338,7 +343,8 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
skb_queue_tail(&ll->tx_wait_q, skb); skb_queue_tail(&ll->tx_wait_q, skb);
break; break;
default: default:
BT_ERR("illegal hcill state: %ld (losing packet)", ll->hcill_state); BT_ERR("illegal hcill state: %ld (losing packet)",
ll->hcill_state);
kfree_skb(skb); kfree_skb(skb);
break; break;
} }
...@@ -438,6 +444,7 @@ static int ll_recv(struct hci_uart *hu, const void *data, int count) ...@@ -438,6 +444,7 @@ static int ll_recv(struct hci_uart *hu, const void *data, int count)
static struct sk_buff *ll_dequeue(struct hci_uart *hu) static struct sk_buff *ll_dequeue(struct hci_uart *hu)
{ {
struct ll_struct *ll = hu->priv; struct ll_struct *ll = hu->priv;
return skb_dequeue(&ll->txq); return skb_dequeue(&ll->txq);
} }
...@@ -449,7 +456,8 @@ static int read_local_version(struct hci_dev *hdev) ...@@ -449,7 +456,8 @@ static int read_local_version(struct hci_dev *hdev)
struct sk_buff *skb; struct sk_buff *skb;
struct hci_rp_read_local_version *ver; struct hci_rp_read_local_version *ver;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, HCI_INIT_TIMEOUT); skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading TI version information failed (%ld)", bt_dev_err(hdev, "Reading TI version information failed (%ld)",
PTR_ERR(skb)); PTR_ERR(skb));
...@@ -469,11 +477,38 @@ static int read_local_version(struct hci_dev *hdev) ...@@ -469,11 +477,38 @@ static int read_local_version(struct hci_dev *hdev)
version = le16_to_cpu(ver->lmp_subver); version = le16_to_cpu(ver->lmp_subver);
out: out:
if (err) bt_dev_err(hdev, "Failed to read TI version info: %d", err); if (err)
bt_dev_err(hdev, "Failed to read TI version info: %d", err);
kfree_skb(skb); kfree_skb(skb);
return err ? err : version; return err ? err : version;
} }
static int send_command_from_firmware(struct ll_device *lldev,
struct hci_command *cmd)
{
struct sk_buff *skb;
if (cmd->opcode == HCI_VS_UPDATE_UART_HCI_BAUDRATE) {
/* ignore remote change
* baud rate HCI VS command
*/
bt_dev_warn(lldev->hu.hdev,
"change remote baud rate command in firmware");
return 0;
}
if (cmd->prefix != 1)
bt_dev_dbg(lldev->hu.hdev, "command type %d", cmd->prefix);
skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen,
&cmd->speed, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(lldev->hu.hdev, "send command failed");
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
/** /**
* download_firmware - * download_firmware -
* internal function which parses through the .bts firmware * internal function which parses through the .bts firmware
...@@ -486,7 +521,6 @@ static int download_firmware(struct ll_device *lldev) ...@@ -486,7 +521,6 @@ static int download_firmware(struct ll_device *lldev)
unsigned char *ptr, *action_ptr; unsigned char *ptr, *action_ptr;
unsigned char bts_scr_name[40]; /* 40 char long bts scr name? */ unsigned char bts_scr_name[40]; /* 40 char long bts scr name? */
const struct firmware *fw; const struct firmware *fw;
struct sk_buff *skb;
struct hci_command *cmd; struct hci_command *cmd;
version = read_local_version(lldev->hu.hdev); version = read_local_version(lldev->hu.hdev);
...@@ -528,23 +562,9 @@ static int download_firmware(struct ll_device *lldev) ...@@ -528,23 +562,9 @@ static int download_firmware(struct ll_device *lldev)
case ACTION_SEND_COMMAND: /* action send */ case ACTION_SEND_COMMAND: /* action send */
bt_dev_dbg(lldev->hu.hdev, "S"); bt_dev_dbg(lldev->hu.hdev, "S");
cmd = (struct hci_command *)action_ptr; cmd = (struct hci_command *)action_ptr;
if (cmd->opcode == HCI_VS_UPDATE_UART_HCI_BAUDRATE) { err = send_command_from_firmware(lldev, cmd);
/* ignore remote change if (err)
* baud rate HCI VS command
*/
bt_dev_warn(lldev->hu.hdev, "change remote baud rate command in firmware");
break;
}
if (cmd->prefix != 1)
bt_dev_dbg(lldev->hu.hdev, "command type %d", cmd->prefix);
skb = __hci_cmd_sync(lldev->hu.hdev, cmd->opcode, cmd->plen, &cmd->speed, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(lldev->hu.hdev, "send command failed");
err = PTR_ERR(skb);
goto out_rel_fw; goto out_rel_fw;
}
kfree_skb(skb);
break; break;
case ACTION_WAIT_EVENT: /* wait */ case ACTION_WAIT_EVENT: /* wait */
/* no need to wait as command was synchronous */ /* no need to wait as command was synchronous */
...@@ -601,6 +621,13 @@ static int ll_setup(struct hci_uart *hu) ...@@ -601,6 +621,13 @@ static int ll_setup(struct hci_uart *hu)
serdev_device_set_flow_control(serdev, true); serdev_device_set_flow_control(serdev, true);
if (hu->oper_speed)
speed = hu->oper_speed;
else if (hu->proto->oper_speed)
speed = hu->proto->oper_speed;
else
speed = 0;
do { do {
/* Reset the Bluetooth device */ /* Reset the Bluetooth device */
gpiod_set_value_cansleep(lldev->enable_gpio, 0); gpiod_set_value_cansleep(lldev->enable_gpio, 0);
...@@ -612,6 +639,20 @@ static int ll_setup(struct hci_uart *hu) ...@@ -612,6 +639,20 @@ static int ll_setup(struct hci_uart *hu)
return err; return err;
} }
if (speed) {
__le32 speed_le = cpu_to_le32(speed);
struct sk_buff *skb;
skb = __hci_cmd_sync(hu->hdev,
HCI_VS_UPDATE_UART_HCI_BAUDRATE,
sizeof(speed_le), &speed_le,
HCI_INIT_TIMEOUT);
if (!IS_ERR(skb)) {
kfree_skb(skb);
serdev_device_set_baudrate(serdev, speed);
}
}
err = download_firmware(lldev); err = download_firmware(lldev);
if (!err) if (!err)
break; break;
...@@ -636,25 +677,7 @@ static int ll_setup(struct hci_uart *hu) ...@@ -636,25 +677,7 @@ static int ll_setup(struct hci_uart *hu)
} }
/* Operational speed if any */ /* Operational speed if any */
if (hu->oper_speed)
speed = hu->oper_speed;
else if (hu->proto->oper_speed)
speed = hu->proto->oper_speed;
else
speed = 0;
if (speed) {
__le32 speed_le = cpu_to_le32(speed);
struct sk_buff *skb;
skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE,
sizeof(speed_le), &speed_le,
HCI_INIT_TIMEOUT);
if (!IS_ERR(skb)) {
kfree_skb(skb);
serdev_device_set_baudrate(serdev, speed);
}
}
return 0; return 0;
} }
...@@ -676,7 +699,9 @@ static int hci_ti_probe(struct serdev_device *serdev) ...@@ -676,7 +699,9 @@ static int hci_ti_probe(struct serdev_device *serdev)
serdev_device_set_drvdata(serdev, lldev); serdev_device_set_drvdata(serdev, lldev);
lldev->serdev = hu->serdev = serdev; lldev->serdev = hu->serdev = serdev;
lldev->enable_gpio = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); lldev->enable_gpio = devm_gpiod_get_optional(&serdev->dev,
"enable",
GPIOD_OUT_LOW);
if (IS_ERR(lldev->enable_gpio)) if (IS_ERR(lldev->enable_gpio))
return PTR_ERR(lldev->enable_gpio); return PTR_ERR(lldev->enable_gpio);
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/of.h>
#include <linux/serdev.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -40,6 +42,10 @@ struct mrvl_data { ...@@ -40,6 +42,10 @@ struct mrvl_data {
u8 id, rev; u8 id, rev;
}; };
struct mrvl_serdev {
struct hci_uart hu;
};
struct hci_mrvl_pkt { struct hci_mrvl_pkt {
__le16 lhs; __le16 lhs;
__le16 rhs; __le16 rhs;
...@@ -49,6 +55,7 @@ struct hci_mrvl_pkt { ...@@ -49,6 +55,7 @@ struct hci_mrvl_pkt {
static int mrvl_open(struct hci_uart *hu) static int mrvl_open(struct hci_uart *hu)
{ {
struct mrvl_data *mrvl; struct mrvl_data *mrvl;
int ret;
BT_DBG("hu %p", hu); BT_DBG("hu %p", hu);
...@@ -62,7 +69,18 @@ static int mrvl_open(struct hci_uart *hu) ...@@ -62,7 +69,18 @@ static int mrvl_open(struct hci_uart *hu)
set_bit(STATE_CHIP_VER_PENDING, &mrvl->flags); set_bit(STATE_CHIP_VER_PENDING, &mrvl->flags);
hu->priv = mrvl; hu->priv = mrvl;
if (hu->serdev) {
ret = serdev_device_open(hu->serdev);
if (ret)
goto err;
}
return 0; return 0;
err:
kfree(mrvl);
return ret;
} }
static int mrvl_close(struct hci_uart *hu) static int mrvl_close(struct hci_uart *hu)
...@@ -71,6 +89,9 @@ static int mrvl_close(struct hci_uart *hu) ...@@ -71,6 +89,9 @@ static int mrvl_close(struct hci_uart *hu)
BT_DBG("hu %p", hu); BT_DBG("hu %p", hu);
if (hu->serdev)
serdev_device_close(hu->serdev);
skb_queue_purge(&mrvl->txq); skb_queue_purge(&mrvl->txq);
skb_queue_purge(&mrvl->rawq); skb_queue_purge(&mrvl->rawq);
kfree_skb(mrvl->rx_skb); kfree_skb(mrvl->rx_skb);
...@@ -339,7 +360,14 @@ static int mrvl_setup(struct hci_uart *hu) ...@@ -339,7 +360,14 @@ static int mrvl_setup(struct hci_uart *hu)
return -EINVAL; return -EINVAL;
} }
hci_uart_set_baudrate(hu, 3000000); /* Let the final ack go out before switching the baudrate */
hci_uart_wait_until_sent(hu);
if (hu->serdev)
serdev_device_set_baudrate(hu->serdev, 3000000);
else
hci_uart_set_baudrate(hu, 3000000);
hci_uart_set_flow_control(hu, false); hci_uart_set_flow_control(hu, false);
err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin"); err = mrvl_load_firmware(hu->hdev, "mrvl/uart8897_bt.bin");
...@@ -362,12 +390,54 @@ static const struct hci_uart_proto mrvl_proto = { ...@@ -362,12 +390,54 @@ static const struct hci_uart_proto mrvl_proto = {
.dequeue = mrvl_dequeue, .dequeue = mrvl_dequeue,
}; };
static int mrvl_serdev_probe(struct serdev_device *serdev)
{
struct mrvl_serdev *mrvldev;
mrvldev = devm_kzalloc(&serdev->dev, sizeof(*mrvldev), GFP_KERNEL);
if (!mrvldev)
return -ENOMEM;
mrvldev->hu.serdev = serdev;
serdev_device_set_drvdata(serdev, mrvldev);
return hci_uart_register_device(&mrvldev->hu, &mrvl_proto);
}
static void mrvl_serdev_remove(struct serdev_device *serdev)
{
struct mrvl_serdev *mrvldev = serdev_device_get_drvdata(serdev);
hci_uart_unregister_device(&mrvldev->hu);
}
#ifdef CONFIG_OF
static const struct of_device_id mrvl_bluetooth_of_match[] = {
{ .compatible = "mrvl,88w8897" },
{ },
};
MODULE_DEVICE_TABLE(of, mrvl_bluetooth_of_match);
#endif
static struct serdev_device_driver mrvl_serdev_driver = {
.probe = mrvl_serdev_probe,
.remove = mrvl_serdev_remove,
.driver = {
.name = "hci_uart_mrvl",
.of_match_table = of_match_ptr(mrvl_bluetooth_of_match),
},
};
int __init mrvl_init(void) int __init mrvl_init(void)
{ {
serdev_device_driver_register(&mrvl_serdev_driver);
return hci_uart_register_proto(&mrvl_proto); return hci_uart_register_proto(&mrvl_proto);
} }
int __exit mrvl_deinit(void) int __exit mrvl_deinit(void)
{ {
serdev_device_driver_unregister(&mrvl_serdev_driver);
return hci_uart_unregister_proto(&mrvl_proto); return hci_uart_unregister_proto(&mrvl_proto);
} }
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/completion.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -53,6 +54,7 @@ ...@@ -53,6 +54,7 @@
enum qca_flags { enum qca_flags {
QCA_IBS_ENABLED, QCA_IBS_ENABLED,
QCA_DROP_VENDOR_EVENT,
}; };
/* HCI_IBS transmit side sleep protocol states */ /* HCI_IBS transmit side sleep protocol states */
...@@ -97,6 +99,7 @@ struct qca_data { ...@@ -97,6 +99,7 @@ struct qca_data {
struct work_struct ws_rx_vote_off; struct work_struct ws_rx_vote_off;
struct work_struct ws_tx_vote_off; struct work_struct ws_tx_vote_off;
unsigned long flags; unsigned long flags;
struct completion drop_ev_comp;
/* For debugging purpose */ /* For debugging purpose */
u64 ibs_sent_wacks; u64 ibs_sent_wacks;
...@@ -156,6 +159,7 @@ struct qca_serdev { ...@@ -156,6 +159,7 @@ struct qca_serdev {
struct qca_power *bt_power; struct qca_power *bt_power;
u32 init_speed; u32 init_speed;
u32 oper_speed; u32 oper_speed;
const char *firmware_name;
}; };
static int qca_power_setup(struct hci_uart *hu, bool on); static int qca_power_setup(struct hci_uart *hu, bool on);
...@@ -177,6 +181,17 @@ static enum qca_btsoc_type qca_soc_type(struct hci_uart *hu) ...@@ -177,6 +181,17 @@ static enum qca_btsoc_type qca_soc_type(struct hci_uart *hu)
return soc_type; return soc_type;
} }
static const char *qca_get_firmware_name(struct hci_uart *hu)
{
if (hu->serdev) {
struct qca_serdev *qsd = serdev_device_get_drvdata(hu->serdev);
return qsd->firmware_name;
} else {
return NULL;
}
}
static void __serial_clock_on(struct tty_struct *tty) static void __serial_clock_on(struct tty_struct *tty)
{ {
/* TODO: Some chipset requires to enable UART clock on client /* TODO: Some chipset requires to enable UART clock on client
...@@ -478,6 +493,7 @@ static int qca_open(struct hci_uart *hu) ...@@ -478,6 +493,7 @@ static int qca_open(struct hci_uart *hu)
INIT_WORK(&qca->ws_tx_vote_off, qca_wq_serial_tx_clock_vote_off); INIT_WORK(&qca->ws_tx_vote_off, qca_wq_serial_tx_clock_vote_off);
qca->hu = hu; qca->hu = hu;
init_completion(&qca->drop_ev_comp);
/* Assume we start with both sides asleep -- extra wakes OK */ /* Assume we start with both sides asleep -- extra wakes OK */
qca->tx_ibs_state = HCI_IBS_TX_ASLEEP; qca->tx_ibs_state = HCI_IBS_TX_ASLEEP;
...@@ -872,6 +888,35 @@ static int qca_recv_acl_data(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -872,6 +888,35 @@ static int qca_recv_acl_data(struct hci_dev *hdev, struct sk_buff *skb)
return hci_recv_frame(hdev, skb); return hci_recv_frame(hdev, skb);
} }
static int qca_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
if (test_bit(QCA_DROP_VENDOR_EVENT, &qca->flags)) {
struct hci_event_hdr *hdr = (void *)skb->data;
/* For the WCN3990 the vendor command for a baudrate change
* isn't sent as synchronous HCI command, because the
* controller sends the corresponding vendor event with the
* new baudrate. The event is received and properly decoded
* after changing the baudrate of the host port. It needs to
* be dropped, otherwise it can be misinterpreted as
* response to a later firmware download command (also a
* vendor command).
*/
if (hdr->evt == HCI_EV_VENDOR)
complete(&qca->drop_ev_comp);
kfree(skb);
return 0;
}
return hci_recv_frame(hdev, skb);
}
#define QCA_IBS_SLEEP_IND_EVENT \ #define QCA_IBS_SLEEP_IND_EVENT \
.type = HCI_IBS_SLEEP_IND, \ .type = HCI_IBS_SLEEP_IND, \
.hlen = 0, \ .hlen = 0, \
...@@ -896,7 +941,7 @@ static int qca_recv_acl_data(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -896,7 +941,7 @@ static int qca_recv_acl_data(struct hci_dev *hdev, struct sk_buff *skb)
static const struct h4_recv_pkt qca_recv_pkts[] = { static const struct h4_recv_pkt qca_recv_pkts[] = {
{ H4_RECV_ACL, .recv = qca_recv_acl_data }, { H4_RECV_ACL, .recv = qca_recv_acl_data },
{ H4_RECV_SCO, .recv = hci_recv_frame }, { H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame }, { H4_RECV_EVENT, .recv = qca_recv_event },
{ QCA_IBS_WAKE_IND_EVENT, .recv = qca_ibs_wake_ind }, { QCA_IBS_WAKE_IND_EVENT, .recv = qca_ibs_wake_ind },
{ QCA_IBS_WAKE_ACK_EVENT, .recv = qca_ibs_wake_ack }, { QCA_IBS_WAKE_ACK_EVENT, .recv = qca_ibs_wake_ack },
{ QCA_IBS_SLEEP_IND_EVENT, .recv = qca_ibs_sleep_ind }, { QCA_IBS_SLEEP_IND_EVENT, .recv = qca_ibs_sleep_ind },
...@@ -1091,6 +1136,7 @@ static int qca_check_speeds(struct hci_uart *hu) ...@@ -1091,6 +1136,7 @@ static int qca_check_speeds(struct hci_uart *hu)
static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
{ {
unsigned int speed, qca_baudrate; unsigned int speed, qca_baudrate;
struct qca_data *qca = hu->priv;
int ret = 0; int ret = 0;
if (speed_type == QCA_INIT_SPEED) { if (speed_type == QCA_INIT_SPEED) {
...@@ -1110,6 +1156,11 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1110,6 +1156,11 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
if (qca_is_wcn399x(soc_type)) if (qca_is_wcn399x(soc_type))
hci_uart_set_flow_control(hu, true); hci_uart_set_flow_control(hu, true);
if (soc_type == QCA_WCN3990) {
reinit_completion(&qca->drop_ev_comp);
set_bit(QCA_DROP_VENDOR_EVENT, &qca->flags);
}
qca_baudrate = qca_get_baudrate_value(speed); qca_baudrate = qca_get_baudrate_value(speed);
bt_dev_dbg(hu->hdev, "Set UART speed to %d", speed); bt_dev_dbg(hu->hdev, "Set UART speed to %d", speed);
ret = qca_set_baudrate(hu->hdev, qca_baudrate); ret = qca_set_baudrate(hu->hdev, qca_baudrate);
...@@ -1121,6 +1172,20 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) ...@@ -1121,6 +1172,20 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
error: error:
if (qca_is_wcn399x(soc_type)) if (qca_is_wcn399x(soc_type))
hci_uart_set_flow_control(hu, false); hci_uart_set_flow_control(hu, false);
if (soc_type == QCA_WCN3990) {
/* Wait for the controller to send the vendor event
* for the baudrate change command.
*/
if (!wait_for_completion_timeout(&qca->drop_ev_comp,
msecs_to_jiffies(100))) {
bt_dev_err(hu->hdev,
"Failed to change controller baudrate\n");
ret = -ETIMEDOUT;
}
clear_bit(QCA_DROP_VENDOR_EVENT, &qca->flags);
}
} }
return ret; return ret;
...@@ -1182,6 +1247,7 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1182,6 +1247,7 @@ static int qca_setup(struct hci_uart *hu)
struct qca_data *qca = hu->priv; struct qca_data *qca = hu->priv;
unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200; unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200;
enum qca_btsoc_type soc_type = qca_soc_type(hu); enum qca_btsoc_type soc_type = qca_soc_type(hu);
const char *firmware_name = qca_get_firmware_name(hu);
int ret; int ret;
int soc_ver = 0; int soc_ver = 0;
...@@ -1232,7 +1298,8 @@ static int qca_setup(struct hci_uart *hu) ...@@ -1232,7 +1298,8 @@ static int qca_setup(struct hci_uart *hu)
bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver); bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver);
/* Setup patch / NVM configurations */ /* Setup patch / NVM configurations */
ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver); ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver,
firmware_name);
if (!ret) { if (!ret) {
set_bit(QCA_IBS_ENABLED, &qca->flags); set_bit(QCA_IBS_ENABLED, &qca->flags);
qca_debugfs_init(hdev); qca_debugfs_init(hdev);
...@@ -1426,6 +1493,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) ...@@ -1426,6 +1493,8 @@ static int qca_serdev_probe(struct serdev_device *serdev)
qcadev->serdev_hu.serdev = serdev; qcadev->serdev_hu.serdev = serdev;
data = of_device_get_match_data(&serdev->dev); data = of_device_get_match_data(&serdev->dev);
serdev_device_set_drvdata(serdev, qcadev); serdev_device_set_drvdata(serdev, qcadev);
device_property_read_string(&serdev->dev, "firmware-name",
&qcadev->firmware_name);
if (data && qca_is_wcn399x(data->soc_type)) { if (data && qca_is_wcn399x(data->soc_type)) {
qcadev->btsoc_type = data->soc_type; qcadev->btsoc_type = data->soc_type;
qcadev->bt_power = devm_kzalloc(&serdev->dev, qcadev->bt_power = devm_kzalloc(&serdev->dev,
......
...@@ -100,6 +100,7 @@ int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p ...@@ -100,6 +100,7 @@ int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p
void hci_uart_unregister_device(struct hci_uart *hu); void hci_uart_unregister_device(struct hci_uart *hu);
int hci_uart_tx_wakeup(struct hci_uart *hu); int hci_uart_tx_wakeup(struct hci_uart *hu);
int hci_uart_wait_until_sent(struct hci_uart *hu);
int hci_uart_init_ready(struct hci_uart *hu); int hci_uart_init_ready(struct hci_uart *hu);
void hci_uart_init_work(struct work_struct *work); void hci_uart_init_work(struct work_struct *work);
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed); void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
......
...@@ -1143,6 +1143,26 @@ struct hci_cp_write_sc_support { ...@@ -1143,6 +1143,26 @@ struct hci_cp_write_sc_support {
__u8 support; __u8 support;
} __packed; } __packed;
#define HCI_OP_READ_AUTH_PAYLOAD_TO 0x0c7b
struct hci_cp_read_auth_payload_to {
__le16 handle;
} __packed;
struct hci_rp_read_auth_payload_to {
__u8 status;
__le16 handle;
__le16 timeout;
} __packed;
#define HCI_OP_WRITE_AUTH_PAYLOAD_TO 0x0c7c
struct hci_cp_write_auth_payload_to {
__le16 handle;
__le16 timeout;
} __packed;
struct hci_rp_write_auth_payload_to {
__u8 status;
__le16 handle;
} __packed;
#define HCI_OP_READ_LOCAL_OOB_EXT_DATA 0x0c7d #define HCI_OP_READ_LOCAL_OOB_EXT_DATA 0x0c7d
struct hci_rp_read_local_oob_ext_data { struct hci_rp_read_local_oob_ext_data {
__u8 status; __u8 status;
......
...@@ -199,6 +199,8 @@ struct adv_info { ...@@ -199,6 +199,8 @@ struct adv_info {
/* Default min/max age of connection information (1s/3s) */ /* Default min/max age of connection information (1s/3s) */
#define DEFAULT_CONN_INFO_MIN_AGE 1000 #define DEFAULT_CONN_INFO_MIN_AGE 1000
#define DEFAULT_CONN_INFO_MAX_AGE 3000 #define DEFAULT_CONN_INFO_MAX_AGE 3000
/* Default authenticated payload timeout 30s */
#define DEFAULT_AUTH_PAYLOAD_TIMEOUT 0x0bb8
struct amp_assoc { struct amp_assoc {
__u16 len; __u16 len;
...@@ -275,6 +277,7 @@ struct hci_dev { ...@@ -275,6 +277,7 @@ struct hci_dev {
__u16 discov_interleaved_timeout; __u16 discov_interleaved_timeout;
__u16 conn_info_min_age; __u16 conn_info_min_age;
__u16 conn_info_max_age; __u16 conn_info_max_age;
__u16 auth_payload_timeout;
__u8 ssp_debug_mode; __u8 ssp_debug_mode;
__u8 hw_error_code; __u8 hw_error_code;
__u32 clock; __u32 clock;
...@@ -481,6 +484,7 @@ struct hci_conn { ...@@ -481,6 +484,7 @@ struct hci_conn {
__u16 disc_timeout; __u16 disc_timeout;
__u16 conn_timeout; __u16 conn_timeout;
__u16 setting; __u16 setting;
__u16 auth_payload_timeout;
__u16 le_conn_min_interval; __u16 le_conn_min_interval;
__u16 le_conn_max_interval; __u16 le_conn_max_interval;
__u16 le_conn_interval; __u16 le_conn_interval;
......
...@@ -18,24 +18,16 @@ extern const struct ndisc_ops lowpan_ndisc_ops; ...@@ -18,24 +18,16 @@ extern const struct ndisc_ops lowpan_ndisc_ops;
int addrconf_ifid_802154_6lowpan(u8 *eui, struct net_device *dev); int addrconf_ifid_802154_6lowpan(u8 *eui, struct net_device *dev);
#ifdef CONFIG_6LOWPAN_DEBUGFS #ifdef CONFIG_6LOWPAN_DEBUGFS
int lowpan_dev_debugfs_init(struct net_device *dev); void lowpan_dev_debugfs_init(struct net_device *dev);
void lowpan_dev_debugfs_exit(struct net_device *dev); void lowpan_dev_debugfs_exit(struct net_device *dev);
int __init lowpan_debugfs_init(void); void __init lowpan_debugfs_init(void);
void lowpan_debugfs_exit(void); void lowpan_debugfs_exit(void);
#else #else
static inline int lowpan_dev_debugfs_init(struct net_device *dev) static inline void lowpan_dev_debugfs_init(struct net_device *dev) { }
{
return 0;
}
static inline void lowpan_dev_debugfs_exit(struct net_device *dev) { } static inline void lowpan_dev_debugfs_exit(struct net_device *dev) { }
static inline int __init lowpan_debugfs_init(void) static inline void __init lowpan_debugfs_init(void) { }
{
return 0;
}
static inline void lowpan_debugfs_exit(void) { } static inline void lowpan_debugfs_exit(void) { }
#endif /* CONFIG_6LOWPAN_DEBUGFS */ #endif /* CONFIG_6LOWPAN_DEBUGFS */
......
...@@ -42,9 +42,7 @@ int lowpan_register_netdevice(struct net_device *dev, ...@@ -42,9 +42,7 @@ int lowpan_register_netdevice(struct net_device *dev,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = lowpan_dev_debugfs_init(dev); lowpan_dev_debugfs_init(dev);
if (ret < 0)
unregister_netdevice(dev);
return ret; return ret;
} }
...@@ -152,9 +150,7 @@ static int __init lowpan_module_init(void) ...@@ -152,9 +150,7 @@ static int __init lowpan_module_init(void)
{ {
int ret; int ret;
ret = lowpan_debugfs_init(); lowpan_debugfs_init();
if (ret < 0)
return ret;
ret = register_netdevice_notifier(&lowpan_notifier); ret = register_netdevice_notifier(&lowpan_notifier);
if (ret < 0) { if (ret < 0) {
......
...@@ -163,11 +163,11 @@ static const struct file_operations lowpan_ctx_pfx_fops = { ...@@ -163,11 +163,11 @@ static const struct file_operations lowpan_ctx_pfx_fops = {
.release = single_release, .release = single_release,
}; };
static int lowpan_dev_debugfs_ctx_init(struct net_device *dev, static void lowpan_dev_debugfs_ctx_init(struct net_device *dev,
struct dentry *ctx, u8 id) struct dentry *ctx, u8 id)
{ {
struct lowpan_dev *ldev = lowpan_dev(dev); struct lowpan_dev *ldev = lowpan_dev(dev);
struct dentry *dentry, *root; struct dentry *root;
char buf[32]; char buf[32];
WARN_ON_ONCE(id > LOWPAN_IPHC_CTX_TABLE_SIZE); WARN_ON_ONCE(id > LOWPAN_IPHC_CTX_TABLE_SIZE);
...@@ -175,34 +175,18 @@ static int lowpan_dev_debugfs_ctx_init(struct net_device *dev, ...@@ -175,34 +175,18 @@ static int lowpan_dev_debugfs_ctx_init(struct net_device *dev,
sprintf(buf, "%d", id); sprintf(buf, "%d", id);
root = debugfs_create_dir(buf, ctx); root = debugfs_create_dir(buf, ctx);
if (!root)
return -EINVAL;
dentry = debugfs_create_file_unsafe("active", 0644, root, debugfs_create_file("active", 0644, root, &ldev->ctx.table[id],
&ldev->ctx.table[id], &lowpan_ctx_flag_active_fops);
&lowpan_ctx_flag_active_fops);
if (!dentry)
return -EINVAL;
dentry = debugfs_create_file_unsafe("compression", 0644, root, debugfs_create_file("compression", 0644, root, &ldev->ctx.table[id],
&ldev->ctx.table[id], &lowpan_ctx_flag_c_fops);
&lowpan_ctx_flag_c_fops);
if (!dentry)
return -EINVAL;
dentry = debugfs_create_file("prefix", 0644, root,
&ldev->ctx.table[id],
&lowpan_ctx_pfx_fops);
if (!dentry)
return -EINVAL;
dentry = debugfs_create_file_unsafe("prefix_len", 0644, root, debugfs_create_file("prefix", 0644, root, &ldev->ctx.table[id],
&ldev->ctx.table[id], &lowpan_ctx_pfx_fops);
&lowpan_ctx_plen_fops);
if (!dentry)
return -EINVAL;
return 0; debugfs_create_file("prefix_len", 0644, root, &ldev->ctx.table[id],
&lowpan_ctx_plen_fops);
} }
static int lowpan_context_show(struct seq_file *file, void *offset) static int lowpan_context_show(struct seq_file *file, void *offset)
...@@ -242,64 +226,39 @@ static int lowpan_short_addr_get(void *data, u64 *val) ...@@ -242,64 +226,39 @@ static int lowpan_short_addr_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(lowpan_short_addr_fops, lowpan_short_addr_get, NULL, DEFINE_DEBUGFS_ATTRIBUTE(lowpan_short_addr_fops, lowpan_short_addr_get, NULL,
"0x%04llx\n"); "0x%04llx\n");
static int lowpan_dev_debugfs_802154_init(const struct net_device *dev, static void lowpan_dev_debugfs_802154_init(const struct net_device *dev,
struct lowpan_dev *ldev) struct lowpan_dev *ldev)
{ {
struct dentry *dentry, *root; struct dentry *root;
if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154)) if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
return 0; return;
root = debugfs_create_dir("ieee802154", ldev->iface_debugfs); root = debugfs_create_dir("ieee802154", ldev->iface_debugfs);
if (!root)
return -EINVAL;
dentry = debugfs_create_file_unsafe("short_addr", 0444, root,
lowpan_802154_dev(dev)->wdev->ieee802154_ptr,
&lowpan_short_addr_fops);
if (!dentry)
return -EINVAL;
return 0; debugfs_create_file("short_addr", 0444, root,
lowpan_802154_dev(dev)->wdev->ieee802154_ptr,
&lowpan_short_addr_fops);
} }
int lowpan_dev_debugfs_init(struct net_device *dev) void lowpan_dev_debugfs_init(struct net_device *dev)
{ {
struct lowpan_dev *ldev = lowpan_dev(dev); struct lowpan_dev *ldev = lowpan_dev(dev);
struct dentry *contexts, *dentry; struct dentry *contexts;
int ret, i; int i;
/* creating the root */ /* creating the root */
ldev->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs); ldev->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs);
if (!ldev->iface_debugfs)
goto fail;
contexts = debugfs_create_dir("contexts", ldev->iface_debugfs); contexts = debugfs_create_dir("contexts", ldev->iface_debugfs);
if (!contexts)
goto remove_root;
dentry = debugfs_create_file("show", 0644, contexts,
&lowpan_dev(dev)->ctx,
&lowpan_context_fops);
if (!dentry)
goto remove_root;
for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
ret = lowpan_dev_debugfs_ctx_init(dev, contexts, i);
if (ret < 0)
goto remove_root;
}
ret = lowpan_dev_debugfs_802154_init(dev, ldev); debugfs_create_file("show", 0644, contexts, &lowpan_dev(dev)->ctx,
if (ret < 0) &lowpan_context_fops);
goto remove_root;
return 0; for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
lowpan_dev_debugfs_ctx_init(dev, contexts, i);
remove_root: lowpan_dev_debugfs_802154_init(dev, ldev);
lowpan_dev_debugfs_exit(dev);
fail:
return -EINVAL;
} }
void lowpan_dev_debugfs_exit(struct net_device *dev) void lowpan_dev_debugfs_exit(struct net_device *dev)
...@@ -307,13 +266,9 @@ void lowpan_dev_debugfs_exit(struct net_device *dev) ...@@ -307,13 +266,9 @@ void lowpan_dev_debugfs_exit(struct net_device *dev)
debugfs_remove_recursive(lowpan_dev(dev)->iface_debugfs); debugfs_remove_recursive(lowpan_dev(dev)->iface_debugfs);
} }
int __init lowpan_debugfs_init(void) void __init lowpan_debugfs_init(void)
{ {
lowpan_debugfs = debugfs_create_dir("6lowpan", NULL); lowpan_debugfs = debugfs_create_dir("6lowpan", NULL);
if (!lowpan_debugfs)
return -EINVAL;
return 0;
} }
void lowpan_debugfs_exit(void) void lowpan_debugfs_exit(void)
......
...@@ -164,26 +164,21 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev, ...@@ -164,26 +164,21 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
int count = atomic_read(&dev->peer_count); int count = atomic_read(&dev->peer_count);
const struct in6_addr *nexthop; const struct in6_addr *nexthop;
struct lowpan_peer *peer; struct lowpan_peer *peer;
struct neighbour *neigh;
BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt); BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
/* If we have multiple 6lowpan peers, then check where we should
* send the packet. If only one peer exists, then we can send the
* packet right away.
*/
if (count == 1) {
rcu_read_lock();
peer = list_first_or_null_rcu(&dev->peers, struct lowpan_peer,
list);
rcu_read_unlock();
return peer;
}
if (!rt) { if (!rt) {
nexthop = &lowpan_cb(skb)->gw; if (ipv6_addr_any(&lowpan_cb(skb)->gw)) {
/* There is neither route nor gateway,
if (ipv6_addr_any(nexthop)) * probably the destination is a direct peer.
return NULL; */
nexthop = daddr;
} else {
/* There is a known gateway
*/
nexthop = &lowpan_cb(skb)->gw;
}
} else { } else {
nexthop = rt6_nexthop(rt, daddr); nexthop = rt6_nexthop(rt, daddr);
...@@ -209,6 +204,20 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev, ...@@ -209,6 +204,20 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
} }
} }
/* use the neighbour cache for matching addresses assigned by SLAAC
*/
neigh = __ipv6_neigh_lookup(dev->netdev, nexthop);
if (neigh) {
list_for_each_entry_rcu(peer, &dev->peers, list) {
if (!memcmp(neigh->ha, peer->lladdr, ETH_ALEN)) {
neigh_release(neigh);
rcu_read_unlock();
return peer;
}
}
neigh_release(neigh);
}
rcu_read_unlock(); rcu_read_unlock();
return NULL; return NULL;
......
...@@ -520,6 +520,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, ...@@ -520,6 +520,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
set_bit(HCI_CONN_POWER_SAVE, &conn->flags); set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
conn->disc_timeout = HCI_DISCONN_TIMEOUT; conn->disc_timeout = HCI_DISCONN_TIMEOUT;
/* Set Default Authenticated payload timeout to 30s */
conn->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
if (conn->role == HCI_ROLE_MASTER) if (conn->role == HCI_ROLE_MASTER)
conn->out = true; conn->out = true;
...@@ -912,7 +915,7 @@ static void hci_req_directed_advertising(struct hci_request *req, ...@@ -912,7 +915,7 @@ static void hci_req_directed_advertising(struct hci_request *req,
sizeof(cp), &cp); sizeof(cp), &cp);
} }
__hci_req_enable_ext_advertising(req); __hci_req_enable_ext_advertising(req, 0x00);
} else { } else {
struct hci_cp_le_set_adv_param cp; struct hci_cp_le_set_adv_param cp;
......
...@@ -2827,7 +2827,7 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags, ...@@ -2827,7 +2827,7 @@ int hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags,
memset(adv_instance->scan_rsp_data, 0, memset(adv_instance->scan_rsp_data, 0,
sizeof(adv_instance->scan_rsp_data)); sizeof(adv_instance->scan_rsp_data));
} else { } else {
if (hdev->adv_instance_cnt >= HCI_MAX_ADV_INSTANCES || if (hdev->adv_instance_cnt >= hdev->le_num_of_adv_sets ||
instance < 1 || instance > HCI_MAX_ADV_INSTANCES) instance < 1 || instance > HCI_MAX_ADV_INSTANCES)
return -EOVERFLOW; return -EOVERFLOW;
...@@ -3195,11 +3195,13 @@ struct hci_dev *hci_alloc_dev(void) ...@@ -3195,11 +3195,13 @@ struct hci_dev *hci_alloc_dev(void)
hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE; hdev->le_min_key_size = SMP_MIN_ENC_KEY_SIZE;
hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M; hdev->le_tx_def_phys = HCI_LE_SET_PHY_1M;
hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M; hdev->le_rx_def_phys = HCI_LE_SET_PHY_1M;
hdev->le_num_of_adv_sets = HCI_MAX_ADV_INSTANCES;
hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT;
hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT; hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT;
hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE; hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE;
hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE; hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE;
hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT;
mutex_init(&hdev->lock); mutex_init(&hdev->lock);
mutex_init(&hdev->req_lock); mutex_init(&hdev->req_lock);
......
...@@ -941,6 +941,35 @@ static int adv_max_interval_get(void *data, u64 *val) ...@@ -941,6 +941,35 @@ static int adv_max_interval_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get,
adv_max_interval_set, "%llu\n"); adv_max_interval_set, "%llu\n");
static int auth_payload_timeout_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val < 0x0001 || val > 0xffff)
return -EINVAL;
hci_dev_lock(hdev);
hdev->auth_payload_timeout = val;
hci_dev_unlock(hdev);
return 0;
}
static int auth_payload_timeout_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->auth_payload_timeout;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(auth_payload_timeout_fops,
auth_payload_timeout_get,
auth_payload_timeout_set, "%llu\n");
DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter, DEFINE_QUIRK_ATTRIBUTE(quirk_strict_duplicate_filter,
HCI_QUIRK_STRICT_DUPLICATE_FILTER); HCI_QUIRK_STRICT_DUPLICATE_FILTER);
DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery, DEFINE_QUIRK_ATTRIBUTE(quirk_simultaneous_discovery,
...@@ -994,6 +1023,8 @@ void hci_debugfs_create_le(struct hci_dev *hdev) ...@@ -994,6 +1023,8 @@ void hci_debugfs_create_le(struct hci_dev *hdev)
&adv_max_interval_fops); &adv_max_interval_fops);
debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs,
&hdev->discov_interleaved_timeout); &hdev->discov_interleaved_timeout);
debugfs_create_file("auth_payload_timeout", 0644, hdev->debugfs, hdev,
&auth_payload_timeout_fops);
debugfs_create_file("quirk_strict_duplicate_filter", 0644, debugfs_create_file("quirk_strict_duplicate_filter", 0644,
hdev->debugfs, hdev, hdev->debugfs, hdev,
......
...@@ -579,6 +579,51 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, ...@@ -579,6 +579,51 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
} }
static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev,
struct sk_buff *skb)
{
struct hci_rp_read_auth_payload_to *rp = (void *)skb->data;
struct hci_conn *conn;
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->auth_payload_timeout = __le16_to_cpu(rp->timeout);
hci_dev_unlock(hdev);
}
static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev,
struct sk_buff *skb)
{
struct hci_rp_write_auth_payload_to *rp = (void *)skb->data;
struct hci_conn *conn;
void *sent;
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
return;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO);
if (!sent)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->auth_payload_timeout = get_unaligned_le16(sent + 2);
hci_dev_unlock(hdev);
}
static void hci_cc_read_local_features(struct hci_dev *hdev, static void hci_cc_read_local_features(struct hci_dev *hdev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -2975,6 +3020,25 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2975,6 +3020,25 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
goto unlock; goto unlock;
} }
/* Set the default Authenticated Payload Timeout after
* an LE Link is established. As per Core Spec v5.0, Vol 2, Part B
* Section 3.3, the HCI command WRITE_AUTH_PAYLOAD_TIMEOUT should be
* sent when the link is active and Encryption is enabled, the conn
* type can be either LE or ACL and controller must support LMP Ping.
* Ensure for AES-CCM encryption as well.
*/
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
test_bit(HCI_CONN_AES_CCM, &conn->flags) &&
((conn->type == ACL_LINK && lmp_ping_capable(hdev)) ||
(conn->type == LE_LINK && (hdev->le_features[0] & HCI_LE_PING)))) {
struct hci_cp_write_auth_payload_to cp;
cp.handle = cpu_to_le16(conn->handle);
cp.timeout = cpu_to_le16(hdev->auth_payload_timeout);
hci_send_cmd(conn->hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO,
sizeof(cp), &cp);
}
notify: notify:
if (conn->state == BT_CONFIG) { if (conn->state == BT_CONFIG) {
if (!ev->status) if (!ev->status)
...@@ -3170,6 +3234,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, ...@@ -3170,6 +3234,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_cc_write_sc_support(hdev, skb); hci_cc_write_sc_support(hdev, skb);
break; break;
case HCI_OP_READ_AUTH_PAYLOAD_TO:
hci_cc_read_auth_payload_timeout(hdev, skb);
break;
case HCI_OP_WRITE_AUTH_PAYLOAD_TO:
hci_cc_write_auth_payload_timeout(hdev, skb);
break;
case HCI_OP_READ_LOCAL_VERSION: case HCI_OP_READ_LOCAL_VERSION:
hci_cc_read_local_version(hdev, skb); hci_cc_read_local_version(hdev, skb);
break; break;
...@@ -5588,6 +5660,11 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, ...@@ -5588,6 +5660,11 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
return send_conn_param_neg_reply(hdev, handle, return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_UNKNOWN_CONN_ID); HCI_ERROR_UNKNOWN_CONN_ID);
if (min < hcon->le_conn_min_interval ||
max > hcon->le_conn_max_interval)
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_INVALID_LL_PARAMS);
if (hci_check_conn_params(min, max, latency, timeout)) if (hci_check_conn_params(min, max, latency, timeout))
return send_conn_param_neg_reply(hdev, handle, return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_INVALID_LL_PARAMS); HCI_ERROR_INVALID_LL_PARAMS);
......
...@@ -1601,7 +1601,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance) ...@@ -1601,7 +1601,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
cp.own_addr_type = own_addr_type; cp.own_addr_type = own_addr_type;
cp.channel_map = hdev->le_adv_channel_map; cp.channel_map = hdev->le_adv_channel_map;
cp.tx_power = 127; cp.tx_power = 127;
cp.handle = 0; cp.handle = instance;
if (flags & MGMT_ADV_FLAG_SEC_2M) { if (flags & MGMT_ADV_FLAG_SEC_2M) {
cp.primary_phy = HCI_ADV_PHY_1M; cp.primary_phy = HCI_ADV_PHY_1M;
...@@ -1643,11 +1643,21 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance) ...@@ -1643,11 +1643,21 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
return 0; return 0;
} }
void __hci_req_enable_ext_advertising(struct hci_request *req) int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance)
{ {
struct hci_dev *hdev = req->hdev;
struct hci_cp_le_set_ext_adv_enable *cp; struct hci_cp_le_set_ext_adv_enable *cp;
struct hci_cp_ext_adv_set *adv_set; struct hci_cp_ext_adv_set *adv_set;
u8 data[sizeof(*cp) + sizeof(*adv_set) * 1]; u8 data[sizeof(*cp) + sizeof(*adv_set) * 1];
struct adv_info *adv_instance;
if (instance > 0) {
adv_instance = hci_find_adv_instance(hdev, instance);
if (!adv_instance)
return -EINVAL;
} else {
adv_instance = NULL;
}
cp = (void *) data; cp = (void *) data;
adv_set = (void *) cp->data; adv_set = (void *) cp->data;
...@@ -1659,11 +1669,23 @@ void __hci_req_enable_ext_advertising(struct hci_request *req) ...@@ -1659,11 +1669,23 @@ void __hci_req_enable_ext_advertising(struct hci_request *req)
memset(adv_set, 0, sizeof(*adv_set)); memset(adv_set, 0, sizeof(*adv_set));
adv_set->handle = 0; adv_set->handle = instance;
/* Set duration per instance since controller is responsible for
* scheduling it.
*/
if (adv_instance && adv_instance->duration) {
u16 duration = adv_instance->duration * MSEC_PER_SEC;
/* Time = N * 10 ms */
adv_set->duration = cpu_to_le16(duration / 10);
}
hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE, hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_ENABLE,
sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets, sizeof(*cp) + sizeof(*adv_set) * cp->num_of_sets,
data); data);
return 0;
} }
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance) int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
...@@ -1679,7 +1701,7 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance) ...@@ -1679,7 +1701,7 @@ int __hci_req_start_ext_adv(struct hci_request *req, u8 instance)
return err; return err;
__hci_req_update_scan_rsp_data(req, instance); __hci_req_update_scan_rsp_data(req, instance);
__hci_req_enable_ext_advertising(req); __hci_req_enable_ext_advertising(req, instance);
return 0; return 0;
} }
...@@ -1723,10 +1745,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance, ...@@ -1723,10 +1745,13 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
adv_instance->remaining_time = adv_instance->remaining_time =
adv_instance->remaining_time - timeout; adv_instance->remaining_time - timeout;
hdev->adv_instance_timeout = timeout; /* Only use work for scheduling instances with legacy advertising */
queue_delayed_work(hdev->req_workqueue, if (!ext_adv_capable(hdev)) {
hdev->adv_instance_timeout = timeout;
queue_delayed_work(hdev->req_workqueue,
&hdev->adv_instance_expire, &hdev->adv_instance_expire,
msecs_to_jiffies(timeout * 1000)); msecs_to_jiffies(timeout * 1000));
}
/* If we're just re-scheduling the same instance again then do not /* If we're just re-scheduling the same instance again then do not
* execute any HCI commands. This happens when a single instance is * execute any HCI commands. This happens when a single instance is
...@@ -2744,7 +2769,8 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt) ...@@ -2744,7 +2769,8 @@ static int powered_update_hci(struct hci_request *req, unsigned long opt)
if (!ext_adv_capable(hdev)) if (!ext_adv_capable(hdev))
__hci_req_enable_advertising(req); __hci_req_enable_advertising(req);
else if (!err) else if (!err)
__hci_req_enable_ext_advertising(req); __hci_req_enable_ext_advertising(req,
0x00);
} }
} else if (!list_empty(&hdev->adv_instances)) { } else if (!list_empty(&hdev->adv_instances)) {
struct adv_info *adv_instance; struct adv_info *adv_instance;
......
...@@ -83,7 +83,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk, ...@@ -83,7 +83,7 @@ void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
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);
int __hci_req_start_ext_adv(struct hci_request *req, u8 instance); int __hci_req_start_ext_adv(struct hci_request *req, u8 instance);
void __hci_req_enable_ext_advertising(struct hci_request *req); int __hci_req_enable_ext_advertising(struct hci_request *req, u8 instance);
void __hci_req_clear_ext_adv_sets(struct hci_request *req); void __hci_req_clear_ext_adv_sets(struct hci_request *req);
int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, int hci_get_random_address(struct hci_dev *hdev, bool require_privacy,
bool use_rpa, struct adv_info *adv_instance, bool use_rpa, struct adv_info *adv_instance,
......
...@@ -775,7 +775,7 @@ static int hidp_setup_hid(struct hidp_session *session, ...@@ -775,7 +775,7 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->version = req->version; hid->version = req->version;
hid->country = req->country; hid->country = req->country;
strncpy(hid->name, req->name, sizeof(hid->name)); strscpy(hid->name, req->name, sizeof(hid->name));
snprintf(hid->phys, sizeof(hid->phys), "%pMR", snprintf(hid->phys, sizeof(hid->phys), "%pMR",
&l2cap_pi(session->ctrl_sock->sk)->chan->src); &l2cap_pi(session->ctrl_sock->sk)->chan->src);
......
...@@ -192,6 +192,7 @@ static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigne ...@@ -192,6 +192,7 @@ static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigne
ca.version = ca32.version; ca.version = ca32.version;
ca.flags = ca32.flags; ca.flags = ca32.flags;
ca.idle_to = ca32.idle_to; ca.idle_to = ca32.idle_to;
ca32.name[sizeof(ca32.name) - 1] = '\0';
memcpy(ca.name, ca32.name, 128); memcpy(ca.name, ca32.name, 128);
csock = sockfd_lookup(ca.ctrl_sock, &err); csock = sockfd_lookup(ca.ctrl_sock, &err);
......
...@@ -168,11 +168,18 @@ static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn, ...@@ -168,11 +168,18 @@ static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
return c; return c;
} }
static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
u8 src_type)
{ {
struct l2cap_chan *c; struct l2cap_chan *c;
list_for_each_entry(c, &chan_list, global_l) { list_for_each_entry(c, &chan_list, global_l) {
if (src_type == BDADDR_BREDR && c->src_type != BDADDR_BREDR)
continue;
if (src_type != BDADDR_BREDR && c->src_type == BDADDR_BREDR)
continue;
if (c->sport == psm && !bacmp(&c->src, src)) if (c->sport == psm && !bacmp(&c->src, src))
return c; return c;
} }
...@@ -185,7 +192,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) ...@@ -185,7 +192,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
write_lock(&chan_list_lock); write_lock(&chan_list_lock);
if (psm && __l2cap_global_chan_by_addr(psm, src)) { if (psm && __l2cap_global_chan_by_addr(psm, src, chan->src_type)) {
err = -EADDRINUSE; err = -EADDRINUSE;
goto done; goto done;
} }
...@@ -209,7 +216,8 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) ...@@ -209,7 +216,8 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
err = -EINVAL; err = -EINVAL;
for (p = start; p <= end; p += incr) for (p = start; p <= end; p += incr)
if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src,
chan->src_type)) {
chan->psm = cpu_to_le16(p); chan->psm = cpu_to_le16(p);
chan->sport = cpu_to_le16(p); chan->sport = cpu_to_le16(p);
err = 0; err = 0;
...@@ -4394,6 +4402,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, ...@@ -4394,6 +4402,12 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
if (chan->state != BT_DISCONN) {
l2cap_chan_unlock(chan);
mutex_unlock(&conn->chan_lock);
return 0;
}
l2cap_chan_hold(chan); l2cap_chan_hold(chan);
l2cap_chan_del(chan, 0); l2cap_chan_del(chan, 0);
...@@ -5291,7 +5305,14 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, ...@@ -5291,7 +5305,14 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
memset(&rsp, 0, sizeof(rsp)); memset(&rsp, 0, sizeof(rsp));
err = hci_check_conn_params(min, max, latency, to_multiplier); if (min < hcon->le_conn_min_interval ||
max > hcon->le_conn_max_interval) {
BT_DBG("requested connection interval exceeds current bounds.");
err = -EINVAL;
} else {
err = hci_check_conn_params(min, max, latency, to_multiplier);
}
if (err) if (err)
rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
else else
......
...@@ -2579,6 +2579,19 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, ...@@ -2579,6 +2579,19 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
goto distribute; goto distribute;
} }
/* Drop IRK if peer is using identity address during pairing but is
* providing different address as identity information.
*
* Microsoft Surface Precision Mouse is known to have this bug.
*/
if (hci_is_identity_address(&hcon->dst, hcon->dst_type) &&
(bacmp(&info->bdaddr, &hcon->dst) ||
info->addr_type != hcon->dst_type)) {
bt_dev_err(hcon->hdev,
"ignoring IRK with invalid identity address");
goto distribute;
}
bacpy(&smp->id_addr, &info->bdaddr); bacpy(&smp->id_addr, &info->bdaddr);
smp->id_addr_type = info->addr_type; smp->id_addr_type = info->addr_type;
......
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