Bluetooth: hci_event: Fix not indicating new connection for BIG Sync
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 31 Jan 2024 16:24:19 +0000 (11:24 -0500)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 6 Mar 2024 22:22:39 +0000 (17:22 -0500)
BIG Sync (aka. Broadcast sink) requires to inform that the device is
connected when a data path is active otherwise userspace could attempt
to free resources allocated to the device object while scanning.

Fixes: 1d11d70d1f6b ("Bluetooth: ISO: Pass BIG encryption info through QoS")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/hci_event.c
net/bluetooth/mgmt.c

index 11b55d1f977272a55f51ad5eb7136a1af7f0ebfd..271c00792801c4ed73f5822455a3afe36d6b208a 100644 (file)
@@ -2524,9 +2524,7 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
         * Only those in BT_CONFIG or BT_CONNECTED states can be
         * considered connected.
         */
-       if (conn &&
-           (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
-           !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+       if (conn && (conn->state == BT_CONFIG || conn->state == BT_CONNECTED))
                mgmt_device_connected(hdev, conn, name, name_len);
 
        if (discov->state == DISCOVERY_STOPPED)
@@ -3758,8 +3756,9 @@ static void hci_remote_features_evt(struct hci_dev *hdev, void *data,
                bacpy(&cp.bdaddr, &conn->dst);
                cp.pscan_rep_mode = 0x02;
                hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
-       } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+       } else {
                mgmt_device_connected(hdev, conn, NULL, 0);
+       }
 
        if (!hci_outgoing_auth_needed(hdev, conn)) {
                conn->state = BT_CONNECTED;
@@ -3932,6 +3931,11 @@ static u8 hci_cc_le_setup_iso_path(struct hci_dev *hdev, void *data,
                 * last.
                 */
                hci_connect_cfm(conn, rp->status);
+
+               /* Notify device connected in case it is a BIG Sync */
+               if (!rp->status && test_bit(HCI_CONN_BIG_SYNC, &conn->flags))
+                       mgmt_device_connected(hdev, conn, NULL, 0);
+
                break;
        }
 
@@ -5006,8 +5010,9 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data,
                bacpy(&cp.bdaddr, &conn->dst);
                cp.pscan_rep_mode = 0x02;
                hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
-       } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+       } else {
                mgmt_device_connected(hdev, conn, NULL, 0);
+       }
 
        if (!hci_outgoing_auth_needed(hdev, conn)) {
                conn->state = BT_CONNECTED;
@@ -5980,8 +5985,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
                goto unlock;
        }
 
-       if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-               mgmt_device_connected(hdev, conn, NULL, 0);
+       mgmt_device_connected(hdev, conn, NULL, 0);
 
        conn->sec_level = BT_SECURITY_LOW;
        conn->state = BT_CONFIG;
@@ -7210,6 +7214,9 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
        /* Notify iso layer */
        hci_connect_cfm(pa_sync, 0x00);
 
+       /* Notify MGMT layer */
+       mgmt_device_connected(hdev, pa_sync, NULL, 0);
+
 unlock:
        hci_dev_unlock(hdev);
 }
index 7713e2cdf9e12b615bcd16f990365c4efc0670ed..064a67157d438b8e3ce29a7bc1b0ee9ced24c6b6 100644 (file)
@@ -3126,6 +3126,7 @@ failed:
 static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
 {
        switch (link_type) {
+       case ISO_LINK:
        case LE_LINK:
                switch (addr_type) {
                case ADDR_LE_DEV_PUBLIC:
@@ -9618,6 +9619,9 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
        u16 eir_len = 0;
        u32 flags = 0;
 
+       if (test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               return;
+
        /* allocate buff for LE or BR/EDR adv */
        if (conn->le_adv_data_len > 0)
                skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_CONNECTED,