Merge tag 'for-net-next-2023-10-23' 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 0bda:b85b for Fn-Link RTL8852BE - ISO: Many fixes for broadcast support - Mark bcm4378/bcm4387 as BROKEN_LE_CODED - Add support ITTIM PE50-M75C - Add RTW8852BE device 13d3:3570 - Add support for QCA2066 - Add support for Intel Misty Peak - 8087:0038 * tag 'for-net-next-2023-10-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: Bluetooth: hci_sync: Fix Opcode prints in bt_dev_dbg/err Bluetooth: Fix double free in hci_conn_cleanup Bluetooth: btmtksdio: enable bluetooth wakeup in system suspend Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE Bluetooth: hci_bcm4377: Mark bcm4378/bcm4387 as BROKEN_LE_CODED Bluetooth: ISO: Copy BASE if service data matches EIR_BAA_SERVICE_UUID Bluetooth: Make handle of hci_conn be unique Bluetooth: btusb: Add date->evt_skb is NULL check Bluetooth: ISO: Fix bcast listener cleanup Bluetooth: msft: __hci_cmd_sync() doesn't return NULL Bluetooth: ISO: Match QoS adv handle with BIG handle Bluetooth: ISO: Allow binding a bcast listener to 0 bises Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables Bluetooth: qca: add support for QCA2066 Bluetooth: ISO: Set CIS bit only for devices with CIS support Bluetooth: Add support for Intel Misty Peak - 8087:0038 Bluetooth: Add support ITTIM PE50-M75C Bluetooth: ISO: Pass BIG encryption info through QoS Bluetooth: ISO: Fix BIS cleanup ==================== Link: https://lore.kernel.org/r/20231023182119.3629194-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -118,6 +118,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
|
|||||||
#define BTMTKSDIO_FUNC_ENABLED 3
|
#define BTMTKSDIO_FUNC_ENABLED 3
|
||||||
#define BTMTKSDIO_PATCH_ENABLED 4
|
#define BTMTKSDIO_PATCH_ENABLED 4
|
||||||
#define BTMTKSDIO_HW_RESET_ACTIVE 5
|
#define BTMTKSDIO_HW_RESET_ACTIVE 5
|
||||||
|
#define BTMTKSDIO_BT_WAKE_ENABLED 6
|
||||||
|
|
||||||
struct mtkbtsdio_hdr {
|
struct mtkbtsdio_hdr {
|
||||||
__le16 len;
|
__le16 len;
|
||||||
@@ -554,7 +555,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
|
|||||||
sdio_claim_host(bdev->func);
|
sdio_claim_host(bdev->func);
|
||||||
|
|
||||||
/* Disable interrupt */
|
/* Disable interrupt */
|
||||||
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
|
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
|
||||||
|
|
||||||
txrx_timeout = jiffies + 5 * HZ;
|
txrx_timeout = jiffies + 5 * HZ;
|
||||||
|
|
||||||
@@ -576,7 +577,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
|
|||||||
if ((int_status & FW_MAILBOX_INT) &&
|
if ((int_status & FW_MAILBOX_INT) &&
|
||||||
bdev->data->chipid == 0x7921) {
|
bdev->data->chipid == 0x7921) {
|
||||||
sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN,
|
sdio_writel(bdev->func, PH2DSM0R_DRIVER_OWN,
|
||||||
MTK_REG_PH2DSM0R, 0);
|
MTK_REG_PH2DSM0R, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (int_status & FW_OWN_BACK_INT)
|
if (int_status & FW_OWN_BACK_INT)
|
||||||
@@ -608,7 +609,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
|
|||||||
} while (int_status || time_is_before_jiffies(txrx_timeout));
|
} while (int_status || time_is_before_jiffies(txrx_timeout));
|
||||||
|
|
||||||
/* Enable interrupt */
|
/* Enable interrupt */
|
||||||
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, 0);
|
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
|
||||||
|
|
||||||
sdio_release_host(bdev->func);
|
sdio_release_host(bdev->func);
|
||||||
|
|
||||||
@@ -620,8 +621,14 @@ static void btmtksdio_interrupt(struct sdio_func *func)
|
|||||||
{
|
{
|
||||||
struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
|
struct btmtksdio_dev *bdev = sdio_get_drvdata(func);
|
||||||
|
|
||||||
|
if (test_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state)) {
|
||||||
|
if (bdev->hdev->suspended)
|
||||||
|
pm_wakeup_event(bdev->dev, 0);
|
||||||
|
clear_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state);
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable interrupt */
|
/* Disable interrupt */
|
||||||
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, 0);
|
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
|
||||||
|
|
||||||
schedule_work(&bdev->txrx_work);
|
schedule_work(&bdev->txrx_work);
|
||||||
}
|
}
|
||||||
@@ -1454,6 +1461,23 @@ static int btmtksdio_runtime_suspend(struct device *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btmtksdio_system_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||||
|
struct btmtksdio_dev *bdev;
|
||||||
|
|
||||||
|
bdev = sdio_get_drvdata(func);
|
||||||
|
if (!bdev)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
set_bit(BTMTKSDIO_BT_WAKE_ENABLED, &bdev->tx_state);
|
||||||
|
|
||||||
|
return btmtksdio_runtime_suspend(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int btmtksdio_runtime_resume(struct device *dev)
|
static int btmtksdio_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||||
@@ -1474,8 +1498,16 @@ static int btmtksdio_runtime_resume(struct device *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UNIVERSAL_DEV_PM_OPS(btmtksdio_pm_ops, btmtksdio_runtime_suspend,
|
static int btmtksdio_system_resume(struct device *dev)
|
||||||
btmtksdio_runtime_resume, NULL);
|
{
|
||||||
|
return btmtksdio_runtime_resume(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops btmtksdio_pm_ops = {
|
||||||
|
SYSTEM_SLEEP_PM_OPS(btmtksdio_system_suspend, btmtksdio_system_resume)
|
||||||
|
RUNTIME_PM_OPS(btmtksdio_runtime_suspend, btmtksdio_runtime_resume, NULL)
|
||||||
|
};
|
||||||
|
|
||||||
#define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
|
#define BTMTKSDIO_PM_OPS (&btmtksdio_pm_ops)
|
||||||
#else /* CONFIG_PM */
|
#else /* CONFIG_PM */
|
||||||
#define BTMTKSDIO_PM_OPS NULL
|
#define BTMTKSDIO_PM_OPS NULL
|
||||||
|
@@ -205,6 +205,44 @@ static int qca_send_reset(struct hci_dev *hdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
|
||||||
|
{
|
||||||
|
u8 cmd;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct edl_event_hdr *edl;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
cmd = EDL_GET_BID_REQ_CMD;
|
||||||
|
skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
|
||||||
|
&cmd, 0, HCI_INIT_TIMEOUT);
|
||||||
|
if (IS_ERR(skb)) {
|
||||||
|
err = PTR_ERR(skb);
|
||||||
|
bt_dev_err(hdev, "Reading QCA board ID failed (%d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
edl = skb_pull_data(skb, sizeof(*edl));
|
||||||
|
if (!edl) {
|
||||||
|
bt_dev_err(hdev, "QCA read board ID with no header");
|
||||||
|
err = -EILSEQ;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
|
||||||
|
edl->rtype != EDL_GET_BID_REQ_CMD) {
|
||||||
|
bt_dev_err(hdev, "QCA Wrong packet: %d %d", edl->cresp, edl->rtype);
|
||||||
|
err = -EIO;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bid = (edl->data[1] << 8) + edl->data[2];
|
||||||
|
bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
|
int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
@@ -574,6 +612,23 @@ 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);
|
||||||
|
|
||||||
|
static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
|
||||||
|
struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
|
||||||
|
{
|
||||||
|
const char *variant;
|
||||||
|
|
||||||
|
/* hsp gf chip */
|
||||||
|
if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID)
|
||||||
|
variant = "g";
|
||||||
|
else
|
||||||
|
variant = "";
|
||||||
|
|
||||||
|
if (bid == 0x0)
|
||||||
|
snprintf(fwname, max_size, "qca/hpnv%02x%s.bin", rom_ver, variant);
|
||||||
|
else
|
||||||
|
snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid);
|
||||||
|
}
|
||||||
|
|
||||||
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, struct qca_btsoc_version ver,
|
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
|
||||||
const char *firmware_name)
|
const char *firmware_name)
|
||||||
@@ -582,6 +637,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
|||||||
int err;
|
int err;
|
||||||
u8 rom_ver = 0;
|
u8 rom_ver = 0;
|
||||||
u32 soc_ver;
|
u32 soc_ver;
|
||||||
|
u16 boardid = 0;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "QCA setup on UART");
|
bt_dev_dbg(hdev, "QCA setup on UART");
|
||||||
|
|
||||||
@@ -615,6 +671,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
|||||||
snprintf(config.fwname, sizeof(config.fwname),
|
snprintf(config.fwname, sizeof(config.fwname),
|
||||||
"qca/apbtfw%02x.tlv", rom_ver);
|
"qca/apbtfw%02x.tlv", rom_ver);
|
||||||
break;
|
break;
|
||||||
|
case QCA_QCA2066:
|
||||||
|
snprintf(config.fwname, sizeof(config.fwname),
|
||||||
|
"qca/hpbtfw%02x.tlv", rom_ver);
|
||||||
|
break;
|
||||||
case QCA_QCA6390:
|
case QCA_QCA6390:
|
||||||
snprintf(config.fwname, sizeof(config.fwname),
|
snprintf(config.fwname, sizeof(config.fwname),
|
||||||
"qca/htbtfw%02x.tlv", rom_ver);
|
"qca/htbtfw%02x.tlv", rom_ver);
|
||||||
@@ -649,6 +709,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
|||||||
/* Give the controller some time to get ready to receive the NVM */
|
/* Give the controller some time to get ready to receive the NVM */
|
||||||
msleep(10);
|
msleep(10);
|
||||||
|
|
||||||
|
if (soc_type == QCA_QCA2066)
|
||||||
|
qca_read_fw_board_id(hdev, &boardid);
|
||||||
|
|
||||||
/* Download NVM configuration */
|
/* Download NVM configuration */
|
||||||
config.type = TLV_TYPE_NVM;
|
config.type = TLV_TYPE_NVM;
|
||||||
if (firmware_name) {
|
if (firmware_name) {
|
||||||
@@ -671,6 +734,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
|||||||
snprintf(config.fwname, sizeof(config.fwname),
|
snprintf(config.fwname, sizeof(config.fwname),
|
||||||
"qca/apnv%02x.bin", rom_ver);
|
"qca/apnv%02x.bin", rom_ver);
|
||||||
break;
|
break;
|
||||||
|
case QCA_QCA2066:
|
||||||
|
qca_generate_hsp_nvm_name(config.fwname,
|
||||||
|
sizeof(config.fwname), ver, rom_ver, boardid);
|
||||||
|
break;
|
||||||
case QCA_QCA6390:
|
case QCA_QCA6390:
|
||||||
snprintf(config.fwname, sizeof(config.fwname),
|
snprintf(config.fwname, sizeof(config.fwname),
|
||||||
"qca/htnv%02x.bin", rom_ver);
|
"qca/htnv%02x.bin", rom_ver);
|
||||||
@@ -702,6 +769,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
|||||||
|
|
||||||
switch (soc_type) {
|
switch (soc_type) {
|
||||||
case QCA_WCN3991:
|
case QCA_WCN3991:
|
||||||
|
case QCA_QCA2066:
|
||||||
case QCA_QCA6390:
|
case QCA_QCA6390:
|
||||||
case QCA_WCN6750:
|
case QCA_WCN6750:
|
||||||
case QCA_WCN6855:
|
case QCA_WCN6855:
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#define EDL_PATCH_VER_REQ_CMD (0x19)
|
#define EDL_PATCH_VER_REQ_CMD (0x19)
|
||||||
#define EDL_PATCH_TLV_REQ_CMD (0x1E)
|
#define EDL_PATCH_TLV_REQ_CMD (0x1E)
|
||||||
#define EDL_GET_BUILD_INFO_CMD (0x20)
|
#define EDL_GET_BUILD_INFO_CMD (0x20)
|
||||||
|
#define EDL_GET_BID_REQ_CMD (0x23)
|
||||||
#define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
|
#define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
|
||||||
#define EDL_PATCH_CONFIG_CMD (0x28)
|
#define EDL_PATCH_CONFIG_CMD (0x28)
|
||||||
#define MAX_SIZE_PER_TLV_SEGMENT (243)
|
#define MAX_SIZE_PER_TLV_SEGMENT (243)
|
||||||
@@ -47,7 +48,8 @@
|
|||||||
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
|
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
|
||||||
|
|
||||||
#define QCA_FW_BUILD_VER_LEN 255
|
#define QCA_FW_BUILD_VER_LEN 255
|
||||||
|
#define QCA_HSP_GF_SOC_ID 0x1200
|
||||||
|
#define QCA_HSP_GF_SOC_MASK 0x0000ff00
|
||||||
|
|
||||||
enum qca_baudrate {
|
enum qca_baudrate {
|
||||||
QCA_BAUDRATE_115200 = 0,
|
QCA_BAUDRATE_115200 = 0,
|
||||||
@@ -146,6 +148,7 @@ enum qca_btsoc_type {
|
|||||||
QCA_WCN3990,
|
QCA_WCN3990,
|
||||||
QCA_WCN3998,
|
QCA_WCN3998,
|
||||||
QCA_WCN3991,
|
QCA_WCN3991,
|
||||||
|
QCA_QCA2066,
|
||||||
QCA_QCA6390,
|
QCA_QCA6390,
|
||||||
QCA_WCN6750,
|
QCA_WCN6750,
|
||||||
QCA_WCN6855,
|
QCA_WCN6855,
|
||||||
|
@@ -477,6 +477,7 @@ static const struct usb_device_id quirks_table[] = {
|
|||||||
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
|
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
|
||||||
{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
|
{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
|
||||||
{ USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED },
|
{ USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED },
|
||||||
|
{ USB_DEVICE(0x8087, 0x0038), .driver_info = BTUSB_INTEL_COMBINED },
|
||||||
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
|
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
|
||||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
|
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
|
||||||
BTUSB_INTEL_NO_WBS_SUPPORT |
|
BTUSB_INTEL_NO_WBS_SUPPORT |
|
||||||
@@ -543,6 +544,10 @@ static const struct usb_device_id quirks_table[] = {
|
|||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
{ USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
{ USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
|
{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
|
||||||
BTUSB_WIDEBAND_SPEECH },
|
BTUSB_WIDEBAND_SPEECH },
|
||||||
|
|
||||||
@@ -644,6 +649,9 @@ static const struct usb_device_id quirks_table[] = {
|
|||||||
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
|
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
|
||||||
BTUSB_WIDEBAND_SPEECH |
|
BTUSB_WIDEBAND_SPEECH |
|
||||||
BTUSB_VALID_LE_STATES },
|
BTUSB_VALID_LE_STATES },
|
||||||
|
{ USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
|
||||||
|
BTUSB_WIDEBAND_SPEECH |
|
||||||
|
BTUSB_VALID_LE_STATES },
|
||||||
|
|
||||||
/* Additional Realtek 8723AE Bluetooth devices */
|
/* Additional Realtek 8723AE Bluetooth devices */
|
||||||
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
|
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
|
||||||
@@ -2818,6 +2826,9 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
|
|||||||
goto err_free_wc;
|
goto err_free_wc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->evt_skb == NULL)
|
||||||
|
goto err_free_wc;
|
||||||
|
|
||||||
/* Parse and handle the return WMT event */
|
/* Parse and handle the return WMT event */
|
||||||
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
|
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
|
||||||
if (wmt_evt->whdr.op != hdr->op) {
|
if (wmt_evt->whdr.op != hdr->op) {
|
||||||
|
@@ -512,6 +512,7 @@ struct bcm4377_hw {
|
|||||||
unsigned long disable_aspm : 1;
|
unsigned long disable_aspm : 1;
|
||||||
unsigned long broken_ext_scan : 1;
|
unsigned long broken_ext_scan : 1;
|
||||||
unsigned long broken_mws_transport_config : 1;
|
unsigned long broken_mws_transport_config : 1;
|
||||||
|
unsigned long broken_le_coded : 1;
|
||||||
|
|
||||||
int (*send_calibration)(struct bcm4377_data *bcm4377);
|
int (*send_calibration)(struct bcm4377_data *bcm4377);
|
||||||
int (*send_ptb)(struct bcm4377_data *bcm4377,
|
int (*send_ptb)(struct bcm4377_data *bcm4377,
|
||||||
@@ -2372,6 +2373,8 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks);
|
set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks);
|
||||||
if (bcm4377->hw->broken_ext_scan)
|
if (bcm4377->hw->broken_ext_scan)
|
||||||
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
|
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
|
||||||
|
if (bcm4377->hw->broken_le_coded)
|
||||||
|
set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks);
|
||||||
|
|
||||||
pci_set_drvdata(pdev, bcm4377);
|
pci_set_drvdata(pdev, bcm4377);
|
||||||
hci_set_drvdata(hdev, bcm4377);
|
hci_set_drvdata(hdev, bcm4377);
|
||||||
@@ -2461,6 +2464,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
|
|||||||
.bar0_core2_window2 = 0x18107000,
|
.bar0_core2_window2 = 0x18107000,
|
||||||
.has_bar0_core2_window2 = true,
|
.has_bar0_core2_window2 = true,
|
||||||
.broken_mws_transport_config = true,
|
.broken_mws_transport_config = true,
|
||||||
|
.broken_le_coded = true,
|
||||||
.send_calibration = bcm4378_send_calibration,
|
.send_calibration = bcm4378_send_calibration,
|
||||||
.send_ptb = bcm4378_send_ptb,
|
.send_ptb = bcm4378_send_ptb,
|
||||||
},
|
},
|
||||||
@@ -2474,6 +2478,7 @@ static const struct bcm4377_hw bcm4377_hw_variants[] = {
|
|||||||
.has_bar0_core2_window2 = true,
|
.has_bar0_core2_window2 = true,
|
||||||
.clear_pciecfg_subsystem_ctrl_bit19 = true,
|
.clear_pciecfg_subsystem_ctrl_bit19 = true,
|
||||||
.broken_mws_transport_config = true,
|
.broken_mws_transport_config = true,
|
||||||
|
.broken_le_coded = true,
|
||||||
.send_calibration = bcm4387_send_calibration,
|
.send_calibration = bcm4387_send_calibration,
|
||||||
.send_ptb = bcm4378_send_ptb,
|
.send_ptb = bcm4378_send_ptb,
|
||||||
},
|
},
|
||||||
|
@@ -1841,6 +1841,10 @@ static int qca_setup(struct hci_uart *hu)
|
|||||||
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
||||||
|
|
||||||
switch (soc_type) {
|
switch (soc_type) {
|
||||||
|
case QCA_QCA2066:
|
||||||
|
soc_name = "qca2066";
|
||||||
|
break;
|
||||||
|
|
||||||
case QCA_WCN3988:
|
case QCA_WCN3988:
|
||||||
case QCA_WCN3990:
|
case QCA_WCN3990:
|
||||||
case QCA_WCN3991:
|
case QCA_WCN3991:
|
||||||
@@ -2032,6 +2036,11 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
|
|||||||
.num_vregs = 4,
|
.num_vregs = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = {
|
||||||
|
.soc_type = QCA_QCA2066,
|
||||||
|
.num_vregs = 0,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
|
static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = {
|
||||||
.soc_type = QCA_QCA6390,
|
.soc_type = QCA_QCA6390,
|
||||||
.num_vregs = 0,
|
.num_vregs = 0,
|
||||||
@@ -2559,6 +2568,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume);
|
|||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static const struct of_device_id qca_bluetooth_of_match[] = {
|
static const struct of_device_id qca_bluetooth_of_match[] = {
|
||||||
|
{ .compatible = "qcom,qca2066-bt", .data = &qca_soc_data_qca2066},
|
||||||
{ .compatible = "qcom,qca6174-bt" },
|
{ .compatible = "qcom,qca6174-bt" },
|
||||||
{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
|
{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},
|
||||||
{ .compatible = "qcom,qca9377-bt" },
|
{ .compatible = "qcom,qca9377-bt" },
|
||||||
@@ -2576,6 +2586,7 @@ MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
|
|||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
static const struct acpi_device_id qca_bluetooth_acpi_match[] = {
|
static const struct acpi_device_id qca_bluetooth_acpi_match[] = {
|
||||||
|
{ "QCOM2066", (kernel_ulong_t)&qca_soc_data_qca2066 },
|
||||||
{ "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 },
|
{ "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 },
|
||||||
{ "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
|
{ "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
|
||||||
{ "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
|
{ "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 },
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
BlueZ - Bluetooth protocol stack for Linux
|
BlueZ - Bluetooth protocol stack for Linux
|
||||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||||
|
Copyright 2023 NXP
|
||||||
|
|
||||||
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
|
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
|
||||||
|
|
||||||
@@ -673,6 +674,8 @@ enum {
|
|||||||
#define HCI_TX_POWER_INVALID 127
|
#define HCI_TX_POWER_INVALID 127
|
||||||
#define HCI_RSSI_INVALID 127
|
#define HCI_RSSI_INVALID 127
|
||||||
|
|
||||||
|
#define HCI_SYNC_HANDLE_INVALID 0xffff
|
||||||
|
|
||||||
#define HCI_ROLE_MASTER 0x00
|
#define HCI_ROLE_MASTER 0x00
|
||||||
#define HCI_ROLE_SLAVE 0x01
|
#define HCI_ROLE_SLAVE 0x01
|
||||||
|
|
||||||
|
@@ -350,6 +350,8 @@ struct hci_dev {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
|
|
||||||
|
struct ida unset_handle_ida;
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
__u16 id;
|
__u16 id;
|
||||||
@@ -1290,31 +1292,8 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct hci_conn *hci_conn_hash_lookup_big_any_dst(struct hci_dev *hdev,
|
|
||||||
__u8 handle)
|
|
||||||
{
|
|
||||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
|
||||||
struct hci_conn *c;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(c, &h->list, list) {
|
|
||||||
if (c->type != ISO_LINK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (handle != BT_ISO_QOS_BIG_UNSET && handle == c->iso_qos.bcast.big) {
|
|
||||||
rcu_read_unlock();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct hci_conn *
|
static inline struct hci_conn *
|
||||||
hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big)
|
hci_conn_hash_lookup_pa_sync_big_handle(struct hci_dev *hdev, __u8 big)
|
||||||
{
|
{
|
||||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||||
struct hci_conn *c;
|
struct hci_conn *c;
|
||||||
@@ -1336,6 +1315,29 @@ hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct hci_conn *
|
||||||
|
hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle)
|
||||||
|
{
|
||||||
|
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||||
|
struct hci_conn *c;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
list_for_each_entry_rcu(c, &h->list, list) {
|
||||||
|
if (c->type != ISO_LINK ||
|
||||||
|
!test_bit(HCI_CONN_PA_SYNC, &c->flags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (c->sync_handle == sync_handle) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
|
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
|
||||||
__u8 type, __u16 state)
|
__u8 type, __u16 state)
|
||||||
{
|
{
|
||||||
@@ -1377,6 +1379,26 @@ static inline void hci_conn_hash_list_state(struct hci_dev *hdev,
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void hci_conn_hash_list_flag(struct hci_dev *hdev,
|
||||||
|
hci_conn_func_t func, __u8 type,
|
||||||
|
__u8 flag, void *data)
|
||||||
|
{
|
||||||
|
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||||
|
struct hci_conn *c;
|
||||||
|
|
||||||
|
if (!func)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
list_for_each_entry_rcu(c, &h->list, list) {
|
||||||
|
if (c->type == type && test_bit(flag, &c->flags))
|
||||||
|
func(c, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
|
static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
struct hci_conn_hash *h = &hdev->conn_hash;
|
||||||
@@ -1426,7 +1448,9 @@ int hci_le_create_cis_pending(struct hci_dev *hdev);
|
|||||||
int hci_conn_check_create_cis(struct hci_conn *conn);
|
int hci_conn_check_create_cis(struct hci_conn *conn);
|
||||||
|
|
||||||
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||||
u8 role);
|
u8 role, u16 handle);
|
||||||
|
struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
|
||||||
|
bdaddr_t *dst, u8 role);
|
||||||
void hci_conn_del(struct hci_conn *conn);
|
void hci_conn_del(struct hci_conn *conn);
|
||||||
void hci_conn_hash_flush(struct hci_dev *hdev);
|
void hci_conn_hash_flush(struct hci_dev *hdev);
|
||||||
void hci_conn_check_pending(struct hci_dev *hdev);
|
void hci_conn_check_pending(struct hci_dev *hdev);
|
||||||
|
@@ -80,6 +80,8 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
|
|||||||
u8 *data, u32 flags, u16 min_interval,
|
u8 *data, u32 flags, u16 min_interval,
|
||||||
u16 max_interval, u16 sync_interval);
|
u16 max_interval, u16 sync_interval);
|
||||||
|
|
||||||
|
int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance);
|
||||||
|
|
||||||
int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
|
int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
|
||||||
u8 instance, bool force);
|
u8 instance, bool force);
|
||||||
int hci_disable_advertising_sync(struct hci_dev *hdev);
|
int hci_disable_advertising_sync(struct hci_dev *hdev);
|
||||||
|
@@ -109,7 +109,7 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
|||||||
struct hci_conn *hcon;
|
struct hci_conn *hcon;
|
||||||
u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
|
u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
|
||||||
|
|
||||||
hcon = hci_conn_add(hdev, AMP_LINK, dst, role);
|
hcon = hci_conn_add(hdev, AMP_LINK, dst, role, __next_handle(mgr));
|
||||||
if (!hcon)
|
if (!hcon)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -117,7 +117,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
|
|||||||
|
|
||||||
hcon->state = BT_CONNECT;
|
hcon->state = BT_CONNECT;
|
||||||
hcon->attempt++;
|
hcon->attempt++;
|
||||||
hcon->handle = __next_handle(mgr);
|
|
||||||
hcon->remote_id = remote_id;
|
hcon->remote_id = remote_id;
|
||||||
hcon->amp_mgr = amp_mgr_get(mgr);
|
hcon->amp_mgr = amp_mgr_get(mgr);
|
||||||
|
|
||||||
|
@@ -153,6 +153,9 @@ static void hci_conn_cleanup(struct hci_conn *conn)
|
|||||||
|
|
||||||
hci_conn_hash_del(hdev, conn);
|
hci_conn_hash_del(hdev, conn);
|
||||||
|
|
||||||
|
if (HCI_CONN_HANDLE_UNSET(conn->handle))
|
||||||
|
ida_free(&hdev->unset_handle_ida, conn->handle);
|
||||||
|
|
||||||
if (conn->cleanup)
|
if (conn->cleanup)
|
||||||
conn->cleanup(conn);
|
conn->cleanup(conn);
|
||||||
|
|
||||||
@@ -169,13 +172,11 @@ static void hci_conn_cleanup(struct hci_conn *conn)
|
|||||||
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
|
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
hci_conn_del_sysfs(conn);
|
|
||||||
|
|
||||||
debugfs_remove_recursive(conn->debugfs);
|
debugfs_remove_recursive(conn->debugfs);
|
||||||
|
|
||||||
hci_dev_put(hdev);
|
hci_conn_del_sysfs(conn);
|
||||||
|
|
||||||
hci_conn_put(conn);
|
hci_dev_put(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_acl_create_connection(struct hci_conn *conn)
|
static void hci_acl_create_connection(struct hci_conn *conn)
|
||||||
@@ -759,6 +760,7 @@ static int terminate_big_sync(struct hci_dev *hdev, void *data)
|
|||||||
|
|
||||||
bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", d->big, d->bis);
|
bt_dev_dbg(hdev, "big 0x%2.2x bis 0x%2.2x", d->big, d->bis);
|
||||||
|
|
||||||
|
hci_disable_per_advertising_sync(hdev, d->bis);
|
||||||
hci_remove_ext_adv_instance_sync(hdev, d->bis, NULL);
|
hci_remove_ext_adv_instance_sync(hdev, d->bis, NULL);
|
||||||
|
|
||||||
/* Only terminate BIG if it has been created */
|
/* Only terminate BIG if it has been created */
|
||||||
@@ -814,6 +816,17 @@ static int big_terminate_sync(struct hci_dev *hdev, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void find_bis(struct hci_conn *conn, void *data)
|
||||||
|
{
|
||||||
|
struct iso_list_data *d = data;
|
||||||
|
|
||||||
|
/* Ignore if BIG doesn't match */
|
||||||
|
if (d->big != conn->iso_qos.bcast.big)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->count++;
|
||||||
|
}
|
||||||
|
|
||||||
static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn)
|
static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
struct iso_list_data *d;
|
struct iso_list_data *d;
|
||||||
@@ -825,10 +838,27 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c
|
|||||||
if (!d)
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memset(d, 0, sizeof(*d));
|
||||||
d->big = big;
|
d->big = big;
|
||||||
d->sync_handle = conn->sync_handle;
|
d->sync_handle = conn->sync_handle;
|
||||||
d->pa_sync_term = test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags);
|
|
||||||
d->big_sync_term = test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags);
|
if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
|
||||||
|
hci_conn_hash_list_flag(hdev, find_bis, ISO_LINK,
|
||||||
|
HCI_CONN_PA_SYNC, d);
|
||||||
|
|
||||||
|
if (!d->count)
|
||||||
|
d->pa_sync_term = true;
|
||||||
|
|
||||||
|
d->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_and_clear_bit(HCI_CONN_BIG_SYNC, &conn->flags)) {
|
||||||
|
hci_conn_hash_list_flag(hdev, find_bis, ISO_LINK,
|
||||||
|
HCI_CONN_BIG_SYNC, d);
|
||||||
|
|
||||||
|
if (!d->count)
|
||||||
|
d->big_sync_term = true;
|
||||||
|
}
|
||||||
|
|
||||||
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
|
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
|
||||||
terminate_big_destroy);
|
terminate_big_destroy);
|
||||||
@@ -864,12 +894,6 @@ static void bis_cleanup(struct hci_conn *conn)
|
|||||||
|
|
||||||
hci_le_terminate_big(hdev, conn);
|
hci_le_terminate_big(hdev, conn);
|
||||||
} else {
|
} else {
|
||||||
bis = hci_conn_hash_lookup_big_any_dst(hdev,
|
|
||||||
conn->iso_qos.bcast.big);
|
|
||||||
|
|
||||||
if (bis)
|
|
||||||
return;
|
|
||||||
|
|
||||||
hci_le_big_terminate(hdev, conn->iso_qos.bcast.big,
|
hci_le_big_terminate(hdev, conn->iso_qos.bcast.big,
|
||||||
conn);
|
conn);
|
||||||
}
|
}
|
||||||
@@ -928,31 +952,18 @@ static void cis_cleanup(struct hci_conn *conn)
|
|||||||
hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
|
hci_le_remove_cig(hdev, conn->iso_qos.ucast.cig);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 hci_conn_hash_alloc_unset(struct hci_dev *hdev)
|
static int hci_conn_hash_alloc_unset(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct hci_conn_hash *h = &hdev->conn_hash;
|
return ida_alloc_range(&hdev->unset_handle_ida, HCI_CONN_HANDLE_MAX + 1,
|
||||||
struct hci_conn *c;
|
U16_MAX, GFP_ATOMIC);
|
||||||
u16 handle = HCI_CONN_HANDLE_MAX + 1;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(c, &h->list, list) {
|
|
||||||
/* Find the first unused handle */
|
|
||||||
if (handle == 0xffff || c->handle != handle)
|
|
||||||
break;
|
|
||||||
handle++;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||||
u8 role)
|
u8 role, u16 handle)
|
||||||
{
|
{
|
||||||
struct hci_conn *conn;
|
struct hci_conn *conn;
|
||||||
|
|
||||||
BT_DBG("%s dst %pMR", hdev->name, dst);
|
bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
|
||||||
|
|
||||||
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
@@ -960,7 +971,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
|
|
||||||
bacpy(&conn->dst, dst);
|
bacpy(&conn->dst, dst);
|
||||||
bacpy(&conn->src, &hdev->bdaddr);
|
bacpy(&conn->src, &hdev->bdaddr);
|
||||||
conn->handle = hci_conn_hash_alloc_unset(hdev);
|
conn->handle = handle;
|
||||||
conn->hdev = hdev;
|
conn->hdev = hdev;
|
||||||
conn->type = type;
|
conn->type = type;
|
||||||
conn->role = role;
|
conn->role = role;
|
||||||
@@ -973,6 +984,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
conn->rssi = HCI_RSSI_INVALID;
|
conn->rssi = HCI_RSSI_INVALID;
|
||||||
conn->tx_power = HCI_TX_POWER_INVALID;
|
conn->tx_power = HCI_TX_POWER_INVALID;
|
||||||
conn->max_tx_power = HCI_TX_POWER_INVALID;
|
conn->max_tx_power = HCI_TX_POWER_INVALID;
|
||||||
|
conn->sync_handle = HCI_SYNC_HANDLE_INVALID;
|
||||||
|
|
||||||
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;
|
||||||
@@ -1044,6 +1056,20 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
|
||||||
|
bdaddr_t *dst, u8 role)
|
||||||
|
{
|
||||||
|
int handle;
|
||||||
|
|
||||||
|
bt_dev_dbg(hdev, "dst %pMR", dst);
|
||||||
|
|
||||||
|
handle = hci_conn_hash_alloc_unset(hdev);
|
||||||
|
if (unlikely(handle < 0))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return hci_conn_add(hdev, type, dst, role, handle);
|
||||||
|
}
|
||||||
|
|
||||||
static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
|
static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
|
||||||
{
|
{
|
||||||
if (!reason)
|
if (!reason)
|
||||||
@@ -1247,6 +1273,12 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In case of BIG/PA sync failed, clear conn flags so that
|
||||||
|
* the conns will be correctly cleaned up by ISO layer
|
||||||
|
*/
|
||||||
|
test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn->flags);
|
||||||
|
test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn->flags);
|
||||||
|
|
||||||
conn->state = BT_CLOSED;
|
conn->state = BT_CLOSED;
|
||||||
hci_connect_cfm(conn, status);
|
hci_connect_cfm(conn, status);
|
||||||
hci_conn_del(conn);
|
hci_conn_del(conn);
|
||||||
@@ -1274,6 +1306,9 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
|
|||||||
if (conn->abort_reason)
|
if (conn->abort_reason)
|
||||||
return conn->abort_reason;
|
return conn->abort_reason;
|
||||||
|
|
||||||
|
if (HCI_CONN_HANDLE_UNSET(conn->handle))
|
||||||
|
ida_free(&hdev->unset_handle_ida, conn->handle);
|
||||||
|
|
||||||
conn->handle = handle;
|
conn->handle = handle;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1381,7 +1416,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
if (conn) {
|
if (conn) {
|
||||||
bacpy(&conn->dst, dst);
|
bacpy(&conn->dst, dst);
|
||||||
} else {
|
} else {
|
||||||
conn = hci_conn_add(hdev, LE_LINK, dst, role);
|
conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
hci_conn_hold(conn);
|
hci_conn_hold(conn);
|
||||||
@@ -1486,6 +1521,18 @@ static int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos)
|
|||||||
|
|
||||||
/* Allocate BIS if not set */
|
/* Allocate BIS if not set */
|
||||||
if (qos->bcast.bis == BT_ISO_QOS_BIS_UNSET) {
|
if (qos->bcast.bis == BT_ISO_QOS_BIS_UNSET) {
|
||||||
|
if (qos->bcast.big != BT_ISO_QOS_BIG_UNSET) {
|
||||||
|
conn = hci_conn_hash_lookup_big(hdev, qos->bcast.big);
|
||||||
|
|
||||||
|
if (conn) {
|
||||||
|
/* If the BIG handle is already matched to an advertising
|
||||||
|
* handle, do not allocate a new one.
|
||||||
|
*/
|
||||||
|
qos->bcast.bis = conn->iso_qos.bcast.bis;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find an unused adv set to advertise BIS, skip instance 0x00
|
/* Find an unused adv set to advertise BIS, skip instance 0x00
|
||||||
* since it is reserved as general purpose set.
|
* since it is reserved as general purpose set.
|
||||||
*/
|
*/
|
||||||
@@ -1546,7 +1593,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
memcmp(conn->le_per_adv_data, base, base_len)))
|
memcmp(conn->le_per_adv_data, base, base_len)))
|
||||||
return ERR_PTR(-EADDRINUSE);
|
return ERR_PTR(-EADDRINUSE);
|
||||||
|
|
||||||
conn = hci_conn_add(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
@@ -1590,7 +1637,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
|
|
||||||
BT_DBG("requesting refresh of dst_addr");
|
BT_DBG("requesting refresh of dst_addr");
|
||||||
|
|
||||||
conn = hci_conn_add(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
|
conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
@@ -1638,7 +1685,7 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
|
|
||||||
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
||||||
if (!acl) {
|
if (!acl) {
|
||||||
acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
|
acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
@@ -1698,7 +1745,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
|||||||
|
|
||||||
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
|
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
|
||||||
if (!sco) {
|
if (!sco) {
|
||||||
sco = hci_conn_add(hdev, type, dst, HCI_ROLE_MASTER);
|
sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
|
||||||
if (!sco) {
|
if (!sco) {
|
||||||
hci_conn_drop(acl);
|
hci_conn_drop(acl);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
@@ -1890,7 +1937,7 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||||||
cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
|
cis = hci_conn_hash_lookup_cis(hdev, dst, dst_type, qos->ucast.cig,
|
||||||
qos->ucast.cis);
|
qos->ucast.cis);
|
||||||
if (!cis) {
|
if (!cis) {
|
||||||
cis = hci_conn_add(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
|
||||||
if (!cis)
|
if (!cis)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
cis->cleanup = cis_cleanup;
|
cis->cleanup = cis_cleanup;
|
||||||
@@ -2139,7 +2186,7 @@ int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
|
|||||||
} pdu;
|
} pdu;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (num_bis > sizeof(pdu.bis))
|
if (num_bis < 0x01 || num_bis > sizeof(pdu.bis))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = qos_set_big(hdev, qos);
|
err = qos_set_big(hdev, qos);
|
||||||
|
@@ -2535,6 +2535,8 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
|
|||||||
mutex_init(&hdev->lock);
|
mutex_init(&hdev->lock);
|
||||||
mutex_init(&hdev->req_lock);
|
mutex_init(&hdev->req_lock);
|
||||||
|
|
||||||
|
ida_init(&hdev->unset_handle_ida);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&hdev->mesh_pending);
|
INIT_LIST_HEAD(&hdev->mesh_pending);
|
||||||
INIT_LIST_HEAD(&hdev->mgmt_pending);
|
INIT_LIST_HEAD(&hdev->mgmt_pending);
|
||||||
INIT_LIST_HEAD(&hdev->reject_list);
|
INIT_LIST_HEAD(&hdev->reject_list);
|
||||||
@@ -2789,6 +2791,7 @@ void hci_release_dev(struct hci_dev *hdev)
|
|||||||
hci_codec_list_clear(&hdev->local_codecs);
|
hci_codec_list_clear(&hdev->local_codecs);
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
|
|
||||||
|
ida_destroy(&hdev->unset_handle_ida);
|
||||||
ida_simple_remove(&hci_index_ida, hdev->id);
|
ida_simple_remove(&hci_index_ida, hdev->id);
|
||||||
kfree_skb(hdev->sent_cmd);
|
kfree_skb(hdev->sent_cmd);
|
||||||
kfree_skb(hdev->recv_event);
|
kfree_skb(hdev->recv_event);
|
||||||
|
@@ -2335,7 +2335,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
|
conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
|
||||||
HCI_ROLE_MASTER);
|
HCI_ROLE_MASTER);
|
||||||
if (!conn)
|
if (!conn)
|
||||||
bt_dev_err(hdev, "no memory for new connection");
|
bt_dev_err(hdev, "no memory for new connection");
|
||||||
@@ -3151,8 +3151,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
|
|||||||
hci_bdaddr_list_lookup_with_flags(&hdev->accept_list,
|
hci_bdaddr_list_lookup_with_flags(&hdev->accept_list,
|
||||||
&ev->bdaddr,
|
&ev->bdaddr,
|
||||||
BDADDR_BREDR)) {
|
BDADDR_BREDR)) {
|
||||||
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
|
conn = hci_conn_add_unset(hdev, ev->link_type,
|
||||||
HCI_ROLE_SLAVE);
|
&ev->bdaddr, HCI_ROLE_SLAVE);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
bt_dev_err(hdev, "no memory for new conn");
|
bt_dev_err(hdev, "no memory for new conn");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@@ -3317,7 +3317,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
|
|||||||
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
|
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
|
||||||
&ev->bdaddr);
|
&ev->bdaddr);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
|
conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
|
||||||
HCI_ROLE_SLAVE);
|
HCI_ROLE_SLAVE);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
bt_dev_err(hdev, "no memory for new connection");
|
bt_dev_err(hdev, "no memory for new connection");
|
||||||
@@ -5890,7 +5890,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||||||
if (status)
|
if (status)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);
|
conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
bt_dev_err(hdev, "no memory for new connection");
|
bt_dev_err(hdev, "no memory for new connection");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@@ -5952,17 +5952,11 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||||||
|
|
||||||
conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL);
|
conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL);
|
||||||
|
|
||||||
if (handle > HCI_CONN_HANDLE_MAX) {
|
|
||||||
bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x", handle,
|
|
||||||
HCI_CONN_HANDLE_MAX);
|
|
||||||
status = HCI_ERROR_INVALID_PARAMETERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All connection failure handling is taken care of by the
|
/* All connection failure handling is taken care of by the
|
||||||
* hci_conn_failed function which is triggered by the HCI
|
* hci_conn_failed function which is triggered by the HCI
|
||||||
* request completion callbacks used for connecting.
|
* request completion callbacks used for connecting.
|
||||||
*/
|
*/
|
||||||
if (status)
|
if (status || hci_conn_set_handle(conn, handle))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
/* Drop the connection if it has been aborted */
|
/* Drop the connection if it has been aborted */
|
||||||
@@ -5986,7 +5980,6 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
|
|||||||
mgmt_device_connected(hdev, conn, NULL, 0);
|
mgmt_device_connected(hdev, conn, NULL, 0);
|
||||||
|
|
||||||
conn->sec_level = BT_SECURITY_LOW;
|
conn->sec_level = BT_SECURITY_LOW;
|
||||||
conn->handle = handle;
|
|
||||||
conn->state = BT_CONFIG;
|
conn->state = BT_CONFIG;
|
||||||
|
|
||||||
/* Store current advertising instance as connection advertising instance
|
/* Store current advertising instance as connection advertising instance
|
||||||
@@ -6603,7 +6596,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
|
|||||||
struct hci_ev_le_pa_sync_established *ev = data;
|
struct hci_ev_le_pa_sync_established *ev = data;
|
||||||
int mask = hdev->link_mode;
|
int mask = hdev->link_mode;
|
||||||
__u8 flags = 0;
|
__u8 flags = 0;
|
||||||
struct hci_conn *bis;
|
struct hci_conn *pa_sync;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
|
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
|
||||||
|
|
||||||
@@ -6620,20 +6613,19 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
|
|||||||
if (!(flags & HCI_PROTO_DEFER))
|
if (!(flags & HCI_PROTO_DEFER))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
/* Add connection to indicate the PA sync event */
|
if (ev->status) {
|
||||||
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
|
/* Add connection to indicate the failed PA sync event */
|
||||||
|
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
|
||||||
HCI_ROLE_SLAVE);
|
HCI_ROLE_SLAVE);
|
||||||
|
|
||||||
if (!bis)
|
if (!pa_sync)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
if (ev->status)
|
set_bit(HCI_CONN_PA_SYNC_FAILED, &pa_sync->flags);
|
||||||
set_bit(HCI_CONN_PA_SYNC_FAILED, &bis->flags);
|
|
||||||
else
|
|
||||||
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
|
|
||||||
|
|
||||||
/* Notify connection to iso layer */
|
/* Notify iso layer */
|
||||||
hci_connect_cfm(bis, ev->status);
|
hci_connect_cfm(pa_sync, ev->status);
|
||||||
|
}
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
@@ -7020,12 +7012,12 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
|
|||||||
|
|
||||||
cis = hci_conn_hash_lookup_handle(hdev, cis_handle);
|
cis = hci_conn_hash_lookup_handle(hdev, cis_handle);
|
||||||
if (!cis) {
|
if (!cis) {
|
||||||
cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE);
|
cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
|
||||||
|
cis_handle);
|
||||||
if (!cis) {
|
if (!cis) {
|
||||||
hci_le_reject_cis(hdev, ev->cis_handle);
|
hci_le_reject_cis(hdev, ev->cis_handle);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
cis->handle = cis_handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cis->iso_qos.ucast.cig = ev->cig_id;
|
cis->iso_qos.ucast.cig = ev->cig_id;
|
||||||
@@ -7113,7 +7105,6 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||||||
{
|
{
|
||||||
struct hci_evt_le_big_sync_estabilished *ev = data;
|
struct hci_evt_le_big_sync_estabilished *ev = data;
|
||||||
struct hci_conn *bis;
|
struct hci_conn *bis;
|
||||||
struct hci_conn *pa_sync;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
|
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
|
||||||
@@ -7124,15 +7115,6 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
if (!ev->status) {
|
|
||||||
pa_sync = hci_conn_hash_lookup_pa_sync(hdev, ev->handle);
|
|
||||||
if (pa_sync)
|
|
||||||
/* Also mark the BIG sync established event on the
|
|
||||||
* associated PA sync hcon
|
|
||||||
*/
|
|
||||||
set_bit(HCI_CONN_BIG_SYNC, &pa_sync->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ev->num_bis; i++) {
|
for (i = 0; i < ev->num_bis; i++) {
|
||||||
u16 handle = le16_to_cpu(ev->bis[i]);
|
u16 handle = le16_to_cpu(ev->bis[i]);
|
||||||
__le32 interval;
|
__le32 interval;
|
||||||
@@ -7140,10 +7122,9 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||||||
bis = hci_conn_hash_lookup_handle(hdev, handle);
|
bis = hci_conn_hash_lookup_handle(hdev, handle);
|
||||||
if (!bis) {
|
if (!bis) {
|
||||||
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
|
bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
|
||||||
HCI_ROLE_SLAVE);
|
HCI_ROLE_SLAVE, handle);
|
||||||
if (!bis)
|
if (!bis)
|
||||||
continue;
|
continue;
|
||||||
bis->handle = handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev->status != 0x42)
|
if (ev->status != 0x42)
|
||||||
@@ -7186,15 +7167,42 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
|
|||||||
struct hci_evt_le_big_info_adv_report *ev = data;
|
struct hci_evt_le_big_info_adv_report *ev = data;
|
||||||
int mask = hdev->link_mode;
|
int mask = hdev->link_mode;
|
||||||
__u8 flags = 0;
|
__u8 flags = 0;
|
||||||
|
struct hci_conn *pa_sync;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle));
|
bt_dev_dbg(hdev, "sync_handle 0x%4.4x", le16_to_cpu(ev->sync_handle));
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
|
mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, ISO_LINK, &flags);
|
||||||
if (!(mask & HCI_LM_ACCEPT))
|
if (!(mask & HCI_LM_ACCEPT)) {
|
||||||
hci_le_pa_term_sync(hdev, ev->sync_handle);
|
hci_le_pa_term_sync(hdev, ev->sync_handle);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & HCI_PROTO_DEFER))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
pa_sync = hci_conn_hash_lookup_pa_sync_handle
|
||||||
|
(hdev,
|
||||||
|
le16_to_cpu(ev->sync_handle));
|
||||||
|
|
||||||
|
if (pa_sync)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
/* Add connection to indicate the PA sync event */
|
||||||
|
pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
|
||||||
|
HCI_ROLE_SLAVE);
|
||||||
|
|
||||||
|
if (!pa_sync)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
|
||||||
|
set_bit(HCI_CONN_PA_SYNC, &pa_sync->flags);
|
||||||
|
|
||||||
|
/* Notify iso layer */
|
||||||
|
hci_connect_cfm(pa_sync, 0x00);
|
||||||
|
|
||||||
|
unlock:
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -152,7 +152,7 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
|
|||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "Opcode 0x%4x", opcode);
|
bt_dev_dbg(hdev, "Opcode 0x%4.4x", opcode);
|
||||||
|
|
||||||
hci_req_init(&req, hdev);
|
hci_req_init(&req, hdev);
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
|
|||||||
skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
|
skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
|
||||||
if (IS_ERR(skb)) {
|
if (IS_ERR(skb)) {
|
||||||
if (!event)
|
if (!event)
|
||||||
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
|
bt_dev_err(hdev, "Opcode 0x%4.4x failed: %ld", opcode,
|
||||||
PTR_ERR(skb));
|
PTR_ERR(skb));
|
||||||
return PTR_ERR(skb);
|
return PTR_ERR(skb);
|
||||||
}
|
}
|
||||||
@@ -1312,7 +1312,7 @@ int hci_start_ext_adv_sync(struct hci_dev *hdev, u8 instance)
|
|||||||
return hci_enable_ext_advertising_sync(hdev, instance);
|
return hci_enable_ext_advertising_sync(hdev, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance)
|
int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance)
|
||||||
{
|
{
|
||||||
struct hci_cp_le_set_per_adv_enable cp;
|
struct hci_cp_le_set_per_adv_enable cp;
|
||||||
struct adv_info *adv = NULL;
|
struct adv_info *adv = NULL;
|
||||||
@@ -4264,12 +4264,12 @@ static int hci_le_set_host_feature_sync(struct hci_dev *hdev)
|
|||||||
{
|
{
|
||||||
struct hci_cp_le_set_host_feature cp;
|
struct hci_cp_le_set_host_feature cp;
|
||||||
|
|
||||||
if (!iso_capable(hdev))
|
if (!cis_capable(hdev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(&cp, 0, sizeof(cp));
|
memset(&cp, 0, sizeof(cp));
|
||||||
|
|
||||||
/* Isochronous Channels (Host Support) */
|
/* Connected Isochronous Channels (Host Support) */
|
||||||
cp.bit_number = 32;
|
cp.bit_number = 32;
|
||||||
cp.bit_value = 1;
|
cp.bit_value = 1;
|
||||||
|
|
||||||
@@ -5232,6 +5232,17 @@ static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn,
|
|||||||
if (conn->type == AMP_LINK)
|
if (conn->type == AMP_LINK)
|
||||||
return hci_disconnect_phy_link_sync(hdev, conn->handle, reason);
|
return hci_disconnect_phy_link_sync(hdev, conn->handle, reason);
|
||||||
|
|
||||||
|
if (test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) {
|
||||||
|
/* This is a BIS connection, hci_conn_del will
|
||||||
|
* do the necessary cleanup.
|
||||||
|
*/
|
||||||
|
hci_dev_lock(hdev);
|
||||||
|
hci_conn_failed(conn, reason);
|
||||||
|
hci_dev_unlock(hdev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&cp, 0, sizeof(cp));
|
memset(&cp, 0, sizeof(cp));
|
||||||
cp.handle = cpu_to_le16(conn->handle);
|
cp.handle = cpu_to_le16(conn->handle);
|
||||||
cp.reason = reason;
|
cp.reason = reason;
|
||||||
@@ -5384,21 +5395,6 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason)
|
|||||||
err = hci_reject_conn_sync(hdev, conn, reason);
|
err = hci_reject_conn_sync(hdev, conn, reason);
|
||||||
break;
|
break;
|
||||||
case BT_OPEN:
|
case BT_OPEN:
|
||||||
hci_dev_lock(hdev);
|
|
||||||
|
|
||||||
/* Cleanup bis or pa sync connections */
|
|
||||||
if (test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn->flags) ||
|
|
||||||
test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn->flags)) {
|
|
||||||
hci_conn_failed(conn, reason);
|
|
||||||
} else if (test_bit(HCI_CONN_PA_SYNC, &conn->flags) ||
|
|
||||||
test_bit(HCI_CONN_BIG_SYNC, &conn->flags)) {
|
|
||||||
conn->state = BT_CLOSED;
|
|
||||||
hci_disconn_cfm(conn, reason);
|
|
||||||
hci_conn_del(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_dev_unlock(hdev);
|
|
||||||
return 0;
|
|
||||||
case BT_BOUND:
|
case BT_BOUND:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -35,7 +35,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
|
|||||||
{
|
{
|
||||||
struct hci_dev *hdev = conn->hdev;
|
struct hci_dev *hdev = conn->hdev;
|
||||||
|
|
||||||
BT_DBG("conn %p", conn);
|
bt_dev_dbg(hdev, "conn %p", conn);
|
||||||
|
|
||||||
conn->dev.type = &bt_link;
|
conn->dev.type = &bt_link;
|
||||||
conn->dev.class = &bt_class;
|
conn->dev.class = &bt_class;
|
||||||
@@ -48,27 +48,30 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
|
|||||||
{
|
{
|
||||||
struct hci_dev *hdev = conn->hdev;
|
struct hci_dev *hdev = conn->hdev;
|
||||||
|
|
||||||
BT_DBG("conn %p", conn);
|
bt_dev_dbg(hdev, "conn %p", conn);
|
||||||
|
|
||||||
if (device_is_registered(&conn->dev))
|
if (device_is_registered(&conn->dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
|
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
|
||||||
|
|
||||||
if (device_add(&conn->dev) < 0) {
|
if (device_add(&conn->dev) < 0)
|
||||||
bt_dev_err(hdev, "failed to register connection device");
|
bt_dev_err(hdev, "failed to register connection device");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_dev_hold(hdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_conn_del_sysfs(struct hci_conn *conn)
|
void hci_conn_del_sysfs(struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = conn->hdev;
|
struct hci_dev *hdev = conn->hdev;
|
||||||
|
|
||||||
if (!device_is_registered(&conn->dev))
|
bt_dev_dbg(hdev, "conn %p", conn);
|
||||||
|
|
||||||
|
if (!device_is_registered(&conn->dev)) {
|
||||||
|
/* If device_add() has *not* succeeded, use *only* put_device()
|
||||||
|
* to drop the reference count.
|
||||||
|
*/
|
||||||
|
put_device(&conn->dev);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@@ -80,9 +83,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
|||||||
put_device(dev);
|
put_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_del(&conn->dev);
|
device_unregister(&conn->dev);
|
||||||
|
|
||||||
hci_dev_put(hdev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bt_host_release(struct device *dev)
|
static void bt_host_release(struct device *dev)
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
#include <net/bluetooth/iso.h>
|
#include <net/bluetooth/iso.h>
|
||||||
|
#include "eir.h"
|
||||||
|
|
||||||
static const struct proto_ops iso_sock_ops;
|
static const struct proto_ops iso_sock_ops;
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ static void iso_sock_kill(struct sock *sk);
|
|||||||
|
|
||||||
#define EIR_SERVICE_DATA_LENGTH 4
|
#define EIR_SERVICE_DATA_LENGTH 4
|
||||||
#define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
|
#define BASE_MAX_LENGTH (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH)
|
||||||
|
#define EIR_BAA_SERVICE_UUID 0x1851
|
||||||
|
|
||||||
/* iso_pinfo flags values */
|
/* iso_pinfo flags values */
|
||||||
enum {
|
enum {
|
||||||
@@ -77,6 +79,7 @@ static struct bt_iso_qos default_qos;
|
|||||||
static bool check_ucast_qos(struct bt_iso_qos *qos);
|
static bool check_ucast_qos(struct bt_iso_qos *qos);
|
||||||
static bool check_bcast_qos(struct bt_iso_qos *qos);
|
static bool check_bcast_qos(struct bt_iso_qos *qos);
|
||||||
static bool iso_match_sid(struct sock *sk, void *data);
|
static bool iso_match_sid(struct sock *sk, void *data);
|
||||||
|
static bool iso_match_sync_handle(struct sock *sk, void *data);
|
||||||
static void iso_sock_disconn(struct sock *sk);
|
static void iso_sock_disconn(struct sock *sk);
|
||||||
|
|
||||||
/* ---- ISO timers ---- */
|
/* ---- ISO timers ---- */
|
||||||
@@ -789,8 +792,7 @@ static int iso_sock_bind_bc(struct socket *sock, struct sockaddr *addr,
|
|||||||
BT_DBG("sk %p bc_sid %u bc_num_bis %u", sk, sa->iso_bc->bc_sid,
|
BT_DBG("sk %p bc_sid %u bc_num_bis %u", sk, sa->iso_bc->bc_sid,
|
||||||
sa->iso_bc->bc_num_bis);
|
sa->iso_bc->bc_num_bis);
|
||||||
|
|
||||||
if (addr_len > sizeof(*sa) + sizeof(*sa->iso_bc) ||
|
if (addr_len > sizeof(*sa) + sizeof(*sa->iso_bc))
|
||||||
sa->iso_bc->bc_num_bis < 0x01 || sa->iso_bc->bc_num_bis > 0x1f)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
bacpy(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr);
|
bacpy(&iso_pi(sk)->dst, &sa->iso_bc->bc_bdaddr);
|
||||||
@@ -1202,7 +1204,6 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||||||
test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) {
|
test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) {
|
||||||
iso_conn_big_sync(sk);
|
iso_conn_big_sync(sk);
|
||||||
sk->sk_state = BT_LISTEN;
|
sk->sk_state = BT_LISTEN;
|
||||||
set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
|
|
||||||
} else {
|
} else {
|
||||||
iso_conn_defer_accept(pi->conn->hcon);
|
iso_conn_defer_accept(pi->conn->hcon);
|
||||||
sk->sk_state = BT_CONFIG;
|
sk->sk_state = BT_CONFIG;
|
||||||
@@ -1461,6 +1462,8 @@ static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
|
|||||||
len = min_t(unsigned int, len, base_len);
|
len = min_t(unsigned int, len, base_len);
|
||||||
if (copy_to_user(optval, base, len))
|
if (copy_to_user(optval, base, len))
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
|
if (put_user(len, optlen))
|
||||||
|
err = -EFAULT;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1579,6 +1582,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||||||
struct sock *sk = conn->sk;
|
struct sock *sk = conn->sk;
|
||||||
struct hci_ev_le_big_sync_estabilished *ev = NULL;
|
struct hci_ev_le_big_sync_estabilished *ev = NULL;
|
||||||
struct hci_ev_le_pa_sync_established *ev2 = NULL;
|
struct hci_ev_le_pa_sync_established *ev2 = NULL;
|
||||||
|
struct hci_evt_le_big_info_adv_report *ev3 = NULL;
|
||||||
struct hci_conn *hcon;
|
struct hci_conn *hcon;
|
||||||
|
|
||||||
BT_DBG("conn %p", conn);
|
BT_DBG("conn %p", conn);
|
||||||
@@ -1603,14 +1607,20 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||||||
parent = iso_get_sock_listen(&hcon->src,
|
parent = iso_get_sock_listen(&hcon->src,
|
||||||
&hcon->dst,
|
&hcon->dst,
|
||||||
iso_match_big, ev);
|
iso_match_big, ev);
|
||||||
} else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags) ||
|
} else if (test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
|
||||||
test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
|
|
||||||
ev2 = hci_recv_event_data(hcon->hdev,
|
ev2 = hci_recv_event_data(hcon->hdev,
|
||||||
HCI_EV_LE_PA_SYNC_ESTABLISHED);
|
HCI_EV_LE_PA_SYNC_ESTABLISHED);
|
||||||
if (ev2)
|
if (ev2)
|
||||||
parent = iso_get_sock_listen(&hcon->src,
|
parent = iso_get_sock_listen(&hcon->src,
|
||||||
&hcon->dst,
|
&hcon->dst,
|
||||||
iso_match_sid, ev2);
|
iso_match_sid, ev2);
|
||||||
|
} else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
|
||||||
|
ev3 = hci_recv_event_data(hcon->hdev,
|
||||||
|
HCI_EVT_LE_BIG_INFO_ADV_REPORT);
|
||||||
|
if (ev3)
|
||||||
|
parent = iso_get_sock_listen(&hcon->src,
|
||||||
|
&hcon->dst,
|
||||||
|
iso_match_sync_handle, ev3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parent)
|
if (!parent)
|
||||||
@@ -1650,11 +1660,13 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||||||
hcon->sync_handle = iso_pi(parent)->sync_handle;
|
hcon->sync_handle = iso_pi(parent)->sync_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev2 && !ev2->status) {
|
if (ev3) {
|
||||||
iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle;
|
|
||||||
iso_pi(sk)->qos = iso_pi(parent)->qos;
|
iso_pi(sk)->qos = iso_pi(parent)->qos;
|
||||||
|
iso_pi(sk)->qos.bcast.encryption = ev3->encryption;
|
||||||
|
hcon->iso_qos = iso_pi(sk)->qos;
|
||||||
iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
|
iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
|
||||||
memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS);
|
memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis, ISO_MAX_NUM_BIS);
|
||||||
|
set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bacpy(&iso_pi(sk)->dst, &hcon->dst);
|
bacpy(&iso_pi(sk)->dst, &hcon->dst);
|
||||||
@@ -1774,12 +1786,16 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|||||||
|
|
||||||
ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT);
|
ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT);
|
||||||
if (ev3) {
|
if (ev3) {
|
||||||
|
size_t base_len = ev3->length;
|
||||||
|
u8 *base;
|
||||||
|
|
||||||
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
|
sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
|
||||||
iso_match_sync_handle_pa_report, ev3);
|
iso_match_sync_handle_pa_report, ev3);
|
||||||
|
base = eir_get_service_data(ev3->data, ev3->length,
|
||||||
if (sk) {
|
EIR_BAA_SERVICE_UUID, &base_len);
|
||||||
memcpy(iso_pi(sk)->base, ev3->data, ev3->length);
|
if (base && sk && base_len <= sizeof(iso_pi(sk)->base)) {
|
||||||
iso_pi(sk)->base_len = ev3->length;
|
memcpy(iso_pi(sk)->base, base, base_len);
|
||||||
|
iso_pi(sk)->base_len = base_len;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL);
|
sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL);
|
||||||
|
@@ -150,10 +150,7 @@ static bool read_supported_features(struct hci_dev *hdev,
|
|||||||
|
|
||||||
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
||||||
HCI_CMD_TIMEOUT);
|
HCI_CMD_TIMEOUT);
|
||||||
if (IS_ERR_OR_NULL(skb)) {
|
if (IS_ERR(skb)) {
|
||||||
if (!skb)
|
|
||||||
skb = ERR_PTR(-EIO);
|
|
||||||
|
|
||||||
bt_dev_err(hdev, "Failed to read MSFT supported features (%ld)",
|
bt_dev_err(hdev, "Failed to read MSFT supported features (%ld)",
|
||||||
PTR_ERR(skb));
|
PTR_ERR(skb));
|
||||||
return false;
|
return false;
|
||||||
@@ -353,7 +350,7 @@ static void msft_remove_addr_filters_sync(struct hci_dev *hdev, u8 handle)
|
|||||||
|
|
||||||
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
||||||
HCI_CMD_TIMEOUT);
|
HCI_CMD_TIMEOUT);
|
||||||
if (IS_ERR_OR_NULL(skb)) {
|
if (IS_ERR(skb)) {
|
||||||
kfree(address_filter);
|
kfree(address_filter);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -442,11 +439,8 @@ static int msft_remove_monitor_sync(struct hci_dev *hdev,
|
|||||||
|
|
||||||
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
||||||
HCI_CMD_TIMEOUT);
|
HCI_CMD_TIMEOUT);
|
||||||
if (IS_ERR_OR_NULL(skb)) {
|
if (IS_ERR(skb))
|
||||||
if (!skb)
|
|
||||||
return -EIO;
|
|
||||||
return PTR_ERR(skb);
|
return PTR_ERR(skb);
|
||||||
}
|
|
||||||
|
|
||||||
return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode,
|
return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode,
|
||||||
monitor, skb);
|
monitor, skb);
|
||||||
@@ -559,7 +553,7 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
|
|||||||
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, total_size, cp,
|
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, total_size, cp,
|
||||||
HCI_CMD_TIMEOUT);
|
HCI_CMD_TIMEOUT);
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(skb)) {
|
if (IS_ERR(skb)) {
|
||||||
err = PTR_ERR(skb);
|
err = PTR_ERR(skb);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
@@ -740,10 +734,10 @@ static int msft_cancel_address_filter_sync(struct hci_dev *hdev, void *data)
|
|||||||
|
|
||||||
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, sizeof(cp), &cp,
|
||||||
HCI_CMD_TIMEOUT);
|
HCI_CMD_TIMEOUT);
|
||||||
if (IS_ERR_OR_NULL(skb)) {
|
if (IS_ERR(skb)) {
|
||||||
bt_dev_err(hdev, "MSFT: Failed to cancel address (%pMR) filter",
|
bt_dev_err(hdev, "MSFT: Failed to cancel address (%pMR) filter",
|
||||||
&address_filter->bdaddr);
|
&address_filter->bdaddr);
|
||||||
err = -EIO;
|
err = PTR_ERR(skb);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
@@ -893,7 +887,7 @@ static int msft_add_address_filter_sync(struct hci_dev *hdev, void *data)
|
|||||||
|
|
||||||
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, size, cp,
|
skb = __hci_cmd_sync(hdev, hdev->msft_opcode, size, cp,
|
||||||
HCI_CMD_TIMEOUT);
|
HCI_CMD_TIMEOUT);
|
||||||
if (IS_ERR_OR_NULL(skb)) {
|
if (IS_ERR(skb)) {
|
||||||
bt_dev_err(hdev, "Failed to enable address %pMR filter",
|
bt_dev_err(hdev, "Failed to enable address %pMR filter",
|
||||||
&address_filter->bdaddr);
|
&address_filter->bdaddr);
|
||||||
skb = NULL;
|
skb = NULL;
|
||||||
|
Reference in New Issue
Block a user