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:
parent
3bbe2c0a07
commit
e4fe7435d7
4 changed files with 93 additions and 3 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue