Commit 024421cf authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz
Browse files

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: 42ecf194 ("Bluetooth: ISO: Do not emit LE BIG Create Sync if previous is pending")
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 6d0417e4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+3 −4
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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);
+5 −84
Original line number Diff line number Diff line
@@ -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)
+3 −6
Original line number Diff line number Diff line
@@ -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),
Loading