mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
Bluetooth: Fix using PHYs bitfields as PHY value
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>
This commit is contained in:
parent
e07094a51a
commit
0e2a6af810
6 changed files with 52 additions and 36 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue