| From 7dac1a3d5a53fc6da14e89692e34cf3300146be1 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 21 Feb 2024 09:38:10 -0500 |
| Subject: Bluetooth: hci_sync: Use QoS to determine which PHY to scan |
| |
| From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| |
| [ Upstream commit 22cbf4f84c00da64196eb15034feee868e63eef0 ] |
| |
| This used the hci_conn QoS to determine which PHY to scan when creating |
| a PA Sync. |
| |
| Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| Stable-dep-of: 53cb4197e63a ("Bluetooth: hci_sync: Fix using the same interval and window for Coded PHY") |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/bluetooth/hci_sync.c | 66 +++++++++++++++++++++++++++++++++------- |
| 1 file changed, 55 insertions(+), 11 deletions(-) |
| |
| diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c |
| index 824ce03bb361b..89bd1c1a3e0e8 100644 |
| --- a/net/bluetooth/hci_sync.c |
| +++ b/net/bluetooth/hci_sync.c |
| @@ -2611,6 +2611,14 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) |
| return filter_policy; |
| } |
| |
| +static void hci_le_scan_phy_params(struct hci_cp_le_scan_phy_params *cp, |
| + u8 type, u16 interval, u16 window) |
| +{ |
| + cp->type = type; |
| + cp->interval = cpu_to_le16(interval); |
| + cp->window = cpu_to_le16(window); |
| +} |
| + |
| static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, |
| u16 interval, u16 window, |
| u8 own_addr_type, u8 filter_policy) |
| @@ -2618,7 +2626,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, |
| struct hci_cp_le_set_ext_scan_params *cp; |
| struct hci_cp_le_scan_phy_params *phy; |
| u8 data[sizeof(*cp) + sizeof(*phy) * 2]; |
| - u8 num_phy = 0; |
| + u8 num_phy = 0x00; |
| |
| cp = (void *)data; |
| phy = (void *)cp->data; |
| @@ -2628,28 +2636,64 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, |
| cp->own_addr_type = own_addr_type; |
| cp->filter_policy = filter_policy; |
| |
| + /* Check if PA Sync is in progress then select the PHY based on the |
| + * hci_conn.iso_qos. |
| + */ |
| + if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) { |
| + struct hci_cp_le_add_to_accept_list *sent; |
| + |
| + sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST); |
| + if (sent) { |
| + struct hci_conn *conn; |
| + |
| + conn = hci_conn_hash_lookup_ba(hdev, ISO_LINK, |
| + &sent->bdaddr); |
| + if (conn) { |
| + struct bt_iso_qos *qos = &conn->iso_qos; |
| + |
| + if (qos->bcast.in.phy & BT_ISO_PHY_1M || |
| + qos->bcast.in.phy & BT_ISO_PHY_2M) { |
| + cp->scanning_phys |= LE_SCAN_PHY_1M; |
| + hci_le_scan_phy_params(phy, type, |
| + interval, |
| + window); |
| + num_phy++; |
| + phy++; |
| + } |
| + |
| + if (qos->bcast.in.phy & BT_ISO_PHY_CODED) { |
| + cp->scanning_phys |= LE_SCAN_PHY_CODED; |
| + hci_le_scan_phy_params(phy, type, |
| + interval, |
| + window); |
| + num_phy++; |
| + phy++; |
| + } |
| + |
| + if (num_phy) |
| + goto done; |
| + } |
| + } |
| + } |
| + |
| if (scan_1m(hdev) || scan_2m(hdev)) { |
| cp->scanning_phys |= LE_SCAN_PHY_1M; |
| - |
| - phy->type = type; |
| - phy->interval = cpu_to_le16(interval); |
| - phy->window = cpu_to_le16(window); |
| - |
| + hci_le_scan_phy_params(phy, type, interval, window); |
| num_phy++; |
| phy++; |
| } |
| |
| if (scan_coded(hdev)) { |
| cp->scanning_phys |= LE_SCAN_PHY_CODED; |
| - |
| - phy->type = type; |
| - phy->interval = cpu_to_le16(interval); |
| - phy->window = cpu_to_le16(window); |
| - |
| + hci_le_scan_phy_params(phy, type, interval, window); |
| num_phy++; |
| phy++; |
| } |
| |
| +done: |
| + if (!num_phy) |
| + return -EINVAL; |
| + |
| return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS, |
| sizeof(*cp) + sizeof(*phy) * num_phy, |
| data, HCI_CMD_TIMEOUT); |
| -- |
| 2.43.0 |
| |