Commit f4dbc2bb authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-next-2023-10-23' of...

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.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4fb56e3e 53088689
...@@ -118,6 +118,7 @@ MODULE_DEVICE_TABLE(sdio, btmtksdio_table); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 { ...@@ -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[] = { ...@@ -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[] = { ...@@ -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[] = { ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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[] = { ...@@ -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[] = { ...@@ -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) ...@@ -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 = { ...@@ -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); ...@@ -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); ...@@ -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 },
......
/* /*
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 { ...@@ -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 { ...@@ -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,8 +1292,8 @@ static inline struct hci_conn *hci_conn_hash_lookup_big(struct hci_dev *hdev, ...@@ -1290,8 +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, static inline struct hci_conn *
__u8 handle) 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;
...@@ -1299,22 +1301,22 @@ static inline struct hci_conn *hci_conn_hash_lookup_big_any_dst(struct hci_dev * ...@@ -1299,22 +1301,22 @@ static inline struct hci_conn *hci_conn_hash_lookup_big_any_dst(struct hci_dev *
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) { list_for_each_entry_rcu(c, &h->list, list) {
if (c->type != ISO_LINK) if (c->type != ISO_LINK ||
!test_bit(HCI_CONN_PA_SYNC, &c->flags))
continue; continue;
if (handle != BT_ISO_QOS_BIG_UNSET && handle == c->iso_qos.bcast.big) { if (c->iso_qos.bcast.big == big) {
rcu_read_unlock(); rcu_read_unlock();
return c; return c;
} }
} }
rcu_read_unlock(); rcu_read_unlock();
return NULL; 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_handle(struct hci_dev *hdev, __u16 sync_handle)
{ {
struct hci_conn_hash *h = &hdev->conn_hash; struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *c; struct hci_conn *c;
...@@ -1326,7 +1328,7 @@ hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big) ...@@ -1326,7 +1328,7 @@ hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big)
!test_bit(HCI_CONN_PA_SYNC, &c->flags)) !test_bit(HCI_CONN_PA_SYNC, &c->flags))
continue; continue;
if (c->iso_qos.bcast.big == big) { if (c->sync_handle == sync_handle) {
rcu_read_unlock(); rcu_read_unlock();
return c; return c;
} }
...@@ -1377,6 +1379,26 @@ static inline void hci_conn_hash_list_state(struct hci_dev *hdev, ...@@ -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); ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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,8 +2335,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) ...@@ -2335,8 +2335,8 @@ 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, ...@@ -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,8 +3317,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, ...@@ -3317,8 +3317,8 @@ 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");
goto unlock; goto unlock;
...@@ -5890,7 +5890,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 */
HCI_ROLE_SLAVE); pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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); ...@@ -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; ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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;
......
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