Bluetooth: Controller: Add abort fairness in overlapping Periodic Sync
Add implementation in Periodic Sync LLL abort to use near fair scheduling to ensure overlapping multiple Periodic Sync set each get to use the radio and not lead to Sync Loss. The implementation is used when overlap in radio event happens in unreserved time space of the event. An abort count is maintain in each Periodic Sync instance and is used to decide whether the current event or the next event is to be aborted when they overlap. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
1a1f347ad3
commit
ddf04997a5
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue