From 92ef586782e679be0b9b0b5d055d005db91aae8e Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Sun, 4 Feb 2024 22:24:58 +0100 Subject: [PATCH] Bluetooth: Support `BT_RECV_WORKQ_BT` with Zephyr LL This patch allows selecting the combination of `CONFIG_BT_RECV_WORKQ_BT` and `BT_LL_SW_SPLIT`. The implementation of `bt_recv_prio` is copied from `hci_raw.c`. This ensures the order of packets is the same as when the controller's `hci_driver.c` is off-chip and sends HCI over UART. Without this patch, the Zephyr LL driver will duplicate some events on behalf of `hci_core`. This duplication is not wanted when `CONFIG_BT_RECV_WORKQ_BT=y`. The above mentioned duplication is not sound and is evidenced in logged warnings, e.g. in `tests/bsim/bluetooth/host/l2cap/stress` with `CONFIG_BT_RECV_WORKQ_BT=y` logging "no transition". This patch is a step towards the deprecation of `CONFIG_BT_RECV_BLOCKING`. `CONFIG_BT_RECV_BLOCKING` is complicated and tightly coupled to `hci_core`. In the future, removing `CONFIG_BT_RECV_BLOCKING` will give a cleaner separation between `hci_core` and the drivers and allow `hci_core` to evolve without changes spilling out into the drivers. Signed-off-by: Aleksander Wasaznik --- subsys/bluetooth/controller/hci/hci_driver.c | 24 ++++++++++++++++++++ subsys/bluetooth/host/hci_core.c | 2 ++ 2 files changed, 26 insertions(+) diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index d4788efa37ab..8be4255cb4a2 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -81,6 +81,30 @@ static sys_slist_t hbuf_pend; static int32_t hbuf_count; #endif +#if !defined(CONFIG_BT_RECV_BLOCKING) +/* Copied here from `hci_raw.c`, which would be used in + * conjunction with this driver when serializing HCI over wire. + * This serves as a converter from the more complicated + * `CONFIG_BT_RECV_BLOCKING` API to the normal single-receiver + * `bt_recv` API. + */ +int bt_recv_prio(struct net_buf *buf) +{ + if (bt_buf_get_type(buf) == BT_BUF_EVT) { + struct bt_hci_evt_hdr *hdr = (void *)buf->data; + uint8_t evt_flags = bt_hci_evt_get_flags(hdr->evt); + + if ((evt_flags & BT_HCI_EVT_FLAG_RECV_PRIO) && + (evt_flags & BT_HCI_EVT_FLAG_RECV)) { + /* Avoid queuing the event twice */ + return 0; + } + } + + return bt_recv(buf); +} +#endif /* CONFIG_BT_RECV_BLOCKING */ + #if defined(CONFIG_BT_CTLR_ISO) #define SDU_HCI_HDR_SIZE (BT_HCI_ISO_HDR_SIZE + BT_HCI_ISO_TS_DATA_HDR_SIZE) diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index b751cb989f14..a7a4c2f77107 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -3881,6 +3881,7 @@ int bt_recv(struct net_buf *buf) } } +#if defined(CONFIG_BT_RECV_BLOCKING) int bt_recv_prio(struct net_buf *buf) { bt_monitor_send(bt_monitor_opcode(buf), buf->data, buf->len); @@ -3891,6 +3892,7 @@ int bt_recv_prio(struct net_buf *buf) return 0; } +#endif /* CONFIG_BT_RECV_BLOCKING */ int bt_hci_driver_register(const struct bt_hci_driver *drv) {