Bluetooth: Controller: Introduce BT_CTLR_PERIPHERAL_RESERVE_MAX

Introduce BT_CTLR_PERIPHERAL_RESERVE_MAX Kconfig option so
that disabling this option will use minimum time reservation
and exercise the peripheral connection event continuation
using is_abort_cb mechanism.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2024-07-12 04:18:38 +02:00 committed by Fabio Baltieri
commit cadef5a64f
10 changed files with 98 additions and 5 deletions

View file

@ -72,6 +72,8 @@ CONFIG_BT_CTLR_SCAN_AUX_SET=1
CONFIG_BT_CTLR_ADV_RESERVE_MAX=n
CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX=n
CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX=n
CONFIG_BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX=y
CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE=n
CONFIG_BT_CTLR_SCAN_UNRESERVED=y
CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH=y

View file

@ -754,6 +754,19 @@ config BT_CTLR_CENTRAL_RESERVE_MAX
Note, currently this value is only used to space multiple central
connections and not for actual ticker time reservations.
config BT_CTLR_PERIPHERAL_RESERVE_MAX
bool "Use maximum data PDU size time reservation for Peripheral"
depends on BT_PERIPHERAL
default y
help
Use the maximum data PDU size time reservation considering the Data
length could be updated from default 27 bytes to maximum support size.
If maximum time reservation is disabled then time reservation required
for empty PDU transmission is used. Overlapping radio events will use
the is_abort_cb mechanism to decide on continuation of the connection
event.
config BT_CTLR_EVENT_OVERHEAD_RESERVE_MAX
bool "Reserve maximum event overhead in time reservations"
default y

View file

@ -509,6 +509,7 @@ struct event_done_extra {
struct {
uint16_t trx_cnt;
uint8_t crc_valid:1;
uint8_t is_aborted:1;
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
uint8_t estab_failed:1;
#endif /* CONFIG_BT_CTLR_SYNC_ISO */

View file

@ -69,11 +69,20 @@ struct lll_conn {
struct {
uint8_t initiated:1;
uint8_t cancelled:1;
uint8_t forced:1;
};
struct {
uint8_t initiated:1;
uint8_t cancelled:1;
uint8_t forced:1;
} central;
#if defined(CONFIG_BT_PERIPHERAL)
struct {
uint8_t initiated:1;
uint8_t cancelled:1;
uint8_t forced:1;
uint8_t latency_enabled:1;
uint32_t window_widening_periodic_us;
@ -160,6 +169,7 @@ int lll_conn_reset(void);
void lll_conn_flush(uint16_t handle, struct lll_conn *lll);
void lll_conn_prepare_reset(void);
int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb);
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param);
void lll_conn_isr_rx(void *param);
void lll_conn_isr_tx(void *param);

View file

@ -59,6 +59,7 @@ static struct pdu_data *get_last_tx_pdu(struct lll_conn *lll);
static uint8_t crc_expire;
static uint8_t crc_valid;
static uint8_t is_aborted;
static uint16_t trx_cnt;
#if defined(CONFIG_BT_CTLR_LE_ENC)
@ -142,12 +143,25 @@ void lll_conn_prepare_reset(void)
trx_cnt = 0U;
crc_valid = 0U;
crc_expire = 0U;
is_aborted = 0U;
#if defined(CONFIG_BT_CTLR_LE_ENC)
mic_state = LLL_CONN_MIC_NONE;
#endif /* CONFIG_BT_CTLR_LE_ENC */
}
int lll_conn_is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb)
{
struct lll_conn *lll = curr;
/* Do not abort if near supervision timeout */
if (lll->forced) {
return 0;
}
return -ECANCELED;
}
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
{
struct event_done_extra *e;
@ -156,6 +170,17 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
/* NOTE: This is not a prepare being cancelled */
if (!prepare_param) {
/* Get reference to LLL connection context */
lll = param;
/* For a peripheral role, ensure at least one PDU is tx-ed
* back to central, otherwise let the supervision timeout
* countdown be started.
*/
if ((lll->role == BT_HCI_ROLE_PERIPHERAL) && (trx_cnt <= 1U)) {
is_aborted = 1U;
}
/* Perform event abort here.
* After event has been cleanly aborted, clean up resources
* and dispatch event done.
@ -171,8 +196,10 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
err = lll_hfclock_off();
LL_ASSERT(err >= 0);
/* Accumulate the latency as event is aborted while being in pipeline */
/* Get reference to LLL connection context */
lll = prepare_param->param;
/* Accumulate the latency as event is aborted while being in pipeline */
lll->latency_prepare += (prepare_param->lazy + 1);
/* Extra done event, to check supervision timeout */
@ -867,6 +894,7 @@ static void isr_done(void *param)
e->type = EVENT_DONE_EXTRA_TYPE_CONN;
e->trx_cnt = trx_cnt;
e->crc_valid = crc_valid;
e->is_aborted = is_aborted;
#if defined(CONFIG_BT_CTLR_LE_ENC)
e->mic_state = mic_state;

View file

@ -89,7 +89,8 @@ void lll_periph_prepare(void *param)
}
/* Invoke common pipeline handling of prepare */
err = lll_prepare(lll_is_abort_cb, lll_conn_abort_cb, prepare_cb, 0, p);
err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb,
0U, p);
LL_ASSERT(!err || err == -EINPROGRESS);
}

View file

@ -1072,6 +1072,7 @@ uint8_t ll_adv_enable(uint8_t enable)
conn_lll->role = 1;
conn_lll->periph.initiated = 0;
conn_lll->periph.cancelled = 0;
conn_lll->periph.forced = 0;
conn_lll->data_chan_sel = 0;
conn_lll->data_chan_use = 0;
conn_lll->event_counter = 0;

View file

@ -253,6 +253,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
conn_lll->role = 0;
conn_lll->central.initiated = 0;
conn_lll->central.cancelled = 0;
conn_lll->central.forced = 0;
/* FIXME: END: Move to ULL? */
#if defined(CONFIG_BT_CTLR_CONN_META)
memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));

View file

@ -943,6 +943,7 @@ void ull_conn_done(struct node_rx_event_done *done)
struct lll_conn *lll;
struct ll_conn *conn;
uint8_t reason_final;
uint8_t force_lll;
uint16_t lazy;
uint8_t force;
@ -1054,7 +1055,7 @@ void ull_conn_done(struct node_rx_event_done *done)
}
/* Reset supervision countdown */
if (done->extra.crc_valid) {
if (done->extra.crc_valid && !done->extra.is_aborted) {
conn->supervision_expire = 0U;
}
@ -1085,6 +1086,7 @@ void ull_conn_done(struct node_rx_event_done *done)
/* check supervision timeout */
force = 0U;
force_lll = 0U;
if (conn->supervision_expire) {
if (conn->supervision_expire > elapsed_event) {
conn->supervision_expire -= elapsed_event;
@ -1096,6 +1098,8 @@ void ull_conn_done(struct node_rx_event_done *done)
* supervision timeout.
*/
if (conn->supervision_expire <= 6U) {
force_lll = 1U;
force = 1U;
}
#if defined(CONFIG_BT_CTLR_CONN_RANDOM_FORCE)
@ -1123,6 +1127,8 @@ void ull_conn_done(struct node_rx_event_done *done)
}
}
lll->forced = force_lll;
/* check procedure timeout */
uint8_t error_code;
@ -1233,26 +1239,41 @@ void ull_conn_done(struct node_rx_event_done *done)
uint32_t ready_delay, rx_time, tx_time, ticks_slot, slot_us;
lll->evt_len_upd = 0;
#if defined(CONFIG_BT_CTLR_PHY)
ready_delay = (lll->role) ?
lll_radio_rx_ready_delay_get(lll->phy_rx, PHY_FLAGS_S8) :
lll_radio_tx_ready_delay_get(lll->phy_tx, lll->phy_flags);
#if defined(CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX)
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
tx_time = lll->dle.eff.max_tx_time;
rx_time = lll->dle.eff.max_rx_time;
#else /* CONFIG_BT_CTLR_DATA_LENGTH */
#else /* CONFIG_BT_CTLR_DATA_LENGTH */
tx_time = MAX(PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, 0),
PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_tx));
rx_time = MAX(PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, 0),
PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_rx));
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#else /* !CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX */
tx_time = PDU_MAX_US(0U, 0U, lll->phy_tx);
rx_time = PDU_MAX_US(0U, 0U, lll->phy_rx);
#endif /* !CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX */
#else /* CONFIG_BT_CTLR_PHY */
ready_delay = (lll->role) ?
lll_radio_rx_ready_delay_get(0, 0) :
lll_radio_tx_ready_delay_get(0, 0);
#if defined(CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX)
tx_time = PDU_DC_MAX_US(lll->dle.eff.max_tx_octets, 0);
rx_time = PDU_DC_MAX_US(lll->dle.eff.max_rx_octets, 0);
#else /* !CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX */
tx_time = PDU_MAX_US(0U, 0U, PHY_1M);
rx_time = PDU_MAX_US(0U, 0U, PHY_1M);
#endif /* !CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX */
#endif /* CONFIG_BT_CTLR_PHY */
/* Calculate event time reservation */

View file

@ -341,25 +341,40 @@ void ull_periph_setup(struct node_rx_pdu *rx, struct node_rx_ftr *ftr,
ll_rx_put_sched(link, rx);
#if defined(CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX)
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
#if defined(CONFIG_BT_CTLR_PHY)
max_tx_time = lll->dle.eff.max_tx_time;
max_rx_time = lll->dle.eff.max_rx_time;
#else /* !CONFIG_BT_CTLR_PHY */
max_tx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
max_rx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
#endif /* !CONFIG_BT_CTLR_PHY */
#else /* !CONFIG_BT_CTLR_DATA_LENGTH */
max_tx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
max_rx_time = PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, PHY_1M);
#if defined(CONFIG_BT_CTLR_PHY)
max_tx_time = MAX(max_tx_time,
PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_tx));
max_rx_time = MAX(max_rx_time,
PDU_DC_MAX_US(PDU_DC_PAYLOAD_SIZE_MIN, lll->phy_rx));
#endif /* !CONFIG_BT_CTLR_PHY */
#endif /* CONFIG_BT_CTLR_PHY */
#endif /* !CONFIG_BT_CTLR_DATA_LENGTH */
#else /* !CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX */
#if defined(CONFIG_BT_CTLR_PHY)
max_tx_time = PDU_MAX_US(0U, 0U, lll->phy_tx);
max_rx_time = PDU_MAX_US(0U, 0U, lll->phy_rx);
#else /* !CONFIG_BT_CTLR_PHY */
max_tx_time = PDU_MAX_US(0U, 0U, PHY_1M);
max_rx_time = PDU_MAX_US(0U, 0U, PHY_1M);
#endif /* !CONFIG_BT_CTLR_PHY */
#endif /* !CONFIG_BT_CTLR_PERIPHERAL_RESERVE_MAX */
#if defined(CONFIG_BT_CTLR_PHY)
ready_delay_us = lll_radio_rx_ready_delay_get(lll->phy_rx, PHY_FLAGS_S8);
#else /* CONFIG_BT_CTLR_PHY */