From 9b1653061ad64bee21de25036c98f1ffb8e0dc65 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 22 Jun 2017 15:52:35 +0300 Subject: [PATCH] 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 --- subsys/bluetooth/host/conn.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 823273656fc..bbb8fcf4489 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -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; 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(); sys_slist_append(&conn->tx_pending, node); 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, @@ -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; bt_conn_tx_cb_t cb; + sys_snode_t *node; int err; 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; bt_buf_set_type(buf, BT_BUF_ACL_OUT); + node = add_pending_tx(conn, cb); + err = bt_send(buf); if (err) { BT_ERR("Unable to send to driver (err %d)", err); + remove_pending_tx(conn, node); goto fail; } - add_pending_tx(conn, cb); return true; fail: