Skip to content

Commit a065e57

Browse files
Johan Hedbergjhedberg
authored andcommitted
Bluetooth: host: Move system workqueue special case to the right place
Now that we've removed the TX allocation dependency from the TX thread we no longer have the need to do special-casing for the system workqueue when allocating buffers. Instead, we do have to special-case the system workqueue when allocating TX contexts since the system workqueue is the only place where they get freed up. Signed-off-by: Johan Hedberg <[email protected]>
1 parent d8689cd commit a065e57

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

subsys/bluetooth/host/conn.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,15 +1197,22 @@ void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, u8_t flags)
11971197

11981198
static struct bt_conn_tx *conn_tx_alloc(void)
11991199
{
1200+
/* The TX context always get freed in the system workqueue,
1201+
* so if we're in the same workqueue but there are no immediate
1202+
* contexts available, there's no chance we'll get one by waiting.
1203+
*/
1204+
if (k_current_get() == &k_sys_work_q.thread) {
1205+
return k_fifo_get(&free_tx, K_NO_WAIT);
1206+
}
1207+
12001208
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
12011209
struct bt_conn_tx *tx = k_fifo_get(&free_tx, K_NO_WAIT);
12021210

1203-
if (!tx) {
1204-
BT_WARN("Unable to get a free conn_tx, yielding...");
1205-
tx = k_fifo_get(&free_tx, K_FOREVER);
1211+
if (tx) {
1212+
return tx;
12061213
}
12071214

1208-
return tx;
1215+
BT_WARN("Unable to get an immediate free conn_tx");
12091216
}
12101217

12111218
return k_fifo_get(&free_tx, K_FOREVER);
@@ -1227,6 +1234,20 @@ int bt_conn_send_cb(struct bt_conn *conn, struct net_buf *buf,
12271234

12281235
if (cb) {
12291236
tx = conn_tx_alloc();
1237+
if (!tx) {
1238+
BT_ERR("Unable to allocate TX context");
1239+
net_buf_unref(buf);
1240+
return -ENOBUFS;
1241+
}
1242+
1243+
/* Verify that we're still connected after blocking */
1244+
if (conn->state != BT_CONN_CONNECTED) {
1245+
BT_WARN("Disconnected while allocating context");
1246+
net_buf_unref(buf);
1247+
tx_free(tx);
1248+
return -ENOTCONN;
1249+
}
1250+
12301251
tx->cb = cb;
12311252
tx->user_data = user_data;
12321253
tx->conn = bt_conn_ref(conn);
@@ -2265,20 +2286,10 @@ struct net_buf *bt_conn_create_pdu_timeout(struct net_buf_pool *pool,
22652286
pool = &acl_tx_pool;
22662287
}
22672288

2268-
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN) ||
2269-
(k_current_get() == &k_sys_work_q.thread && timeout == K_FOREVER)) {
2289+
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
22702290
buf = net_buf_alloc(pool, K_NO_WAIT);
22712291
if (!buf) {
22722292
BT_WARN("Unable to allocate buffer with K_NO_WAIT");
2273-
/* Cannot block with K_FOREVER on k_sys_work_q as that
2274-
* can cause a deadlock when trying to dispatch TX
2275-
* notification.
2276-
*/
2277-
if (k_current_get() == &k_sys_work_q.thread) {
2278-
BT_WARN("Unable to allocate buffer: timeout %d",
2279-
timeout);
2280-
return NULL;
2281-
}
22822293
buf = net_buf_alloc(pool, timeout);
22832294
}
22842295
} else {

0 commit comments

Comments
 (0)