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.
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

View file

@ -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);

View file

@ -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;

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,
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 */