@@ -71,7 +71,7 @@ static int init_reset(void);
7171static inline void done_inc (void );
7272#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
7373static inline bool is_done_sync (void );
74- static inline struct lll_event * prepare_dequeue_iter_ready_get (uint8_t * idx );
74+ static inline struct lll_event * prepare_dequeue_iter_ready_get (void * * idx );
7575static inline struct lll_event * resume_enqueue (lll_is_abort_cb_t is_abort_cb ,
7676 lll_abort_cb_t abort_cb , lll_prepare_cb_t resume_cb ,
7777 void * param );
@@ -491,9 +491,9 @@ void lll_disable(void *param)
491491 }
492492 {
493493 struct lll_event * next ;
494- uint8_t idx ;
494+ void * idx ;
495495
496- idx = UINT8_MAX ;
496+ idx = NULL ;
497497 next = ull_prepare_dequeue_iter (& idx );
498498 while (next ) {
499499 if (!next -> is_aborted &&
@@ -507,8 +507,10 @@ void lll_disable(void *param)
507507 * the prepare pipeline hence re-iterate
508508 * through the prepare pipeline.
509509 */
510- idx = UINT8_MAX ;
510+ idx = NULL ;
511511#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
512+ } else if (!idx ) {
513+ break ;
512514 }
513515
514516 next = ull_prepare_dequeue_iter (& idx );
@@ -860,78 +862,26 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
860862 struct lll_event * ready_short = NULL ;
861863 struct lll_event * ready ;
862864 struct lll_event * next ;
863- uint8_t idx ;
865+ void * idx ;
864866 int err ;
865867
866868 /* Find the ready prepare in the pipeline */
867- idx = UINT8_MAX ;
869+ idx = NULL ;
868870 ready = prepare_dequeue_iter_ready_get (& idx );
869871
870872 /* Find any short prepare */
871- if (ready ) {
872- uint32_t ticks_at_preempt_min = prepare_param -> ticks_at_expire ;
873- uint32_t ticks_at_preempt_next ;
874- uint8_t idx_backup = idx ;
873+ if (ready && (& ready -> prepare_param != prepare_param )) {
875874 uint32_t diff ;
876875
877- ticks_at_preempt_next = ready -> prepare_param .ticks_at_expire ;
878- diff = ticker_ticks_diff_get (ticks_at_preempt_min ,
879- ticks_at_preempt_next );
880- /* If the enqueued prepare is a resume or current ready prepare is shorter, then we
881- * should pick current ready prepare for setting up the prepare timeout.
882- */
883- if (is_resume || ((diff & BIT (HAL_TICKER_CNTR_MSBIT )) == 0U )) {
884- ticks_at_preempt_min = ticks_at_preempt_next ;
885- if (& ready -> prepare_param != prepare_param ) {
886- /* There is a shorter prepare in the pipeline */
887- ready_short = ready ;
888- } else {
889- /* It is the same prepare in the pipeline being enqueued.
890- * This can happen executing `lll_done()`.
891- * Hence, we should ignore it being the `first` that setup the
892- * preempt timeout and also it has already setup the preempt
893- * timeout, refer to `preempt_ticker_start()` for details.
894- *
895- * We also set the `ready` to NULL as it is the same ready, the one
896- * being enqueued. This help short circuit a related assertion check
897- * later in this function.
898- */
899- ready = NULL ;
900- }
876+ diff = ticker_ticks_diff_get (prepare_param -> ticks_at_expire ,
877+ ready -> prepare_param .ticks_at_expire );
878+ if (is_resume || (diff && ((diff & BIT (HAL_TICKER_CNTR_MSBIT )) == 0U ))) {
879+ ready_short = ready ;
901880 } else {
902881 ready = NULL ;
903- idx_backup = UINT8_MAX ;
904882 }
905-
906- /* Loop and find any short prepare present out-of-order in the prepare pipeline.
907- *
908- * NOTE: This loop is O(n), where n is number of items in prepare pipeline present
909- * before a short prepare was enqueued in to the FIFO.
910- * Use of ordered linked list implementation has show improved lower latencies
911- * and less CPU use.
912- * TODO: Replace use of FIFO for prepare pipeline with ordered linked list
913- * implementation.
914- */
915- do {
916- struct lll_event * ready_next ;
917-
918- ready_next = prepare_dequeue_iter_ready_get (& idx );
919- if (!ready_next ) {
920- break ;
921- }
922-
923- ticks_at_preempt_next = ready_next -> prepare_param .ticks_at_expire ;
924- diff = ticker_ticks_diff_get (ticks_at_preempt_next ,
925- ticks_at_preempt_min );
926- if ((diff & BIT (HAL_TICKER_CNTR_MSBIT )) == 0U ) {
927- continue ;
928- }
929-
930- ready_short = ready_next ;
931- ticks_at_preempt_min = ticks_at_preempt_next ;
932- } while (true);
933-
934- idx = idx_backup ;
883+ } else {
884+ ready = NULL ;
935885 }
936886
937887 /* Current event active or another prepare is ready in the pipeline */
@@ -986,6 +936,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
986936 } else {
987937 next = ready ;
988938 }
939+ } else if (!idx ) {
940+ break ;
989941 }
990942
991943 ready = ull_prepare_dequeue_iter (& idx );
@@ -1047,6 +999,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
1047999 */
10481000
10491001 /* Find next prepare needing preempt timeout to be setup */
1002+ idx = NULL ;
10501003 next = prepare_dequeue_iter_ready_get (& idx );
10511004 if (!next ) {
10521005 return err ;
@@ -1083,14 +1036,20 @@ static inline bool is_done_sync(void)
10831036#endif /* !CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
10841037}
10851038
1086- static inline struct lll_event * prepare_dequeue_iter_ready_get (uint8_t * idx )
1039+ static inline struct lll_event * prepare_dequeue_iter_ready_get (void * * idx )
10871040{
10881041 struct lll_event * ready ;
10891042
1090- do {
1043+ ready = ull_prepare_dequeue_iter (idx );
1044+ while ((ready != NULL ) && ((ready -> is_aborted != 0U ) || (ready -> is_resume != 0U ) ||
1045+ (ready -> prepare_param .defer != 0U ))) {
1046+ if (!* idx ) {
1047+ ready = NULL ;
1048+ break ;
1049+ }
1050+
10911051 ready = ull_prepare_dequeue_iter (idx );
1092- } while ((ready != NULL ) && ((ready -> is_aborted != 0U ) || (ready -> is_resume != 0U ) ||
1093- (ready -> prepare_param .defer != 0U )));
1052+ }
10941053
10951054 return ready ;
10961055}
@@ -1281,7 +1240,7 @@ static void preempt(void *param)
12811240{
12821241 lll_prepare_cb_t resume_cb ;
12831242 struct lll_event * ready ;
1284- uint8_t idx ;
1243+ void * idx ;
12851244 int err ;
12861245
12871246 /* No event to abort */
@@ -1306,9 +1265,8 @@ static void preempt(void *param)
13061265 return ;
13071266 }
13081267
1309- preempt_find_preemptor :
13101268 /* Find a prepare that is ready and not a resume */
1311- idx = UINT8_MAX ;
1269+ idx = NULL ;
13121270 ready = prepare_dequeue_iter_ready_get (& idx );
13131271 if (!ready ) {
13141272 /* No ready prepare */
@@ -1317,87 +1275,14 @@ static void preempt(void *param)
13171275
13181276 /* Preemptor not in pipeline */
13191277 if (ready -> prepare_param .param != param ) {
1320- uint32_t ticks_at_preempt_min = ready -> prepare_param .ticks_at_expire ;
1321- struct lll_event * ready_short = NULL ;
1322- struct lll_event * ready_next = NULL ;
1323- struct lll_event * preemptor ;
1324-
1325- /* Find if the short prepare request in the pipeline */
1326- do {
1327- uint32_t ticks_at_preempt_next ;
1328- uint32_t diff ;
1329-
1330- preemptor = prepare_dequeue_iter_ready_get (& idx );
1331- if (!preemptor ) {
1332- break ;
1333- }
1334-
1335- if (!ready_next ) {
1336- ready_next = preemptor ;
1337- }
1338-
1339- if (preemptor -> prepare_param .param == param ) {
1340- break ;
1341- }
1342-
1343- ticks_at_preempt_next = preemptor -> prepare_param .ticks_at_expire ;
1344- diff = ticker_ticks_diff_get (ticks_at_preempt_next ,
1345- ticks_at_preempt_min );
1346- if ((diff & BIT (HAL_TICKER_CNTR_MSBIT )) == 0U ) {
1347- continue ;
1348- }
1349-
1350- ready_short = preemptor ;
1351- ticks_at_preempt_min = ticks_at_preempt_next ;
1352- } while (true);
1353-
1354- /* "The" short prepare we were looking for is not in pipeline */
1355- if (!preemptor ) {
1356- uint32_t ret ;
1357-
1358- /* Find any short prepare */
1359- if (ready_short ) {
1360- ready = ready_short ;
1361- }
1362-
1363- /* Start the preempt timeout for (short) ready event */
1364- ret = preempt_ticker_start (ready , NULL , ready );
1365- LL_ASSERT_ERR ((ret == TICKER_STATUS_SUCCESS ) ||
1366- (ret == TICKER_STATUS_BUSY ));
1367-
1368- return ;
1369- }
1370-
1371- /* FIXME: Prepare pipeline is not a ordered list implementation,
1372- * and for short prepare being enqueued, ideally the
1373- * pipeline has to be implemented as ordered list.
1374- * Until then a workaround to abort a prepare present
1375- * before the short prepare being enqueued is implemented
1376- * below.
1377- * A proper solution will be to re-design the pipeline
1378- * as a ordered list, instead of the current FIFO.
1379- */
1380-
1381- /* Abort the prepare that is present before the short prepare */
1382- ready -> is_aborted = 1 ;
1383- ready -> abort_cb (& ready -> prepare_param , ready -> prepare_param .param );
1278+ uint32_t ret ;
13841279
1385- /* Abort all events in pipeline before the short prepare */
1386- if ( preemptor != ready_next ) {
1387- goto preempt_find_preemptor ;
1388- }
1280+ /* Start the preempt timeout for ready event */
1281+ ret = preempt_ticker_start ( ready , NULL , ready );
1282+ LL_ASSERT (( ret == TICKER_STATUS_SUCCESS ) ||
1283+ ( ret == TICKER_STATUS_BUSY ));
13891284
1390- /* As the prepare queue has been refreshed due to the call of
1391- * abort_cb which invokes the lll_done, find the latest prepare
1392- */
1393- idx = UINT8_MAX ;
1394- ready = prepare_dequeue_iter_ready_get (& idx );
1395- if (!ready ) {
1396- /* No ready prepare */
1397- return ;
1398- }
1399-
1400- LL_ASSERT_ERR (ready -> prepare_param .param == param );
1285+ return ;
14011286 }
14021287
14031288 if (IS_ENABLED (CONFIG_BT_CTLR_LLL_PREPARE_AT_MARGIN )) {
@@ -1446,10 +1331,9 @@ static void preempt(void *param)
14461331 if (err == - EAGAIN ) {
14471332 lll_is_abort_cb_t is_abort_cb ;
14481333 lll_abort_cb_t abort_cb ;
1449- uint8_t is_resume_abort ;
14501334 struct lll_event * iter ;
1451- uint8_t iter_idx ;
14521335 void * curr_param ;
1336+ void * iter_idx ;
14531337
14541338 /* Remove parameter assignment from currently active radio event so that done event
14551339 * is not generated.
@@ -1461,18 +1345,11 @@ static void preempt(void *param)
14611345 is_abort_cb = event .curr .is_abort_cb ;
14621346 abort_cb = event .curr .abort_cb ;
14631347
1464- /* Iterate twice to ensure preempt timeout is setup after all duplicate resume
1465- * events are aborted.
1466- */
1467- is_resume_abort = 0U ;
1468-
1469- preempt_abort_resume :
1470- /* Abort any duplicate non-resume, that they get dequeued */
1471- iter_idx = UINT8_MAX ;
1348+ /* Abort any duplicates so that they get dequeued */
1349+ iter_idx = NULL ;
14721350 iter = ull_prepare_dequeue_iter (& iter_idx );
14731351 while (iter ) {
14741352 if (!iter -> is_aborted &&
1475- (is_resume_abort || !iter -> is_resume ) &&
14761353 (curr_param == iter -> prepare_param .param )) {
14771354 iter -> is_aborted = 1 ;
14781355 iter -> abort_cb (& iter -> prepare_param ,
@@ -1483,19 +1360,15 @@ static void preempt(void *param)
14831360 * the prepare pipeline hence re-iterate
14841361 * through the prepare pipeline.
14851362 */
1486- iter_idx = UINT8_MAX ;
1363+ iter_idx = NULL ;
14871364#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
1365+ } else if (!iter_idx ) {
1366+ break ;
14881367 }
14891368
14901369 iter = ull_prepare_dequeue_iter (& iter_idx );
14911370 }
14921371
1493- if (!is_resume_abort ) {
1494- is_resume_abort = 1U ;
1495-
1496- goto preempt_abort_resume ;
1497- }
1498-
14991372 /* Enqueue as resume event */
15001373 iter = resume_enqueue (is_abort_cb , abort_cb , resume_cb , curr_param );
15011374 LL_ASSERT_ERR (iter );
0 commit comments