]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Bluetooth: ISO: Fix BIS cleanup
authorIulia Tanasescu <iulia.tanasescu@nxp.com>
Wed, 6 Sep 2023 13:59:54 +0000 (16:59 +0300)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 23 Oct 2023 17:54:06 +0000 (10:54 -0700)
This fixes the master BIS cleanup procedure - as opposed to CIS cleanup,
no HCI disconnect command should be issued. A master BIS should only be
terminated by disabling periodic and extended advertising, and terminating
the BIG.

In case of a Broadcast Receiver, all BIS and PA connections can be
cleaned up by calling hci_conn_failed, since it contains all function
calls that are necessary for successful cleanup.

Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/hci_sync.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_sync.c

index 57eeb07aeb251126994cb11c3626098e6a193f91..6efbc2152146bdef355d068aa09ade14678a03ec 100644 (file)
@@ -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,
                           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,
                                u8 instance, bool force);
 int hci_disable_advertising_sync(struct hci_dev *hdev);
index 73470cc3518a71e5a88759a833c6107902669ceb..973c9de01a0428444af635cb1a6fcf629afc45a7 100644 (file)
@@ -759,6 +759,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);
 
+       hci_disable_per_advertising_sync(hdev, d->bis);
        hci_remove_ext_adv_instance_sync(hdev, d->bis, NULL);
 
        /* Only terminate BIG if it has been created */
@@ -1247,6 +1248,12 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
                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;
        hci_connect_cfm(conn, status);
        hci_conn_del(conn);
index a15ab0b874a9d5cf5d6a2a77f3e93c8408aef83d..3485602518fed36ed00097596c3abdf64392c9d2 100644 (file)
@@ -1312,7 +1312,7 @@ int hci_start_ext_adv_sync(struct hci_dev *hdev, u8 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 adv_info *adv = NULL;
@@ -5232,6 +5232,17 @@ static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn,
        if (conn->type == AMP_LINK)
                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));
        cp.handle = cpu_to_le16(conn->handle);
        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);
                break;
        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:
                break;
        default: