]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Bluetooth: Fix using PHYs bitfields as PHY value
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 22 Dec 2025 19:36:45 +0000 (14:36 -0500)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 29 Jan 2026 18:27:47 +0000 (13:27 -0500)
This renames the PHY fields in bt_iso_io_qos to PHYs (plural) since it
represents a bitfield where multiple PHYs can be set and make the same
change also to HCI_OP_LE_SET_CIG_PARAMS since both c_phy and p_phy
fields are bitfields.

This also fixes the assumption that hci_evt_le_cis_established PHYs
fields are compatible with bt_iso_io_qos, they are not, the fields in
hci_evt_le_cis_established represent just a single PHY value so they
need to be converted to bitfield when set in bt_iso_io_qos.

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

index 89a60919050b00e585fd1c31f7ecc3c1fcf93573..69eed69f7f265667409cc8ba19d944c093ada0cc 100644 (file)
@@ -182,7 +182,7 @@ struct bt_iso_io_qos {
        __u32 interval;
        __u16 latency;
        __u16 sdu;
-       __u8  phy;
+       __u8  phys;
        __u8  rtn;
 };
 
@@ -221,9 +221,9 @@ struct bt_iso_qos {
        };
 };
 
-#define BT_ISO_PHY_1M          0x01
-#define BT_ISO_PHY_2M          0x02
-#define BT_ISO_PHY_CODED       0x04
+#define BT_ISO_PHY_1M          BIT(0)
+#define BT_ISO_PHY_2M          BIT(1)
+#define BT_ISO_PHY_CODED       BIT(2)
 #define BT_ISO_PHY_ANY         (BT_ISO_PHY_1M | BT_ISO_PHY_2M | \
                                 BT_ISO_PHY_CODED)
 
index db76c2d1eeaa1120f4717dbe5c1e399efae83693..89ad9470fa71b1444824267c62922c214c3009fe 100644 (file)
@@ -1891,7 +1891,7 @@ struct hci_cp_le_set_phy {
        __u8    all_phys;
        __u8    tx_phys;
        __u8    rx_phys;
-       __le16   phy_opts;
+       __le16  phy_opts;
 } __packed;
 
 #define HCI_OP_LE_SET_EXT_SCAN_PARAMS   0x2041
@@ -2147,8 +2147,8 @@ struct hci_cis_params {
        __u8    cis_id;
        __le16  c_sdu;
        __le16  p_sdu;
-       __u8    c_phy;
-       __u8    p_phy;
+       __u8    c_phys;
+       __u8    p_phys;
        __u8    c_rtn;
        __u8    p_rtn;
 } __packed;
index 1a4b6badf2b35650bbeec799fc60773fd6f0334e..0795818963a5249184bd5e9c4299d667735a7061 100644 (file)
@@ -1825,7 +1825,7 @@ static int hci_le_create_big(struct hci_conn *conn, struct bt_iso_qos *qos)
        cp.bis.sdu = cpu_to_le16(qos->bcast.out.sdu);
        cp.bis.latency =  cpu_to_le16(qos->bcast.out.latency);
        cp.bis.rtn  = qos->bcast.out.rtn;
-       cp.bis.phy  = qos->bcast.out.phy;
+       cp.bis.phy  = qos->bcast.out.phys;
        cp.bis.packing = qos->bcast.packing;
        cp.bis.framing = qos->bcast.framing;
        cp.bis.encryption = qos->bcast.encryption;
@@ -1875,10 +1875,10 @@ static int set_cig_params_sync(struct hci_dev *hdev, void *data)
                cis->cis_id = cis_id;
                cis->c_sdu  = cpu_to_le16(conn->iso_qos.ucast.out.sdu);
                cis->p_sdu  = cpu_to_le16(conn->iso_qos.ucast.in.sdu);
-               cis->c_phy  = qos->ucast.out.phy ? qos->ucast.out.phy :
-                             qos->ucast.in.phy;
-               cis->p_phy  = qos->ucast.in.phy ? qos->ucast.in.phy :
-                             qos->ucast.out.phy;
+               cis->c_phys = qos->ucast.out.phys ? qos->ucast.out.phys :
+                             qos->ucast.in.phys;
+               cis->p_phys = qos->ucast.in.phys ? qos->ucast.in.phys :
+                             qos->ucast.out.phys;
                cis->c_rtn  = qos->ucast.out.rtn;
                cis->p_rtn  = qos->ucast.in.rtn;
        }
@@ -1980,8 +1980,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
                return cis;
 
        /* Update LINK PHYs according to QoS preference */
-       cis->le_tx_phy = qos->ucast.out.phy;
-       cis->le_rx_phy = qos->ucast.in.phy;
+       cis->le_tx_phy = qos->ucast.out.phys;
+       cis->le_rx_phy = qos->ucast.in.phys;
 
        /* If output interval is not set use the input interval as it cannot be
         * 0x000000.
@@ -2096,15 +2096,15 @@ int hci_le_create_cis_pending(struct hci_dev *hdev)
 }
 
 static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
-                             struct bt_iso_io_qos *qos, __u8 phy)
+                             struct bt_iso_io_qos *qos, __u8 phys)
 {
        /* Only set MTU if PHY is enabled */
-       if (!qos->sdu && qos->phy)
+       if (!qos->sdu && qos->phys)
                qos->sdu = conn->mtu;
 
        /* Use the same PHY as ACL if set to any */
-       if (qos->phy == BT_ISO_PHY_ANY)
-               qos->phy = phy;
+       if (qos->phys == BT_ISO_PHY_ANY)
+               qos->phys = phys;
 
        /* Use LE ACL connection interval if not set */
        if (!qos->interval)
@@ -2124,7 +2124,7 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
        u32 flags = 0;
        int err;
 
-       if (qos->bcast.out.phy == 0x02)
+       if (qos->bcast.out.phys == BIT(1))
                flags |= MGMT_ADV_FLAG_SEC_2M;
 
        /* Align intervals */
@@ -2233,8 +2233,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
                return conn;
 
        /* Update LINK PHYs according to QoS preference */
-       conn->le_tx_phy = qos->bcast.out.phy;
-       conn->le_tx_phy = qos->bcast.out.phy;
+       conn->le_tx_def_phys = qos->bcast.out.phys;
 
        /* Add Basic Announcement into Peridic Adv Data if BASE is set */
        if (base_len && base) {
@@ -2243,7 +2242,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
        }
 
        hci_iso_qos_setup(hdev, conn, &qos->bcast.out,
-                         conn->le_tx_phy ? conn->le_tx_phy :
+                         conn->le_tx_def_phys ? conn->le_tx_def_phys :
                          hdev->le_tx_def_phys);
 
        conn->iso_qos = *qos;
@@ -2363,9 +2362,11 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
                return le;
 
        hci_iso_qos_setup(hdev, le, &qos->ucast.out,
-                         le->le_tx_phy ? le->le_tx_phy : hdev->le_tx_def_phys);
+                         le->le_tx_def_phys ? le->le_tx_def_phys :
+                         hdev->le_tx_def_phys);
        hci_iso_qos_setup(hdev, le, &qos->ucast.in,
-                         le->le_rx_phy ? le->le_rx_phy : hdev->le_rx_def_phys);
+                         le->le_rx_def_phys ? le->le_rx_def_phys :
+                         hdev->le_rx_def_phys);
 
        cis = hci_bind_cis(hdev, dst, dst_type, qos, timeout);
        if (IS_ERR(cis)) {
index 467710a42d4537689bff13ed5e8a8a0b58c5277d..286529d2e554a45a5cebc2b30cbfb1cb9ae10895 100644 (file)
@@ -6867,6 +6867,21 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+/* Convert LE PHY to QoS PHYs */
+static u8 le_phy_qos(u8 phy)
+{
+       switch (phy) {
+       case 0x01:
+               return HCI_LE_SET_PHY_1M;
+       case 0x02:
+               return HCI_LE_SET_PHY_2M;
+       case 0x03:
+               return HCI_LE_SET_PHY_CODED;
+       }
+
+       return 0;
+}
+
 static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
                                       struct sk_buff *skb)
 {
@@ -6928,8 +6943,8 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
                                          1000);
                qos->ucast.in.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0;
                qos->ucast.out.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0;
-               qos->ucast.in.phy = ev->c_phy;
-               qos->ucast.out.phy = ev->p_phy;
+               qos->ucast.in.phys = le_phy_qos(ev->c_phy);
+               qos->ucast.out.phys = le_phy_qos(ev->p_phy);
                break;
        case HCI_ROLE_MASTER:
                qos->ucast.in.interval = p_sdu_interval;
@@ -6943,8 +6958,8 @@ static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data,
                                          1000);
                qos->ucast.out.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0;
                qos->ucast.in.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0;
-               qos->ucast.out.phy = ev->c_phy;
-               qos->ucast.in.phy = ev->p_phy;
+               qos->ucast.out.phys = le_phy_qos(ev->c_phy);
+               qos->ucast.in.phys = le_phy_qos(ev->p_phy);
                break;
        }
 
index 0e6660ddc00a7c200ee44c5343e24a7dfb9b3a3f..f04a90bce4a94e1e9a78ab2a5665a9d19f2202c7 100644 (file)
@@ -2948,8 +2948,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
                        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) {
+                               if (qos->bcast.in.phys & BT_ISO_PHY_1M ||
+                                   qos->bcast.in.phys & BT_ISO_PHY_2M) {
                                        cp->scanning_phys |= LE_SCAN_PHY_1M;
                                        hci_le_scan_phy_params(phy, type,
                                                               interval,
@@ -2958,7 +2958,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
                                        phy++;
                                }
 
-                               if (qos->bcast.in.phy & BT_ISO_PHY_CODED) {
+                               if (qos->bcast.in.phys & BT_ISO_PHY_CODED) {
                                        cp->scanning_phys |= LE_SCAN_PHY_CODED;
                                        hci_le_scan_phy_params(phy, type,
                                                               interval * 3,
index e36d24a9098b9d57a3cf786cb5faef3ebadeeee4..1459ab161fd2a9d1d59a7d94e080183bd3836c1e 100644 (file)
@@ -361,7 +361,7 @@ static int iso_connect_bis(struct sock *sk)
        }
 
        /* Fail if out PHYs are marked as disabled */
-       if (!iso_pi(sk)->qos.bcast.out.phy) {
+       if (!iso_pi(sk)->qos.bcast.out.phys) {
                err = -EINVAL;
                goto unlock;
        }
@@ -458,7 +458,7 @@ static int iso_connect_cis(struct sock *sk)
        }
 
        /* Fail if either PHYs are marked as disabled */
-       if (!iso_pi(sk)->qos.ucast.in.phy && !iso_pi(sk)->qos.ucast.out.phy) {
+       if (!iso_pi(sk)->qos.ucast.in.phys && !iso_pi(sk)->qos.ucast.out.phys) {
                err = -EINVAL;
                goto unlock;
        }
@@ -894,7 +894,7 @@ static struct proto iso_proto = {
        .interval       = 10000u, \
        .latency        = 10u, \
        .sdu            = 40u, \
-       .phy            = BT_ISO_PHY_2M, \
+       .phys           = BT_ISO_PHY_2M, \
        .rtn            = 2u, \
 }
 
@@ -1661,7 +1661,7 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
 static bool check_io_qos(struct bt_iso_io_qos *qos)
 {
        /* If no PHY is enable SDU must be 0 */
-       if (!qos->phy && qos->sdu)
+       if (!qos->phys && qos->sdu)
                return false;
 
        if (qos->interval && (qos->interval < 0xff || qos->interval > 0xfffff))
@@ -1670,7 +1670,7 @@ static bool check_io_qos(struct bt_iso_io_qos *qos)
        if (qos->latency && (qos->latency < 0x05 || qos->latency > 0xfa0))
                return false;
 
-       if (qos->phy > BT_ISO_PHY_ANY)
+       if (qos->phys > BT_ISO_PHY_ANY)
                return false;
 
        return true;