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) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index fa4eb269e7b20..a9c1668afe665 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) @@ -1483,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); @@ -1693,14 +1703,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(); 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 <\ 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