diff --git a/subsys/bluetooth/controller/ll_sw/lll_sync.h b/subsys/bluetooth/controller/ll_sw/lll_sync.h index 4ad8832a90a..20ca0781d6d 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_sync.h +++ b/subsys/bluetooth/controller/ll_sw/lll_sync.h @@ -32,6 +32,14 @@ struct lll_sync { uint8_t sca:3; #endif /* CONFIG_BT_CTLR_SYNC_ISO */ +#if defined(CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN) + /* Counter used by LLL abort of event when in unreserved time space to + * provide near fair scheduling of overlapping multiple Periodic + * Sync sets. + */ + uint8_t abort_count; +#endif /* CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */ + uint16_t skip_prepare; uint16_t skip_event; uint16_t event_counter; @@ -66,3 +74,4 @@ void lll_sync_prepare(void *param); enum sync_status lll_sync_cte_is_allowed(uint8_t cte_type_mask, uint8_t filter_policy, uint8_t rx_cte_time, uint8_t rx_cte_type); extern uint16_t ull_sync_lll_handle_get(struct lll_sync *lll); +extern struct lll_sync *ull_sync_lll_is_valid_get(struct lll_sync *lll); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c index dcae61c8a5f..f1e43088e18 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync.c @@ -467,21 +467,60 @@ static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb) /* Different radio event overlap */ if (next != curr) { + struct lll_scan_aux *lll_aux; struct lll_scan *lll; lll = ull_scan_lll_is_valid_get(next); - if (!lll) { - struct lll_scan_aux *lll_aux; - - lll_aux = ull_scan_aux_lll_is_valid_get(next); - if (IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_SKIP_ON_SCAN_AUX) || - !lll_aux) { - /* Abort current event as next event is not a - * scan and not a scan aux event. - */ - return -ECANCELED; - } + if (lll) { + /* Do not abort current periodic sync event as next + * event is a scan event. + */ + return 0; } + + lll_aux = ull_scan_aux_lll_is_valid_get(next); + if (!IS_ENABLED(CONFIG_BT_CTLR_SYNC_PERIODIC_SKIP_ON_SCAN_AUX) && + lll_aux) { + /* Do not abort current periodic sync event as next + * event is a scan aux event. + */ + return 0; + } + +#if defined(CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN) + struct lll_sync *lll_sync_next; + struct lll_sync *lll_sync_curr; + + lll_sync_next = ull_sync_lll_is_valid_get(next); + if (!lll_sync_next) { + /* Abort current event as next event is not a + * scan and not a scan aux event. + */ + return -ECANCELED; + } + + lll_sync_curr = curr; + if (lll_sync_curr->abort_count < lll_sync_next->abort_count) { + if (lll_sync_curr->abort_count < UINT8_MAX) { + lll_sync_curr->abort_count++; + } + + /* Abort current event as next event has higher abort + * count. + */ + return -ECANCELED; + } + + if (lll_sync_next->abort_count < UINT8_MAX) { + lll_sync_next->abort_count++; + } + +#else /* !CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */ + /* Abort current event as next event is not a + * scan and not a scan aux event. + */ + return -ECANCELED; +#endif /* !CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */ } /* Do not abort if current periodic sync event overlaps next interval @@ -1012,6 +1051,14 @@ static void isr_rx_done_cleanup(struct lll_sync *lll, uint8_t crc_ok, bool sync_ /* Reset window widening, as anchor point sync-ed */ lll->window_widening_event_us = 0U; lll->window_size_event_us = 0U; + +#if defined(CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN) + /* Reset LLL abort count as LLL event is gracefully done and + * was not aborted by any other event when current event could + * have been using unreserved time space. + */ + lll->abort_count = 0U; +#endif /* CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */ } lll_isr_cleanup(lll); diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync.c b/subsys/bluetooth/controller/ll_sw/ull_sync.c index 98197db94a1..e64754cd43b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync.c @@ -253,6 +253,11 @@ uint8_t ll_sync_create(uint8_t options, uint8_t sid, uint8_t adv_addr_type, ull_hdr_init(&sync->ull); lll_hdr_init(lll_sync, sync); +#if defined(CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN) + /* Initialise LLL abort count */ + lll_sync->abort_count = 0U; +#endif /* CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */ + /* Enable scanner to create sync */ scan->periodic.sync = sync; @@ -529,6 +534,19 @@ struct ll_sync_set *ull_sync_is_valid_get(struct ll_sync_set *sync) return sync; } +struct lll_sync *ull_sync_lll_is_valid_get(struct lll_sync *lll) +{ + struct ll_sync_set *sync; + + sync = HDR_LLL2ULL(lll); + sync = ull_sync_is_valid_get(sync); + if (sync) { + return &sync->lll; + } + + return NULL; +} + uint16_t ull_sync_handle_get(struct ll_sync_set *sync) { return mem_index_get(sync, ll_sync_pool, sizeof(struct ll_sync_set));