From cadef5a64fa570a8b61e16d047021a67eb61432a Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 12 Jul 2024 04:18:38 +0200 Subject: [PATCH] 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 --- .../nrf5340_cpunet_iso-bt_ll_sw_split.conf | 2 ++ .../bluetooth/controller/Kconfig.ll_sw_split | 13 ++++++++ subsys/bluetooth/controller/ll_sw/lll.h | 1 + subsys/bluetooth/controller/ll_sw/lll_conn.h | 10 +++++++ .../controller/ll_sw/nordic/lll/lll_conn.c | 30 ++++++++++++++++++- .../ll_sw/nordic/lll/lll_peripheral.c | 3 +- subsys/bluetooth/controller/ll_sw/ull_adv.c | 1 + .../bluetooth/controller/ll_sw/ull_central.c | 1 + subsys/bluetooth/controller/ll_sw/ull_conn.c | 25 ++++++++++++++-- .../controller/ll_sw/ull_peripheral.c | 17 ++++++++++- 10 files changed, 98 insertions(+), 5 deletions(-) diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 9dd89e2b04f..672d8b40fa9 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -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 diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index e6d32e8251b..bfb0c47772d 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -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 diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 048aa8edaf8..4cecde96f8e 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -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 */ diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index f18e4656786..a32b06bf122 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -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); 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 131fcde4d48..5e7d357b0dd 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_conn.c @@ -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; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c index 30ad77fb532..0f8b89e4b3a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral.c @@ -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); } diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index c0f2f86bb2a..e9fb8e47a6b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -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; diff --git a/subsys/bluetooth/controller/ll_sw/ull_central.c b/subsys/bluetooth/controller/ll_sw/ull_central.c index a39ef8b5989..397c0d0b5f9 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_central.c +++ b/subsys/bluetooth/controller/ll_sw/ull_central.c @@ -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)); diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 50fe53127cc..19eaa527aa8 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -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 */ diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c index 5abde0647e8..cb2eda86592 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral.c @@ -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 */