From eabd220d4034450ad635a259506c9136010f2457 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 12 Nov 2025 14:04:23 +0100 Subject: [PATCH 1/8] Revert "[nrf fromtree] bluetooth: buf: Add a callback for freed buffer in rx pool" This reverts commit fa2f75ecfc59ab2391f1599d89f33966a803b47c. Signed-off-by: Vinayak Kariappa Chettimada --- include/zephyr/bluetooth/buf.h | 21 -------- subsys/bluetooth/host/buf.c | 71 ++++------------------------ subsys/bluetooth/host/hci_raw.c | 21 +------- subsys/bluetooth/host/iso.c | 20 +------- subsys/bluetooth/host/iso_internal.h | 10 ---- 5 files changed, 13 insertions(+), 130 deletions(-) diff --git a/include/zephyr/bluetooth/buf.h b/include/zephyr/bluetooth/buf.h index 4e6056141f18..2ab7287dcaf8 100644 --- a/include/zephyr/bluetooth/buf.h +++ b/include/zephyr/bluetooth/buf.h @@ -146,27 +146,6 @@ BUILD_ASSERT(CONFIG_BT_BUF_EVT_RX_COUNT > CONFIG_BT_BUF_ACL_TX_COUNT, */ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout); -/** A callback to notify about freed buffer in the incoming data pool. - * - * This callback is called when a buffer of a given type is freed and can be requested through the - * @ref bt_buf_get_rx function. However, this callback is called from the context of the buffer - * freeing operation and must not attempt to allocate a new buffer from the same pool. - * - * @warning When this callback is called, the scheduler is locked and the callee must not perform - * any action that makes the current thread unready. This callback must only be used for very - * short non-blocking operation (e.g. submitting a work item). - * - * @param type_mask A bit mask of buffer types that have been freed. - */ -typedef void (*bt_buf_rx_freed_cb_t)(enum bt_buf_type type_mask); - -/** Set the callback to notify about freed buffer in the incoming data pool. - * - * @param cb Callback to notify about freed buffer in the incoming data pool. If NULL, the callback - * is disabled. - */ -void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb); - /** Allocate a buffer for outgoing data * * This will set the buffer type so bt_buf_set_type() does not need to diff --git a/subsys/bluetooth/host/buf.c b/subsys/bluetooth/host/buf.c index 713db81d929f..54777fe1c795 100644 --- a/subsys/bluetooth/host/buf.c +++ b/subsys/bluetooth/host/buf.c @@ -22,26 +22,6 @@ */ #define SYNC_EVT_SIZE (BT_BUF_RESERVE + BT_HCI_EVT_HDR_SIZE + 255) -static bt_buf_rx_freed_cb_t buf_rx_freed_cb; - -static void buf_rx_freed_notify(enum bt_buf_type mask) -{ - k_sched_lock(); - - if (buf_rx_freed_cb) { - buf_rx_freed_cb(mask); - } - - k_sched_unlock(); -} - -#if defined(CONFIG_BT_ISO_RX) -static void iso_rx_freed_cb(void) -{ - buf_rx_freed_notify(BT_BUF_ISO_IN); -} -#endif - /* Pool for RX HCI buffers that are always freed by `bt_recv` * before it returns. * @@ -57,37 +37,17 @@ NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT, sizeof(struct bt_buf_data), NULL); #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -static void acl_in_pool_destroy(struct net_buf *buf) -{ - bt_hci_host_num_completed_packets(buf); - buf_rx_freed_notify(BT_BUF_ACL_IN); -} - -static void evt_pool_destroy(struct net_buf *buf) -{ - net_buf_destroy(buf); - buf_rx_freed_notify(BT_BUF_EVT); -} +NET_BUF_POOL_DEFINE(acl_in_pool, BT_BUF_ACL_RX_COUNT, + BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), + sizeof(struct acl_data), bt_hci_host_num_completed_packets); -NET_BUF_POOL_DEFINE(acl_in_pool, BT_BUF_ACL_RX_COUNT, BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), - sizeof(struct acl_data), acl_in_pool_destroy); - -NET_BUF_POOL_FIXED_DEFINE(evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, BT_BUF_EVT_RX_SIZE, - sizeof(struct bt_buf_data), evt_pool_destroy); +NET_BUF_POOL_FIXED_DEFINE(evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, + BT_BUF_EVT_RX_SIZE, sizeof(struct bt_buf_data), + NULL); #else -static void hci_rx_pool_destroy(struct net_buf *buf) -{ - net_buf_destroy(buf); - - /* When ACL Flow Control is disabled, a single pool is used for events and acl data. - * Therefore the callback will always notify about both types of buffers, BT_BUF_EVT and - * BT_BUF_ACL_IN. - */ - buf_rx_freed_notify(BT_BUF_EVT | BT_BUF_ACL_IN); -} - -NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, BT_BUF_RX_SIZE, sizeof(struct acl_data), - hci_rx_pool_destroy); +NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, + BT_BUF_RX_SIZE, sizeof(struct acl_data), + NULL); #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) @@ -119,19 +79,6 @@ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) return buf; } -void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb) -{ - k_sched_lock(); - - buf_rx_freed_cb = cb; - -#if defined(CONFIG_BT_ISO_RX) - bt_iso_buf_rx_freed_cb_set(cb != NULL ? iso_rx_freed_cb : NULL); -#endif - - k_sched_unlock(); -} - struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout) { diff --git a/subsys/bluetooth/host/hci_raw.c b/subsys/bluetooth/host/hci_raw.c index 82209f68e8d0..4da8cb8a2321 100644 --- a/subsys/bluetooth/host/hci_raw.c +++ b/subsys/bluetooth/host/hci_raw.c @@ -43,20 +43,8 @@ static uint8_t raw_mode = BT_HCI_RAW_MODE_H4; static uint8_t raw_mode; #endif -static bt_buf_rx_freed_cb_t buf_rx_freed_cb; - -static void hci_rx_buf_destroy(struct net_buf *buf) -{ - net_buf_destroy(buf); - - if (buf_rx_freed_cb) { - /* bt_buf_get_rx is used for all types of RX buffers */ - buf_rx_freed_cb(BT_BUF_EVT | BT_BUF_ACL_IN | BT_BUF_ISO_IN); - } -} - -NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, BT_BUF_RX_SIZE, sizeof(struct bt_buf_data), - hci_rx_buf_destroy); +NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, + BT_BUF_RX_SIZE, sizeof(struct bt_buf_data), NULL); NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, BT_BUF_CMD_TX_COUNT, BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE), sizeof(struct bt_buf_data), NULL); @@ -118,11 +106,6 @@ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) return buf; } -void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb) -{ - buf_rx_freed_cb = cb; -} - struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout, const void *data, size_t size) { diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index 2bac55225cfc..9c081bf2a98b 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -35,20 +35,9 @@ LOG_MODULE_REGISTER(bt_iso); #define iso_chan(_iso) ((_iso)->iso.chan); #if defined(CONFIG_BT_ISO_RX) -static bt_iso_buf_rx_freed_cb_t buf_rx_freed_cb; - -static void iso_rx_buf_destroy(struct net_buf *buf) -{ - net_buf_destroy(buf); - - if (buf_rx_freed_cb) { - buf_rx_freed_cb(); - } -} - NET_BUF_POOL_FIXED_DEFINE(iso_rx_pool, CONFIG_BT_ISO_RX_BUF_COUNT, - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_RX_MTU), sizeof(struct iso_data), - iso_rx_buf_destroy); + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_RX_MTU), + sizeof(struct iso_data), NULL); static struct bt_iso_recv_info iso_info_data[CONFIG_BT_ISO_RX_BUF_COUNT]; #define iso_info(buf) (&iso_info_data[net_buf_id(buf)]) @@ -594,11 +583,6 @@ struct net_buf *bt_iso_get_rx(k_timeout_t timeout) return buf; } -void bt_iso_buf_rx_freed_cb_set(bt_iso_buf_rx_freed_cb_t cb) -{ - buf_rx_freed_cb = cb; -} - void bt_iso_recv(struct bt_conn *iso, struct net_buf *buf, uint8_t flags) { struct bt_hci_iso_data_hdr *hdr; diff --git a/subsys/bluetooth/host/iso_internal.h b/subsys/bluetooth/host/iso_internal.h index f67121436a98..10fc9409643f 100644 --- a/subsys/bluetooth/host/iso_internal.h +++ b/subsys/bluetooth/host/iso_internal.h @@ -78,16 +78,6 @@ void hci_iso(struct net_buf *buf); /* Allocates RX buffer */ struct net_buf *bt_iso_get_rx(k_timeout_t timeout); -/** A callback used to notify about freed buffer in the iso rx pool. */ -typedef void (*bt_iso_buf_rx_freed_cb_t)(void); - -/** Set a callback to notify about freed buffer in the iso rx pool. - * - * @param cb Callback to notify about freed buffer in the iso rx pool. If NULL, the callback is - * disabled. - */ -void bt_iso_buf_rx_freed_cb_set(bt_iso_buf_rx_freed_cb_t cb); - /* Process CIS Established event */ void hci_le_cis_established(struct net_buf *buf); From dba59d55203293fb87c170aaffb3254738cc12f2 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 12 Nov 2025 14:04:26 +0100 Subject: [PATCH 2/8] Revert "[nrf noup] Bluetooth: Controller: Fix use of HAS_BT_CTLR with BT_CTLR" This reverts commit 7af2bc5e02d7f038cde9b24526c2b4e777273940. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/common/Kconfig | 4 ++-- subsys/bluetooth/common/hci_common_internal.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index c73229449625..014524b2080b 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -203,11 +203,11 @@ config BT_BUF_CMD_TX_SIZE config BT_BUF_CMD_TX_COUNT # This option is only visible for a user when Host and Controller are build together, or for # Host-only builds. - int "Number of HCI command buffers" if !BT_HCI_RAW || !BT_CTLR + int "Number of HCI command buffers" if !BT_HCI_RAW || !HAS_BT_CTLR # This option is present when Host and Controller are build together, or # for Host only builds, or when Controller-to-Host ACL data flow control # is disabled. - depends on !BT_HCI_RAW || !BT_CTLR || !BT_HCI_ACL_FLOW_CONTROL + depends on !BT_HCI_RAW || !HAS_BT_CTLR || !BT_HCI_ACL_FLOW_CONTROL # The Mesh stack usage in applications and tests can start both advertising and scanning in # parallel. Also, when BT_MESH_WORKQ_SYS is enabled, the Mesh stack is starting Extended # Advertising in the receive callback run in the system work queue and as the Host also uses diff --git a/subsys/bluetooth/common/hci_common_internal.h b/subsys/bluetooth/common/hci_common_internal.h index c8b8b37434ff..910ea4b4af34 100644 --- a/subsys/bluetooth/common/hci_common_internal.h +++ b/subsys/bluetooth/common/hci_common_internal.h @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#if !defined(CONFIG_BT_HCI_RAW) || !defined(CONFIG_BT_CTLR) || \ +#if !defined(CONFIG_BT_HCI_RAW) || !defined(CONFIG_HAS_BT_CTLR) || \ !defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) /* Following build configurations use configurable CONFIG_BT_BUF_CMD_TX_COUNT: * 1. Host + Controller build with and without Controller to Host data flow control, or @@ -20,11 +20,11 @@ #define BT_BUF_CMD_TX_AUTO_DATA_LEN_UPDATE COND_CODE_1(CONFIG_BT_AUTO_DATA_LEN_UPDATE, (1), (0)) #else /* CONFIG_BT_HCI_RAW */ -#if defined(CONFIG_BT_CTLR) +#if defined(CONFIG_HAS_BT_CTLR) /* Controller-only build need no additional HCI command buffers */ BUILD_ASSERT((CONFIG_BT_BUF_CMD_TX_COUNT == CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX), "Mismatch in allocated HCI command buffers compared to Controller supported value."); -#endif /* CONFIG_BT_CTLR */ +#endif /* CONFIG_HAS_BT_CTLR */ /* Controller-only build do not enqueue auto initiated HCI commands */ #define BT_BUF_CMD_TX_REMOTE_VERSION 0 From 5089754bf46c08dc15a958aab41491dcf152260c Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 12 Nov 2025 14:04:28 +0100 Subject: [PATCH 3/8] Revert "[nrf fromtree] Bluetooth: Controller: Fix HCI command buffer allocation failure" This reverts commit eabfcff0111f2c74a63900ebfb670239c3a90c90. Signed-off-by: Vinayak Kariappa Chettimada --- include/zephyr/bluetooth/buf.h | 23 ++-- .../nrf5340_cpunet_bis-bt_ll_sw_split.conf | 5 + ...nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf | 5 + .../nrf5340_cpunet_cis-bt_ll_sw_split.conf | 5 + .../nrf5340_cpunet_df-bt_ll_sw_split.conf | 5 + .../nrf5340_cpunet_iso-bt_ll_sw_split.conf | 5 + ...340_cpunet_iso_central-bt_ll_sw_split.conf | 4 + ..._cpunet_iso_peripheral-bt_ll_sw_split.conf | 4 + samples/bluetooth/hci_ipc/prj.conf | 5 + samples/bluetooth/hci_uart/prj.conf | 4 + samples/bluetooth/hci_usb/prj.conf | 4 + .../bluetooth/mesh/boards/bbc_microbit.conf | 4 +- .../bluetooth/peripheral_hr/prj_minimal.conf | 2 +- subsys/bluetooth/common/Kconfig | 61 ++--------- subsys/bluetooth/common/hci_common_internal.h | 100 ------------------ subsys/bluetooth/controller/Kconfig | 9 -- subsys/bluetooth/controller/hci/hci.c | 66 +++--------- subsys/bluetooth/host/buf.c | 5 +- subsys/bluetooth/host/hci_common.c | 20 ---- subsys/bluetooth/host/hci_core.c | 9 +- subsys/bluetooth/host/hci_raw.c | 5 +- tests/bluetooth/hci_codecs_info/src/main.c | 4 - .../host/att/sequential/tester/prj.conf | 2 + .../host/att/sequential/tester/src/main.c | 3 +- .../host/l2cap/split/tester/prj.conf | 2 + .../host/l2cap/split/tester/src/main.c | 3 +- .../host/misc/disconnect/tester/prj.conf | 2 + .../host/misc/disconnect/tester/src/main.c | 3 +- ...0_cpunet_iso_acl_group-bt_ll_sw_split.conf | 5 + tests/bsim/bluetooth/ll/throughput/prj.conf | 5 - 30 files changed, 98 insertions(+), 281 deletions(-) delete mode 100644 subsys/bluetooth/common/hci_common_internal.h diff --git a/include/zephyr/bluetooth/buf.h b/include/zephyr/bluetooth/buf.h index 2ab7287dcaf8..bf2dcd5072e1 100644 --- a/include/zephyr/bluetooth/buf.h +++ b/include/zephyr/bluetooth/buf.h @@ -100,13 +100,13 @@ struct bt_buf_data { * available for the HCI driver to allocate from. * * TODO: When CONFIG_BT_BUF_ACL_RX_COUNT is removed, - * remove the MAX and only keep the 1. + * remove the MAX and only keep (CONFIG_BT_MAX_CONN + 1) */ -#define BT_BUF_ACL_RX_COUNT_EXTRA CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA -#define BT_BUF_ACL_RX_COUNT (MAX(CONFIG_BT_BUF_ACL_RX_COUNT, 1) + BT_BUF_ACL_RX_COUNT_EXTRA) +#define BT_BUF_ACL_RX_COUNT \ + (MAX(CONFIG_BT_BUF_ACL_RX_COUNT, (CONFIG_BT_MAX_CONN + 1)) + \ + CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA) #else -#define BT_BUF_ACL_RX_COUNT_EXTRA 0 -#define BT_BUF_ACL_RX_COUNT 0 +#define BT_BUF_ACL_RX_COUNT 0 #endif /* CONFIG_BT_CONN && CONFIG_BT_HCI_HOST */ #if defined(CONFIG_BT_BUF_ACL_RX_COUNT) && CONFIG_BT_BUF_ACL_RX_COUNT > 0 @@ -120,15 +120,10 @@ BUILD_ASSERT(BT_BUF_ACL_RX_COUNT <= BT_BUF_ACL_RX_COUNT_MAX, #define BT_BUF_RX_SIZE (MAX(MAX(BT_BUF_ACL_RX_SIZE, BT_BUF_EVT_RX_SIZE), \ BT_BUF_ISO_RX_SIZE)) -/* Controller can generate up to CONFIG_BT_BUF_ACL_TX_COUNT number of unique HCI Number of Completed - * Packets events. - */ -BUILD_ASSERT(CONFIG_BT_BUF_EVT_RX_COUNT > CONFIG_BT_BUF_ACL_TX_COUNT, - "Increase Event RX buffer count to be greater than ACL TX buffer count"); - -/** Buffer count needed for HCI ACL or HCI ISO plus Event RX buffers */ -#define BT_BUF_RX_COUNT (CONFIG_BT_BUF_EVT_RX_COUNT + \ - MAX(BT_BUF_ACL_RX_COUNT, BT_BUF_ISO_RX_COUNT)) +/** Buffer count needed for HCI ACL, HCI ISO or Event RX buffers */ +#define BT_BUF_RX_COUNT (MAX(MAX(CONFIG_BT_BUF_EVT_RX_COUNT, \ + BT_BUF_ACL_RX_COUNT), \ + BT_BUF_ISO_RX_COUNT)) /** Data size needed for HCI Command buffers. */ #define BT_BUF_CMD_TX_SIZE BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE) diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf index ed542c44d725..f0a22f760f9b 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf @@ -13,7 +13,12 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=2 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_COUNT=16 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf index 50f071290f95..37e29435d49b 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf @@ -11,6 +11,11 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=16 + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + # Controller CONFIG_BT_LL_SW_SPLIT=y diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf index 1437c5339059..7fab285f3bed 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf @@ -13,7 +13,12 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=2 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_COUNT=16 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf index 7b6f64d6f411..21d4a042ad75 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_df-bt_ll_sw_split.conf @@ -13,7 +13,12 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=2 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_COUNT=16 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 69305951b0bf..e9e5ac634835 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -13,7 +13,12 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=2 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_COUNT=16 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf index c150dc6852b4..f29917aaf935 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf @@ -12,6 +12,10 @@ CONFIG_BT=y CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf index d4388c7685b5..ddd7d7e7b317 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf @@ -12,6 +12,10 @@ CONFIG_BT=y CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/samples/bluetooth/hci_ipc/prj.conf b/samples/bluetooth/hci_ipc/prj.conf index e6104e9fe47d..755a1f4ac1e5 100644 --- a/samples/bluetooth/hci_ipc/prj.conf +++ b/samples/bluetooth/hci_ipc/prj.conf @@ -11,6 +11,11 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=16 + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + # Enable and adjust the below value as necessary # CONFIG_BT_BUF_EVT_RX_COUNT=16 # CONFIG_BT_BUF_EVT_RX_SIZE=255 diff --git a/samples/bluetooth/hci_uart/prj.conf b/samples/bluetooth/hci_uart/prj.conf index 0bdcc2cf8850..bdc73dd68e2e 100644 --- a/samples/bluetooth/hci_uart/prj.conf +++ b/samples/bluetooth/hci_uart/prj.conf @@ -17,3 +17,7 @@ CONFIG_BT_TINYCRYPT_ECC=n CONFIG_BT_CTLR_DTM_HCI=y CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 diff --git a/samples/bluetooth/hci_usb/prj.conf b/samples/bluetooth/hci_usb/prj.conf index 7f0a2d9fe6aa..0f809e424d6d 100644 --- a/samples/bluetooth/hci_usb/prj.conf +++ b/samples/bluetooth/hci_usb/prj.conf @@ -11,3 +11,7 @@ CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n CONFIG_SERIAL=n CONFIG_CONSOLE=n CONFIG_UART_CONSOLE=n + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 diff --git a/samples/bluetooth/mesh/boards/bbc_microbit.conf b/samples/bluetooth/mesh/boards/bbc_microbit.conf index d71bc9400ae7..053053e78187 100644 --- a/samples/bluetooth/mesh/boards/bbc_microbit.conf +++ b/samples/bluetooth/mesh/boards/bbc_microbit.conf @@ -13,11 +13,9 @@ CONFIG_BT_PERIPHERAL=n CONFIG_BT_EXT_ADV=n CONFIG_BT_RX_STACK_SIZE=1100 CONFIG_BT_BUF_EVT_RX_COUNT=3 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=3 -# CONFIG_BT_BUF_ACL_TX_COUNT has to be less than CONFIG_BT_BUF_EVT_RX_COUNT -CONFIG_BT_BUF_ACL_TX_COUNT=1 - CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_MESH_ADV_BUF_COUNT=3 diff --git a/samples/bluetooth/peripheral_hr/prj_minimal.conf b/samples/bluetooth/peripheral_hr/prj_minimal.conf index 50e873cd66d4..ee8f43974bfc 100644 --- a/samples/bluetooth/peripheral_hr/prj_minimal.conf +++ b/samples/bluetooth/peripheral_hr/prj_minimal.conf @@ -101,7 +101,7 @@ CONFIG_BT_CTLR_PHY_2M=n # Reduce Bluetooth buffers CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=1 CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=45 -CONFIG_BT_BUF_EVT_RX_COUNT=4 +CONFIG_BT_BUF_EVT_RX_COUNT=2 CONFIG_BT_CONN_TX_MAX=2 CONFIG_BT_L2CAP_TX_BUF_COUNT=2 diff --git a/subsys/bluetooth/common/Kconfig b/subsys/bluetooth/common/Kconfig index 014524b2080b..c837fc559cf6 100644 --- a/subsys/bluetooth/common/Kconfig +++ b/subsys/bluetooth/common/Kconfig @@ -93,23 +93,15 @@ config BT_BUF_ACL_RX_SIZE K-frame. config BT_BUF_ACL_RX_COUNT_EXTRA - # As Host implementation unconditionally references this Kconfig, we - # hide it for !BT_CONN and default to 0. - int "Number of extra incoming ACL data buffers" if BT_CONN - range 1 65535 if BT_CONN - default BT_MAX_CONN if BT_CONN - range 0 0 + int "Number of extra incoming ACL data buffers" default 0 + range 0 65535 help Number of incoming extra ACL data buffers sent from the Controller to the Host. - By default, the total number of incoming ACL data buffers is equal to - CONFIG_BT_MAX_CONN + 1, to support L2CAP recombination. - - The L2CAP recombination in the Host keeps the first Rx buffer for each - connection and uses one Rx buffer across all connections to receive a - fragment from the Controller. + By default, the number of incoming ACL data buffers is equal to + CONFIG_BT_MAX_CONN + 1. config BT_BUF_ACL_RX_COUNT int "[DEPRECATED] Number of incoming ACL data buffers" @@ -143,8 +135,7 @@ config BT_BUF_EVT_RX_SIZE config BT_BUF_EVT_RX_COUNT int "Number of HCI Event buffers" - default 8 if BT_HCI_RAW - default 4 if BT_RECV_BLOCKING + default 3 if BT_RECV_BLOCKING default 20 if (BT_MESH && !(BT_BUF_EVT_DISCARDABLE_COUNT > 0)) default 10 range 2 255 @@ -201,48 +192,12 @@ config BT_BUF_CMD_TX_SIZE to the maximum of 255. config BT_BUF_CMD_TX_COUNT - # This option is only visible for a user when Host and Controller are build together, or for - # Host-only builds. - int "Number of HCI command buffers" if !BT_HCI_RAW || !HAS_BT_CTLR - # This option is present when Host and Controller are build together, or - # for Host only builds, or when Controller-to-Host ACL data flow control - # is disabled. - depends on !BT_HCI_RAW || !HAS_BT_CTLR || !BT_HCI_ACL_FLOW_CONTROL - # The Mesh stack usage in applications and tests can start both advertising and scanning in - # parallel. Also, when BT_MESH_WORKQ_SYS is enabled, the Mesh stack is starting Extended - # Advertising in the receive callback run in the system work queue and as the Host also uses - # the system work queue for HCI command Tx towards the Controller, one additional HCI - # command buffer is needed. - range 2 64 if BT_MESH - range 1 64 - default 2 if BT_MESH - default 1 + int "Number of HCI command buffers" + default 2 + range 2 64 help Number of buffers available for outgoing HCI commands from the Host. - HCI Controllers may not support Num_HCI_Command_Packets > 1, hence they default to 1 when - not enabling Controller to Host data flow control (BT_HCI_ACL_FLOW_CONTROL), Read Remote - Version Information (BT_REMOTE_VERSION), Auto-Initiate PHY update (BT_AUTO_PHY_UPDATE), or - Auto-Initiate Data Length Update (BT_AUTO_DATA_LEN_UPDATE). - - Normal HCI commands follow the HCI command flow control using Num_HCI_Command_Packets - return in HCI command complete and status. - - The Host Number of Completed Packets command does not follow normal flow control of HCI - commands and the Controller side HCI drivers that allocates HCI command buffers with - K_NO_WAIT can end up running out of command buffers. - - When Controller to Host data flow control is enabled in the Host-only or combined - Host plus Controller build, the internal BT_BUF_CMD_TX_COUNT is adjusted accordingly - taking into considerations the enabled auto-initiated procedures, and to follow the normal - HCI command flow control to be able to send Ncmd normal HCI commands and - BT_BUF_ACL_RX_COUNT of Host Number of Completed Packets command down to the Controller. - - When Controller to Host data flow control is supported in the Controller-only build, - the internal BT_BUF_CMD_TX_COUNT is adjusted to be equal to (BT_BUF_RX_COUNT + Ncmd). - - Where Ncmd is supported maximum Num_HCI_Command_Packets in the Controller implementation. - endmenu config BT_HAS_HCI_VS diff --git a/subsys/bluetooth/common/hci_common_internal.h b/subsys/bluetooth/common/hci_common_internal.h deleted file mode 100644 index 910ea4b4af34..000000000000 --- a/subsys/bluetooth/common/hci_common_internal.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#if !defined(CONFIG_BT_HCI_RAW) || !defined(CONFIG_HAS_BT_CTLR) || \ - !defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -/* Following build configurations use configurable CONFIG_BT_BUF_CMD_TX_COUNT: - * 1. Host + Controller build with and without Controller to Host data flow control, or - * 2. Host-only with and without Controller to Host data flow control, or - * 3. Controller-only without Controller to Host data flow control support - */ -#if !defined(CONFIG_BT_HCI_RAW) -/* Host + Controller build, and Host-only build */ - -/* Auto initiated additional HCI command buffers enqueued in the Host */ -#define BT_BUF_CMD_TX_REMOTE_VERSION COND_CODE_1(CONFIG_BT_REMOTE_VERSION, (1), (0)) -#define BT_BUF_CMD_TX_AUTO_PHY_UPDATE COND_CODE_1(CONFIG_BT_AUTO_PHY_UPDATE, (1), (0)) -#define BT_BUF_CMD_TX_AUTO_DATA_LEN_UPDATE COND_CODE_1(CONFIG_BT_AUTO_DATA_LEN_UPDATE, (1), (0)) - -#else /* CONFIG_BT_HCI_RAW */ -#if defined(CONFIG_HAS_BT_CTLR) -/* Controller-only build need no additional HCI command buffers */ -BUILD_ASSERT((CONFIG_BT_BUF_CMD_TX_COUNT == CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX), - "Mismatch in allocated HCI command buffers compared to Controller supported value."); -#endif /* CONFIG_HAS_BT_CTLR */ - -/* Controller-only build do not enqueue auto initiated HCI commands */ -#define BT_BUF_CMD_TX_REMOTE_VERSION 0 -#define BT_BUF_CMD_TX_AUTO_PHY_UPDATE 0 -#define BT_BUF_CMD_TX_AUTO_DATA_LEN_UPDATE 0 -#endif /* !CONFIG_BT_HCI_RAW */ - -#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -/* When Controller to Host data flow control is supported in Host plus Controller build, or - * Host-only build, then we need additional BT_BUF_ACL_RX_COUNT number of HCI command buffers for - * enqueuing Host Number of Completed Packets command. - * - * Host keeps the first, and subsequent, Rx buffers (that comes from the driver) for each connection - * to do re-assembly into, up to the L2CAP SDU length required number of Rx buffers. - * BT_BUF_ACL_RX_COUNT_EXTRA holds the application configured number of buffers across active - * connections for recombination of HCI data packets to L2CAP SDUs. - * - * BT_BUF_HCI_EVT_RX_COUNT defines the number of available buffers reserved for "synchronous" - * processing of HCI events like Number of Completed Packets, disconnection complete etc. - * - * BT_BUF_HCI_ACL_RX_COUNT defines the number of available buffers for Controller to Host data - * flow control; keeping the application configured BT_BUF_ACL_RX_COUNT_EXTRA number of buffers - * available for L2CAP recombination, and a reserved number of buffers for processing HCI events. - */ - -/* FIXME: Calculate the maximum number of HCI events of different types that a connection can - * enqueue while the Host is slow at processing HCI events. - * - * 1. Disconnection Complete event - * 2. LE Connection Update Complete event - * 3. LE Long Term Key Request event - * 4. LE Remote Connection Parameter Request Event - * 5. LE Data Length Change event - * 6. LE PHY Update Complete event - * 7. ... - * - * As there is no HCI event flow control defined, implementations will need a transport level flow - * control to restrict buffers required on resource constraint devices, i.e. if these events are not - * processed "synchronous". - */ -#define BT_BUF_HCI_EVT_RX_COUNT 1 -#define BT_BUF_HCI_ACL_RX_COUNT (BT_BUF_RX_COUNT - BT_BUF_HCI_EVT_RX_COUNT - \ - BT_BUF_ACL_RX_COUNT_EXTRA) -#define BT_BUF_CMD_TX_HOST_NUM_CMPLT_PKT (BT_BUF_HCI_ACL_RX_COUNT) - -#else /* !CONFIG_BT_HCI_ACL_FLOW_CONTROL */ -#define BT_BUF_CMD_TX_HOST_NUM_CMPLT_PKT 0 -#endif /* !CONFIG_BT_HCI_ACL_FLOW_CONTROL */ - -/* Based on Host + Controller, Host-only or Controller-only; Calculate the HCI Command Tx count. */ -#define BT_BUF_CMD_TX_COUNT (CONFIG_BT_BUF_CMD_TX_COUNT + \ - BT_BUF_CMD_TX_HOST_NUM_CMPLT_PKT + \ - BT_BUF_CMD_TX_REMOTE_VERSION + \ - BT_BUF_CMD_TX_AUTO_PHY_UPDATE + \ - BT_BUF_CMD_TX_AUTO_DATA_LEN_UPDATE) - -#elif defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -/* When Controller to Host data flow control is supported in the Controller-only build, ensure - * that BT_BUF_CMD_TX_COUNT is greater than or equal to (BT_BUF_RX_COUNT + Ncmd), - * where Ncmd is supported maximum Num_HCI_Command_Packets in the Controller implementation. - */ -BUILD_ASSERT(!IS_ENABLED(CONFIG_BT_BUF_CMD_TX_COUNT), - "Configurable HCI command buffer count disallowed."); -BUILD_ASSERT(IS_ENABLED(CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX), - "Undefined Controller implementation supported Num_HCI_Command_Packets value."); - -/** Can use all of buffer count needed for HCI ACL, HCI ISO or Event RX buffers for ACL RX */ -#define BT_BUF_HCI_ACL_RX_COUNT (BT_BUF_RX_COUNT) - -/* Controller-only with Controller to Host data flow control */ -#define BT_BUF_CMD_TX_COUNT (BT_BUF_RX_COUNT + CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX) - -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index e0914cc2c298..a7b2c1a74f10 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -127,15 +127,6 @@ endchoice comment "BLE Controller configuration" -config BT_CTLR_HCI_NUM_CMD_PKT_MAX - # Hidden Controller implementation supported Num_HCI_Command_Packets value. - # This value will be used to calculate the total number of HCI command buffers to be - # allocated, BT_BUF_CMD_TX_COUNT, dependent on HCI Controller to Host data flow control - # being enabled. - int - default 1 if BT_LL_SW_SPLIT - default 1 - config BT_CTLR_CRYPTO bool "Crypto functions in Controller" default y diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 2b6ff78d8ab0..2fd7dc41a9eb 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -21,8 +21,6 @@ #include #include -#include "common/hci_common_internal.h" - #include "../host/hci_ecc.h" #include "util/util.h" @@ -185,13 +183,13 @@ static uint8_t sf_curr; #endif #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -int32_t hci_hbuf_total; -uint32_t hci_hbuf_sent; -uint32_t hci_hbuf_acked; -uint16_t hci_hbuf_pend[CONFIG_BT_MAX_CONN]; +int32_t hci_hbuf_total; +uint32_t hci_hbuf_sent; +uint32_t hci_hbuf_acked; +uint16_t hci_hbuf_pend[CONFIG_BT_MAX_CONN]; atomic_t hci_state_mask; static struct k_poll_signal *hbuf_signal; -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ +#endif #if defined(CONFIG_BT_CONN) static uint32_t conn_count; @@ -476,7 +474,7 @@ static void reset(struct net_buf *buf, struct net_buf **evt) atomic_set_bit(&hci_state_mask, HCI_STATE_BIT_RESET); k_poll_signal_raise(hbuf_signal, 0x0); } -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ +#endif hci_recv_fifo_reset(); } @@ -524,22 +522,6 @@ static void set_ctl_to_host_flow(struct net_buf *buf, struct net_buf **evt) hci_hbuf_total = -hci_hbuf_total; } -/* Host Number of Completed Packets command does not follow normal flow - * control of HCI commands and the Controller side HCI drivers that - * allocates HCI command buffers with K_NO_WAIT can end up running out - * of command buffers. - * - * Host will generate up to acl_pkts number of Host Number of Completed - * Packets command plus a number of normal HCI commands. - * - * Normal HCI commands follow the HCI command flow control using - * Num_HCI_Command_Packets return in HCI command complete and status. - * - * Note: Zephyr Controller does not support Num_HCI_Command_Packets > 1. - */ -BUILD_ASSERT(BT_BUF_HCI_ACL_RX_COUNT < BT_BUF_CMD_TX_COUNT, - "Too low HCI command buffers compare to ACL Rx buffers."); - static void host_buffer_size(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_host_buffer_size *cmd = (void *)buf->data; @@ -553,38 +535,15 @@ static void host_buffer_size(struct net_buf *buf, struct net_buf **evt) ccst->status = BT_HCI_ERR_CMD_DISALLOWED; return; } - - /* Fragmentation from Controller to Host not supported, require + /* fragmentation from controller to host not supported, require * ACL MTU to be at least the LL MTU */ if (acl_mtu < LL_LENGTH_OCTETS_RX_MAX) { - LOG_ERR("FC: Require Host ACL MTU (%u) >= LL Max Data Length (%u)", acl_mtu, - LL_LENGTH_OCTETS_RX_MAX); ccst->status = BT_HCI_ERR_INVALID_PARAM; return; } - /* Host Number of Completed Packets command does not follow normal flow - * control of HCI commands and the Controller side HCI drivers that - * allocates HCI command buffers with K_NO_WAIT can end up running out - * of command buffers. - * - * Host will generate up to acl_pkts number of Host Number of Completed - * Packets command plus a number of normal HCI commands. - * - * Normal HCI commands follow the HCI command flow control using - * Num_HCI_Command_Packets return in HCI command complete and status. - * - * Note: Zephyr Controller does not support Num_HCI_Command_Packets > 1. - */ - if (acl_pkts >= BT_BUF_CMD_TX_COUNT) { - LOG_WRN("FC: Host ACL packets (%u), BT_BUF_CMD_TX_COUNT (%u)", acl_pkts, - BT_BUF_CMD_TX_COUNT); - acl_pkts = BT_BUF_CMD_TX_COUNT - CONFIG_BT_CTLR_HCI_NUM_CMD_PKT_MAX; - } - - LOG_DBG("FC: host buf size %u count %u", acl_mtu, acl_pkts); - + LOG_DBG("FC: host buf size: %d", acl_pkts); hci_hbuf_total = -acl_pkts; } @@ -626,7 +585,7 @@ static void host_num_completed_packets(struct net_buf *buf, hci_hbuf_acked += count; k_poll_signal_raise(hbuf_signal, 0x0); } -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ +#endif #if defined(CONFIG_BT_CTLR_LE_PING) static void read_auth_payload_timeout(struct net_buf *buf, struct net_buf **evt) @@ -787,7 +746,7 @@ static int ctrl_bb_cmd_handle(uint16_t ocf, struct net_buf *cmd, case BT_OCF(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS): host_num_completed_packets(cmd, evt); break; -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ +#endif #if defined(CONFIG_BT_CTLR_LE_PING) case BT_OCF(BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT): @@ -8810,7 +8769,7 @@ void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf) LL_ASSERT(handle < ARRAY_SIZE(hci_hbuf_pend)); hci_hbuf_pend[handle]++; } -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ +#endif break; default: @@ -9012,7 +8971,6 @@ void hci_init(struct k_poll_signal *signal_host_buf) { #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) hbuf_signal = signal_host_buf; -#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ - +#endif reset(NULL, NULL); } diff --git a/subsys/bluetooth/host/buf.c b/subsys/bluetooth/host/buf.c index 54777fe1c795..f2c2d12bbeed 100644 --- a/subsys/bluetooth/host/buf.c +++ b/subsys/bluetooth/host/buf.c @@ -5,16 +5,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include -#include "common/hci_common_internal.h" - #include "hci_core.h" #include "conn_internal.h" #include "iso_internal.h" +#include + /* Events have a length field of 1 byte. This size fits all events. * * It's true that we don't put all kinds of events there (yet). However, the diff --git a/subsys/bluetooth/host/hci_common.c b/subsys/bluetooth/host/hci_common.c index 26bb1913d837..272d472896b5 100644 --- a/subsys/bluetooth/host/hci_common.c +++ b/subsys/bluetooth/host/hci_common.c @@ -30,17 +30,7 @@ struct net_buf *bt_hci_cmd_complete_create(uint16_t op, uint8_t plen) buf = bt_hci_evt_create(BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen); cc = net_buf_add(buf, sizeof(*cc)); - - /* The Num_HCI_Command_Packets parameter allows the Controller to - * indicate the number of HCI command packets the Host can send to the - * Controller. If the Controller requires the Host to stop sending - * commands, Num_HCI_Command_Packets will be set to zero. - * - * NOTE: Zephyr Controller (and may be other Controllers) do not support - * higher Number of HCI Command packets than 1. - */ cc->ncmd = 1U; - cc->opcode = sys_cpu_to_le16(op); return buf; @@ -55,17 +45,7 @@ struct net_buf *bt_hci_cmd_status_create(uint16_t op, uint8_t status) cs = net_buf_add(buf, sizeof(*cs)); cs->status = status; - - /* The Num_HCI_Command_Packets parameter allows the Controller to - * indicate the number of HCI command packets the Host can send to the - * Controller. If the Controller requires the Host to stop sending - * commands, Num_HCI_Command_Packets will be set to zero. - * - * NOTE: Zephyr Controller (and may be other Controllers) do not support - * higher Number of HCI Command packets than 1. - */ cs->ncmd = 1U; - cs->opcode = sys_cpu_to_le16(op); return buf; diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 0e406091a059..92b6d1433ba3 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -29,11 +29,10 @@ #include #include -#include "common/hci_common_internal.h" #include "common/bt_str.h" -#include "common/rpa.h" #include "common/assert.h" +#include "common/rpa.h" #include "keys.h" #include "monitor.h" #include "hci_core.h" @@ -110,7 +109,7 @@ struct cmd_data { struct k_sem *sync; }; -static struct cmd_data cmd_data[BT_BUF_CMD_TX_COUNT]; +static struct cmd_data cmd_data[CONFIG_BT_BUF_CMD_TX_COUNT]; #define cmd(buf) (&cmd_data[net_buf_id(buf)]) #define acl(buf) ((struct acl_data *)net_buf_user_data(buf)) @@ -130,7 +129,7 @@ void bt_hci_cmd_state_set_init(struct net_buf *buf, * command complete or command status. */ #define CMD_BUF_SIZE MAX(BT_BUF_EVT_RX_SIZE, BT_BUF_CMD_TX_SIZE) -NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, BT_BUF_CMD_TX_COUNT, +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, CMD_BUF_SIZE, sizeof(struct bt_buf_data), NULL); struct event_handler { @@ -1904,7 +1903,7 @@ static int set_flow_control(void) hbs = net_buf_add(buf, sizeof(*hbs)); (void)memset(hbs, 0, sizeof(*hbs)); hbs->acl_mtu = sys_cpu_to_le16(CONFIG_BT_BUF_ACL_RX_SIZE); - hbs->acl_pkts = sys_cpu_to_le16(BT_BUF_HCI_ACL_RX_COUNT); + hbs->acl_pkts = sys_cpu_to_le16(BT_BUF_ACL_RX_COUNT); err = bt_hci_cmd_send_sync(BT_HCI_OP_HOST_BUFFER_SIZE, buf, NULL); if (err) { diff --git a/subsys/bluetooth/host/hci_raw.c b/subsys/bluetooth/host/hci_raw.c index 4da8cb8a2321..16113c8d25a1 100644 --- a/subsys/bluetooth/host/hci_raw.c +++ b/subsys/bluetooth/host/hci_raw.c @@ -18,10 +18,7 @@ #include -#include "common/hci_common_internal.h" - #include "hci_ecc.h" - #include "monitor.h" #include "hci_raw_internal.h" @@ -45,7 +42,7 @@ static uint8_t raw_mode; NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, BT_BUF_RX_SIZE, sizeof(struct bt_buf_data), NULL); -NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, BT_BUF_CMD_TX_COUNT, +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE), sizeof(struct bt_buf_data), NULL); NET_BUF_POOL_FIXED_DEFINE(hci_acl_pool, CONFIG_BT_BUF_ACL_TX_COUNT, diff --git a/tests/bluetooth/hci_codecs_info/src/main.c b/tests/bluetooth/hci_codecs_info/src/main.c index a4eabc9b7a9f..de9537ebabcc 100644 --- a/tests/bluetooth/hci_codecs_info/src/main.c +++ b/tests/bluetooth/hci_codecs_info/src/main.c @@ -209,8 +209,6 @@ ZTEST(test_hci_codecs_info, test_read_codec_capabilities) ptr = &rp->capabilities[0]; zassert_mem_equal(ptr, codec_capabilities, sizeof(codec_capabilities), 0, "Reading codec capabilities content failed"); - - net_buf_unref(rsp); } #define READ_DELAY_CODING_FMT 0xff @@ -293,6 +291,4 @@ ZTEST(test_hci_codecs_info, test_read_ctlr_delay) "Reading controller min delay failed"); zassert_equal(sys_get_le24(rp->max_ctlr_delay), MAX_CTLR_DELAY, "Reading controller max delay failed"); - - net_buf_unref(rsp); } diff --git a/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf b/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf index fc5c80fa13d8..461c7dd50295 100644 --- a/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf +++ b/tests/bsim/bluetooth/host/att/sequential/tester/prj.conf @@ -6,6 +6,8 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=1 +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 diff --git a/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c b/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c index 13148bb70c05..cecbd8cab137 100644 --- a/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c +++ b/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c @@ -15,7 +15,6 @@ #include #include -#include "common/hci_common_internal.h" #include "common/bt_str.h" #include "host/conn_internal.h" @@ -49,7 +48,7 @@ static uint16_t server_write_handle; static K_FIFO_DEFINE(rx_queue); #define CMD_BUF_SIZE MAX(BT_BUF_EVT_RX_SIZE, BT_BUF_CMD_TX_SIZE) -NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, BT_BUF_CMD_TX_COUNT, +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, CMD_BUF_SIZE, 8, NULL); static K_SEM_DEFINE(cmd_sem, 1, 1); diff --git a/tests/bsim/bluetooth/host/l2cap/split/tester/prj.conf b/tests/bsim/bluetooth/host/l2cap/split/tester/prj.conf index 905ae4bbdca1..82dfa9686ee0 100644 --- a/tests/bsim/bluetooth/host/l2cap/split/tester/prj.conf +++ b/tests/bsim/bluetooth/host/l2cap/split/tester/prj.conf @@ -6,6 +6,8 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=16 +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 diff --git a/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c b/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c index 7b6fece797a1..f762ee824737 100644 --- a/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c @@ -15,7 +15,6 @@ #include #include -#include "common/hci_common_internal.h" #include "common/bt_str.h" #include "host/conn_internal.h" @@ -35,7 +34,7 @@ DEFINE_FLAG(flag_data_length_updated); static K_FIFO_DEFINE(rx_queue); #define CMD_BUF_SIZE MAX(BT_BUF_EVT_RX_SIZE, BT_BUF_CMD_TX_SIZE) -NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, BT_BUF_CMD_TX_COUNT, +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, CMD_BUF_SIZE, 8, NULL); static K_SEM_DEFINE(cmd_sem, 1, 1); diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf b/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf index fc5c80fa13d8..461c7dd50295 100644 --- a/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/prj.conf @@ -6,6 +6,8 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=1 +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c index 47a3e785455e..4755a55d4d38 100644 --- a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c @@ -15,7 +15,6 @@ #include #include -#include "common/hci_common_internal.h" #include "common/bt_str.h" #include "host/conn_internal.h" @@ -45,7 +44,7 @@ DEFINE_FLAG(flag_data_length_updated); static K_FIFO_DEFINE(rx_queue); #define CMD_BUF_SIZE MAX(BT_BUF_EVT_RX_SIZE, BT_BUF_CMD_TX_SIZE) -NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, BT_BUF_CMD_TX_COUNT, +NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, CMD_BUF_SIZE, 8, NULL); static K_SEM_DEFINE(cmd_sem, 1, 1); diff --git a/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf b/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf index 9f7868e815ab..a3c8f43c71f7 100644 --- a/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf +++ b/tests/bsim/bluetooth/ll/cis/sysbuild/hci_ipc/nrf5340_cpunet_iso_acl_group-bt_ll_sw_split.conf @@ -14,7 +14,12 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_HCI_RAW_RESERVE=1 CONFIG_BT_MAX_CONN=4 +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + CONFIG_BT_BUF_EVT_RX_COUNT=16 + CONFIG_BT_BUF_EVT_RX_SIZE=255 CONFIG_BT_BUF_ACL_RX_SIZE=255 CONFIG_BT_BUF_ACL_TX_SIZE=251 diff --git a/tests/bsim/bluetooth/ll/throughput/prj.conf b/tests/bsim/bluetooth/ll/throughput/prj.conf index f4805907f607..6f52a3d5091c 100644 --- a/tests/bsim/bluetooth/ll/throughput/prj.conf +++ b/tests/bsim/bluetooth/ll/throughput/prj.conf @@ -11,9 +11,4 @@ CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 CONFIG_BT_L2CAP_TX_MTU=247 -# BT HCI ACL RX Data Buffers -CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 -CONFIG_BT_BUF_ACL_RX_SIZE=255 - -# Maximum LL ACL PDU length CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 From 005add5906dbf2e553f5444641a47b401d8d8730 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Thu, 7 Nov 2024 09:50:37 +0100 Subject: [PATCH 4/8] [nrf fromtree] bluetooth: buf: Add a callback for freed buffer in rx pool The Bluetooth data buffer API currently lacks a mechanism to notify when a buffer is freed in the RX pool. This limitation forces HCI drivers to adopt inefficient workarounds to manage buffer allocation. HCI drivers face two suboptimal options: - Blocking calls: Use bt_buf_get_rx with K_FOREVER, which blocks the execution context until a buffer becomes available. - Polling: Repeatedly call bt_buf_get_rx with K_NO_WAIT, which increases CPU load and reduces efficiency. This commit introduces a callback mechanism that is triggered each time a buffer is freed in the RX pool. With this feature, HCI drivers can: - Call bt_buf_get_rx with K_NO_WAIT. - Wait for the callback notification if a NULL buffer is returned, avoiding unnecessary polling. The new callback improves efficiency by enabling event-driven behavior for buffer management, reducing CPU overhead while maintaining responsiveness. Signed-off-by: Pavel Vasilyev (cherry picked from commit c2488fdd3021bacb5c8f2cc4a6fe43cb2d0515d2) Signed-off-by: Vinayak Kariappa Chettimada --- include/zephyr/bluetooth/buf.h | 21 ++++++++ subsys/bluetooth/host/buf.c | 71 ++++++++++++++++++++++++---- subsys/bluetooth/host/hci_raw.c | 21 +++++++- subsys/bluetooth/host/iso.c | 20 +++++++- subsys/bluetooth/host/iso_internal.h | 10 ++++ 5 files changed, 130 insertions(+), 13 deletions(-) diff --git a/include/zephyr/bluetooth/buf.h b/include/zephyr/bluetooth/buf.h index bf2dcd5072e1..0bb59b82d6c7 100644 --- a/include/zephyr/bluetooth/buf.h +++ b/include/zephyr/bluetooth/buf.h @@ -141,6 +141,27 @@ BUILD_ASSERT(BT_BUF_ACL_RX_COUNT <= BT_BUF_ACL_RX_COUNT_MAX, */ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout); +/** A callback to notify about freed buffer in the incoming data pool. + * + * This callback is called when a buffer of a given type is freed and can be requested through the + * @ref bt_buf_get_rx function. However, this callback is called from the context of the buffer + * freeing operation and must not attempt to allocate a new buffer from the same pool. + * + * @warning When this callback is called, the scheduler is locked and the callee must not perform + * any action that makes the current thread unready. This callback must only be used for very + * short non-blocking operation (e.g. submitting a work item). + * + * @param type_mask A bit mask of buffer types that have been freed. + */ +typedef void (*bt_buf_rx_freed_cb_t)(enum bt_buf_type type_mask); + +/** Set the callback to notify about freed buffer in the incoming data pool. + * + * @param cb Callback to notify about freed buffer in the incoming data pool. If NULL, the callback + * is disabled. + */ +void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb); + /** Allocate a buffer for outgoing data * * This will set the buffer type so bt_buf_set_type() does not need to diff --git a/subsys/bluetooth/host/buf.c b/subsys/bluetooth/host/buf.c index f2c2d12bbeed..112b9af59921 100644 --- a/subsys/bluetooth/host/buf.c +++ b/subsys/bluetooth/host/buf.c @@ -21,6 +21,26 @@ */ #define SYNC_EVT_SIZE (BT_BUF_RESERVE + BT_HCI_EVT_HDR_SIZE + 255) +static bt_buf_rx_freed_cb_t buf_rx_freed_cb; + +static void buf_rx_freed_notify(enum bt_buf_type mask) +{ + k_sched_lock(); + + if (buf_rx_freed_cb) { + buf_rx_freed_cb(mask); + } + + k_sched_unlock(); +} + +#if defined(CONFIG_BT_ISO_RX) +static void iso_rx_freed_cb(void) +{ + buf_rx_freed_notify(BT_BUF_ISO_IN); +} +#endif + /* Pool for RX HCI buffers that are always freed by `bt_recv` * before it returns. * @@ -36,17 +56,37 @@ NET_BUF_POOL_FIXED_DEFINE(discardable_pool, CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT, sizeof(struct bt_buf_data), NULL); #if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL) -NET_BUF_POOL_DEFINE(acl_in_pool, BT_BUF_ACL_RX_COUNT, - BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), - sizeof(struct acl_data), bt_hci_host_num_completed_packets); +static void acl_in_pool_destroy(struct net_buf *buf) +{ + bt_hci_host_num_completed_packets(buf); + buf_rx_freed_notify(BT_BUF_ACL_IN); +} + +static void evt_pool_destroy(struct net_buf *buf) +{ + net_buf_destroy(buf); + buf_rx_freed_notify(BT_BUF_EVT); +} -NET_BUF_POOL_FIXED_DEFINE(evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, - BT_BUF_EVT_RX_SIZE, sizeof(struct bt_buf_data), - NULL); +NET_BUF_POOL_DEFINE(acl_in_pool, BT_BUF_ACL_RX_COUNT, BT_BUF_ACL_SIZE(CONFIG_BT_BUF_ACL_RX_SIZE), + sizeof(struct acl_data), acl_in_pool_destroy); + +NET_BUF_POOL_FIXED_DEFINE(evt_pool, CONFIG_BT_BUF_EVT_RX_COUNT, BT_BUF_EVT_RX_SIZE, + sizeof(struct bt_buf_data), evt_pool_destroy); #else -NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, - BT_BUF_RX_SIZE, sizeof(struct acl_data), - NULL); +static void hci_rx_pool_destroy(struct net_buf *buf) +{ + net_buf_destroy(buf); + + /* When ACL Flow Control is disabled, a single pool is used for events and acl data. + * Therefore the callback will always notify about both types of buffers, BT_BUF_EVT and + * BT_BUF_ACL_IN. + */ + buf_rx_freed_notify(BT_BUF_EVT | BT_BUF_ACL_IN); +} + +NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, BT_BUF_RX_SIZE, sizeof(struct acl_data), + hci_rx_pool_destroy); #endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) @@ -78,6 +118,19 @@ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) return buf; } +void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb) +{ + k_sched_lock(); + + buf_rx_freed_cb = cb; + +#if defined(CONFIG_BT_ISO_RX) + bt_iso_buf_rx_freed_cb_set(cb != NULL ? iso_rx_freed_cb : NULL); +#endif + + k_sched_unlock(); +} + struct net_buf *bt_buf_get_evt(uint8_t evt, bool discardable, k_timeout_t timeout) { diff --git a/subsys/bluetooth/host/hci_raw.c b/subsys/bluetooth/host/hci_raw.c index 16113c8d25a1..3366b7b3935c 100644 --- a/subsys/bluetooth/host/hci_raw.c +++ b/subsys/bluetooth/host/hci_raw.c @@ -40,8 +40,20 @@ static uint8_t raw_mode = BT_HCI_RAW_MODE_H4; static uint8_t raw_mode; #endif -NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, - BT_BUF_RX_SIZE, sizeof(struct bt_buf_data), NULL); +static bt_buf_rx_freed_cb_t buf_rx_freed_cb; + +static void hci_rx_buf_destroy(struct net_buf *buf) +{ + net_buf_destroy(buf); + + if (buf_rx_freed_cb) { + /* bt_buf_get_rx is used for all types of RX buffers */ + buf_rx_freed_cb(BT_BUF_EVT | BT_BUF_ACL_IN | BT_BUF_ISO_IN); + } +} + +NET_BUF_POOL_FIXED_DEFINE(hci_rx_pool, BT_BUF_RX_COUNT, BT_BUF_RX_SIZE, sizeof(struct bt_buf_data), + hci_rx_buf_destroy); NET_BUF_POOL_FIXED_DEFINE(hci_cmd_pool, CONFIG_BT_BUF_CMD_TX_COUNT, BT_BUF_CMD_SIZE(CONFIG_BT_BUF_CMD_TX_SIZE), sizeof(struct bt_buf_data), NULL); @@ -103,6 +115,11 @@ struct net_buf *bt_buf_get_rx(enum bt_buf_type type, k_timeout_t timeout) return buf; } +void bt_buf_rx_freed_cb_set(bt_buf_rx_freed_cb_t cb) +{ + buf_rx_freed_cb = cb; +} + struct net_buf *bt_buf_get_tx(enum bt_buf_type type, k_timeout_t timeout, const void *data, size_t size) { diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index 9c081bf2a98b..2bac55225cfc 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -35,9 +35,20 @@ LOG_MODULE_REGISTER(bt_iso); #define iso_chan(_iso) ((_iso)->iso.chan); #if defined(CONFIG_BT_ISO_RX) +static bt_iso_buf_rx_freed_cb_t buf_rx_freed_cb; + +static void iso_rx_buf_destroy(struct net_buf *buf) +{ + net_buf_destroy(buf); + + if (buf_rx_freed_cb) { + buf_rx_freed_cb(); + } +} + NET_BUF_POOL_FIXED_DEFINE(iso_rx_pool, CONFIG_BT_ISO_RX_BUF_COUNT, - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_RX_MTU), - sizeof(struct iso_data), NULL); + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_RX_MTU), sizeof(struct iso_data), + iso_rx_buf_destroy); static struct bt_iso_recv_info iso_info_data[CONFIG_BT_ISO_RX_BUF_COUNT]; #define iso_info(buf) (&iso_info_data[net_buf_id(buf)]) @@ -583,6 +594,11 @@ struct net_buf *bt_iso_get_rx(k_timeout_t timeout) return buf; } +void bt_iso_buf_rx_freed_cb_set(bt_iso_buf_rx_freed_cb_t cb) +{ + buf_rx_freed_cb = cb; +} + void bt_iso_recv(struct bt_conn *iso, struct net_buf *buf, uint8_t flags) { struct bt_hci_iso_data_hdr *hdr; diff --git a/subsys/bluetooth/host/iso_internal.h b/subsys/bluetooth/host/iso_internal.h index 10fc9409643f..f67121436a98 100644 --- a/subsys/bluetooth/host/iso_internal.h +++ b/subsys/bluetooth/host/iso_internal.h @@ -78,6 +78,16 @@ void hci_iso(struct net_buf *buf); /* Allocates RX buffer */ struct net_buf *bt_iso_get_rx(k_timeout_t timeout); +/** A callback used to notify about freed buffer in the iso rx pool. */ +typedef void (*bt_iso_buf_rx_freed_cb_t)(void); + +/** Set a callback to notify about freed buffer in the iso rx pool. + * + * @param cb Callback to notify about freed buffer in the iso rx pool. If NULL, the callback is + * disabled. + */ +void bt_iso_buf_rx_freed_cb_set(bt_iso_buf_rx_freed_cb_t cb); + /* Process CIS Established event */ void hci_le_cis_established(struct net_buf *buf); From 89fbc25b8a66134a76de99fef9cb3a48cab4c4f7 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Wed, 3 Apr 2024 14:35:36 +0200 Subject: [PATCH 5/8] tests: Bluetooth: Add common helpers for bsim This code can be found (kinda) duplicated all over `tests/bsim/bluetooth`. Put it in a common place. Refactoring the current tests will be done in a future commit. Signed-off-by: Jonathan Rico (cherry picked from commit 389192a94d208b5da18d2c350007eb903e916c56) Signed-off-by: Vinayak Kariappa Chettimada --- tests/bsim/babblekit/CMakeLists.txt | 19 +++ .../bsim/babblekit/include/babblekit/flags.h | 55 +++++++++ tests/bsim/babblekit/include/babblekit/sync.h | 43 +++++++ .../babblekit/include/babblekit/testcase.h | 112 ++++++++++++++++++ tests/bsim/babblekit/src/sync.c | 67 +++++++++++ 5 files changed, 296 insertions(+) create mode 100644 tests/bsim/babblekit/CMakeLists.txt create mode 100644 tests/bsim/babblekit/include/babblekit/flags.h create mode 100644 tests/bsim/babblekit/include/babblekit/sync.h create mode 100644 tests/bsim/babblekit/include/babblekit/testcase.h create mode 100644 tests/bsim/babblekit/src/sync.c diff --git a/tests/bsim/babblekit/CMakeLists.txt b/tests/bsim/babblekit/CMakeLists.txt new file mode 100644 index 000000000000..67fdbc8bd31f --- /dev/null +++ b/tests/bsim/babblekit/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Helpers that can be used on bsim targets but don't have other +# dependencies (e.g. on Bluetooth, etc). +add_library(babblekit) + +target_link_libraries(babblekit PUBLIC + kernel + zephyr_interface +) + +target_include_directories(babblekit PUBLIC + include +) + +target_sources(babblekit PRIVATE + src/sync.c +) diff --git a/tests/bsim/babblekit/include/babblekit/flags.h b/tests/bsim/babblekit/include/babblekit/flags.h new file mode 100644 index 000000000000..89c8b45ca3e9 --- /dev/null +++ b/tests/bsim/babblekit/include/babblekit/flags.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * Provides a way to set/clear and block on binary flags. + * + * These flags are often used to wait until the test has gotten in a particular + * state, e.g. a connection is established or a message has been successfully + * sent. + * + * These macros can only be called from Zephyr threads. They can't be called + * from e.g. a bs_tests callback. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Declare a flag that has been defined in another file */ +#define DECLARE_FLAG(flag) extern atomic_t flag + +/* Define a new binary flag. + * Declare them static if defining flags with the same name in multiple files. + * + * @param flag Name of the flag + */ +#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false + +#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) +#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) + +#define IS_FLAG_SET(flag) (atomic_get(&flag) != false) + +/* Block until `flag` is equal to `val` */ +#define WAIT_FOR_VAL(var, val) \ + while (atomic_get(&var) != val) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +/* Block until `flag` is true */ +#define WAIT_FOR_FLAG(flag) \ + while (!(bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +/* Block until `flag` is false */ +#define WAIT_FOR_FLAG_UNSET(flag) \ + while ((bool)atomic_get(&flag)) { \ + (void)k_sleep(K_MSEC(1)); \ + } + +/* Block until `flag` is true and set it to false */ +#define TAKE_FLAG(flag) \ + while (!(bool)atomic_cas(&flag, true, false)) { \ + (void)k_sleep(K_MSEC(1)); \ + } diff --git a/tests/bsim/babblekit/include/babblekit/sync.h b/tests/bsim/babblekit/include/babblekit/sync.h new file mode 100644 index 000000000000..d57538ac4d91 --- /dev/null +++ b/tests/bsim/babblekit/include/babblekit/sync.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file provides a synchronization mechanism between devices, for the + * simple use-case when there are only two devices in the simulation. + */ + + +/* + * @brief Initialize the sync library + * + * This initializes a simple synchronization library based on bsim backchannels. + * + * Calling `bk_sync_wait()` on device A will make it block until + * `bk_sync_send()` is called on device B. + * + * @note Only works between two devices in a simulation, with IDs 0 and 1. + * + * @retval 0 Sync channel operational + * @retval -1 Failed to open sync channel + * + */ +int bk_sync_init(void); + +/* + * @brief Send a synchronization packet + * + * @note Only works between two devices in a simulation, with IDs 0 and 1. + * + */ +void bk_sync_send(void); + +/* + * @brief Wait for a synchronization packet + * + * This blocks until the other device has called `bk_sync_send()`. + * + * @note Only works between two devices in a simulation, with IDs 0 and 1. + * + */ +void bk_sync_wait(void); diff --git a/tests/bsim/babblekit/include/babblekit/testcase.h b/tests/bsim/babblekit/include/babblekit/testcase.h new file mode 100644 index 000000000000..9d13a1a00300 --- /dev/null +++ b/tests/bsim/babblekit/include/babblekit/testcase.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_tracing.h" +#include "bs_types.h" +#include "bstests.h" + +extern enum bst_result_t bst_result; + +/* + * @brief Mark the test as in progress + * + * Call this at the start of the test entry point. + * + * @param ... format-string and arguments to print to console + * + */ +#define TEST_START(msg, ...) \ + do { \ + bst_result = In_progress; \ + bs_trace_info_time(2, "Test start: " msg "\n", ##__VA_ARGS__); \ + } while (0) + +/* + * @brief Fail the test and exit + * + * Printf-like function that also terminates the device with an error code. + * + * @param ... format-string and arguments to print to console + * + */ +#define TEST_FAIL(msg, ...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(msg "\n", ##__VA_ARGS__); \ + } while (0) + +/* + * @brief Mark the currently-running test as "Passed" + * + * Mark the test as "passed". The execution continues after that point. + * + * @note Use this if you use backchannels (testlib/bsim/sync.h). + * + * After calling this, the executable will eventually return 0 when it exits. + * Unless `TEST_FAIL` is called (e.g. in a callback). + * + * @param ... format-string and arguments to print to console + * + */ +#define TEST_PASS(msg, ...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(2, "Test end: " msg "\n", ##__VA_ARGS__); \ + } while (0) + +/* + * @brief Mark test case as passed and end execution + * + * Mark the role / test-case as "Passed" and return 0. + * + * @note DO NOT use this if you use backchannels (testlib/bsim/sync.h). + * + * @note This macro only ends execution for the current executable, not all + * executables in a simulation. + * + * @param ... format-string and arguments to print to console + * + */ +#define TEST_PASS_AND_EXIT(msg, ...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(2, "Test end: " msg "\n", ##__VA_ARGS__); \ + bs_trace_silent_exit(0); \ + } while (0) + +/* + * @brief Assert `expr` is true + * + * Assert that `expr` is true. If assertion is false, print a printf-like + * message to the console and fail the test. I.e. return non-zero. + * + * @note This is different than `sys/__assert.h`. + * + * @param message String to print to console + * + */ +#define TEST_ASSERT(expr, ...) \ + do { \ + if (!(expr)) { \ + TEST_FAIL(__VA_ARGS__); \ + } \ + } while (0) + +/* + * @brief Print a value. Lower-level than `printk` or `LOG_xx`. + * + * Print a message to console. + * + * This can be safely called at any time in the execution of the device. + * Use it to print when the logging subsystem is not available, e.g. early + * startup or shutdown. + * + * @param ... format-string and arguments to print to console + * + */ +#define TEST_PRINT(msg, ...) \ + bs_trace_print(BS_TRACE_INFO, __FILE__, __LINE__, 0, BS_TRACE_AUTOTIME, 0, \ + msg "\n", ##__VA_ARGS__) diff --git a/tests/bsim/babblekit/src/sync.c b/tests/bsim/babblekit/src/sync.c new file mode 100644 index 000000000000..6a2124200772 --- /dev/null +++ b/tests/bsim/babblekit/src/sync.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "argparse.h" +#include "bs_types.h" +#include "bs_tracing.h" +#include "time_machine.h" +#include "bs_pc_backchannel.h" + +#include +LOG_MODULE_REGISTER(sync, CONFIG_LOG_DEFAULT_LEVEL); + +#define CHANNEL_ID 0 +#define MSG_SIZE 1 + +int bk_sync_init(void) +{ + uint device_number = get_device_nbr(); + uint peer_number = device_number ^ 1; + uint device_numbers[] = { peer_number }; + uint channel_numbers[] = { CHANNEL_ID }; + uint *ch; + + ch = bs_open_back_channel(device_number, device_numbers, channel_numbers, + ARRAY_SIZE(channel_numbers)); + if (!ch) { + return -1; + } + + LOG_DBG("Sync initialized"); + + return 0; +} + +void bk_sync_send(void) +{ + uint8_t sync_msg[MSG_SIZE] = { get_device_nbr() }; + + LOG_DBG("Sending sync"); + bs_bc_send_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg)); +} + +void bk_sync_wait(void) +{ + uint8_t sync_msg[MSG_SIZE]; + + LOG_DBG("Waiting for sync"); + + while (true) { + if (bs_bc_is_msg_received(CHANNEL_ID) > 0) { + bs_bc_receive_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg)); + if (sync_msg[0] != get_device_nbr()) { + /* Received a message from another device, exit */ + break; + } + } + + k_sleep(K_MSEC(1)); + } + + LOG_DBG("Sync received"); +} From cd7559cf5217284f2c183cf85289beb0457cd0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20Reierstad?= Date: Mon, 10 Feb 2025 09:20:54 +0100 Subject: [PATCH 6/8] Bluetooth: tests: Add macros to babblekit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two macros to the babblekit library: * DEFINE_FLAG_STATIC * TEST_ASSERT_NO_MSG Signed-off-by: HÃ¥vard Reierstad (cherry picked from commit c2c4f2e0d110edaeb12c47a4a81f69a895d28a7d) Signed-off-by: Vinayak Kariappa Chettimada --- tests/bsim/babblekit/include/babblekit/flags.h | 8 +++++++- tests/bsim/babblekit/include/babblekit/testcase.h | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/bsim/babblekit/include/babblekit/flags.h b/tests/bsim/babblekit/include/babblekit/flags.h index 89c8b45ca3e9..a614e811309d 100644 --- a/tests/bsim/babblekit/include/babblekit/flags.h +++ b/tests/bsim/babblekit/include/babblekit/flags.h @@ -19,12 +19,18 @@ #define DECLARE_FLAG(flag) extern atomic_t flag /* Define a new binary flag. - * Declare them static if defining flags with the same name in multiple files. + * Use @ref DEFINE_FLAG_STATIC if defining flags with the same name in multiple files. * * @param flag Name of the flag */ #define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false +/* Define a new, static binary flag. + * + * @param flag Name of the flag + */ +#define DEFINE_FLAG_STATIC(flag) static atomic_t flag = (atomic_t) false + #define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true) #define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false) diff --git a/tests/bsim/babblekit/include/babblekit/testcase.h b/tests/bsim/babblekit/include/babblekit/testcase.h index 9d13a1a00300..0cbbb7562fff 100644 --- a/tests/bsim/babblekit/include/babblekit/testcase.h +++ b/tests/bsim/babblekit/include/babblekit/testcase.h @@ -95,6 +95,17 @@ extern enum bst_result_t bst_result; } \ } while (0) +/* + * @brief Assert `expr` is true + * + * Assert that `expr` is true. If assertion is false, fail the test. I.e. return non-zero. + * + * @note This is different than `sys/__assert.h`. + * + */ +#define TEST_ASSERT_NO_MSG(expr) \ + TEST_ASSERT(expr, "") + /* * @brief Print a value. Lower-level than `printk` or `LOG_xx`. * From 33fcfb822c2be30118e8d7cf53da6b7e33e50557 Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Tue, 18 Feb 2025 13:28:09 +0100 Subject: [PATCH 7/8] tests: bsim: bluetooth: host: add hci driver stress test This commit adds a stress test to verify that the HCI driver does not drop any data. Specifically, it tests whether the HCI IPC driver can reliably pass data between the Host and Controller. Due to the current HCI IPC driver implementation, this test is guaranteed to fail if Controller-to-Host HCI ACL data flow control is disabled. Signed-off-by: Pavel Vasilyev (cherry picked from commit a43b893a153508c0b9fbfba13afd6be630fc89e5) Signed-off-by: Vinayak Kariappa Chettimada --- .../host/gatt/notify_stress/CMakeLists.txt | 17 + .../host/gatt/notify_stress/Kconfig.sysbuild | 14 + .../nrf5340_cpunet-bt_ll_sw_split.conf | 30 ++ .../host/gatt/notify_stress/prj.conf | 35 ++ .../host/gatt/notify_stress/src/common.h | 21 ++ .../gatt/notify_stress/src/gatt_client_test.c | 317 ++++++++++++++++++ .../gatt/notify_stress/src/gatt_server_test.c | 193 +++++++++++ .../host/gatt/notify_stress/src/main.c | 22 ++ .../host/gatt/notify_stress/sysbuild.cmake | 19 ++ .../notify_stress/test_scripts/run_test.sh | 55 +++ .../host/gatt/notify_stress/testcase.yaml | 12 + 11 files changed, 735 insertions(+) create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/CMakeLists.txt create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/src/common.h create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/src/main.c create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/sysbuild.cmake create mode 100755 tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh create mode 100644 tests/bsim/bluetooth/host/gatt/notify_stress/testcase.yaml diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/CMakeLists.txt b/tests/bsim/bluetooth/host/gatt/notify_stress/CMakeLists.txt new file mode 100644 index 000000000000..b279e8c14396 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bsim_test_gatt) + +add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit) +target_link_libraries(app PRIVATE babblekit) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources} ) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild b/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild new file mode 100644 index 000000000000..79d8f9919609 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild @@ -0,0 +1,14 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf b/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf new file mode 100644 index 000000000000..853adc082dac --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf @@ -0,0 +1,30 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 +CONFIG_HEAP_MEM_POOL_SIZE=4096 +CONFIG_CBPRINTF_REDUCED_INTEGRAL=y +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=1 + +# Controller +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ASSERT_HANDLER=y + +CONFIG_BT_CTLR_DATA_LENGTH_MAX=70 +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 +CONFIG_BT_CTLR_RX_BUFFERS=10 + +CONFIG_BT_BUF_CMD_TX_SIZE=65 +CONFIG_BT_BUF_EVT_RX_SIZE=68 +CONFIG_BT_BUF_EVT_RX_COUNT=17 +CONFIG_BT_BUF_ACL_TX_COUNT=16 +CONFIG_BT_BUF_ACL_TX_SIZE=70 +CONFIG_BT_BUF_ACL_RX_SIZE=70 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf b/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf new file mode 100644 index 000000000000..5e04334eecc4 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf @@ -0,0 +1,35 @@ +CONFIG_BT=y +CONFIG_BT_DEVICE_NAME="GATT tester" +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_GATT_CLIENT=y + +CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y + +CONFIG_BT_SMP=y +CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BT_L2CAP_ECRED=y +CONFIG_BT_EATT=y + +CONFIG_BT_AUTO_PHY_UPDATE=n +CONFIG_BT_AUTO_DATA_LEN_UPDATE=n + +CONFIG_ASSERT=y +CONFIG_BT_TESTING=y +CONFIG_LOG=y + +# Maximum possible EATT channels are used to parallelize notifications as much as possible, +# increasing traffic towards Central. +CONFIG_BT_EATT_MAX=16 + +# This is aligned with CONFIG_BT_EATT_MAX to utilize all EATT channels +CONFIG_BT_BUF_ACL_TX_COUNT=16 + +# Aligned with characteristic size +CONFIG_BT_BUF_ACL_RX_SIZE=70 +CONFIG_BT_BUF_ACL_TX_SIZE=70 + +CONFIG_BT_BUF_EVT_RX_COUNT=17 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 + +CONFIG_BT_BUF_CMD_TX_COUNT=2 diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/src/common.h b/tests/bsim/bluetooth/host/gatt/notify_stress/src/common.h new file mode 100644 index 000000000000..4258969f4dae --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/src/common.h @@ -0,0 +1,21 @@ +/** + * Common macros used by both sides of the test + * + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define CHRC_SIZE 60 + +#define TEST_SERVICE_UUID \ + BT_UUID_DECLARE_128(0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, \ + 0x07, 0x08, 0x09, 0x00, 0x00) + +#define TEST_CHRC_UUID \ + BT_UUID_DECLARE_128(0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, \ + 0x07, 0x08, 0x09, 0xFF, 0x11) + +#define NOTIFICATION_COUNT 30 diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c new file mode 100644 index 000000000000..bd866ec254d1 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "babblekit/testcase.h" +#include "babblekit/flags.h" +#include "common.h" + +DEFINE_FLAG_STATIC(flag_is_connected); +DEFINE_FLAG_STATIC(flag_is_encrypted); +DEFINE_FLAG_STATIC(flag_discover_complete); +DEFINE_FLAG_STATIC(flag_long_subscribed); + +static struct bt_conn *g_conn; +static uint16_t long_chrc_handle; +static const struct bt_uuid *test_svc_uuid = TEST_SERVICE_UUID; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + TEST_FAIL("Failed to connect to %s (%u)", addr, err); + return; + } + + printk("Connected to %s\n", addr); + + SET_FLAG(flag_is_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != g_conn) { + return; + } + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(g_conn); + + g_conn = NULL; + UNSET_FLAG(flag_is_connected); +} + +void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + if (err) { + TEST_FAIL("Encryption failure (%d)", err); + } else if (level < BT_SECURITY_L2) { + TEST_FAIL("Insufficient sec level (%d)", level); + } else { + SET_FLAG(flag_is_encrypted); + } +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed, +}; + +void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + int err; + + if (g_conn != NULL) { + return; + } + + /* We're only interested in connectable events */ + if (type != BT_HCI_ADV_IND && type != BT_HCI_ADV_DIRECT_IND) { + return; + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + printk("Device found: %s (RSSI %d)\n", addr_str, rssi); + + printk("Stopping scan\n"); + err = bt_le_scan_stop(); + if (err != 0) { + TEST_FAIL("Could not stop scan: %d"); + return; + } + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn); + if (err != 0) { + TEST_FAIL("Could not connect to peer: %d", err); + } +} + +static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr, + struct bt_gatt_discover_params *params) +{ + int err; + + if (attr == NULL) { + if (long_chrc_handle == 0) { + TEST_FAIL("Did not discover long_chrc (%x)", long_chrc_handle); + } + + (void)memset(params, 0, sizeof(*params)); + + SET_FLAG(flag_discover_complete); + + return BT_GATT_ITER_STOP; + } + + printk("[ATTRIBUTE] handle %u\n", attr->handle); + + if (params->type == BT_GATT_DISCOVER_PRIMARY && + bt_uuid_cmp(params->uuid, TEST_SERVICE_UUID) == 0) { + printk("Found test service\n"); + params->uuid = NULL; + params->start_handle = attr->handle + 1; + params->type = BT_GATT_DISCOVER_CHARACTERISTIC; + + err = bt_gatt_discover(conn, params); + if (err != 0) { + TEST_FAIL("Discover failed (err %d)", err); + } + + return BT_GATT_ITER_STOP; + } else if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC) { + const struct bt_gatt_chrc *chrc = (struct bt_gatt_chrc *)attr->user_data; + + if (bt_uuid_cmp(chrc->uuid, TEST_CHRC_UUID) == 0) { + printk("Found long_chrc\n"); + long_chrc_handle = chrc->value_handle; + } + } + + return BT_GATT_ITER_CONTINUE; +} + +static void gatt_discover(enum bt_att_chan_opt opt) +{ + static struct bt_gatt_discover_params discover_params; + int err; + + printk("Discovering services and characteristics\n"); + + discover_params.uuid = test_svc_uuid; + discover_params.func = discover_func; + discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + discover_params.type = BT_GATT_DISCOVER_PRIMARY; + discover_params.chan_opt = opt; + + err = bt_gatt_discover(g_conn, &discover_params); + if (err != 0) { + TEST_FAIL("Discover failed(err %d)", err); + } + + WAIT_FOR_FLAG(flag_discover_complete); + printk("Discover complete\n"); +} + +static void test_long_subscribed(struct bt_conn *conn, uint8_t err, + struct bt_gatt_subscribe_params *params) +{ + if (err) { + TEST_FAIL("Subscribe failed (err %d)", err); + } + + SET_FLAG(flag_long_subscribed); + + if (!params) { + printk("params NULL\n"); + return; + } + + if (params->value_handle == long_chrc_handle) { + printk("Subscribed to long characteristic\n"); + } else { + TEST_FAIL("Unknown handle %d", params->value_handle); + } +} + +static volatile size_t num_notifications; +uint8_t test_notify(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, const void *data, + uint16_t length) +{ + printk("Received notification #%u with length %d\n", num_notifications++, length); + + /* This causes ACL data drop in HCI IPC driver. */ + k_sleep(K_MSEC(1000)); + + return BT_GATT_ITER_CONTINUE; +} + +static struct bt_gatt_discover_params disc_params_long; +static struct bt_gatt_subscribe_params sub_params_long = { + .notify = test_notify, + .subscribe = test_long_subscribed, + .ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE, + .disc_params = &disc_params_long, + .end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE, + .value = BT_GATT_CCC_NOTIFY, +}; + +static void gatt_subscribe_long(enum bt_att_chan_opt opt) +{ + int err; + + UNSET_FLAG(flag_long_subscribed); + sub_params_long.value_handle = long_chrc_handle; + sub_params_long.chan_opt = opt; + err = bt_gatt_subscribe(g_conn, &sub_params_long); + if (err < 0) { + TEST_FAIL("Failed to subscribe"); + } else { + printk("Subscribe request sent\n"); + } +} + +static void gatt_unsubscribe_long(enum bt_att_chan_opt opt) +{ + int err; + + UNSET_FLAG(flag_long_subscribed); + sub_params_long.value_handle = long_chrc_handle; + sub_params_long.chan_opt = opt; + err = bt_gatt_unsubscribe(g_conn, &sub_params_long); + if (err < 0) { + TEST_FAIL("Failed to unsubscribe"); + } else { + printk("Unsubscribe request sent\n"); + } +} + +static void setup(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + TEST_FAIL("Bluetooth discover failed (err %d)", err); + } + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + if (err != 0) { + TEST_FAIL("Scanning failed to start (err %d)", err); + } + + printk("Scanning successfully started\n"); + + WAIT_FOR_FLAG(flag_is_connected); + + err = bt_conn_set_security(g_conn, BT_SECURITY_L2); + if (err) { + TEST_FAIL("Starting encryption procedure failed (%d)", err); + } + + WAIT_FOR_FLAG(flag_is_encrypted); + + while (bt_eatt_count(g_conn) < CONFIG_BT_EATT_MAX) { + k_sleep(K_MSEC(10)); + } + + printk("EATT connected\n"); +} + +static void test_main_client(void) +{ + setup(); + + gatt_discover(BT_ATT_CHAN_OPT_ENHANCED_ONLY); + gatt_subscribe_long(BT_ATT_CHAN_OPT_ENHANCED_ONLY); + WAIT_FOR_FLAG(flag_long_subscribed); + + printk("Subscribed\n"); + + while (num_notifications < NOTIFICATION_COUNT) { + k_sleep(K_MSEC(100)); + } + + gatt_unsubscribe_long(BT_ATT_CHAN_OPT_ENHANCED_ONLY); + WAIT_FOR_FLAG(flag_long_subscribed); + + printk("Unsubscribed\n"); + + TEST_PASS("GATT client Passed"); +} + +static const struct bst_test_instance test_vcs[] = { + { + .test_id = "gatt_client_enhanced_notif_stress", + .test_main_f = test_main_client, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_gatt_client_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_vcs); +} diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c new file mode 100644 index 000000000000..cde37821c330 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "babblekit/testcase.h" +#include "babblekit/flags.h" +#include "common.h" + +extern enum bst_result_t bst_result; + +DEFINE_FLAG_STATIC(flag_is_connected); +DEFINE_FLAG_STATIC(flag_subscribe); + +static struct bt_conn *g_conn; + +#define ARRAY_ITEM(i, _) i +const uint8_t chrc_data[] = { LISTIFY(CHRC_SIZE, ARRAY_ITEM, (,)) }; /* 1, 2, 3 ... */ + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + TEST_FAIL("Failed to connect to %s (%u)", addr, err); + return; + } + + printk("Connected to %s\n", addr); + + g_conn = bt_conn_ref(conn); + SET_FLAG(flag_is_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != g_conn) { + return; + } + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(g_conn); + + g_conn = NULL; + UNSET_FLAG(flag_is_connected); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +static ssize_t read_test_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, + uint16_t len, uint16_t offset) +{ + printk("Read char\n"); + return bt_gatt_attr_read(conn, attr, buf, len, offset, (void *)chrc_data, + sizeof(chrc_data)); +} + +static void subscribe(const struct bt_gatt_attr *attr, uint16_t value) +{ + const bool notif_enabled = (value == BT_GATT_CCC_NOTIFY); + + if (notif_enabled) { + SET_FLAG(flag_subscribe); + } + + printk("Notifications %s\n", notif_enabled ? "enabled" : "disabled"); +} + +BT_GATT_SERVICE_DEFINE(test_svc, BT_GATT_PRIMARY_SERVICE(TEST_SERVICE_UUID), + BT_GATT_CHARACTERISTIC(TEST_CHRC_UUID, + BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_READ, + BT_GATT_PERM_READ, read_test_chrc, NULL, NULL), + BT_GATT_CCC(subscribe, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)); + +static volatile size_t num_notifications_sent; + +static void notification_sent(struct bt_conn *conn, void *user_data) +{ + size_t *length = user_data; + + printk("Sent notification #%u with length %d\n", num_notifications_sent++, *length); +} + +static void notify(void) +{ + static size_t length = CHRC_SIZE; + static struct bt_gatt_notify_params params = { + .attr = &attr_test_svc[1], + .data = chrc_data, + .len = CHRC_SIZE, + .func = notification_sent, + .user_data = &length, + .uuid = NULL, + .chan_opt = BT_ATT_CHAN_OPT_ENHANCED_ONLY, + }; + int err; + + do { + err = bt_gatt_notify_cb(g_conn, ¶ms); + + if (err == -ENOMEM) { + /* The delay is needed to schedule other threads, but keep it as short as + * possible. + */ + k_sleep(K_MSEC(1)); + } else if (err) { + TEST_FAIL("Notify failed (err %d)", err); + } + } while (err); +} + +static void setup(void) +{ + int err; + const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + }; + + err = bt_enable(NULL); + if (err != 0) { + TEST_FAIL("Bluetooth init failed (err %d)", err); + return; + } + + printk("Bluetooth initialized\n"); + + err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0); + if (err != 0) { + TEST_FAIL("Advertising failed to start (err %d)", err); + return; + } + + printk("Advertising successfully started\n"); + + WAIT_FOR_FLAG(flag_is_connected); + + while (bt_eatt_count(g_conn) < CONFIG_BT_EATT_MAX) { + k_sleep(K_MSEC(100)); + } + printk("EATT connected\n"); + + WAIT_FOR_FLAG(flag_subscribe); +} + +static void test_main_server(void) +{ + setup(); + + for (int i = 0; i < NOTIFICATION_COUNT; i++) { + notify(); + } + + while (num_notifications_sent < NOTIFICATION_COUNT) { + k_sleep(K_MSEC(100)); + } + + TEST_PASS("GATT server passed"); +} + +static const struct bst_test_instance test_gatt_server[] = { + { + .test_id = "gatt_server_enhanced_notif_stress", + .test_main_f = test_main_server, + }, + BSTEST_END_MARKER, +}; + +struct bst_test_list *test_gatt_server_install(struct bst_test_list *tests) +{ + return bst_add_tests(tests, test_gatt_server); +} diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/src/main.c b/tests/bsim/bluetooth/host/gatt/notify_stress/src/main.c new file mode 100644 index 000000000000..14ee71fd4d24 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_gatt_server_install(struct bst_test_list *tests); +extern struct bst_test_list *test_gatt_client_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_gatt_server_install, + test_gatt_client_install, + NULL +}; + +int main(void) +{ + bst_main(); + return 0; +} diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/sysbuild.cmake b/tests/bsim/bluetooth/host/gatt/notify_stress/sysbuild.cmake new file mode 100644 index 000000000000..2ef52ac6f612 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/sysbuild.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE ${APP_DIR}/nrf5340_cpunet-bt_ll_sw_split.conf CACHE INTERNAL "") + + native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh new file mode 100755 index 000000000000..489bea278afd --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Test purpose: +# +# Verify that the Central can receive 30 notifications from the Peripheral over all available EATT +# channels. +# +# Note: The number of notifications and the size of the characteristic are chosen empirically. +# +# This test is designed to stress HCI driver to guarantee that no data is dropped between Host and +# Controller. Specifically, the HCI IPC driver that tends to drop data when the Host is not able to +# process it fast enough. The test is guaranteed to fail with Controller to Host HCI data flow +# control being disabled. +# +# Test Setup: +# +# - Devices: Central and Peripheral +# - Characteristic Length: Peripheral exposes a long characteristic (greater than 23 bytes). +# - Connection: Central connects to Peripheral. +# - Notification subscription: Central subscribes to notificaitons from the Peripheral. +# - EATT Usage: EATT is enabled, and the maximum possible EATT channels are established to +# parallelize notifications as much as possible, increasing traffic towards Central. +# +# Test Steps: +# +# 1. The Peripheral sends 30 notifications to the Central over all available EATT channels. +# 2. Upon receiving a notification, the Central holds the received notification callback for 1 +# second before releasing it. +# 3. The test passes if all 30 notifications are successfully sent by the Peripheral and received +# by the Central. + +set -eu + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +EXECUTE_TIMEOUT=150 + +verbosity_level=2 +simulation_id="gatt_notify_enhanced_stress" +server_id="gatt_server_enhanced_notif_stress" +client_id="gatt_client_enhanced_notif_stress" + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=${client_id} -RealEncryption=1 + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=${server_id} -RealEncryption=1 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} -D=2 -sim_length=70e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/testcase.yaml b/tests/bsim/bluetooth/host/gatt/notify_stress/testcase.yaml new file mode 100644 index 000000000000..ead6f5effdd8 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/testcase.yaml @@ -0,0 +1,12 @@ +tests: + bluetooth.host.gatt.notify_stress: + build_only: true + sysbuild: true + tags: + - bluetooth + platform_allow: + - nrf52_bsim/native + - nrf5340bsim/nrf5340/cpuapp + harness: bsim + harness_config: + bsim_exe_name: tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf From 72b6ee72c00bbd67c42945f4a93bc06d9e7b7f5b Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 10 Nov 2025 14:40:04 +0100 Subject: [PATCH 8/8] tests: bsim: Bluetooth: Host: Port gatt notify_stress test Port GATT notify_stress test. Signed-off-by: Vinayak Kariappa Chettimada --- tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh | 2 ++ tests/bsim/bluetooth/host/compile.sh | 1 + .../bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild | 4 ++-- .../gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf | 2 +- tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf | 6 ++++++ .../host/gatt/notify_stress/src/gatt_client_test.c | 2 +- .../host/gatt/notify_stress/src/gatt_server_test.c | 2 +- .../host/gatt/notify_stress/test_scripts/run_test.sh | 4 ++-- 8 files changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh index 65769185867f..e7b14cbba416 100755 --- a/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh +++ b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh @@ -19,6 +19,8 @@ mkdir -p ${WORK_DIR} source ${ZEPHYR_BASE}/tests/bsim/compile.source +app=tests/bsim/bluetooth/host/gatt/notify_stress sysbuild=1 compile + app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_privacy.conf sysbuild=1 compile app=tests/bsim/bluetooth/ll/bis sysbuild=1 compile app=tests/bsim/bluetooth/ll/cis conf_overlay=overlay-acl_group.conf sysbuild=1 compile diff --git a/tests/bsim/bluetooth/host/compile.sh b/tests/bsim/bluetooth/host/compile.sh index 098c983d75f6..2f2c32749973 100755 --- a/tests/bsim/bluetooth/host/compile.sh +++ b/tests/bsim/bluetooth/host/compile.sh @@ -45,6 +45,7 @@ app=tests/bsim/bluetooth/host/gatt/authorization compile app=tests/bsim/bluetooth/host/gatt/caching compile app=tests/bsim/bluetooth/host/gatt/general compile app=tests/bsim/bluetooth/host/gatt/notify compile +app=tests/bsim/bluetooth/host/gatt/notify_stress compile app=tests/bsim/bluetooth/host/gatt/notify_multiple compile app=tests/bsim/bluetooth/host/gatt/settings compile app=tests/bsim/bluetooth/host/gatt/settings conf_file=prj_2.conf compile diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild b/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild index 79d8f9919609..7b30da2f0a2e 100644 --- a/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/Kconfig.sysbuild @@ -5,10 +5,10 @@ source "share/sysbuild/Kconfig" config NET_CORE_BOARD string - default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + default "nrf5340bsim_nrf5340_cpunet" if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX int # Let's pass the test arguments to the application MCU test # otherwise by default they would have gone to the net core. - default 0 if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp" diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf b/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf index 853adc082dac..69b946201e96 100644 --- a/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/nrf5340_cpunet-bt_ll_sw_split.conf @@ -14,7 +14,7 @@ CONFIG_BT_HCI_RAW=y CONFIG_BT_MAX_CONN=1 # Controller -CONFIG_BT_LL_SW_SPLIT=y +# CONFIG_BT_LL_SW_SPLIT=y CONFIG_BT_CTLR_ASSERT_HANDLER=y CONFIG_BT_CTLR_DATA_LENGTH_MAX=70 diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf b/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf index 5e04334eecc4..8b5ca4899aa9 100644 --- a/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/prj.conf @@ -14,6 +14,9 @@ CONFIG_BT_EATT=y CONFIG_BT_AUTO_PHY_UPDATE=n CONFIG_BT_AUTO_DATA_LEN_UPDATE=n +# Zephyr Controller has bug, connection update fails with instant passed under high throughput +CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n + CONFIG_ASSERT=y CONFIG_BT_TESTING=y CONFIG_LOG=y @@ -33,3 +36,6 @@ CONFIG_BT_BUF_EVT_RX_COUNT=17 CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 CONFIG_BT_BUF_CMD_TX_COUNT=2 + +# Explicitly use Zephyr Controller, defaults to SDC in nRFConnect SDK +# CONFIG_BT_LL_SW_SPLIT=y diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c index bd866ec254d1..d298e0940d8e 100644 --- a/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_client_test.c @@ -213,7 +213,7 @@ static struct bt_gatt_discover_params disc_params_long; static struct bt_gatt_subscribe_params sub_params_long = { .notify = test_notify, .subscribe = test_long_subscribed, - .ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE, + .ccc_handle = 0x0000, .disc_params = &disc_params_long, .end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE, .value = BT_GATT_CCC_NOTIFY, diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c index cde37821c330..4046deb60011 100644 --- a/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/src/gatt_server_test.c @@ -146,7 +146,7 @@ static void setup(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); if (err != 0) { TEST_FAIL("Advertising failed to start (err %d)", err); return; diff --git a/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh b/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh index 489bea278afd..61096ae50e7a 100755 --- a/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh +++ b/tests/bsim/bluetooth/host/gatt/notify_stress/test_scripts/run_test.sh @@ -44,10 +44,10 @@ client_id="gatt_client_enhanced_notif_stress" cd ${BSIM_OUT_PATH}/bin -Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf \ +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf \ -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=${client_id} -RealEncryption=1 -Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf \ +Execute ./bs_${BOARD}_tests_bsim_bluetooth_host_gatt_notify_stress_prj_conf \ -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=${server_id} -RealEncryption=1 Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} -D=2 -sim_length=70e6 $@