Commit 53fb430e authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-next-2022-03-18' of...

Merge tag 'for-net-next-2022-03-18' 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 Asus TF103C
 - Add support for Realtek RTL8852B
 - Add support for Realtek RTL8723BE
 - Add WBS support to mt7921s

* tag 'for-net-next-2022-03-18' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: (24 commits)
  Bluetooth: ath3k: remove superfluous header files
  Bluetooth: bcm203x: remove superfluous header files
  Bluetooth: hci_bcm: Add the Asus TF103C to the bcm_broken_irq_dmi_table
  Bluetooth: mt7921s: Add WBS support
  Bluetooth: mt7921s: Add .btmtk_get_codec_config_data
  Bluetooth: mt7921s: Add .get_data_path_id
  Bluetooth: mt7921s: Set HCI_QUIRK_VALID_LE_STATES
  Bluetooth: btmtksdio: Fix kernel oops in btmtksdio_interrupt
  Bluetooth: btmtkuart: fix error handling in mtk_hci_wmt_sync()
  Bluetooth: call hci_le_conn_failed with hdev lock in hci_le_conn_failed
  Bluetooth: Send AdvMonitor Dev Found for all matched devices
  Bluetooth: msft: Clear tracked devices on resume
  Bluetooth: fix incorrect nonblock bitmask in bt_sock_wait_ready()
  Bluetooth: Don't assign twice the same value
  Bluetooth: btrtl: Add support for RTL8852B
  Bluetooth: hci_uart: add missing NULL check in h5_enqueue
  Bluetooth: Fix use after free in hci_send_acl
  Bluetooth: btusb: Use quirk to skip HCI_FLT_CLEAR_ALL on fake CSR controllers
  Bluetooth: hci_sync: Add a new quirk to skip HCI_FLT_CLEAR_ALL
  Bluetooth: btmtkuart: fix the conflict between mtk and msft vendor event
  ...
====================

Link: https://lore.kernel.org/r/20220318224752.1477292-1-luiz.dentz@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 79fdce05 726c0eb7
...@@ -400,6 +400,7 @@ config BT_MTKSDIO ...@@ -400,6 +400,7 @@ config BT_MTKSDIO
config BT_MTKUART config BT_MTKUART
tristate "MediaTek HCI UART driver" tristate "MediaTek HCI UART driver"
depends on SERIAL_DEV_BUS depends on SERIAL_DEV_BUS
select BT_MTK
help help
MediaTek Bluetooth HCI UART driver. MediaTek Bluetooth HCI UART driver.
This driver is required if you want to use MediaTek Bluetooth This driver is required if you want to use MediaTek Bluetooth
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/device.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/atomic.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
......
...@@ -285,6 +285,7 @@ MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>"); ...@@ -285,6 +285,7 @@ MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION); MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_MT7622);
MODULE_FIRMWARE(FIRMWARE_MT7663); MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668); MODULE_FIRMWARE(FIRMWARE_MT7668);
MODULE_FIRMWARE(FIRMWARE_MT7961); MODULE_FIRMWARE(FIRMWARE_MT7961);
/* SPDX-License-Identifier: ISC */ /* SPDX-License-Identifier: ISC */
/* Copyright (C) 2021 MediaTek Inc. */ /* Copyright (C) 2021 MediaTek Inc. */
#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin" #define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
......
...@@ -936,6 +936,62 @@ static int btmtksdio_mtk_reg_write(struct hci_dev *hdev, u32 reg, u32 val, u32 m ...@@ -936,6 +936,62 @@ static int btmtksdio_mtk_reg_write(struct hci_dev *hdev, u32 reg, u32 val, u32 m
return err; return err;
} }
static int btmtksdio_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id)
{
/* uses 1 as data path id for all the usecases */
*data_path_id = 1;
return 0;
}
static int btmtksdio_get_codec_config_data(struct hci_dev *hdev,
__u8 link, struct bt_codec *codec,
__u8 *ven_len, __u8 **ven_data)
{
int err = 0;
if (!ven_data || !ven_len)
return -EINVAL;
*ven_len = 0;
*ven_data = NULL;
if (link != ESCO_LINK) {
bt_dev_err(hdev, "Invalid link type(%u)", link);
return -EINVAL;
}
*ven_data = kmalloc(sizeof(__u8), GFP_KERNEL);
if (!ven_data) {
err = -ENOMEM;
goto error;
}
/* supports only CVSD and mSBC offload codecs */
switch (codec->id) {
case 0x02:
**ven_data = 0x00;
break;
case 0x05:
**ven_data = 0x01;
break;
default:
err = -EINVAL;
bt_dev_err(hdev, "Invalid codec id(%u)", codec->id);
goto error;
}
/* codec and its capabilities are pre-defined to ids
* preset id = 0x00 represents CVSD codec with sampling rate 8K
* preset id = 0x01 represents mSBC codec with sampling rate 16K
*/
*ven_len = sizeof(__u8);
return err;
error:
kfree(*ven_data);
*ven_data = NULL;
return err;
}
static int btmtksdio_sco_setting(struct hci_dev *hdev) static int btmtksdio_sco_setting(struct hci_dev *hdev)
{ {
const struct btmtk_sco sco_setting = { const struct btmtk_sco sco_setting = {
...@@ -968,7 +1024,14 @@ static int btmtksdio_sco_setting(struct hci_dev *hdev) ...@@ -968,7 +1024,14 @@ static int btmtksdio_sco_setting(struct hci_dev *hdev)
return err; return err;
val |= 0x00000101; val |= 0x00000101;
return btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0); err = btmtksdio_mtk_reg_write(hdev, MT7921_PINMUX_1, val, ~0);
if (err < 0)
return err;
hdev->get_data_path_id = btmtksdio_get_data_path_id;
hdev->get_codec_config_data = btmtksdio_get_codec_config_data;
return err;
} }
static int btmtksdio_reset_setting(struct hci_dev *hdev) static int btmtksdio_reset_setting(struct hci_dev *hdev)
...@@ -1060,6 +1123,9 @@ static int btmtksdio_setup(struct hci_dev *hdev) ...@@ -1060,6 +1123,9 @@ static int btmtksdio_setup(struct hci_dev *hdev)
return err; return err;
} }
/* Enable WBS with mSBC codec */
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
/* Enable GPIO reset mechanism */ /* Enable GPIO reset mechanism */
if (bdev->reset) { if (bdev->reset) {
err = btmtksdio_reset_setting(hdev); err = btmtksdio_reset_setting(hdev);
...@@ -1070,6 +1136,9 @@ static int btmtksdio_setup(struct hci_dev *hdev) ...@@ -1070,6 +1136,9 @@ static int btmtksdio_setup(struct hci_dev *hdev)
} }
} }
/* Valid LE States quirk for MediaTek 7921 */
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
break; break;
case 0x7663: case 0x7663:
case 0x7668: case 0x7668:
...@@ -1281,6 +1350,8 @@ static int btmtksdio_probe(struct sdio_func *func, ...@@ -1281,6 +1350,8 @@ static int btmtksdio_probe(struct sdio_func *func,
hdev->manufacturer = 70; hdev->manufacturer = 70;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
sdio_set_drvdata(func, bdev);
err = hci_register_dev(hdev); err = hci_register_dev(hdev);
if (err < 0) { if (err < 0) {
dev_err(&func->dev, "Can't register HCI device\n"); dev_err(&func->dev, "Can't register HCI device\n");
...@@ -1288,8 +1359,6 @@ static int btmtksdio_probe(struct sdio_func *func, ...@@ -1288,8 +1359,6 @@ static int btmtksdio_probe(struct sdio_func *func,
return err; return err;
} }
sdio_set_drvdata(func, bdev);
/* pm_runtime_enable would be done after the firmware is being /* pm_runtime_enable would be done after the firmware is being
* downloaded because the core layer probably already enables * downloaded because the core layer probably already enables
* runtime PM for this func such as the case host->caps & * runtime PM for this func such as the case host->caps &
......
...@@ -28,13 +28,10 @@ ...@@ -28,13 +28,10 @@
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#include "h4_recv.h" #include "h4_recv.h"
#include "btmtk.h"
#define VERSION "0.2" #define VERSION "0.2"
#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
#define MTK_STP_TLR_SIZE 2 #define MTK_STP_TLR_SIZE 2
#define BTMTKUART_TX_STATE_ACTIVE 1 #define BTMTKUART_TX_STATE_ACTIVE 1
...@@ -44,25 +41,6 @@ ...@@ -44,25 +41,6 @@
#define BTMTKUART_FLAG_STANDALONE_HW BIT(0) #define BTMTKUART_FLAG_STANDALONE_HW BIT(0)
enum {
MTK_WMT_PATCH_DWNLD = 0x1,
MTK_WMT_TEST = 0x2,
MTK_WMT_WAKEUP = 0x3,
MTK_WMT_HIF = 0x4,
MTK_WMT_FUNC_CTRL = 0x6,
MTK_WMT_RST = 0x7,
MTK_WMT_SEMAPHORE = 0x17,
};
enum {
BTMTK_WMT_INVALID,
BTMTK_WMT_PATCH_UNDONE,
BTMTK_WMT_PATCH_DONE,
BTMTK_WMT_ON_UNDONE,
BTMTK_WMT_ON_DONE,
BTMTK_WMT_ON_PROGRESS,
};
struct mtk_stp_hdr { struct mtk_stp_hdr {
u8 prefix; u8 prefix;
__be16 dlen; __be16 dlen;
...@@ -74,44 +52,6 @@ struct btmtkuart_data { ...@@ -74,44 +52,6 @@ struct btmtkuart_data {
const char *fwname; const char *fwname;
}; };
struct mtk_wmt_hdr {
u8 dir;
u8 op;
__le16 dlen;
u8 flag;
} __packed;
struct mtk_hci_wmt_cmd {
struct mtk_wmt_hdr hdr;
u8 data[256];
} __packed;
struct btmtk_hci_wmt_evt {
struct hci_event_hdr hhdr;
struct mtk_wmt_hdr whdr;
} __packed;
struct btmtk_hci_wmt_evt_funcc {
struct btmtk_hci_wmt_evt hwhdr;
__be16 status;
} __packed;
struct btmtk_tci_sleep {
u8 mode;
__le16 duration;
__le16 host_duration;
u8 host_wakeup_pin;
u8 time_compensation;
} __packed;
struct btmtk_hci_wmt_params {
u8 op;
u8 flag;
u16 dlen;
const void *data;
u32 *status;
};
struct btmtkuart_dev { struct btmtkuart_dev {
struct hci_dev *hdev; struct hci_dev *hdev;
struct serdev_device *serdev; struct serdev_device *serdev;
...@@ -153,29 +93,36 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, ...@@ -153,29 +93,36 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
u32 hlen, status = BTMTK_WMT_INVALID; u32 hlen, status = BTMTK_WMT_INVALID;
struct btmtk_hci_wmt_evt *wmt_evt; struct btmtk_hci_wmt_evt *wmt_evt;
struct mtk_hci_wmt_cmd wc; struct btmtk_hci_wmt_cmd *wc;
struct mtk_wmt_hdr *hdr; struct btmtk_wmt_hdr *hdr;
int err; int err;
/* Send the WMT command and wait until the WMT event returns */
hlen = sizeof(*hdr) + wmt_params->dlen; hlen = sizeof(*hdr) + wmt_params->dlen;
if (hlen > 255) { if (hlen > 255) {
err = -EINVAL; err = -EINVAL;
goto err_free_skb; goto err_free_skb;
} }
hdr = (struct mtk_wmt_hdr *)&wc; wc = kzalloc(hlen, GFP_KERNEL);
if (!wc) {
err = -ENOMEM;
goto err_free_skb;
}
hdr = &wc->hdr;
hdr->dir = 1; hdr->dir = 1;
hdr->op = wmt_params->op; hdr->op = wmt_params->op;
hdr->dlen = cpu_to_le16(wmt_params->dlen + 1); hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
hdr->flag = wmt_params->flag; hdr->flag = wmt_params->flag;
memcpy(wc.data, wmt_params->data, wmt_params->dlen); memcpy(wc->data, wmt_params->data, wmt_params->dlen);
set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc); err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
if (err < 0) { if (err < 0) {
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
goto err_free_skb; goto err_free_wc;
} }
/* The vendor specific WMT commands are all answered by a vendor /* The vendor specific WMT commands are all answered by a vendor
...@@ -192,14 +139,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, ...@@ -192,14 +139,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
if (err == -EINTR) { if (err == -EINTR) {
bt_dev_err(hdev, "Execution of wmt command interrupted"); bt_dev_err(hdev, "Execution of wmt command interrupted");
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
goto err_free_skb; goto err_free_wc;
} }
if (err) { if (err) {
bt_dev_err(hdev, "Execution of wmt command timed out"); bt_dev_err(hdev, "Execution of wmt command timed out");
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
err = -ETIMEDOUT; err = -ETIMEDOUT;
goto err_free_skb; goto err_free_wc;
} }
/* Parse and handle the return WMT event */ /* Parse and handle the return WMT event */
...@@ -208,17 +155,17 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, ...@@ -208,17 +155,17 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
bt_dev_err(hdev, "Wrong op received %d expected %d", bt_dev_err(hdev, "Wrong op received %d expected %d",
wmt_evt->whdr.op, hdr->op); wmt_evt->whdr.op, hdr->op);
err = -EIO; err = -EIO;
goto err_free_skb; goto err_free_wc;
} }
switch (wmt_evt->whdr.op) { switch (wmt_evt->whdr.op) {
case MTK_WMT_SEMAPHORE: case BTMTK_WMT_SEMAPHORE:
if (wmt_evt->whdr.flag == 2) if (wmt_evt->whdr.flag == 2)
status = BTMTK_WMT_PATCH_UNDONE; status = BTMTK_WMT_PATCH_UNDONE;
else else
status = BTMTK_WMT_PATCH_DONE; status = BTMTK_WMT_PATCH_DONE;
break; break;
case MTK_WMT_FUNC_CTRL: case BTMTK_WMT_FUNC_CTRL:
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404) if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
status = BTMTK_WMT_ON_DONE; status = BTMTK_WMT_ON_DONE;
...@@ -232,6 +179,8 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, ...@@ -232,6 +179,8 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
if (wmt_params->status) if (wmt_params->status)
*wmt_params->status = status; *wmt_params->status = status;
err_free_wc:
kfree(wc);
err_free_skb: err_free_skb:
kfree_skb(bdev->evt_skb); kfree_skb(bdev->evt_skb);
bdev->evt_skb = NULL; bdev->evt_skb = NULL;
...@@ -239,95 +188,12 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, ...@@ -239,95 +188,12 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
return err; return err;
} }
static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname)
{
struct btmtk_hci_wmt_params wmt_params;
const struct firmware *fw;
const u8 *fw_ptr;
size_t fw_size;
int err, dlen;
u8 flag;
err = request_firmware(&fw, fwname, &hdev->dev);
if (err < 0) {
bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
return err;
}
fw_ptr = fw->data;
fw_size = fw->size;
/* The size of patch header is 30 bytes, should be skip */
if (fw_size < 30) {
err = -EINVAL;
goto free_fw;
}
fw_size -= 30;
fw_ptr += 30;
flag = 1;
wmt_params.op = MTK_WMT_PATCH_DWNLD;
wmt_params.status = NULL;
while (fw_size > 0) {
dlen = min_t(int, 250, fw_size);
/* Tell device the position in sequence */
if (fw_size - dlen <= 0)
flag = 3;
else if (fw_size < fw->size - 30)
flag = 2;
wmt_params.flag = flag;
wmt_params.dlen = dlen;
wmt_params.data = fw_ptr;
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
err);
goto free_fw;
}
fw_size -= dlen;
fw_ptr += dlen;
}
wmt_params.op = MTK_WMT_RST;
wmt_params.flag = 4;
wmt_params.dlen = 0;
wmt_params.data = NULL;
wmt_params.status = NULL;
/* Activate funciton the firmware providing to */
err = mtk_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
goto free_fw;
}
/* Wait a few moments for firmware activation done */
usleep_range(10000, 12000);
free_fw:
release_firmware(fw);
return err;
}
static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb) static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
struct hci_event_hdr *hdr = (void *)skb->data; struct hci_event_hdr *hdr = (void *)skb->data;
int err; int err;
/* Fix up the vendor event id with 0xff for vendor specific instead
* of 0xe4 so that event send via monitoring socket can be parsed
* properly.
*/
if (hdr->evt == 0xe4)
hdr->evt = HCI_EV_VENDOR;
/* When someone waits for the WMT event, the skb is being cloned /* When someone waits for the WMT event, the skb is being cloned
* and being processed the events from there then. * and being processed the events from there then.
*/ */
...@@ -343,7 +209,7 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -343,7 +209,7 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
if (err < 0) if (err < 0)
goto err_free_skb; goto err_free_skb;
if (hdr->evt == HCI_EV_VENDOR) { if (hdr->evt == HCI_EV_WMT) {
if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT, if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT,
&bdev->tx_state)) { &bdev->tx_state)) {
/* Barrier to sync with other CPUs */ /* Barrier to sync with other CPUs */
...@@ -645,7 +511,7 @@ static int btmtkuart_func_query(struct hci_dev *hdev) ...@@ -645,7 +511,7 @@ static int btmtkuart_func_query(struct hci_dev *hdev)
u8 param = 0; u8 param = 0;
/* Query whether the function is enabled */ /* Query whether the function is enabled */
wmt_params.op = MTK_WMT_FUNC_CTRL; wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 4; wmt_params.flag = 4;
wmt_params.dlen = sizeof(param); wmt_params.dlen = sizeof(param);
wmt_params.data = &param; wmt_params.data = &param;
...@@ -672,7 +538,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev) ...@@ -672,7 +538,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
* ready to change a new baudrate. * ready to change a new baudrate.
*/ */
baudrate = cpu_to_le32(bdev->desired_speed); baudrate = cpu_to_le32(bdev->desired_speed);
wmt_params.op = MTK_WMT_HIF; wmt_params.op = BTMTK_WMT_HIF;
wmt_params.flag = 1; wmt_params.flag = 1;
wmt_params.dlen = 4; wmt_params.dlen = 4;
wmt_params.data = &baudrate; wmt_params.data = &baudrate;
...@@ -706,7 +572,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev) ...@@ -706,7 +572,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
usleep_range(20000, 22000); usleep_range(20000, 22000);
/* Test the new baudrate */ /* Test the new baudrate */
wmt_params.op = MTK_WMT_TEST; wmt_params.op = BTMTK_WMT_TEST;
wmt_params.flag = 7; wmt_params.flag = 7;
wmt_params.dlen = 0; wmt_params.dlen = 0;
wmt_params.data = NULL; wmt_params.data = NULL;
...@@ -741,7 +607,7 @@ static int btmtkuart_setup(struct hci_dev *hdev) ...@@ -741,7 +607,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
* do any setups. * do any setups.
*/ */
if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) { if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) {
wmt_params.op = MTK_WMT_WAKEUP; wmt_params.op = BTMTK_WMT_WAKEUP;
wmt_params.flag = 3; wmt_params.flag = 3;
wmt_params.dlen = 0; wmt_params.dlen = 0;
wmt_params.data = NULL; wmt_params.data = NULL;
...@@ -760,7 +626,7 @@ static int btmtkuart_setup(struct hci_dev *hdev) ...@@ -760,7 +626,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
btmtkuart_change_baudrate(hdev); btmtkuart_change_baudrate(hdev);
/* Query whether the firmware is already download */ /* Query whether the firmware is already download */
wmt_params.op = MTK_WMT_SEMAPHORE; wmt_params.op = BTMTK_WMT_SEMAPHORE;
wmt_params.flag = 1; wmt_params.flag = 1;
wmt_params.dlen = 0; wmt_params.dlen = 0;
wmt_params.data = NULL; wmt_params.data = NULL;
...@@ -778,7 +644,7 @@ static int btmtkuart_setup(struct hci_dev *hdev) ...@@ -778,7 +644,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
} }
/* Setup a firmware which the device definitely requires */ /* Setup a firmware which the device definitely requires */
err = mtk_setup_firmware(hdev, bdev->data->fwname); err = btmtk_setup_firmware(hdev, bdev->data->fwname, mtk_hci_wmt_sync);
if (err < 0) if (err < 0)
return err; return err;
...@@ -801,7 +667,7 @@ static int btmtkuart_setup(struct hci_dev *hdev) ...@@ -801,7 +667,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
} }
/* Enable Bluetooth protocol */ /* Enable Bluetooth protocol */
wmt_params.op = MTK_WMT_FUNC_CTRL; wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0; wmt_params.flag = 0;
wmt_params.dlen = sizeof(param); wmt_params.dlen = sizeof(param);
wmt_params.data = &param; wmt_params.data = &param;
...@@ -846,7 +712,7 @@ static int btmtkuart_shutdown(struct hci_dev *hdev) ...@@ -846,7 +712,7 @@ static int btmtkuart_shutdown(struct hci_dev *hdev)
int err; int err;
/* Disable the device */ /* Disable the device */
wmt_params.op = MTK_WMT_FUNC_CTRL; wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0; wmt_params.flag = 0;
wmt_params.dlen = sizeof(param); wmt_params.dlen = sizeof(param);
wmt_params.data = &param; wmt_params.data = &param;
...@@ -1007,6 +873,7 @@ static int btmtkuart_probe(struct serdev_device *serdev) ...@@ -1007,6 +873,7 @@ static int btmtkuart_probe(struct serdev_device *serdev)
hdev->setup = btmtkuart_setup; hdev->setup = btmtkuart_setup;
hdev->shutdown = btmtkuart_shutdown; hdev->shutdown = btmtkuart_shutdown;
hdev->send = btmtkuart_send_frame; hdev->send = btmtkuart_send_frame;
hdev->set_bdaddr = btmtk_set_bdaddr;
SET_HCIDEV_DEV(hdev, &serdev->dev); SET_HCIDEV_DEV(hdev, &serdev->dev);
hdev->manufacturer = 70; hdev->manufacturer = 70;
...@@ -1131,6 +998,3 @@ MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); ...@@ -1131,6 +998,3 @@ MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION); MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_MT7622);
MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668);
...@@ -49,6 +49,7 @@ enum btrtl_chip_id { ...@@ -49,6 +49,7 @@ enum btrtl_chip_id {
CHIP_ID_8822C = 13, CHIP_ID_8822C = 13,
CHIP_ID_8761B, CHIP_ID_8761B,
CHIP_ID_8852A = 18, CHIP_ID_8852A = 18,
CHIP_ID_8852B = 20,
}; };
struct id_table { struct id_table {
...@@ -187,6 +188,14 @@ static const struct id_table ic_id_table[] = { ...@@ -187,6 +188,14 @@ static const struct id_table ic_id_table[] = {
.has_msft_ext = true, .has_msft_ext = true,
.fw_name = "rtl_bt/rtl8852au_fw.bin", .fw_name = "rtl_bt/rtl8852au_fw.bin",
.cfg_name = "rtl_bt/rtl8852au_config" }, .cfg_name = "rtl_bt/rtl8852au_config" },
/* 8852B */
{ IC_INFO(RTL_ROM_LMP_8852A, 0xb, 0xb, HCI_USB),
.config_needed = false,
.has_rom_version = true,
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8852bu_fw.bin",
.cfg_name = "rtl_bt/rtl8852bu_config" },
}; };
static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev, static const struct id_table *btrtl_match_ic(u16 lmp_subver, u16 hci_rev,
...@@ -295,6 +304,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev, ...@@ -295,6 +304,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
{ RTL_ROM_LMP_8822B, 13 }, /* 8822C */ { RTL_ROM_LMP_8822B, 13 }, /* 8822C */
{ RTL_ROM_LMP_8761A, 14 }, /* 8761B */ { RTL_ROM_LMP_8761A, 14 }, /* 8761B */
{ RTL_ROM_LMP_8852A, 18 }, /* 8852A */ { RTL_ROM_LMP_8852A, 18 }, /* 8852A */
{ RTL_ROM_LMP_8852A, 20 }, /* 8852B */
}; };
min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3; min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
...@@ -757,6 +767,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev) ...@@ -757,6 +767,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
switch (btrtl_dev->project_id) { switch (btrtl_dev->project_id) {
case CHIP_ID_8822C: case CHIP_ID_8822C:
case CHIP_ID_8852A: case CHIP_ID_8852A:
case CHIP_ID_8852B:
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
hci_set_aosp_capable(hdev); hci_set_aosp_capable(hdev);
...@@ -934,3 +945,5 @@ MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin"); ...@@ -934,3 +945,5 @@ MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin");
...@@ -477,6 +477,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -477,6 +477,7 @@ static const struct usb_device_id blacklist_table[] = {
/* Additional Realtek 8723BE Bluetooth devices */ /* Additional Realtek 8723BE Bluetooth devices */
{ USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x04f2, 0xb49f), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
...@@ -2057,6 +2058,8 @@ static int btusb_setup_csr(struct hci_dev *hdev) ...@@ -2057,6 +2058,8 @@ static int btusb_setup_csr(struct hci_dev *hdev)
*/ */
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
/* Clear the reset quirk since this is not an actual /* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR. * early Bluetooth 1.1 device from CSR.
...@@ -2067,7 +2070,7 @@ static int btusb_setup_csr(struct hci_dev *hdev) ...@@ -2067,7 +2070,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
/* /*
* Special workaround for these BT 4.0 chip clones, and potentially more: * Special workaround for these BT 4.0 chip clones, and potentially more:
* *
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x1012 sub: 0x0810) * - 0x0134: a Barrot 8041a02 (HCI rev: 0x0810 sub: 0x1012)
* - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709) * - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709)
* *
* These controllers are really messed-up. * These controllers are really messed-up.
...@@ -2096,7 +2099,7 @@ static int btusb_setup_csr(struct hci_dev *hdev) ...@@ -2096,7 +2099,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
if (ret >= 0) if (ret >= 0)
msleep(200); msleep(200);
else else
bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround"); bt_dev_warn(hdev, "CSR: Couldn't suspend the device for our Barrot 8041a02 receive-issue workaround");
pm_runtime_forbid(&data->udev->dev); pm_runtime_forbid(&data->udev->dev);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dmi.h> #include <linux/dmi.h>
...@@ -870,7 +871,23 @@ static int bcm_resume(struct device *dev) ...@@ -870,7 +871,23 @@ static int bcm_resume(struct device *dev)
#endif #endif
/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */ /* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
static struct gpiod_lookup_table asus_tf103c_irq_gpios = {
.dev_id = "serial0-0",
.table = {
GPIO_LOOKUP("INT33FC:02", 17, "host-wakeup-alt", GPIO_ACTIVE_HIGH),
{ }
},
};
static const struct dmi_system_id bcm_broken_irq_dmi_table[] = { static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
{
.ident = "Asus TF103C",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
},
.driver_data = &asus_tf103c_irq_gpios,
},
{ {
.ident = "Meegopad T08", .ident = "Meegopad T08",
.matches = { .matches = {
...@@ -1027,7 +1044,8 @@ static struct clk *bcm_get_txco(struct device *dev) ...@@ -1027,7 +1044,8 @@ static struct clk *bcm_get_txco(struct device *dev)
static int bcm_get_resources(struct bcm_device *dev) static int bcm_get_resources(struct bcm_device *dev)
{ {
const struct dmi_system_id *dmi_id; const struct dmi_system_id *broken_irq_dmi_id;
const char *irq_con_id = "host-wakeup";
int err; int err;
dev->name = dev_name(dev->dev); dev->name = dev_name(dev->dev);
...@@ -1083,23 +1101,33 @@ static int bcm_get_resources(struct bcm_device *dev) ...@@ -1083,23 +1101,33 @@ static int bcm_get_resources(struct bcm_device *dev)
if (err) if (err)
return err; return err;
broken_irq_dmi_id = dmi_first_match(bcm_broken_irq_dmi_table);
if (broken_irq_dmi_id && broken_irq_dmi_id->driver_data) {
gpiod_add_lookup_table(broken_irq_dmi_id->driver_data);
irq_con_id = "host-wakeup-alt";
dev->irq_active_low = false;
dev->irq = 0;
}
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */ /* IRQ can be declared in ACPI table as Interrupt or GpioInt */
if (dev->irq <= 0) { if (dev->irq <= 0) {
struct gpio_desc *gpio; struct gpio_desc *gpio;
gpio = devm_gpiod_get_optional(dev->dev, "host-wakeup", gpio = devm_gpiod_get_optional(dev->dev, irq_con_id, GPIOD_IN);
GPIOD_IN);
if (IS_ERR(gpio)) if (IS_ERR(gpio))
return PTR_ERR(gpio); return PTR_ERR(gpio);
dev->irq = gpiod_to_irq(gpio); dev->irq = gpiod_to_irq(gpio);
} }
dmi_id = dmi_first_match(bcm_broken_irq_dmi_table); if (broken_irq_dmi_id) {
if (dmi_id) { if (broken_irq_dmi_id->driver_data) {
dev_info(dev->dev, "%s: Has a broken IRQ config, disabling IRQ support / runtime-pm\n", gpiod_remove_lookup_table(broken_irq_dmi_id->driver_data);
dmi_id->ident); } else {
dev->irq = 0; dev_info(dev->dev, "%s: Has a broken IRQ config, disabling IRQ support / runtime-pm\n",
broken_irq_dmi_id->ident);
dev->irq = 0;
}
} }
dev_dbg(dev->dev, "BCM irq: %d\n", dev->irq); dev_dbg(dev->dev, "BCM irq: %d\n", dev->irq);
......
...@@ -629,9 +629,11 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -629,9 +629,11 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
break; break;
} }
pm_runtime_get_sync(&hu->serdev->dev); if (hu->serdev) {
pm_runtime_mark_last_busy(&hu->serdev->dev); pm_runtime_get_sync(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev); pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
}
return 0; return 0;
} }
......
...@@ -345,7 +345,7 @@ int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -345,7 +345,7 @@ int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg,
__poll_t bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); __poll_t bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
int bt_sock_wait_ready(struct sock *sk, unsigned long flags); int bt_sock_wait_ready(struct sock *sk, unsigned int msg_flags);
void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh); void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh);
void bt_accept_unlink(struct sock *sk); void bt_accept_unlink(struct sock *sk);
......
...@@ -255,6 +255,16 @@ enum { ...@@ -255,6 +255,16 @@ enum {
* during the hdev->setup vendor callback. * during the hdev->setup vendor callback.
*/ */
HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER,
/* When this quirk is set, HCI_OP_SET_EVENT_FLT requests with
* HCI_FLT_CLEAR_ALL are ignored and event filtering is
* completely avoided. A subset of the CSR controller
* clones struggle with this and instantly lock up.
*
* Note that devices using this must (separately) disable
* runtime suspend, because event filtering takes place there.
*/
HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL,
}; };
/* HCI device flags */ /* HCI device flags */
......
...@@ -568,7 +568,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) ...@@ -568,7 +568,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
EXPORT_SYMBOL(bt_sock_wait_state); EXPORT_SYMBOL(bt_sock_wait_state);
/* This function expects the sk lock to be held when called */ /* This function expects the sk lock to be held when called */
int bt_sock_wait_ready(struct sock *sk, unsigned long flags) int bt_sock_wait_ready(struct sock *sk, unsigned int msg_flags)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
unsigned long timeo; unsigned long timeo;
...@@ -576,7 +576,7 @@ int bt_sock_wait_ready(struct sock *sk, unsigned long flags) ...@@ -576,7 +576,7 @@ int bt_sock_wait_ready(struct sock *sk, unsigned long flags)
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); timeo = sock_sndtimeo(sk, !!(msg_flags & MSG_DONTWAIT));
add_wait_queue(sk_sleep(sk), &wait); add_wait_queue(sk_sleep(sk), &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
......
...@@ -669,7 +669,9 @@ static void le_conn_timeout(struct work_struct *work) ...@@ -669,7 +669,9 @@ static void le_conn_timeout(struct work_struct *work)
if (conn->role == HCI_ROLE_SLAVE) { if (conn->role == HCI_ROLE_SLAVE) {
/* Disable LE Advertising */ /* Disable LE Advertising */
le_disable_advertising(hdev); le_disable_advertising(hdev);
hci_dev_lock(hdev);
hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT); hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
hci_dev_unlock(hdev);
return; return;
} }
......
...@@ -5453,8 +5453,9 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data, ...@@ -5453,8 +5453,9 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (hcon) { if (hcon && hcon->type == AMP_LINK) {
hcon->state = BT_CLOSED; hcon->state = BT_CLOSED;
hci_disconn_cfm(hcon, ev->reason);
hci_conn_del(hcon); hci_conn_del(hcon);
} }
......
...@@ -2809,6 +2809,9 @@ static int hci_set_event_filter_sync(struct hci_dev *hdev, u8 flt_type, ...@@ -2809,6 +2809,9 @@ static int hci_set_event_filter_sync(struct hci_dev *hdev, u8 flt_type,
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return 0; return 0;
if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks))
return 0;
memset(&cp, 0, sizeof(cp)); memset(&cp, 0, sizeof(cp));
cp.flt_type = flt_type; cp.flt_type = flt_type;
...@@ -2829,6 +2832,13 @@ static int hci_clear_event_filter_sync(struct hci_dev *hdev) ...@@ -2829,6 +2832,13 @@ static int hci_clear_event_filter_sync(struct hci_dev *hdev)
if (!hci_dev_test_flag(hdev, HCI_EVENT_FILTER_CONFIGURED)) if (!hci_dev_test_flag(hdev, HCI_EVENT_FILTER_CONFIGURED))
return 0; return 0;
/* In theory the state machine should not reach here unless
* a hci_set_event_filter_sync() call succeeds, but we do
* the check both for parity and as a future reminder.
*/
if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks))
return 0;
return hci_set_event_filter_sync(hdev, HCI_FLT_CLEAR_ALL, 0x00, return hci_set_event_filter_sync(hdev, HCI_FLT_CLEAR_ALL, 0x00,
BDADDR_ANY, 0x00); BDADDR_ANY, 0x00);
} }
...@@ -4828,6 +4838,12 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev) ...@@ -4828,6 +4838,12 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev)
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return 0; return 0;
/* Some fake CSR controllers lock up after setting this type of
* filter, so avoid sending the request altogether.
*/
if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks))
return 0;
/* Always clear event filter when starting */ /* Always clear event filter when starting */
hci_clear_event_filter_sync(hdev); hci_clear_event_filter_sync(hdev);
......
...@@ -1444,7 +1444,6 @@ static void l2cap_ecred_connect(struct l2cap_chan *chan) ...@@ -1444,7 +1444,6 @@ static void l2cap_ecred_connect(struct l2cap_chan *chan)
data.pdu.scid[0] = cpu_to_le16(chan->scid); data.pdu.scid[0] = cpu_to_le16(chan->scid);
chan->ident = l2cap_get_ident(conn); chan->ident = l2cap_get_ident(conn);
data.pid = chan->ops->get_peer_pid(chan);
data.count = 1; data.count = 1;
data.chan = chan; data.chan = chan;
......
...@@ -7955,7 +7955,7 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data, ...@@ -7955,7 +7955,7 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
return false; return false;
/* Make sure that the data is correctly formatted. */ /* Make sure that the data is correctly formatted. */
for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) { for (i = 0; i < len; i += (cur_len + 1)) {
cur_len = data[i]; cur_len = data[i];
if (!cur_len) if (!cur_len)
...@@ -9628,17 +9628,44 @@ void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle, ...@@ -9628,17 +9628,44 @@ void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
NULL); NULL);
} }
static void mgmt_send_adv_monitor_device_found(struct hci_dev *hdev,
struct sk_buff *skb,
struct sock *skip_sk,
u16 handle)
{
struct sk_buff *advmon_skb;
size_t advmon_skb_len;
__le16 *monitor_handle;
if (!skb)
return;
advmon_skb_len = (sizeof(struct mgmt_ev_adv_monitor_device_found) -
sizeof(struct mgmt_ev_device_found)) + skb->len;
advmon_skb = mgmt_alloc_skb(hdev, MGMT_EV_ADV_MONITOR_DEVICE_FOUND,
advmon_skb_len);
if (!advmon_skb)
return;
/* ADV_MONITOR_DEVICE_FOUND is similar to DEVICE_FOUND event except
* that it also has 'monitor_handle'. Make a copy of DEVICE_FOUND and
* store monitor_handle of the matched monitor.
*/
monitor_handle = skb_put(advmon_skb, sizeof(*monitor_handle));
*monitor_handle = cpu_to_le16(handle);
skb_put_data(advmon_skb, skb->data, skb->len);
mgmt_event_skb(advmon_skb, skip_sk);
}
static void mgmt_adv_monitor_device_found(struct hci_dev *hdev, static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
bdaddr_t *bdaddr, bool report_device, bdaddr_t *bdaddr, bool report_device,
struct sk_buff *skb, struct sk_buff *skb,
struct sock *skip_sk) struct sock *skip_sk)
{ {
struct sk_buff *advmon_skb;
size_t advmon_skb_len;
__le16 *monitor_handle;
struct monitored_device *dev, *tmp; struct monitored_device *dev, *tmp;
bool matched = false; bool matched = false;
bool notify = false; bool notified = false;
/* We have received the Advertisement Report because: /* We have received the Advertisement Report because:
* 1. the kernel has initiated active discovery * 1. the kernel has initiated active discovery
...@@ -9660,25 +9687,6 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev, ...@@ -9660,25 +9687,6 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
return; return;
} }
advmon_skb_len = (sizeof(struct mgmt_ev_adv_monitor_device_found) -
sizeof(struct mgmt_ev_device_found)) + skb->len;
advmon_skb = mgmt_alloc_skb(hdev, MGMT_EV_ADV_MONITOR_DEVICE_FOUND,
advmon_skb_len);
if (!advmon_skb) {
if (report_device)
mgmt_event_skb(skb, skip_sk);
else
kfree_skb(skb);
return;
}
/* ADV_MONITOR_DEVICE_FOUND is similar to DEVICE_FOUND event except
* that it also has 'monitor_handle'. Make a copy of DEVICE_FOUND and
* store monitor_handle of the matched monitor.
*/
monitor_handle = skb_put(advmon_skb, sizeof(*monitor_handle));
skb_put_data(advmon_skb, skb->data, skb->len);
hdev->advmon_pend_notify = false; hdev->advmon_pend_notify = false;
list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) { list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) {
...@@ -9686,8 +9694,10 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev, ...@@ -9686,8 +9694,10 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
matched = true; matched = true;
if (!dev->notified) { if (!dev->notified) {
*monitor_handle = cpu_to_le16(dev->handle); mgmt_send_adv_monitor_device_found(hdev, skb,
notify = true; skip_sk,
dev->handle);
notified = true;
dev->notified = true; dev->notified = true;
} }
} }
...@@ -9697,25 +9707,19 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev, ...@@ -9697,25 +9707,19 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
} }
if (!report_device && if (!report_device &&
((matched && !notify) || !msft_monitor_supported(hdev))) { ((matched && !notified) || !msft_monitor_supported(hdev))) {
/* Handle 0 indicates that we are not active scanning and this /* Handle 0 indicates that we are not active scanning and this
* is a subsequent advertisement report for an already matched * is a subsequent advertisement report for an already matched
* Advertisement Monitor or the controller offloading support * Advertisement Monitor or the controller offloading support
* is not available. * is not available.
*/ */
*monitor_handle = 0; mgmt_send_adv_monitor_device_found(hdev, skb, skip_sk, 0);
notify = true;
} }
if (report_device) if (report_device)
mgmt_event_skb(skb, skip_sk); mgmt_event_skb(skb, skip_sk);
else else
kfree_skb(skb); kfree_skb(skb);
if (notify)
mgmt_event_skb(advmon_skb, skip_sk);
else
kfree_skb(advmon_skb);
} }
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
......
...@@ -330,12 +330,13 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev, ...@@ -330,12 +330,13 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
/* Do not free the monitor if it is being removed due to /* Do not free the monitor if it is being removed due to
* suspend. It will be re-monitored on resume. * suspend. It will be re-monitored on resume.
*/ */
if (monitor && !msft->suspending) if (monitor && !msft->suspending) {
hci_free_adv_monitor(hdev, monitor); hci_free_adv_monitor(hdev, monitor);
/* Clear any monitored devices by this Adv Monitor */ /* Clear any monitored devices by this Adv Monitor */
msft_monitor_device_del(hdev, handle_data->mgmt_handle, NULL, msft_monitor_device_del(hdev, handle_data->mgmt_handle,
0, false); NULL, 0, false);
}
list_del(&handle_data->list); list_del(&handle_data->list);
kfree(handle_data); kfree(handle_data);
...@@ -522,6 +523,16 @@ int msft_resume_sync(struct hci_dev *hdev) ...@@ -522,6 +523,16 @@ int msft_resume_sync(struct hci_dev *hdev)
if (!msft || !msft_monitor_supported(hdev)) if (!msft || !msft_monitor_supported(hdev))
return 0; return 0;
hci_dev_lock(hdev);
/* Clear already tracked devices on resume. Once the monitors are
* reregistered, devices in range will be found again after resume.
*/
hdev->advmon_pend_notify = false;
msft_monitor_device_del(hdev, 0, NULL, 0, true);
hci_dev_unlock(hdev);
msft->resuming = true; msft->resuming = true;
while (1) { while (1) {
......
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