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
config BT_MTKUART
tristate "MediaTek HCI UART driver"
depends on SERIAL_DEV_BUS
select BT_MTK
help
MediaTek Bluetooth HCI UART driver.
This driver is required if you want to use MediaTek Bluetooth
......
......@@ -10,7 +10,6 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/usb.h>
#include <asm/unaligned.h>
......
......@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
......
......@@ -285,6 +285,7 @@ MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_MT7622);
MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668);
MODULE_FIRMWARE(FIRMWARE_MT7961);
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2021 MediaTek Inc. */
#define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.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
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)
{
const struct btmtk_sco sco_setting = {
......@@ -968,7 +1024,14 @@ static int btmtksdio_sco_setting(struct hci_dev *hdev)
return err;
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)
......@@ -1060,6 +1123,9 @@ static int btmtksdio_setup(struct hci_dev *hdev)
return err;
}
/* Enable WBS with mSBC codec */
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
/* Enable GPIO reset mechanism */
if (bdev->reset) {
err = btmtksdio_reset_setting(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;
case 0x7663:
case 0x7668:
......@@ -1281,6 +1350,8 @@ static int btmtksdio_probe(struct sdio_func *func,
hdev->manufacturer = 70;
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
sdio_set_drvdata(func, bdev);
err = hci_register_dev(hdev);
if (err < 0) {
dev_err(&func->dev, "Can't register HCI device\n");
......@@ -1288,8 +1359,6 @@ static int btmtksdio_probe(struct sdio_func *func,
return err;
}
sdio_set_drvdata(func, bdev);
/* pm_runtime_enable would be done after the firmware is being
* downloaded because the core layer probably already enables
* runtime PM for this func such as the case host->caps &
......
......@@ -28,13 +28,10 @@
#include <net/bluetooth/hci_core.h>
#include "h4_recv.h"
#include "btmtk.h"
#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 BTMTKUART_TX_STATE_ACTIVE 1
......@@ -44,25 +41,6 @@
#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 {
u8 prefix;
__be16 dlen;
......@@ -74,44 +52,6 @@ struct btmtkuart_data {
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 hci_dev *hdev;
struct serdev_device *serdev;
......@@ -153,29 +93,36 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
u32 hlen, status = BTMTK_WMT_INVALID;
struct btmtk_hci_wmt_evt *wmt_evt;
struct mtk_hci_wmt_cmd wc;
struct mtk_wmt_hdr *hdr;
struct btmtk_hci_wmt_cmd *wc;
struct btmtk_wmt_hdr *hdr;
int err;
/* Send the WMT command and wait until the WMT event returns */
hlen = sizeof(*hdr) + wmt_params->dlen;
if (hlen > 255) {
err = -EINVAL;
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->op = wmt_params->op;
hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
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);
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
if (err < 0) {
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
......@@ -192,14 +139,14 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
if (err == -EINTR) {
bt_dev_err(hdev, "Execution of wmt command interrupted");
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
goto err_free_skb;
goto err_free_wc;
}
if (err) {
bt_dev_err(hdev, "Execution of wmt command timed out");
clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
err = -ETIMEDOUT;
goto err_free_skb;
goto err_free_wc;
}
/* Parse and handle the return WMT event */
......@@ -208,17 +155,17 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
bt_dev_err(hdev, "Wrong op received %d expected %d",
wmt_evt->whdr.op, hdr->op);
err = -EIO;
goto err_free_skb;
goto err_free_wc;
}
switch (wmt_evt->whdr.op) {
case MTK_WMT_SEMAPHORE:
case BTMTK_WMT_SEMAPHORE:
if (wmt_evt->whdr.flag == 2)
status = BTMTK_WMT_PATCH_UNDONE;
else
status = BTMTK_WMT_PATCH_DONE;
break;
case MTK_WMT_FUNC_CTRL:
case BTMTK_WMT_FUNC_CTRL:
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
status = BTMTK_WMT_ON_DONE;
......@@ -232,6 +179,8 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
if (wmt_params->status)
*wmt_params->status = status;
err_free_wc:
kfree(wc);
err_free_skb:
kfree_skb(bdev->evt_skb);
bdev->evt_skb = NULL;
......@@ -239,95 +188,12 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
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)
{
struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
struct hci_event_hdr *hdr = (void *)skb->data;
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
* 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)
if (err < 0)
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,
&bdev->tx_state)) {
/* Barrier to sync with other CPUs */
......@@ -645,7 +511,7 @@ static int btmtkuart_func_query(struct hci_dev *hdev)
u8 param = 0;
/* 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.dlen = sizeof(param);
wmt_params.data = &param;
......@@ -672,7 +538,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
* ready to change a new baudrate.
*/
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.dlen = 4;
wmt_params.data = &baudrate;
......@@ -706,7 +572,7 @@ static int btmtkuart_change_baudrate(struct hci_dev *hdev)
usleep_range(20000, 22000);
/* Test the new baudrate */
wmt_params.op = MTK_WMT_TEST;
wmt_params.op = BTMTK_WMT_TEST;
wmt_params.flag = 7;
wmt_params.dlen = 0;
wmt_params.data = NULL;
......@@ -741,7 +607,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
* do any setups.
*/
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.dlen = 0;
wmt_params.data = NULL;
......@@ -760,7 +626,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
btmtkuart_change_baudrate(hdev);
/* 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.dlen = 0;
wmt_params.data = NULL;
......@@ -778,7 +644,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
}
/* 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)
return err;
......@@ -801,7 +667,7 @@ static int btmtkuart_setup(struct hci_dev *hdev)
}
/* Enable Bluetooth protocol */
wmt_params.op = MTK_WMT_FUNC_CTRL;
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
wmt_params.dlen = sizeof(param);
wmt_params.data = &param;
......@@ -846,7 +712,7 @@ static int btmtkuart_shutdown(struct hci_dev *hdev)
int err;
/* Disable the device */
wmt_params.op = MTK_WMT_FUNC_CTRL;
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
wmt_params.dlen = sizeof(param);
wmt_params.data = &param;
......@@ -1007,6 +873,7 @@ static int btmtkuart_probe(struct serdev_device *serdev)
hdev->setup = btmtkuart_setup;
hdev->shutdown = btmtkuart_shutdown;
hdev->send = btmtkuart_send_frame;
hdev->set_bdaddr = btmtk_set_bdaddr;
SET_HCIDEV_DEV(hdev, &serdev->dev);
hdev->manufacturer = 70;
......@@ -1131,6 +998,3 @@ MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE_MT7622);
MODULE_FIRMWARE(FIRMWARE_MT7663);
MODULE_FIRMWARE(FIRMWARE_MT7668);
......@@ -49,6 +49,7 @@ enum btrtl_chip_id {
CHIP_ID_8822C = 13,
CHIP_ID_8761B,
CHIP_ID_8852A = 18,
CHIP_ID_8852B = 20,
};
struct id_table {
......@@ -187,6 +188,14 @@ static const struct id_table ic_id_table[] = {
.has_msft_ext = true,
.fw_name = "rtl_bt/rtl8852au_fw.bin",
.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,
......@@ -295,6 +304,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
{ RTL_ROM_LMP_8822B, 13 }, /* 8822C */
{ RTL_ROM_LMP_8761A, 14 }, /* 8761B */
{ RTL_ROM_LMP_8852A, 18 }, /* 8852A */
{ RTL_ROM_LMP_8852A, 20 }, /* 8852B */
};
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)
switch (btrtl_dev->project_id) {
case CHIP_ID_8822C:
case CHIP_ID_8852A:
case CHIP_ID_8852B:
set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks);
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
hci_set_aosp_capable(hdev);
......@@ -934,3 +945,5 @@ MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin");
MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin");
MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.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[] = {
/* Additional Realtek 8723BE Bluetooth devices */
{ USB_DEVICE(0x0489, 0xe085), .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, 0x3416), .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)
*/
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_FILTER_CLEAR_ALL, &hdev->quirks);
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
/* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR.
......@@ -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:
*
* - 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)
*
* These controllers are really messed-up.
......@@ -2096,7 +2099,7 @@ static int btusb_setup_csr(struct hci_dev *hdev)
if (ret >= 0)
msleep(200);
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);
......
......@@ -20,6 +20,7 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/dmi.h>
......@@ -870,7 +871,23 @@ static int bcm_resume(struct device *dev)
#endif
/* 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[] = {
{
.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",
.matches = {
......@@ -1027,7 +1044,8 @@ static struct clk *bcm_get_txco(struct 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;
dev->name = dev_name(dev->dev);
......@@ -1083,23 +1101,33 @@ static int bcm_get_resources(struct bcm_device *dev)
if (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 */
if (dev->irq <= 0) {
struct gpio_desc *gpio;
gpio = devm_gpiod_get_optional(dev->dev, "host-wakeup",
GPIOD_IN);
gpio = devm_gpiod_get_optional(dev->dev, irq_con_id, GPIOD_IN);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
dev->irq = gpiod_to_irq(gpio);
}
dmi_id = dmi_first_match(bcm_broken_irq_dmi_table);
if (dmi_id) {
dev_info(dev->dev, "%s: Has a broken IRQ config, disabling IRQ support / runtime-pm\n",
dmi_id->ident);
dev->irq = 0;
if (broken_irq_dmi_id) {
if (broken_irq_dmi_id->driver_data) {
gpiod_remove_lookup_table(broken_irq_dmi_id->driver_data);
} else {
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);
......
......@@ -629,9 +629,11 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
break;
}
pm_runtime_get_sync(&hu->serdev->dev);
pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
if (hu->serdev) {
pm_runtime_get_sync(&hu->serdev->dev);
pm_runtime_mark_last_busy(&hu->serdev->dev);
pm_runtime_put_autosuspend(&hu->serdev->dev);
}
return 0;
}
......
......@@ -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);
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_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_unlink(struct sock *sk);
......
......@@ -255,6 +255,16 @@ enum {
* during the hdev->setup vendor callback.
*/
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 */
......
......@@ -568,7 +568,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
EXPORT_SYMBOL(bt_sock_wait_state);
/* 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);
unsigned long timeo;
......@@ -576,7 +576,7 @@ int bt_sock_wait_ready(struct sock *sk, unsigned long flags)
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);
set_current_state(TASK_INTERRUPTIBLE);
......
......@@ -669,7 +669,9 @@ static void le_conn_timeout(struct work_struct *work)
if (conn->role == HCI_ROLE_SLAVE) {
/* Disable LE Advertising */
le_disable_advertising(hdev);
hci_dev_lock(hdev);
hci_le_conn_failed(conn, HCI_ERROR_ADVERTISING_TIMEOUT);
hci_dev_unlock(hdev);
return;
}
......
......@@ -5453,8 +5453,9 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (hcon) {
if (hcon && hcon->type == AMP_LINK) {
hcon->state = BT_CLOSED;
hci_disconn_cfm(hcon, ev->reason);
hci_conn_del(hcon);
}
......
......@@ -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))
return 0;
if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks))
return 0;
memset(&cp, 0, sizeof(cp));
cp.flt_type = flt_type;
......@@ -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))
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,
BDADDR_ANY, 0x00);
}
......@@ -4828,6 +4838,12 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev)
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
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 */
hci_clear_event_filter_sync(hdev);
......
......@@ -1444,7 +1444,6 @@ static void l2cap_ecred_connect(struct l2cap_chan *chan)
data.pdu.scid[0] = cpu_to_le16(chan->scid);
chan->ident = l2cap_get_ident(conn);
data.pid = chan->ops->get_peer_pid(chan);
data.count = 1;
data.chan = chan;
......
......@@ -7955,7 +7955,7 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
return false;
/* 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];
if (!cur_len)
......@@ -9628,17 +9628,44 @@ void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
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,
bdaddr_t *bdaddr, bool report_device,
struct sk_buff *skb,
struct sock *skip_sk)
{
struct sk_buff *advmon_skb;
size_t advmon_skb_len;
__le16 *monitor_handle;
struct monitored_device *dev, *tmp;
bool matched = false;
bool notify = false;
bool notified = false;
/* We have received the Advertisement Report because:
* 1. the kernel has initiated active discovery
......@@ -9660,25 +9687,6 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
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;
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,
matched = true;
if (!dev->notified) {
*monitor_handle = cpu_to_le16(dev->handle);
notify = true;
mgmt_send_adv_monitor_device_found(hdev, skb,
skip_sk,
dev->handle);
notified = true;
dev->notified = true;
}
}
......@@ -9697,25 +9707,19 @@ static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
}
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
* is a subsequent advertisement report for an already matched
* Advertisement Monitor or the controller offloading support
* is not available.
*/
*monitor_handle = 0;
notify = true;
mgmt_send_adv_monitor_device_found(hdev, skb, skip_sk, 0);
}
if (report_device)
mgmt_event_skb(skb, skip_sk);
else
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,
......
......@@ -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
* suspend. It will be re-monitored on resume.
*/
if (monitor && !msft->suspending)
if (monitor && !msft->suspending) {
hci_free_adv_monitor(hdev, monitor);
/* Clear any monitored devices by this Adv Monitor */
msft_monitor_device_del(hdev, handle_data->mgmt_handle, NULL,
0, false);
/* Clear any monitored devices by this Adv Monitor */
msft_monitor_device_del(hdev, handle_data->mgmt_handle,
NULL, 0, false);
}
list_del(&handle_data->list);
kfree(handle_data);
......@@ -522,6 +523,16 @@ int msft_resume_sync(struct hci_dev *hdev)
if (!msft || !msft_monitor_supported(hdev))
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;
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