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 <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-09-16 15:21:50 +05:30 committed by Ioannis Glaropoulos
commit e4fe7435d7
4 changed files with 93 additions and 3 deletions

View file

@ -391,8 +391,9 @@ config BT_CTLR_THROUGHPUT
Measure incoming Tx throughput and log the results. Measure incoming Tx throughput and log the results.
config BT_CTLR_FORCE_MD_COUNT 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 range 0 255
default 1 if BT_CTLR_FORCE_MD_AUTO
default 0 default 0
help help
No. of times to force MD bit to be set in Tx PDU after a successful 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 where applications want to send data in same connection event but are
slow in providing new Tx data. 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 config BT_CTLR_CONN_RSSI_EVENT
bool "Connection RSSI event" bool "Connection RSSI event"
depends on BT_CTLR_CONN_RSSI depends on BT_CTLR_CONN_RSSI

View file

@ -122,10 +122,12 @@ struct lll_conn {
int lll_conn_init(void); int lll_conn_init(void);
int lll_conn_reset(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); uint8_t lll_conn_sca_local_get(void);
uint32_t lll_conn_ppm_local_get(void); uint32_t lll_conn_ppm_local_get(void);
uint32_t lll_conn_ppm_get(uint8_t sca); uint32_t lll_conn_ppm_get(uint8_t sca);
void lll_conn_prepare_reset(void); void lll_conn_prepare_reset(void);
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param); void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param);
void lll_conn_isr_rx(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_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_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_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 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); extern uint16_t ull_conn_lll_max_tx_octets_get(struct lll_conn *lll);

View file

@ -53,6 +53,12 @@ static uint8_t mic_state;
#if defined(CONFIG_BT_CTLR_FORCE_MD_COUNT) && \ #if defined(CONFIG_BT_CTLR_FORCE_MD_COUNT) && \
(CONFIG_BT_CTLR_FORCE_MD_COUNT > 0) (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; static uint8_t force_md_cnt;
#define FORCE_MD_CNT_INIT() \ #define FORCE_MD_CNT_INIT() \
@ -73,7 +79,7 @@ static uint8_t force_md_cnt;
do { \ do { \
if (force_md_cnt || \ if (force_md_cnt || \
(trx_cnt >= ((CONFIG_BT_CTLR_TX_BUFFERS) - 1))) { \ (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) } 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; *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) static int init_reset(void)
{ {
return 0; return 0;

View file

@ -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, static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
struct pdu_data *pdu_rx, struct ll_conn *conn); 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) #if !defined(BT_CTLR_USER_TX_BUFFER_OVERHEAD)
#define BT_CTLR_USER_TX_BUFFER_OVERHEAD 0 #define BT_CTLR_USER_TX_BUFFER_OVERHEAD 0
#endif /* BT_CTLR_USER_TX_BUFFER_OVERHEAD */ #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 memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, tx_demux}; 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; mfy.param = conn;
mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH, mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_ULL_HIGH,
0, &mfy); 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) #if defined(CONFIG_BT_PERIPHERAL)
@ -6291,3 +6313,42 @@ ull_conn_rx_unknown_rsp_send:
return nack; 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 */