mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
Bluetooth: hci_conn: Fix not setting timeout for BIG Create Sync
BIG Create Sync requires the command to just generates a status so this
makes use of __hci_cmd_sync_status_sk to wait for
HCI_EVT_LE_BIG_SYNC_ESTABLISHED, also because of this chance it is not
longer necessary to use a custom method to serialize the process of
creating the BIG sync since the cmd_work_sync itself ensures only one
command would be pending which now awaits for
HCI_EVT_LE_BIG_SYNC_ESTABLISHED before proceeding to next connection.
Fixes: 42ecf19471
("Bluetooth: ISO: Do not emit LE BIG Create Sync if previous is pending")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
6d0417e4e1
commit
024421cf39
7 changed files with 88 additions and 109 deletions
|
@ -2832,7 +2832,7 @@ struct hci_evt_le_create_big_complete {
|
|||
__le16 bis_handle[];
|
||||
} __packed;
|
||||
|
||||
#define HCI_EVT_LE_BIG_SYNC_ESTABILISHED 0x1d
|
||||
#define HCI_EVT_LE_BIG_SYNC_ESTABLISHED 0x1d
|
||||
struct hci_evt_le_big_sync_estabilished {
|
||||
__u8 status;
|
||||
__u8 handle;
|
||||
|
|
|
@ -1524,7 +1524,6 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
|
|||
void hci_sco_setup(struct hci_conn *conn, __u8 status);
|
||||
bool hci_iso_setup_path(struct hci_conn *conn);
|
||||
int hci_le_create_cis_pending(struct hci_dev *hdev);
|
||||
int hci_le_big_create_sync_pending(struct hci_dev *hdev);
|
||||
int hci_conn_check_create_cis(struct hci_conn *conn);
|
||||
|
||||
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
|
||||
|
@ -1565,9 +1564,9 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
__u8 data_len, __u8 *data);
|
||||
struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
|
||||
__u8 dst_type, __u8 sid, struct bt_iso_qos *qos);
|
||||
int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
|
||||
struct bt_iso_qos *qos,
|
||||
__u16 sync_handle, __u8 num_bis, __u8 bis[]);
|
||||
int hci_conn_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
|
||||
struct bt_iso_qos *qos, __u16 sync_handle,
|
||||
__u8 num_bis, __u8 bis[]);
|
||||
int hci_conn_check_link_mode(struct hci_conn *conn);
|
||||
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
|
||||
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type,
|
||||
|
|
|
@ -187,3 +187,4 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn,
|
|||
struct hci_conn_params *params);
|
||||
|
||||
int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn);
|
||||
int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn);
|
||||
|
|
|
@ -2087,89 +2087,9 @@ struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
|
|||
return conn;
|
||||
}
|
||||
|
||||
static bool hci_conn_check_create_big_sync(struct hci_conn *conn)
|
||||
{
|
||||
if (!conn->num_bis)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void big_create_sync_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
bt_dev_dbg(hdev, "");
|
||||
|
||||
if (err)
|
||||
bt_dev_err(hdev, "Unable to create BIG sync: %d", err);
|
||||
}
|
||||
|
||||
static int big_create_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
DEFINE_FLEX(struct hci_cp_le_big_create_sync, pdu, bis, num_bis, 0x11);
|
||||
struct hci_conn *conn;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
pdu->num_bis = 0;
|
||||
|
||||
/* The spec allows only one pending LE BIG Create Sync command at
|
||||
* a time. If the command is pending now, don't do anything. We
|
||||
* check for pending connections after each BIG Sync Established
|
||||
* event.
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
|
||||
* page 2586:
|
||||
*
|
||||
* If the Host sends this command when the Controller is in the
|
||||
* process of synchronizing to any BIG, i.e. the HCI_LE_BIG_Sync_
|
||||
* Established event has not been generated, the Controller shall
|
||||
* return the error code Command Disallowed (0x0C).
|
||||
*/
|
||||
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
|
||||
if (test_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags))
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
|
||||
if (hci_conn_check_create_big_sync(conn)) {
|
||||
struct bt_iso_qos *qos = &conn->iso_qos;
|
||||
|
||||
set_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
|
||||
pdu->handle = qos->bcast.big;
|
||||
pdu->sync_handle = cpu_to_le16(conn->sync_handle);
|
||||
pdu->encryption = qos->bcast.encryption;
|
||||
memcpy(pdu->bcode, qos->bcast.bcode,
|
||||
sizeof(pdu->bcode));
|
||||
pdu->mse = qos->bcast.mse;
|
||||
pdu->timeout = cpu_to_le16(qos->bcast.timeout);
|
||||
pdu->num_bis = conn->num_bis;
|
||||
memcpy(pdu->bis, conn->bis, conn->num_bis);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!pdu->num_bis)
|
||||
return 0;
|
||||
|
||||
return hci_send_cmd(hdev, HCI_OP_LE_BIG_CREATE_SYNC,
|
||||
struct_size(pdu, bis, pdu->num_bis), pdu);
|
||||
}
|
||||
|
||||
int hci_le_big_create_sync_pending(struct hci_dev *hdev)
|
||||
{
|
||||
/* Queue big_create_sync */
|
||||
return hci_cmd_sync_queue_once(hdev, big_create_sync,
|
||||
NULL, big_create_sync_complete);
|
||||
}
|
||||
|
||||
int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
|
||||
struct bt_iso_qos *qos,
|
||||
__u16 sync_handle, __u8 num_bis, __u8 bis[])
|
||||
int hci_conn_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
|
||||
struct bt_iso_qos *qos, __u16 sync_handle,
|
||||
__u8 num_bis, __u8 bis[])
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -2186,9 +2106,10 @@ int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
|
|||
|
||||
hcon->num_bis = num_bis;
|
||||
memcpy(hcon->bis, bis, num_bis);
|
||||
hcon->conn_timeout = msecs_to_jiffies(qos->bcast.timeout * 10);
|
||||
}
|
||||
|
||||
return hci_le_big_create_sync_pending(hdev);
|
||||
return hci_connect_big_sync(hdev, hcon);
|
||||
}
|
||||
|
||||
static void create_big_complete(struct hci_dev *hdev, void *data, int err)
|
||||
|
|
|
@ -6928,7 +6928,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
|
||||
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
|
||||
|
||||
if (!hci_le_ev_skb_pull(hdev, skb, HCI_EVT_LE_BIG_SYNC_ESTABILISHED,
|
||||
if (!hci_le_ev_skb_pull(hdev, skb, HCI_EVT_LE_BIG_SYNC_ESTABLISHED,
|
||||
flex_array_size(ev, bis, ev->num_bis)))
|
||||
return;
|
||||
|
||||
|
@ -6999,9 +6999,6 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||
}
|
||||
|
||||
unlock:
|
||||
/* Handle any other pending BIG sync command */
|
||||
hci_le_big_create_sync_pending(hdev);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
|
@ -7123,8 +7120,8 @@ static const struct hci_le_ev {
|
|||
hci_le_create_big_complete_evt,
|
||||
sizeof(struct hci_evt_le_create_big_complete),
|
||||
HCI_MAX_EVENT_SIZE),
|
||||
/* [0x1d = HCI_EV_LE_BIG_SYNC_ESTABILISHED] */
|
||||
HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_ESTABILISHED,
|
||||
/* [0x1d = HCI_EV_LE_BIG_SYNC_ESTABLISHED] */
|
||||
HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_ESTABLISHED,
|
||||
hci_le_big_sync_established_evt,
|
||||
sizeof(struct hci_evt_le_big_sync_estabilished),
|
||||
HCI_MAX_EVENT_SIZE),
|
||||
|
|
|
@ -6972,3 +6972,66 @@ int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
|||
return hci_cmd_sync_queue_once(hdev, hci_le_pa_create_sync, conn,
|
||||
create_pa_complete);
|
||||
}
|
||||
|
||||
static void create_big_complete(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
struct hci_conn *conn = data;
|
||||
|
||||
bt_dev_dbg(hdev, "err %d", err);
|
||||
|
||||
if (err == -ECANCELED)
|
||||
return;
|
||||
|
||||
if (hci_conn_valid(hdev, conn))
|
||||
clear_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
}
|
||||
|
||||
static int hci_le_big_create_sync(struct hci_dev *hdev, void *data)
|
||||
{
|
||||
DEFINE_FLEX(struct hci_cp_le_big_create_sync, cp, bis, num_bis, 0x11);
|
||||
struct hci_conn *conn = data;
|
||||
struct bt_iso_qos *qos = &conn->iso_qos;
|
||||
int err;
|
||||
|
||||
if (!hci_conn_valid(hdev, conn))
|
||||
return -ECANCELED;
|
||||
|
||||
set_bit(HCI_CONN_CREATE_BIG_SYNC, &conn->flags);
|
||||
|
||||
memset(cp, 0, sizeof(*cp));
|
||||
cp->handle = qos->bcast.big;
|
||||
cp->sync_handle = cpu_to_le16(conn->sync_handle);
|
||||
cp->encryption = qos->bcast.encryption;
|
||||
memcpy(cp->bcode, qos->bcast.bcode, sizeof(cp->bcode));
|
||||
cp->mse = qos->bcast.mse;
|
||||
cp->timeout = cpu_to_le16(qos->bcast.timeout);
|
||||
cp->num_bis = conn->num_bis;
|
||||
memcpy(cp->bis, conn->bis, conn->num_bis);
|
||||
|
||||
/* The spec allows only one pending LE BIG Create Sync command at
|
||||
* a time, so we forcefully wait for BIG Sync Established event since
|
||||
* cmd_work can only schedule one command at a time.
|
||||
*
|
||||
* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
|
||||
* page 2586:
|
||||
*
|
||||
* If the Host sends this command when the Controller is in the
|
||||
* process of synchronizing to any BIG, i.e. the HCI_LE_BIG_Sync_
|
||||
* Established event has not been generated, the Controller shall
|
||||
* return the error code Command Disallowed (0x0C).
|
||||
*/
|
||||
err = __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_BIG_CREATE_SYNC,
|
||||
struct_size(cp, bis, cp->num_bis), cp,
|
||||
HCI_EVT_LE_BIG_SYNC_ESTABLISHED,
|
||||
conn->conn_timeout, NULL);
|
||||
if (err == -ETIMEDOUT)
|
||||
hci_le_big_terminate_sync(hdev, cp->handle);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn)
|
||||
{
|
||||
return hci_cmd_sync_queue_once(hdev, hci_le_big_create_sync, conn,
|
||||
create_big_complete);
|
||||
}
|
||||
|
|
|
@ -1462,14 +1462,13 @@ static void iso_conn_big_sync(struct sock *sk)
|
|||
lock_sock(sk);
|
||||
|
||||
if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
|
||||
err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
|
||||
&iso_pi(sk)->qos,
|
||||
iso_pi(sk)->sync_handle,
|
||||
iso_pi(sk)->bc_num_bis,
|
||||
iso_pi(sk)->bc_bis);
|
||||
err = hci_conn_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
|
||||
&iso_pi(sk)->qos,
|
||||
iso_pi(sk)->sync_handle,
|
||||
iso_pi(sk)->bc_num_bis,
|
||||
iso_pi(sk)->bc_bis);
|
||||
if (err)
|
||||
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
||||
err);
|
||||
bt_dev_err(hdev, "hci_big_create_sync: %d", err);
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
|
@ -1922,7 +1921,7 @@ static void iso_conn_ready(struct iso_conn *conn)
|
|||
hcon);
|
||||
} else if (test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
|
||||
ev = hci_recv_event_data(hcon->hdev,
|
||||
HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
|
||||
HCI_EVT_LE_BIG_SYNC_ESTABLISHED);
|
||||
|
||||
/* Get reference to PA sync parent socket, if it exists */
|
||||
parent = iso_get_sock(&hcon->src, &hcon->dst,
|
||||
|
@ -2113,12 +2112,11 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|||
|
||||
if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
|
||||
!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
|
||||
err = hci_le_big_create_sync(hdev,
|
||||
hcon,
|
||||
&iso_pi(sk)->qos,
|
||||
iso_pi(sk)->sync_handle,
|
||||
iso_pi(sk)->bc_num_bis,
|
||||
iso_pi(sk)->bc_bis);
|
||||
err = hci_conn_big_create_sync(hdev, hcon,
|
||||
&iso_pi(sk)->qos,
|
||||
iso_pi(sk)->sync_handle,
|
||||
iso_pi(sk)->bc_num_bis,
|
||||
iso_pi(sk)->bc_bis);
|
||||
if (err) {
|
||||
bt_dev_err(hdev, "hci_le_big_create_sync: %d",
|
||||
err);
|
||||
|
|
Loading…
Add table
Reference in a new issue