]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections
authorYang Li <yang.li@amlogic.com>
Thu, 10 Jul 2025 10:52:47 +0000 (18:52 +0800)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 23 Jul 2025 14:35:14 +0000 (10:35 -0400)
Currently, BIS_LINK is used for both BIG sync and PA sync connections,
which makes it impossible to distinguish them when searching for a PA
sync connection.

Adding PA_LINK will make the distinction clearer and simplify future
extensions for PA-related features.

Signed-off-by: Yang Li <yang.li@amlogic.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/mgmt.c

index e90a7b753926636a7d310c9d76a2115d35c6b4da..df1847b74e55e96567cb09582a84f2569a6e5044 100644 (file)
@@ -562,6 +562,7 @@ enum {
 #define LE_LINK                0x80
 #define CIS_LINK       0x82
 #define BIS_LINK       0x83
+#define PA_LINK                0x84
 #define INVALID_LINK   0xff
 
 /* LMP features */
index 3728495f0819bdd913b8774ac20b03c6e1a8a3c1..4dc11c66f7b819727b2c77eca19ca8556485f249 100644 (file)
@@ -1015,6 +1015,7 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
                break;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                h->iso_num++;
                break;
        }
@@ -1042,6 +1043,7 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
                break;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                h->iso_num--;
                break;
        }
@@ -1060,6 +1062,7 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
                return h->sco_num;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                return h->iso_num;
        default:
                return 0;
@@ -1142,7 +1145,7 @@ hci_conn_hash_lookup_create_pa_sync(struct hci_dev *hdev)
        rcu_read_lock();
 
        list_for_each_entry_rcu(c, &h->list, list) {
-               if (c->type != BIS_LINK)
+               if (c->type != PA_LINK)
                        continue;
 
                if (!test_bit(HCI_CONN_CREATE_PA_SYNC, &c->flags))
@@ -1337,7 +1340,7 @@ hci_conn_hash_lookup_big_sync_pend(struct hci_dev *hdev,
        rcu_read_lock();
 
        list_for_each_entry_rcu(c, &h->list, list) {
-               if (c->type != BIS_LINK)
+               if (c->type != PA_LINK)
                        continue;
 
                if (handle == c->iso_qos.bcast.big && num_bis == c->num_bis) {
@@ -1407,7 +1410,7 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle)
        rcu_read_lock();
 
        list_for_each_entry_rcu(c, &h->list, list) {
-               if (c->type != BIS_LINK)
+               if (c->type != PA_LINK)
                        continue;
 
                /* Ignore the listen hcon, we are looking
@@ -2006,6 +2009,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
 
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                return iso_connect_ind(hdev, bdaddr, flags);
 
        default:
index b2e09e7f70e17cfe47acf6c9c964015687fc9fc1..7d1e79f69cd1cb13066935835b546fa84fae5f1e 100644 (file)
@@ -785,7 +785,7 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c
        d->sync_handle = conn->sync_handle;
 
        if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
-               hci_conn_hash_list_flag(hdev, find_bis, BIS_LINK,
+               hci_conn_hash_list_flag(hdev, find_bis, PA_LINK,
                                        HCI_CONN_PA_SYNC, d);
 
                if (!d->count)
@@ -914,6 +914,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
                break;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                if (hdev->iso_mtu)
                        /* Dedicated ISO Buffer exists */
                        break;
@@ -979,6 +980,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
                break;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                /* conn->src should reflect the local identity address */
                hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
 
@@ -1033,7 +1035,6 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
        }
 
        hci_conn_init_sysfs(conn);
-
        return conn;
 }
 
@@ -1077,6 +1078,7 @@ static void hci_conn_cleanup_child(struct hci_conn *conn, u8 reason)
                break;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                if ((conn->state != BT_CONNECTED &&
                    !test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) ||
                    test_bit(HCI_CONN_BIG_CREATED, &conn->flags))
@@ -1152,7 +1154,8 @@ void hci_conn_del(struct hci_conn *conn)
        } else {
                /* Unacked ISO frames */
                if (conn->type == CIS_LINK ||
-                   conn->type == BIS_LINK) {
+                   conn->type == BIS_LINK ||
+                   conn->type == PA_LINK) {
                        if (hdev->iso_pkts)
                                hdev->iso_cnt += conn->sent;
                        else if (hdev->le_pkts)
@@ -2081,7 +2084,7 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
 
        bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid);
 
-       conn = hci_conn_add_unset(hdev, BIS_LINK, dst, HCI_ROLE_SLAVE);
+       conn = hci_conn_add_unset(hdev, PA_LINK, dst, HCI_ROLE_SLAVE);
        if (IS_ERR(conn))
                return conn;
 
@@ -2246,7 +2249,7 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
         * the start periodic advertising and create BIG commands have
         * been queued
         */
-       hci_conn_hash_list_state(hdev, bis_mark_per_adv, BIS_LINK,
+       hci_conn_hash_list_state(hdev, bis_mark_per_adv, PA_LINK,
                                 BT_BOUND, &data);
 
        /* Queue start periodic advertising and create BIG */
@@ -2980,6 +2983,7 @@ void hci_conn_tx_queue(struct hci_conn *conn, struct sk_buff *skb)
        switch (conn->type) {
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
        case ACL_LINK:
        case LE_LINK:
                break;
index f2fbe9c8e1be0ddce4a68135b5bd8e0aaeb8a40c..55e0722fd06622310fb0b28b380860c49b9b277a 100644 (file)
@@ -2936,12 +2936,14 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
        case HCI_ACLDATA_PKT:
                /* Detect if ISO packet has been sent as ACL */
                if (hci_conn_num(hdev, CIS_LINK) ||
-                   hci_conn_num(hdev, BIS_LINK)) {
+                   hci_conn_num(hdev, BIS_LINK) ||
+                       hci_conn_num(hdev, PA_LINK)) {
                        __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
                        __u8 type;
 
                        type = hci_conn_lookup_type(hdev, hci_handle(handle));
-                       if (type == CIS_LINK || type == BIS_LINK)
+                       if (type == CIS_LINK || type == BIS_LINK ||
+                           type == PA_LINK)
                                hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
                }
                break;
@@ -3396,6 +3398,7 @@ static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote)
                break;
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
                cnt = hdev->iso_mtu ? hdev->iso_cnt :
                        hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
                break;
@@ -3409,7 +3412,7 @@ static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote)
 }
 
 static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
-                                    __u8 type2, int *quote)
+                                    int *quote)
 {
        struct hci_conn_hash *h = &hdev->conn_hash;
        struct hci_conn *conn = NULL, *c;
@@ -3421,7 +3424,7 @@ static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
        rcu_read_lock();
 
        list_for_each_entry_rcu(c, &h->list, list) {
-               if ((c->type != type && c->type != type2) ||
+               if (c->type != type ||
                    skb_queue_empty(&c->data_q))
                        continue;
 
@@ -3625,7 +3628,7 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
        else
                cnt = &hdev->sco_cnt;
 
-       while (*cnt && (conn = hci_low_sent(hdev, type, type, &quote))) {
+       while (*cnt && (conn = hci_low_sent(hdev, type, &quote))) {
                while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
                        BT_DBG("skb %p len %d", skb, skb->len);
                        hci_send_conn_frame(hdev, conn, skb);
@@ -3744,8 +3747,8 @@ static void hci_sched_le(struct hci_dev *hdev)
                hci_prio_recalculate(hdev, LE_LINK);
 }
 
-/* Schedule CIS */
-static void hci_sched_iso(struct hci_dev *hdev)
+/* Schedule iso */
+static void hci_sched_iso(struct hci_dev *hdev, __u8 type)
 {
        struct hci_conn *conn;
        struct sk_buff *skb;
@@ -3753,14 +3756,12 @@ static void hci_sched_iso(struct hci_dev *hdev)
 
        BT_DBG("%s", hdev->name);
 
-       if (!hci_conn_num(hdev, CIS_LINK) &&
-           !hci_conn_num(hdev, BIS_LINK))
+       if (!hci_conn_num(hdev, type))
                return;
 
        cnt = hdev->iso_pkts ? &hdev->iso_cnt :
                hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt;
-       while (*cnt && (conn = hci_low_sent(hdev, CIS_LINK, BIS_LINK,
-                                           &quote))) {
+       while (*cnt && (conn = hci_low_sent(hdev, type, &quote))) {
                while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
                        BT_DBG("skb %p len %d", skb, skb->len);
                        hci_send_conn_frame(hdev, conn, skb);
@@ -3785,7 +3786,9 @@ static void hci_tx_work(struct work_struct *work)
                /* Schedule queues and send stuff to HCI driver */
                hci_sched_sco(hdev, SCO_LINK);
                hci_sched_sco(hdev, ESCO_LINK);
-               hci_sched_iso(hdev);
+               hci_sched_iso(hdev, CIS_LINK);
+               hci_sched_iso(hdev, BIS_LINK);
+               hci_sched_iso(hdev, PA_LINK);
                hci_sched_acl(hdev);
                hci_sched_le(hdev);
        }
index b7b473473b70abdadee0b65eebd9b755f90922f9..8aa5039b975a28237408e3780fbe51c59facf560 100644 (file)
@@ -4432,6 +4432,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
 
                case CIS_LINK:
                case BIS_LINK:
+               case PA_LINK:
                        if (hdev->iso_pkts) {
                                hdev->iso_cnt += count;
                                if (hdev->iso_cnt > hdev->iso_pkts)
@@ -6381,7 +6382,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,
        conn->sync_handle = le16_to_cpu(ev->handle);
        conn->sid = HCI_SID_INVALID;
 
-       mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, BIS_LINK,
+       mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, PA_LINK,
                                      &flags);
        if (!(mask & HCI_LM_ACCEPT)) {
                hci_le_pa_term_sync(hdev, ev->handle);
@@ -6392,7 +6393,7 @@ static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data,
                goto unlock;
 
        /* Add connection to indicate PA sync event */
-       pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY,
+       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
                                     HCI_ROLE_SLAVE);
 
        if (IS_ERR(pa_sync))
@@ -6423,7 +6424,7 @@ static void hci_le_per_adv_report_evt(struct hci_dev *hdev, void *data,
 
        hci_dev_lock(hdev);
 
-       mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, BIS_LINK, &flags);
+       mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, PA_LINK, &flags);
        if (!(mask & HCI_LM_ACCEPT))
                goto unlock;
 
index e9df6502e58eab286555e57ddcb0f04afde8bada..2b4f21fbf9c1440dfc37aecbf7bb908a970d1018 100644 (file)
@@ -2929,7 +2929,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
                if (sent) {
                        struct hci_conn *conn;
 
-                       conn = hci_conn_hash_lookup_ba(hdev, BIS_LINK,
+                       conn = hci_conn_hash_lookup_ba(hdev, PA_LINK,
                                                       &sent->bdaddr);
                        if (conn) {
                                struct bt_iso_qos *qos = &conn->iso_qos;
@@ -5493,7 +5493,7 @@ static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn,
 {
        struct hci_cp_disconnect cp;
 
-       if (conn->type == BIS_LINK) {
+       if (conn->type == BIS_LINK || conn->type == PA_LINK) {
                /* This is a BIS connection, hci_conn_del will
                 * do the necessary cleanup.
                 */
@@ -5562,7 +5562,7 @@ static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn,
                return HCI_ERROR_LOCAL_HOST_TERM;
        }
 
-       if (conn->type == BIS_LINK) {
+       if (conn->type == BIS_LINK || conn->type == PA_LINK) {
                /* There is no way to cancel a BIS without terminating the BIG
                 * which is done later on connection cleanup.
                 */
@@ -5627,7 +5627,7 @@ static int hci_reject_conn_sync(struct hci_dev *hdev, struct hci_conn *conn,
        if (conn->type == CIS_LINK)
                return hci_le_reject_cis_sync(hdev, conn, reason);
 
-       if (conn->type == BIS_LINK)
+       if (conn->type == BIS_LINK || conn->type == PA_LINK)
                return -EINVAL;
 
        if (conn->type == SCO_LINK || conn->type == ESCO_LINK)
@@ -6994,7 +6994,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
                goto unlock;
 
        /* Add connection to indicate PA sync error */
-       pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY,
+       pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
                                     HCI_ROLE_SLAVE);
 
        if (IS_ERR(pa_sync))
index 2f45e46a9b6aeef62ad399d3424940c06ad6c47a..7bd3aa0a6db9ad43e05189f267b9840ec0d94f2d 100644 (file)
@@ -2237,7 +2237,8 @@ done:
 
 static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
 {
-       if (hcon->type != CIS_LINK && hcon->type != BIS_LINK) {
+       if (hcon->type != CIS_LINK && hcon->type != BIS_LINK &&
+           hcon->type != PA_LINK) {
                if (hcon->type != LE_LINK)
                        return;
 
@@ -2278,7 +2279,8 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
 
 static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 {
-       if (hcon->type != CIS_LINK && hcon->type != BIS_LINK)
+       if (hcon->type != CIS_LINK && hcon->type !=  BIS_LINK &&
+           hcon->type != PA_LINK)
                return;
 
        BT_DBG("hcon %p reason %d", hcon, reason);
index 63dba0503653bd18c73b382b7afe4d06b5f42b25..1ce682038b519325c5119af4f3e0c6b1d4ff85c8 100644 (file)
@@ -3237,6 +3237,7 @@ static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
        switch (link_type) {
        case CIS_LINK:
        case BIS_LINK:
+       case PA_LINK:
        case LE_LINK:
                switch (addr_type) {
                case ADDR_LE_DEV_PUBLIC: