From f2e11a6cbc8d4b4125e96c1fbc9fc6d7010e05b5 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 4 Jul 2025 14:16:13 +0200 Subject: [PATCH 1/4] Bluetooth: Controller: Remove duplicate define CONN_DATA_BUFFERS Remove duplicate define CONN_DATA_BUFFERS and use CONFIG_BT_BUF_ACL_TX_COUNT instead. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index fa4eb269e7b20..809f0ded8c082 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -127,23 +127,18 @@ static uint8_t force_md_cnt_calc(struct lll_conn *lll_conn, uint32_t tx_rate); (LL_LENGTH_OCTETS_TX_MAX + \ BT_CTLR_USER_TX_BUFFER_OVERHEAD)) -#define CONN_DATA_BUFFERS CONFIG_BT_BUF_ACL_TX_COUNT - -static MFIFO_DEFINE(conn_tx, sizeof(struct lll_tx), CONN_DATA_BUFFERS); +static MFIFO_DEFINE(conn_tx, sizeof(struct lll_tx), CONFIG_BT_BUF_ACL_TX_COUNT); static MFIFO_DEFINE(conn_ack, sizeof(struct lll_tx), - (CONN_DATA_BUFFERS + - LLCP_TX_CTRL_BUF_COUNT)); + (CONFIG_BT_BUF_ACL_TX_COUNT + LLCP_TX_CTRL_BUF_COUNT)); static struct { void *free; - uint8_t pool[CONN_TX_BUF_SIZE * CONN_DATA_BUFFERS]; + uint8_t pool[CONN_TX_BUF_SIZE * CONFIG_BT_BUF_ACL_TX_COUNT]; } mem_conn_tx; static struct { void *free; - uint8_t pool[sizeof(memq_link_t) * - (CONN_DATA_BUFFERS + - LLCP_TX_CTRL_BUF_COUNT)]; + uint8_t pool[sizeof(memq_link_t) * (CONFIG_BT_BUF_ACL_TX_COUNT + LLCP_TX_CTRL_BUF_COUNT)]; } mem_link_tx; #if defined(CONFIG_BT_CTLR_DATA_LENGTH) @@ -1693,14 +1688,11 @@ static int init_reset(void) } /* Initialize tx pool. */ - mem_init(mem_conn_tx.pool, CONN_TX_BUF_SIZE, CONN_DATA_BUFFERS, - &mem_conn_tx.free); + mem_init(mem_conn_tx.pool, CONN_TX_BUF_SIZE, CONFIG_BT_BUF_ACL_TX_COUNT, &mem_conn_tx.free); /* Initialize tx link pool. */ mem_init(mem_link_tx.pool, sizeof(memq_link_t), - (CONN_DATA_BUFFERS + - LLCP_TX_CTRL_BUF_COUNT), - &mem_link_tx.free); + (CONFIG_BT_BUF_ACL_TX_COUNT + LLCP_TX_CTRL_BUF_COUNT), &mem_link_tx.free); /* Initialize control procedure system. */ ull_cp_init(); From 3b15397f3196e3d5c0b79857caad2cab51c03ab4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 4 Jul 2025 14:16:23 +0200 Subject: [PATCH 2/4] tests: bsim: Bluetooth: Add param update to throughput test Add connection parameter update to throughput test to cover any connection timeout performing connection update while subjected to high throughput scenarios. Signed-off-by: Vinayak Kariappa Chettimada --- .../src/gatt_write_common.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/samples/bluetooth/central_gatt_write/src/gatt_write_common.c b/samples/bluetooth/central_gatt_write/src/gatt_write_common.c index 99d2e830aea90..3dfed916f913a 100644 --- a/samples/bluetooth/central_gatt_write/src/gatt_write_common.c +++ b/samples/bluetooth/central_gatt_write/src/gatt_write_common.c @@ -17,6 +17,10 @@ static uint32_t phy_update_countdown; static uint8_t phy_param_idx; +/* Count down number of metrics intervals before performing a param update */ +#define PARAM_UPDATE_COUNTDOWN PHY_UPDATE_COUNTDOWN +static uint32_t param_update_countdown; + static void phy_update_iterate(struct bt_conn *conn) { const struct bt_conn_le_phy_param phy_param[] = { @@ -178,6 +182,34 @@ static void write_cmd_cb(struct bt_conn *conn, void *user_data) phy_update_iterate(conn); } + const struct bt_le_conn_param update_params[2] = {{ + .interval_min = 0x0029, + .interval_max = 0x0029, + .latency = 0, + .timeout = 31, + }, { + .interval_min = 0x0028, + .interval_max = 0x0028, + .latency = 0, + .timeout = 30, + }, + }; + static uint8_t param_update_count; + int err; + + if ((param_update_countdown--) != 0U) { + return; + } + + param_update_countdown = PARAM_UPDATE_COUNTDOWN; + + err = bt_conn_le_param_update(conn, &update_params[param_update_count & 0x1]); + if (err != 0) { + printk("Parameter update failed (err %d)\n", err); + } + + param_update_count++; + } else { uint16_t len; @@ -256,6 +288,14 @@ static void connected(struct bt_conn *conn, uint8_t conn_err) phy_update_countdown = PHY_UPDATE_COUNTDOWN; phy_param_idx = 0U; } + + /* Every 1 second the acknowledged total GATT Write without Response data size is used for + * the throughput calculation. + * PHY update is performed in reference to this calculation interval, and connection update + * is offset by 1 of this interval so that connection update is initiated one such interval + * after PHY update was requested. + */ + param_update_countdown = PARAM_UPDATE_COUNTDOWN + 1U; } static void disconnected(struct bt_conn *conn, uint8_t reason) From 8c72e60fcca613571acae770e9e009876b3e5aee Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 4 Jul 2025 14:16:27 +0200 Subject: [PATCH 3/4] tests: bsim: Bluetooth: Fail throughput test with increased Tx count Make the throughput test to fail when increasing Tx buffers that will delay a LE Connection Ind PDU from being transmitted on air due to previously queued Data PDUs. Unlike legacy Zephyr Controller's double headed Tx queue linked list, the new split Zephyr Controller's new LLCP does not place a control PDU at the head of the queue causing control PDUs to be delayed on air. Signed-off-by: Vinayak Kariappa Chettimada --- tests/bsim/bluetooth/ll/throughput/prj.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bsim/bluetooth/ll/throughput/prj.conf b/tests/bsim/bluetooth/ll/throughput/prj.conf index e8848bbf25dbd..2306711e7141a 100644 --- a/tests/bsim/bluetooth/ll/throughput/prj.conf +++ b/tests/bsim/bluetooth/ll/throughput/prj.conf @@ -24,7 +24,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 # BT HCI Event Buffers # Greater than BT_BUF_ACL_TX_COUNT, to be able to receive Number of Completed Packets events -CONFIG_BT_BUF_EVT_RX_COUNT=4 +CONFIG_BT_BUF_EVT_RX_COUNT=7 CONFIG_BT_BUF_EVT_RX_SIZE=255 # BT HCI Discardable Event Buffers @@ -32,7 +32,7 @@ CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=3 CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 # BT HCI ACL TX Data Buffers -CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_COUNT=6 CONFIG_BT_BUF_ACL_TX_SIZE=251 # BT HCI ACL RX Data Buffers From a3347a3ba6e35e1816704eac58f882b89e4757a2 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 4 Jul 2025 14:16:38 +0200 Subject: [PATCH 4/4] Bluetooth: Controller: Fix conn timeout due to delayed conn upd ind Unlike legacy Zephyr Controller's double headed Tx queue linked list, the new split Zephyr Controller's new LLCP does not place a control PDU at the head of the Tx queue causing control PDUs to be delayed on air. Pause the data enqueue until pending PDUs are transmitted across before enqueuing LE Connection Update Ind PDU, and thereafter resume other PDUs being enqueued again. There can still be connection timeout if enqueued PDUs are not being transmitted/acked during repeated retransmissions. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 15 +++++++++++++++ .../controller/ll_sw/ull_conn_internal.h | 1 + .../controller/ll_sw/ull_llcp_conn_upd.c | 6 +++++- .../controller/ll_sw/ull_llcp_internal.h | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 809f0ded8c082..a9c1668afe665 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1478,6 +1478,21 @@ void ull_conn_tx_lll_enqueue(struct ll_conn *conn, uint8_t count) } } +uint16_t ull_conn_tx_enqueue_count_get(struct ll_conn *conn) +{ + uint16_t count = 0; + memq_link_t *curr; + + curr = memq_peek(conn->lll.memq_tx.head, conn->lll.memq_tx.tail, NULL); + while (curr != NULL) { + count++; + + curr = memq_peek(curr->next, conn->lll.memq_tx.tail, NULL); + } + + return count; +} + void ull_conn_link_tx_release(void *link) { mem_release(link, &mem_link_tx.free); diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index dad6d5e29e0e1..0b03369b55587 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -31,6 +31,7 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, void ull_conn_done(struct node_rx_event_done *done); void ull_conn_tx_demux(uint8_t count); void ull_conn_tx_lll_enqueue(struct ll_conn *conn, uint8_t count); +uint16_t ull_conn_tx_enqueue_count_get(struct ll_conn *conn); void ull_conn_link_tx_release(void *link); uint8_t ull_conn_ack_last_idx_get(void); memq_link_t *ull_conn_ack_peek(uint8_t *ack_last, uint16_t *handle, diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index b107371dc77ff..b16d72a74b7f9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -438,7 +438,9 @@ static void lp_cu_send_conn_update_ind_finalize(struct ll_conn *conn, struct pro static void lp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) { - if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx)) { + if (llcp_lr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx) || + ull_conn_tx_enqueue_count_get(conn) != 0U) { + llcp_tx_pause_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_CONN_UPD); ctx->state = LP_CU_STATE_WAIT_TX_CONN_UPDATE_IND; } else { /* ensure alloc of TX node, before possibly waiting for NTF node */ @@ -448,6 +450,7 @@ static void lp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ct ctx->state = LP_CU_STATE_WAIT_NTF_AVAIL; } else { lp_cu_send_conn_update_ind_finalize(conn, ctx, evt, param); + llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_CONN_UPD); } } } @@ -459,6 +462,7 @@ static void lp_cu_st_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ctx, case LP_CU_EVT_RUN: if (llcp_ntf_alloc_is_available()) { lp_cu_send_conn_update_ind_finalize(conn, ctx, evt, param); + llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_CONN_UPD); } break; default: diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 446d78aeadb73..8c50558a08e1f 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -47,6 +47,7 @@ enum llcp_tx_q_pause_data_mask { LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE = 0x02, LLCP_TX_QUEUE_PAUSE_DATA_DATA_LENGTH = 0x04, LLCP_TX_QUEUE_PAUSE_DATA_TERMINATE = 0x08, + LLCP_TX_QUEUE_PAUSE_DATA_CONN_UPD = 0x10, }; #if ((CONFIG_BT_CTLR_LLCP_COMMON_TX_CTRL_BUF_NUM <\