forked from mirrors/linux
		
	Bluetooth: ISO: Do not emit LE PA Create Sync if previous is pending
The Bluetooth Core spec does not allow a LE PA Create sync command to be sent to Controller if another one is pending (Vol 4, Part E, page 2493). In order to avoid this issue, the HCI_CONN_CREATE_PA_SYNC was added to mark that the LE PA Create Sync command has been sent for a hcon. Once the PA Sync Established event is received, the hcon flag is erased and the next pending hcon is handled. Signed-off-by: Iulia Tanasescu <iulia.tanasescu@nxp.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
		
							parent
							
								
									2dc98ac1cb
								
							
						
					
					
						commit
						4a5e0ba686
					
				
					 4 changed files with 139 additions and 40 deletions
				
			
		| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
   BlueZ - Bluetooth protocol stack for Linux
 | 
					   BlueZ - Bluetooth protocol stack for Linux
 | 
				
			||||||
   Copyright (C) 2000-2001 Qualcomm Incorporated
 | 
					   Copyright (C) 2000-2001 Qualcomm Incorporated
 | 
				
			||||||
   Copyright 2023 NXP
 | 
					   Copyright 2023-2024 NXP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 | 
					   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -697,6 +697,7 @@ enum {
 | 
				
			||||||
#define HCI_RSSI_INVALID	127
 | 
					#define HCI_RSSI_INVALID	127
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HCI_SYNC_HANDLE_INVALID	0xffff
 | 
					#define HCI_SYNC_HANDLE_INVALID	0xffff
 | 
				
			||||||
 | 
					#define HCI_SID_INVALID		0xff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HCI_ROLE_MASTER		0x00
 | 
					#define HCI_ROLE_MASTER		0x00
 | 
				
			||||||
#define HCI_ROLE_SLAVE		0x01
 | 
					#define HCI_ROLE_SLAVE		0x01
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -668,6 +668,7 @@ struct hci_conn {
 | 
				
			||||||
	__u8		adv_instance;
 | 
						__u8		adv_instance;
 | 
				
			||||||
	__u16		handle;
 | 
						__u16		handle;
 | 
				
			||||||
	__u16		sync_handle;
 | 
						__u16		sync_handle;
 | 
				
			||||||
 | 
						__u8		sid;
 | 
				
			||||||
	__u16		state;
 | 
						__u16		state;
 | 
				
			||||||
	__u16		mtu;
 | 
						__u16		mtu;
 | 
				
			||||||
	__u8		mode;
 | 
						__u8		mode;
 | 
				
			||||||
| 
						 | 
					@ -947,6 +948,7 @@ enum {
 | 
				
			||||||
	HCI_CONN_CREATE_CIS,
 | 
						HCI_CONN_CREATE_CIS,
 | 
				
			||||||
	HCI_CONN_BIG_SYNC,
 | 
						HCI_CONN_BIG_SYNC,
 | 
				
			||||||
	HCI_CONN_BIG_SYNC_FAILED,
 | 
						HCI_CONN_BIG_SYNC_FAILED,
 | 
				
			||||||
 | 
						HCI_CONN_CREATE_PA_SYNC,
 | 
				
			||||||
	HCI_CONN_PA_SYNC,
 | 
						HCI_CONN_PA_SYNC,
 | 
				
			||||||
	HCI_CONN_PA_SYNC_FAILED,
 | 
						HCI_CONN_PA_SYNC_FAILED,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1099,6 +1101,30 @@ static inline struct hci_conn *hci_conn_hash_lookup_bis(struct hci_dev *hdev,
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct hci_conn *hci_conn_hash_lookup_sid(struct hci_dev *hdev,
 | 
				
			||||||
 | 
												__u8 sid,
 | 
				
			||||||
 | 
												bdaddr_t *dst,
 | 
				
			||||||
 | 
												__u8 dst_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hci_conn_hash *h = &hdev->conn_hash;
 | 
				
			||||||
 | 
						struct hci_conn  *c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry_rcu(c, &h->list, list) {
 | 
				
			||||||
 | 
							if (c->type != ISO_LINK  || bacmp(&c->dst, dst) ||
 | 
				
			||||||
 | 
							    c->dst_type != dst_type || c->sid != sid)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
							return c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct hci_conn *
 | 
					static inline struct hci_conn *
 | 
				
			||||||
hci_conn_hash_lookup_per_adv_bis(struct hci_dev *hdev,
 | 
					hci_conn_hash_lookup_per_adv_bis(struct hci_dev *hdev,
 | 
				
			||||||
				 bdaddr_t *ba,
 | 
									 bdaddr_t *ba,
 | 
				
			||||||
| 
						 | 
					@ -1328,6 +1354,13 @@ hci_conn_hash_lookup_pa_sync_handle(struct hci_dev *hdev, __u16 sync_handle)
 | 
				
			||||||
		if (c->type != ISO_LINK)
 | 
							if (c->type != ISO_LINK)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Ignore the listen hcon, we are looking
 | 
				
			||||||
 | 
							 * for the child hcon that was created as
 | 
				
			||||||
 | 
							 * a result of the PA sync established event.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (c->state == BT_LISTEN)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (c->sync_handle == sync_handle) {
 | 
							if (c->sync_handle == sync_handle) {
 | 
				
			||||||
			rcu_read_unlock();
 | 
								rcu_read_unlock();
 | 
				
			||||||
			return c;
 | 
								return c;
 | 
				
			||||||
| 
						 | 
					@ -1445,6 +1478,7 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle);
 | 
				
			||||||
void hci_sco_setup(struct hci_conn *conn, __u8 status);
 | 
					void hci_sco_setup(struct hci_conn *conn, __u8 status);
 | 
				
			||||||
bool hci_iso_setup_path(struct hci_conn *conn);
 | 
					bool hci_iso_setup_path(struct hci_conn *conn);
 | 
				
			||||||
int hci_le_create_cis_pending(struct hci_dev *hdev);
 | 
					int hci_le_create_cis_pending(struct hci_dev *hdev);
 | 
				
			||||||
 | 
					int hci_pa_create_sync_pending(struct hci_dev *hdev);
 | 
				
			||||||
int hci_conn_check_create_cis(struct hci_conn *conn);
 | 
					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,
 | 
					struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -952,6 +952,7 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
 | 
				
			||||||
	conn->tx_power = HCI_TX_POWER_INVALID;
 | 
						conn->tx_power = HCI_TX_POWER_INVALID;
 | 
				
			||||||
	conn->max_tx_power = HCI_TX_POWER_INVALID;
 | 
						conn->max_tx_power = HCI_TX_POWER_INVALID;
 | 
				
			||||||
	conn->sync_handle = HCI_SYNC_HANDLE_INVALID;
 | 
						conn->sync_handle = HCI_SYNC_HANDLE_INVALID;
 | 
				
			||||||
 | 
						conn->sid = HCI_SID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
 | 
						set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
 | 
				
			||||||
	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 | 
						conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 | 
				
			||||||
| 
						 | 
					@ -2062,73 +2063,119 @@ static int create_big_sync(struct hci_dev *hdev, void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
 | 
					static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hci_cp_le_pa_create_sync *cp = data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bt_dev_dbg(hdev, "");
 | 
						bt_dev_dbg(hdev, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		bt_dev_err(hdev, "Unable to create PA: %d", err);
 | 
							bt_dev_err(hdev, "Unable to create PA: %d", err);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kfree(cp);
 | 
					static bool hci_conn_check_create_pa_sync(struct hci_conn *conn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (conn->type != ISO_LINK || conn->sid == HCI_SID_INVALID)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int create_pa_sync(struct hci_dev *hdev, void *data)
 | 
					static int create_pa_sync(struct hci_dev *hdev, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hci_cp_le_pa_create_sync *cp = data;
 | 
						struct hci_cp_le_pa_create_sync *cp = NULL;
 | 
				
			||||||
	int err;
 | 
						struct hci_conn *conn;
 | 
				
			||||||
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC,
 | 
						hci_dev_lock(hdev);
 | 
				
			||||||
				    sizeof(*cp), cp, HCI_CMD_TIMEOUT);
 | 
					
 | 
				
			||||||
	if (err) {
 | 
						rcu_read_lock();
 | 
				
			||||||
		hci_dev_clear_flag(hdev, HCI_PA_SYNC);
 | 
					
 | 
				
			||||||
		return err;
 | 
						/* The spec allows only one pending LE Periodic Advertising Create
 | 
				
			||||||
 | 
						 * Sync command at a time. If the command is pending now, don't do
 | 
				
			||||||
 | 
						 * anything. We check for pending connections after each PA Sync
 | 
				
			||||||
 | 
						 * Established event.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E
 | 
				
			||||||
 | 
						 * page 2493:
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If the Host issues this command when another HCI_LE_Periodic_
 | 
				
			||||||
 | 
						 * Advertising_Create_Sync command is pending, 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_PA_SYNC, &conn->flags))
 | 
				
			||||||
 | 
								goto unlock;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return hci_update_passive_scan_sync(hdev);
 | 
						list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
 | 
				
			||||||
 | 
							if (hci_conn_check_create_pa_sync(conn)) {
 | 
				
			||||||
 | 
								struct bt_iso_qos *qos = &conn->iso_qos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								cp = kzalloc(sizeof(*cp), GFP_KERNEL);
 | 
				
			||||||
 | 
								if (!cp) {
 | 
				
			||||||
 | 
									err = -ENOMEM;
 | 
				
			||||||
 | 
									goto unlock;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								cp->options = qos->bcast.options;
 | 
				
			||||||
 | 
								cp->sid = conn->sid;
 | 
				
			||||||
 | 
								cp->addr_type = conn->dst_type;
 | 
				
			||||||
 | 
								bacpy(&cp->addr, &conn->dst);
 | 
				
			||||||
 | 
								cp->skip = cpu_to_le16(qos->bcast.skip);
 | 
				
			||||||
 | 
								cp->sync_timeout = cpu_to_le16(qos->bcast.sync_timeout);
 | 
				
			||||||
 | 
								cp->sync_cte_type = qos->bcast.sync_cte_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hci_dev_unlock(hdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cp) {
 | 
				
			||||||
 | 
							hci_dev_set_flag(hdev, HCI_PA_SYNC);
 | 
				
			||||||
 | 
							set_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC,
 | 
				
			||||||
 | 
										    sizeof(*cp), cp, HCI_CMD_TIMEOUT);
 | 
				
			||||||
 | 
							if (!err)
 | 
				
			||||||
 | 
								err = hci_update_passive_scan_sync(hdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							kfree(cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (err) {
 | 
				
			||||||
 | 
								hci_dev_clear_flag(hdev, HCI_PA_SYNC);
 | 
				
			||||||
 | 
								clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int hci_pa_create_sync_pending(struct hci_dev *hdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Queue start pa_create_sync and scan */
 | 
				
			||||||
 | 
						return hci_cmd_sync_queue(hdev, create_pa_sync,
 | 
				
			||||||
 | 
									  NULL, create_pa_complete);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
 | 
					struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
 | 
				
			||||||
				    __u8 dst_type, __u8 sid,
 | 
									    __u8 dst_type, __u8 sid,
 | 
				
			||||||
				    struct bt_iso_qos *qos)
 | 
									    struct bt_iso_qos *qos)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hci_cp_le_pa_create_sync *cp;
 | 
					 | 
				
			||||||
	struct hci_conn *conn;
 | 
						struct hci_conn *conn;
 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC))
 | 
					 | 
				
			||||||
		return ERR_PTR(-EBUSY);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
 | 
						conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
 | 
				
			||||||
	if (IS_ERR(conn))
 | 
						if (IS_ERR(conn))
 | 
				
			||||||
		return conn;
 | 
							return conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	conn->iso_qos = *qos;
 | 
						conn->iso_qos = *qos;
 | 
				
			||||||
 | 
						conn->dst_type = dst_type;
 | 
				
			||||||
 | 
						conn->sid = sid;
 | 
				
			||||||
	conn->state = BT_LISTEN;
 | 
						conn->state = BT_LISTEN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hci_conn_hold(conn);
 | 
						hci_conn_hold(conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
 | 
						hci_pa_create_sync_pending(hdev);
 | 
				
			||||||
	if (!cp) {
 | 
					 | 
				
			||||||
		hci_dev_clear_flag(hdev, HCI_PA_SYNC);
 | 
					 | 
				
			||||||
		hci_conn_drop(conn);
 | 
					 | 
				
			||||||
		return ERR_PTR(-ENOMEM);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cp->options = qos->bcast.options;
 | 
					 | 
				
			||||||
	cp->sid = sid;
 | 
					 | 
				
			||||||
	cp->addr_type = dst_type;
 | 
					 | 
				
			||||||
	bacpy(&cp->addr, dst);
 | 
					 | 
				
			||||||
	cp->skip = cpu_to_le16(qos->bcast.skip);
 | 
					 | 
				
			||||||
	cp->sync_timeout = cpu_to_le16(qos->bcast.sync_timeout);
 | 
					 | 
				
			||||||
	cp->sync_cte_type = qos->bcast.sync_cte_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Queue start pa_create_sync and scan */
 | 
					 | 
				
			||||||
	err = hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete);
 | 
					 | 
				
			||||||
	if (err < 0) {
 | 
					 | 
				
			||||||
		hci_conn_drop(conn);
 | 
					 | 
				
			||||||
		kfree(cp);
 | 
					 | 
				
			||||||
		return ERR_PTR(err);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return conn;
 | 
						return conn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6352,7 +6352,7 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
 | 
				
			||||||
	struct hci_ev_le_pa_sync_established *ev = data;
 | 
						struct hci_ev_le_pa_sync_established *ev = data;
 | 
				
			||||||
	int mask = hdev->link_mode;
 | 
						int mask = hdev->link_mode;
 | 
				
			||||||
	__u8 flags = 0;
 | 
						__u8 flags = 0;
 | 
				
			||||||
	struct hci_conn *pa_sync;
 | 
						struct hci_conn *pa_sync, *conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 | 
						bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6360,6 +6360,20 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hci_dev_clear_flag(hdev, HCI_PA_SYNC);
 | 
						hci_dev_clear_flag(hdev, HCI_PA_SYNC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn = hci_conn_hash_lookup_sid(hdev, ev->sid, &ev->bdaddr,
 | 
				
			||||||
 | 
										ev->bdaddr_type);
 | 
				
			||||||
 | 
						if (!conn) {
 | 
				
			||||||
 | 
							bt_dev_err(hdev,
 | 
				
			||||||
 | 
								   "Unable to find connection for dst %pMR sid 0x%2.2x",
 | 
				
			||||||
 | 
								   &ev->bdaddr, ev->sid);
 | 
				
			||||||
 | 
							goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						conn->sync_handle = le16_to_cpu(ev->handle);
 | 
				
			||||||
 | 
						conn->sid = HCI_SID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ISO_LINK, &flags);
 | 
						mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ISO_LINK, &flags);
 | 
				
			||||||
	if (!(mask & HCI_LM_ACCEPT)) {
 | 
						if (!(mask & HCI_LM_ACCEPT)) {
 | 
				
			||||||
		hci_le_pa_term_sync(hdev, ev->handle);
 | 
							hci_le_pa_term_sync(hdev, ev->handle);
 | 
				
			||||||
| 
						 | 
					@ -6386,6 +6400,9 @@ static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
 | 
						/* Handle any other pending PA sync command */
 | 
				
			||||||
 | 
						hci_pa_create_sync_pending(hdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hci_dev_unlock(hdev);
 | 
						hci_dev_unlock(hdev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue