Bluetooth: conn: Add pending tx before calling bt_send()
It's possible that the controller will emit the number of completed packets event before bt_send() returns, or possibly preempt send_frag() before it manages to call add_pending_tx(). We have to therefore add the pending TX entry before calling bt_send(). Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
3c23c6f53d
commit
9b1653061a
1 changed files with 18 additions and 2 deletions
|
@ -1099,7 +1099,7 @@ void bt_conn_notify_tx(struct bt_conn *conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_pending_tx(struct bt_conn *conn, bt_conn_tx_cb_t cb)
|
static sys_snode_t *add_pending_tx(struct bt_conn *conn, bt_conn_tx_cb_t cb)
|
||||||
{
|
{
|
||||||
sys_snode_t *node;
|
sys_snode_t *node;
|
||||||
unsigned int key;
|
unsigned int key;
|
||||||
|
@ -1114,6 +1114,19 @@ static void add_pending_tx(struct bt_conn *conn, bt_conn_tx_cb_t cb)
|
||||||
key = irq_lock();
|
key = irq_lock();
|
||||||
sys_slist_append(&conn->tx_pending, node);
|
sys_slist_append(&conn->tx_pending, node);
|
||||||
irq_unlock(key);
|
irq_unlock(key);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_pending_tx(struct bt_conn *conn, sys_snode_t *node)
|
||||||
|
{
|
||||||
|
unsigned int key;
|
||||||
|
|
||||||
|
key = irq_lock();
|
||||||
|
sys_slist_find_and_remove(&conn->tx_pending, node);
|
||||||
|
irq_unlock(key);
|
||||||
|
|
||||||
|
tx_free(CONTAINER_OF(node, struct bt_conn_tx, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool send_frag(struct bt_conn *conn, struct net_buf *buf, u8_t flags,
|
static bool send_frag(struct bt_conn *conn, struct net_buf *buf, u8_t flags,
|
||||||
|
@ -1121,6 +1134,7 @@ static bool send_frag(struct bt_conn *conn, struct net_buf *buf, u8_t flags,
|
||||||
{
|
{
|
||||||
struct bt_hci_acl_hdr *hdr;
|
struct bt_hci_acl_hdr *hdr;
|
||||||
bt_conn_tx_cb_t cb;
|
bt_conn_tx_cb_t cb;
|
||||||
|
sys_snode_t *node;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("conn %p buf %p len %u flags 0x%02x", conn, buf, buf->len,
|
BT_DBG("conn %p buf %p len %u flags 0x%02x", conn, buf, buf->len,
|
||||||
|
@ -1144,13 +1158,15 @@ static bool send_frag(struct bt_conn *conn, struct net_buf *buf, u8_t flags,
|
||||||
cb = conn_tx(buf)->cb;
|
cb = conn_tx(buf)->cb;
|
||||||
bt_buf_set_type(buf, BT_BUF_ACL_OUT);
|
bt_buf_set_type(buf, BT_BUF_ACL_OUT);
|
||||||
|
|
||||||
|
node = add_pending_tx(conn, cb);
|
||||||
|
|
||||||
err = bt_send(buf);
|
err = bt_send(buf);
|
||||||
if (err) {
|
if (err) {
|
||||||
BT_ERR("Unable to send to driver (err %d)", err);
|
BT_ERR("Unable to send to driver (err %d)", err);
|
||||||
|
remove_pending_tx(conn, node);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_pending_tx(conn, cb);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue