Bluetooth: Rotate outgoing ACL packets via a pending queue
To ensure that we never have more outgoing ACL buffers available than
the controller is willing to accept we should hold on to them between
calling drv->send() and getting the corresponding Number of Completed
Packets event. This patch adds a temporary FIFO in bt_dev for this.
Change-Id: I918119a03081d507de2bb4a731b2709ea99a648d
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
diff --git a/net/bluetooth/conn.c b/net/bluetooth/conn.c
index e55e008..632d017 100644
--- a/net/bluetooth/conn.c
+++ b/net/bluetooth/conn.c
@@ -208,7 +208,7 @@
}
dev->drv->send(buf);
- bt_buf_put(buf);
+ nano_fiber_fifo_put(&dev->acl_pend, buf);
}
BT_DBG("handle %u disconnected - cleaning up\n", conn->handle);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b69328b..73346ca 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -357,14 +357,22 @@
for (i = 0; i < num_handles; i++) {
uint16_t handle, count;
+ struct bt_buf *buf;
handle = sys_le16_to_cpu(evt->h[i].handle);
count = sys_le16_to_cpu(evt->h[i].count);
BT_DBG("handle %u count %u\n", handle, count);
- while (count--)
+ while (count--) {
nano_fiber_sem_give(&dev.le_pkts_sem);
+ buf = nano_fiber_fifo_get(&dev.acl_pend);
+ if (!buf) {
+ BT_ERR("Mismatch with pending ACL buffers\n");
+ continue;
+ }
+ bt_buf_put(buf);
+ }
}
}
@@ -647,6 +655,9 @@
if (err)
return err;
+ /* Initialize pending ACL packets FIFO */
+ nano_fifo_init(&dev.acl_pend);
+
/* Re-initialize buffers now that we know the ACL counts */
if (dev.le_pkts > ACL_OUT_MAX)
acl_out = ACL_OUT_MAX;
diff --git a/net/bluetooth/hci_core.h b/net/bluetooth/hci_core.h
index 1e0ca11..83dba36 100644
--- a/net/bluetooth/hci_core.h
+++ b/net/bluetooth/hci_core.h
@@ -71,6 +71,9 @@
/* Queue for outgoing HCI commands */
struct nano_fifo cmd_queue;
+ /* Pending outgoing ACL packets */
+ struct nano_fifo acl_pend;
+
/* Registered HCI driver */
struct bt_driver *drv;
};