From e4fe7435d737c0bda80324b0eb4c402f083d020d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 16 Sep 2020 15:21:50 +0530 Subject: [PATCH] Bluetooth: controller: Added Force MD bit automatic feature Added automatic runtime calculation of Forced MD bit count based on incoming Tx buffer throughput. Signed-off-by: Vinayak Kariappa Chettimada --- .../bluetooth/controller/Kconfig.ll_sw_split | 11 +++- subsys/bluetooth/controller/ll_sw/lll_conn.h | 4 +- .../controller/ll_sw/nordic/lll/lll_conn.c | 20 +++++- subsys/bluetooth/controller/ll_sw/ull_conn.c | 61 +++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index e2598110617..cbd6b525868 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -391,8 +391,9 @@ config BT_CTLR_THROUGHPUT Measure incoming Tx throughput and log the results. config BT_CTLR_FORCE_MD_COUNT - int "Forced MD bit count" + int "Forced MD bit count" if !BT_CTLR_FORCE_MD_AUTO range 0 255 + default 1 if BT_CTLR_FORCE_MD_AUTO default 0 help No. of times to force MD bit to be set in Tx PDU after a successful @@ -402,6 +403,14 @@ config BT_CTLR_FORCE_MD_COUNT where applications want to send data in same connection event but are slow in providing new Tx data. +config BT_CTLR_FORCE_MD_AUTO + bool "Forced MD bit automatic calculation" + select BT_CTLR_THROUGHPUT + default y if BT_HCI_RAW + help + Force MD bit in transmitted PDU based on runtime incoming transmit + data throughput. + config BT_CTLR_CONN_RSSI_EVENT bool "Connection RSSI event" depends on BT_CTLR_CONN_RSSI diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index 67ab0389afd..9e2955fd2cb 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -122,10 +122,12 @@ struct lll_conn { int lll_conn_init(void); int lll_conn_reset(void); +void lll_conn_flush(uint16_t handle, struct lll_conn *lll); uint8_t lll_conn_sca_local_get(void); uint32_t lll_conn_ppm_local_get(void); uint32_t lll_conn_ppm_get(uint8_t sca); + void lll_conn_prepare_reset(void); void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param); void lll_conn_isr_rx(void *param); @@ -133,7 +135,7 @@ void lll_conn_isr_tx(void *param); void lll_conn_rx_pkt_set(struct lll_conn *lll); void lll_conn_tx_pkt_set(struct lll_conn *lll, struct pdu_data *pdu_data_tx); void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx); -void lll_conn_flush(uint16_t handle, struct lll_conn *lll); +uint8_t lll_conn_force_md_cnt_set(uint8_t force_md_cnt); extern void ull_conn_lll_ack_enqueue(uint16_t handle, struct node_tx *tx); extern uint16_t ull_conn_lll_max_tx_octets_get(struct lll_conn *lll); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c index 2d82abce835..aabe19ff484 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -53,6 +53,12 @@ static uint8_t mic_state; #if defined(CONFIG_BT_CTLR_FORCE_MD_COUNT) && \ (CONFIG_BT_CTLR_FORCE_MD_COUNT > 0) +#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO) +static uint8_t force_md_cnt_reload; +#define BT_CTLR_FORCE_MD_COUNT force_md_cnt_reload +#else +#define BT_CTLR_FORCE_MD_COUNT CONFIG_BT_CTLR_FORCE_MD_COUNT +#endif static uint8_t force_md_cnt; #define FORCE_MD_CNT_INIT() \ @@ -73,7 +79,7 @@ static uint8_t force_md_cnt; do { \ if (force_md_cnt || \ (trx_cnt >= ((CONFIG_BT_CTLR_TX_BUFFERS) - 1))) { \ - force_md_cnt = CONFIG_BT_CTLR_FORCE_MD_COUNT; \ + force_md_cnt = BT_CTLR_FORCE_MD_COUNT; \ } \ } while (0) @@ -593,6 +599,18 @@ void lll_conn_pdu_tx_prep(struct lll_conn *lll, struct pdu_data **pdu_data_tx) *pdu_data_tx = p; } +#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO) +uint8_t lll_conn_force_md_cnt_set(uint8_t force_md_cnt) +{ + uint8_t previous; + + previous = force_md_cnt_reload; + force_md_cnt_reload = force_md_cnt; + + return previous; +} +#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */ + static int init_reset(void) { return 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 652bd5d4b89..55b223ef37a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -116,6 +116,10 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, struct pdu_data *pdu_rx, struct ll_conn *conn); +#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO) +static uint8_t force_md_cnt_calc(struct lll_conn *lll_conn, uint32_t tx_rate); +#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */ + #if !defined(BT_CTLR_USER_TX_BUFFER_OVERHEAD) #define BT_CTLR_USER_TX_BUFFER_OVERHEAD 0 #endif /* BT_CTLR_USER_TX_BUFFER_OVERHEAD */ @@ -246,10 +250,28 @@ int ll_tx_mem_enqueue(uint16_t handle, void *tx) static memq_link_t link; static struct mayfly mfy = {0, 0, &link, NULL, tx_demux}; +#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO) + if (tx_cnt >= CONFIG_BT_CTLR_TX_BUFFERS) { + uint8_t previous, force_md_cnt; + + force_md_cnt = force_md_cnt_calc(&conn->lll, tx_rate); + previous = lll_conn_force_md_cnt_set(force_md_cnt); + if (previous != force_md_cnt) { + BT_INFO("force_md_cnt: old= %u, new= %u.", + previous, force_md_cnt); + } + } +#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */ + mfy.param = conn; mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, 0, &mfy); + +#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO) + } else { + lll_conn_force_md_cnt_set(0U); +#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */ } #if defined(CONFIG_BT_PERIPHERAL) @@ -6291,3 +6313,42 @@ ull_conn_rx_unknown_rsp_send: return nack; } + +#if defined(CONFIG_BT_CTLR_FORCE_MD_AUTO) +static uint8_t force_md_cnt_calc(struct lll_conn *lll_conn, uint32_t tx_rate) +{ + uint32_t time_incoming, time_outgoing; + uint8_t force_md_cnt; + uint8_t phy; + +#if defined(CONFIG_BT_CTLR_PHY) + phy = lll_conn->phy_tx; +#else /* !CONFIG_BT_CTLR_PHY */ + phy = PHY_1M; +#endif /* !CONFIG_BT_CTLR_PHY */ + + time_incoming = (CONFIG_BT_CTLR_DATA_LENGTH_MAX << 3) * + 1000000UL / tx_rate; + time_outgoing = PKT_DC_US(CONFIG_BT_CTLR_DATA_LENGTH_MAX, + (PDU_MIC_SIZE * lll_conn->enc_tx), phy) + + PKT_DC_US(0U, 0U, phy) + + (EVENT_IFS_US << 1); + + force_md_cnt = 0U; + if (time_incoming > time_outgoing) { + uint32_t delta; + uint32_t time_keep_alive; + + delta = (time_incoming << 1) - time_outgoing; + time_keep_alive = (PKT_DC_US(0U, 0U, phy) + EVENT_IFS_US) << 1; + force_md_cnt = (delta + (time_keep_alive - 1)) / + time_keep_alive; + BT_DBG("Time: incoming= %u, expected outgoing= %u, delta= %u, " + "keepalive= %u, force_md_cnt = %u.", + time_incoming, time_outgoing, delta, time_keep_alive, + force_md_cnt); + } + + return force_md_cnt; +} +#endif /* CONFIG_BT_CTLR_FORCE_MD_AUTO */