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 <johan.hedberg@intel.com>
This commit is contained in:
parent
d8689cdc72
commit
a065e5782a
1 changed files with 26 additions and 15 deletions
|
@ -1197,15 +1197,22 @@ void bt_conn_recv(struct bt_conn *conn, struct net_buf *buf, u8_t flags)
|
||||||
|
|
||||||
static struct bt_conn_tx *conn_tx_alloc(void)
|
static struct bt_conn_tx *conn_tx_alloc(void)
|
||||||
{
|
{
|
||||||
|
/* The TX context always get freed in the system workqueue,
|
||||||
|
* so if we're in the same workqueue but there are no immediate
|
||||||
|
* contexts available, there's no chance we'll get one by waiting.
|
||||||
|
*/
|
||||||
|
if (k_current_get() == &k_sys_work_q.thread) {
|
||||||
|
return k_fifo_get(&free_tx, K_NO_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
|
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
|
||||||
struct bt_conn_tx *tx = k_fifo_get(&free_tx, K_NO_WAIT);
|
struct bt_conn_tx *tx = k_fifo_get(&free_tx, K_NO_WAIT);
|
||||||
|
|
||||||
if (!tx) {
|
if (tx) {
|
||||||
BT_WARN("Unable to get a free conn_tx, yielding...");
|
return tx;
|
||||||
tx = k_fifo_get(&free_tx, K_FOREVER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx;
|
BT_WARN("Unable to get an immediate free conn_tx");
|
||||||
}
|
}
|
||||||
|
|
||||||
return k_fifo_get(&free_tx, K_FOREVER);
|
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,
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
tx = conn_tx_alloc();
|
tx = conn_tx_alloc();
|
||||||
|
if (!tx) {
|
||||||
|
BT_ERR("Unable to allocate TX context");
|
||||||
|
net_buf_unref(buf);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that we're still connected after blocking */
|
||||||
|
if (conn->state != BT_CONN_CONNECTED) {
|
||||||
|
BT_WARN("Disconnected while allocating context");
|
||||||
|
net_buf_unref(buf);
|
||||||
|
tx_free(tx);
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
|
||||||
tx->cb = cb;
|
tx->cb = cb;
|
||||||
tx->user_data = user_data;
|
tx->user_data = user_data;
|
||||||
tx->conn = bt_conn_ref(conn);
|
tx->conn = bt_conn_ref(conn);
|
||||||
|
@ -2265,20 +2286,10 @@ struct net_buf *bt_conn_create_pdu_timeout(struct net_buf_pool *pool,
|
||||||
pool = &acl_tx_pool;
|
pool = &acl_tx_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN) ||
|
if (IS_ENABLED(CONFIG_BT_DEBUG_CONN)) {
|
||||||
(k_current_get() == &k_sys_work_q.thread && timeout == K_FOREVER)) {
|
|
||||||
buf = net_buf_alloc(pool, K_NO_WAIT);
|
buf = net_buf_alloc(pool, K_NO_WAIT);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
BT_WARN("Unable to allocate buffer with K_NO_WAIT");
|
BT_WARN("Unable to allocate buffer with K_NO_WAIT");
|
||||||
/* Cannot block with K_FOREVER on k_sys_work_q as that
|
|
||||||
* can cause a deadlock when trying to dispatch TX
|
|
||||||
* notification.
|
|
||||||
*/
|
|
||||||
if (k_current_get() == &k_sys_work_q.thread) {
|
|
||||||
BT_WARN("Unable to allocate buffer: timeout %d",
|
|
||||||
timeout);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
buf = net_buf_alloc(pool, timeout);
|
buf = net_buf_alloc(pool, timeout);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue