Skip to content

Commit 881559a

Browse files
committed
Bluetooth: hci_sync: Attempt to dequeue connection attempt
If connection is still queued/pending in the cmd_sync queue it means no command has been generated and it should be safe to just dequeue the callback when it is being aborted. Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 505ea2b commit 881559a

File tree

4 files changed

+102
-71
lines changed

4 files changed

+102
-71
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,24 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev)
10831083
return c->acl_num + c->amp_num + c->sco_num + c->le_num + c->iso_num;
10841084
}
10851085

1086+
static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn)
1087+
{
1088+
struct hci_conn_hash *h = &hdev->conn_hash;
1089+
struct hci_conn *c;
1090+
1091+
rcu_read_lock();
1092+
1093+
list_for_each_entry_rcu(c, &h->list, list) {
1094+
if (c == conn) {
1095+
rcu_read_unlock();
1096+
return true;
1097+
}
1098+
}
1099+
rcu_read_unlock();
1100+
1101+
return false;
1102+
}
1103+
10861104
static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
10871105
{
10881106
struct hci_conn_hash *h = &hdev->conn_hash;
@@ -1493,6 +1511,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
14931511
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
14941512
u8 dst_type, bool dst_resolved, u8 sec_level,
14951513
u16 conn_timeout, u8 role);
1514+
void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status);
14961515
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
14971516
u8 sec_level, u8 auth_type,
14981517
enum conn_reasons conn_reason, u16 timeout);

include/net/bluetooth/hci_sync.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
4848
void *data, hci_cmd_sync_work_destroy_t destroy);
4949
int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
5050
void *data, hci_cmd_sync_work_destroy_t destroy);
51+
int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
52+
void *data, hci_cmd_sync_work_destroy_t destroy);
5153
struct hci_cmd_sync_work_entry *
5254
hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
5355
void *data, hci_cmd_sync_work_destroy_t destroy);
54-
int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
55-
void *data, hci_cmd_sync_work_destroy_t destroy);
5656
void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
5757
struct hci_cmd_sync_work_entry *entry);
5858
bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
@@ -139,8 +139,6 @@ struct hci_conn;
139139

140140
int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
141141

142-
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);
143-
144142
int hci_le_create_cis_sync(struct hci_dev *hdev);
145143

146144
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
@@ -152,3 +150,7 @@ int hci_le_big_terminate_sync(struct hci_dev *hdev, u8 handle);
152150
int hci_le_pa_terminate_sync(struct hci_dev *hdev, u16 handle);
153151

154152
int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn);
153+
154+
int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn);
155+
156+
int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn);

net/bluetooth/hci_conn.c

Lines changed: 12 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
6868
};
6969

7070
/* This function requires the caller holds hdev->lock */
71-
static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
71+
void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
7272
{
7373
struct hci_conn_params *params;
7474
struct hci_dev *hdev = conn->hdev;
@@ -1124,6 +1124,9 @@ void hci_conn_del(struct hci_conn *conn)
11241124
* rest of hci_conn_del.
11251125
*/
11261126
hci_conn_cleanup(conn);
1127+
1128+
/* Dequeue callbacks using connection pointer as data */
1129+
hci_cmd_sync_dequeue(hdev, NULL, conn, NULL);
11271130
}
11281131

11291132
struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
@@ -1258,53 +1261,6 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
12581261
return 0;
12591262
}
12601263

1261-
static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
1262-
{
1263-
struct hci_conn *conn;
1264-
u16 handle = PTR_UINT(data);
1265-
1266-
conn = hci_conn_hash_lookup_handle(hdev, handle);
1267-
if (!conn)
1268-
return;
1269-
1270-
bt_dev_dbg(hdev, "err %d", err);
1271-
1272-
hci_dev_lock(hdev);
1273-
1274-
if (!err) {
1275-
hci_connect_le_scan_cleanup(conn, 0x00);
1276-
goto done;
1277-
}
1278-
1279-
/* Check if connection is still pending */
1280-
if (conn != hci_lookup_le_connect(hdev))
1281-
goto done;
1282-
1283-
/* Flush to make sure we send create conn cancel command if needed */
1284-
flush_delayed_work(&conn->le_conn_timeout);
1285-
hci_conn_failed(conn, bt_status(err));
1286-
1287-
done:
1288-
hci_dev_unlock(hdev);
1289-
}
1290-
1291-
static int hci_connect_le_sync(struct hci_dev *hdev, void *data)
1292-
{
1293-
struct hci_conn *conn;
1294-
u16 handle = PTR_UINT(data);
1295-
1296-
conn = hci_conn_hash_lookup_handle(hdev, handle);
1297-
if (!conn)
1298-
return 0;
1299-
1300-
bt_dev_dbg(hdev, "conn %p", conn);
1301-
1302-
clear_bit(HCI_CONN_SCANNING, &conn->flags);
1303-
conn->state = BT_CONNECT;
1304-
1305-
return hci_le_create_conn_sync(hdev, conn);
1306-
}
1307-
13081264
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
13091265
u8 dst_type, bool dst_resolved, u8 sec_level,
13101266
u16 conn_timeout, u8 role)
@@ -1371,9 +1327,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
13711327
conn->sec_level = BT_SECURITY_LOW;
13721328
conn->conn_timeout = conn_timeout;
13731329

1374-
err = hci_cmd_sync_queue(hdev, hci_connect_le_sync,
1375-
UINT_PTR(conn->handle),
1376-
create_le_conn_complete);
1330+
err = hci_connect_le_sync(hdev, conn);
13771331
if (err) {
13781332
hci_conn_del(conn);
13791333
return ERR_PTR(err);
@@ -2909,12 +2863,10 @@ u32 hci_conn_get_phy(struct hci_conn *conn)
29092863

29102864
static int abort_conn_sync(struct hci_dev *hdev, void *data)
29112865
{
2912-
struct hci_conn *conn;
2913-
u16 handle = PTR_UINT(data);
2866+
struct hci_conn *conn = data;
29142867

2915-
conn = hci_conn_hash_lookup_handle(hdev, handle);
2916-
if (!conn)
2917-
return 0;
2868+
if (!hci_conn_valid(hdev, conn))
2869+
return -ECANCELED;
29182870

29192871
return hci_abort_conn_sync(hdev, conn, conn->abort_reason);
29202872
}
@@ -2949,8 +2901,10 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
29492901
hci_cmd_sync_cancel(hdev, -ECANCELED);
29502902
break;
29512903
}
2904+
/* Cancel connect attempt if still queued/pending */
2905+
} else if (!hci_cancel_connect_sync(hdev, conn)) {
2906+
return 0;
29522907
}
29532908

2954-
return hci_cmd_sync_queue(hdev, abort_conn_sync, UINT_PTR(conn->handle),
2955-
NULL);
2909+
return hci_cmd_sync_queue_once(hdev, abort_conn_sync, conn, NULL);
29562910
}

net/bluetooth/hci_sync.c

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6285,12 +6285,21 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
62856285
conn->conn_timeout, NULL);
62866286
}
62876287

6288-
int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
6288+
static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
62896289
{
62906290
struct hci_cp_le_create_conn cp;
62916291
struct hci_conn_params *params;
62926292
u8 own_addr_type;
62936293
int err;
6294+
struct hci_conn *conn = data;
6295+
6296+
if (!hci_conn_valid(hdev, conn))
6297+
return -ECANCELED;
6298+
6299+
bt_dev_dbg(hdev, "conn %p", conn);
6300+
6301+
clear_bit(HCI_CONN_SCANNING, &conn->flags);
6302+
conn->state = BT_CONNECT;
62946303

62956304
/* If requested to connect as peripheral use directed advertising */
62966305
if (conn->role == HCI_ROLE_SLAVE) {
@@ -6611,16 +6620,11 @@ int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
66116620

66126621
static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
66136622
{
6614-
struct hci_conn *conn;
6615-
u16 handle = PTR_UINT(data);
6623+
struct hci_conn *conn = data;
66166624
struct inquiry_entry *ie;
66176625
struct hci_cp_create_conn cp;
66186626
int err;
66196627

6620-
conn = hci_conn_hash_lookup_handle(hdev, handle);
6621-
if (!conn)
6622-
return 0;
6623-
66246628
/* Many controllers disallow HCI Create Connection while it is doing
66256629
* HCI Inquiry. So we cancel the Inquiry first before issuing HCI Create
66266630
* Connection. This may cause the MGMT discovering state to become false
@@ -6679,6 +6683,58 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
66796683

66806684
int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn)
66816685
{
6682-
return hci_cmd_sync_queue(hdev, hci_acl_create_conn_sync,
6683-
UINT_PTR(conn->handle), NULL);
6686+
return hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
6687+
NULL);
6688+
}
6689+
6690+
static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
6691+
{
6692+
struct hci_conn *conn = data;
6693+
6694+
bt_dev_dbg(hdev, "err %d", err);
6695+
6696+
if (err == -ECANCELED)
6697+
return;
6698+
6699+
hci_dev_lock(hdev);
6700+
6701+
if (!err) {
6702+
hci_connect_le_scan_cleanup(conn, 0x00);
6703+
goto done;
6704+
}
6705+
6706+
/* Check if connection is still pending */
6707+
if (conn != hci_lookup_le_connect(hdev))
6708+
goto done;
6709+
6710+
/* Flush to make sure we send create conn cancel command if needed */
6711+
flush_delayed_work(&conn->le_conn_timeout);
6712+
hci_conn_failed(conn, bt_status(err));
6713+
6714+
done:
6715+
hci_dev_unlock(hdev);
6716+
}
6717+
6718+
int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn)
6719+
{
6720+
return hci_cmd_sync_queue_once(hdev, hci_le_create_conn_sync, conn,
6721+
create_le_conn_complete);
6722+
}
6723+
6724+
int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn)
6725+
{
6726+
if (conn->state != BT_OPEN)
6727+
return -EINVAL;
6728+
6729+
switch (conn->type) {
6730+
case ACL_LINK:
6731+
return !hci_cmd_sync_dequeue_once(hdev,
6732+
hci_acl_create_conn_sync,
6733+
conn, NULL);
6734+
case LE_LINK:
6735+
return !hci_cmd_sync_dequeue_once(hdev, hci_le_create_conn_sync,
6736+
conn, create_le_conn_complete);
6737+
}
6738+
6739+
return -ENOENT;
66846740
}

0 commit comments

Comments
 (0)