Skip to content

Commit 3308317

Browse files
committed
Bluetooth: Controller: Replace prepare pipeline with ordered list
Replace prepare pipeline with ordered linked list. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent d8bdcc6 commit 3308317

File tree

4 files changed

+263
-224
lines changed

4 files changed

+263
-224
lines changed

subsys/bluetooth/controller/ll_sw/lll.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ struct lll_event *ull_prepare_enqueue(lll_is_abort_cb_t is_abort_cb,
611611
lll_prepare_cb_t prepare_cb,
612612
uint8_t is_resume);
613613
void *ull_prepare_dequeue_get(void);
614-
void *ull_prepare_dequeue_iter(uint8_t *idx);
614+
void *ull_prepare_dequeue_iter(void **idx);
615615
void ull_prepare_dequeue(uint8_t caller_id);
616616
void *ull_pdu_rx_alloc_peek(uint8_t count);
617617
void *ull_pdu_rx_alloc_peek_iter(uint8_t *idx);

subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c

Lines changed: 42 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static int init_reset(void);
7070
static inline void done_inc(void);
7171
#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
7272
static inline bool is_done_sync(void);
73-
static inline struct lll_event *prepare_dequeue_iter_ready_get(uint8_t *idx);
73+
static inline struct lll_event *prepare_dequeue_iter_ready_get(void **idx);
7474
static inline struct lll_event *resume_enqueue(lll_is_abort_cb_t is_abort_cb,
7575
lll_abort_cb_t abort_cb, lll_prepare_cb_t resume_cb,
7676
void *param);
@@ -466,9 +466,9 @@ void lll_disable(void *param)
466466
}
467467
{
468468
struct lll_event *next;
469-
uint8_t idx;
469+
void *idx;
470470

471-
idx = UINT8_MAX;
471+
idx = NULL;
472472
next = ull_prepare_dequeue_iter(&idx);
473473
while (next) {
474474
if (!next->is_aborted &&
@@ -482,8 +482,10 @@ void lll_disable(void *param)
482482
* the prepare pipeline hence re-iterate
483483
* through the prepare pipeline.
484484
*/
485-
idx = UINT8_MAX;
485+
idx = NULL;
486486
#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
487+
} else if (!idx) {
488+
break;
487489
}
488490

489491
next = ull_prepare_dequeue_iter(&idx);
@@ -835,53 +837,26 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
835837
struct lll_event *ready_short = NULL;
836838
struct lll_event *ready;
837839
struct lll_event *next;
838-
uint8_t idx;
840+
void *idx;
839841
int err;
840842

841843
/* Find the ready prepare in the pipeline */
842-
idx = UINT8_MAX;
844+
idx = NULL;
843845
ready = prepare_dequeue_iter_ready_get(&idx);
844846

845847
/* Find any short prepare */
846-
if (ready) {
847-
uint32_t ticks_at_preempt_min = prepare_param->ticks_at_expire;
848-
uint32_t ticks_at_preempt_next;
849-
uint8_t idx_backup = idx;
848+
if (ready && (&ready->prepare_param != prepare_param)) {
850849
uint32_t diff;
851850

852-
ticks_at_preempt_next = ready->prepare_param.ticks_at_expire;
853-
diff = ticker_ticks_diff_get(ticks_at_preempt_min,
854-
ticks_at_preempt_next);
855-
if (is_resume || ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U)) {
856-
ticks_at_preempt_min = ticks_at_preempt_next;
857-
if (&ready->prepare_param != prepare_param) {
858-
ready_short = ready;
859-
}
851+
diff = ticker_ticks_diff_get(prepare_param->ticks_at_expire,
852+
ready->prepare_param.ticks_at_expire);
853+
if (is_resume || (diff && ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U))) {
854+
ready_short = ready;
860855
} else {
861856
ready = NULL;
862-
idx_backup = UINT8_MAX;
863857
}
864-
865-
do {
866-
struct lll_event *ready_next;
867-
868-
ready_next = prepare_dequeue_iter_ready_get(&idx);
869-
if (!ready_next) {
870-
break;
871-
}
872-
873-
ticks_at_preempt_next = ready_next->prepare_param.ticks_at_expire;
874-
diff = ticker_ticks_diff_get(ticks_at_preempt_next,
875-
ticks_at_preempt_min);
876-
if ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U) {
877-
continue;
878-
}
879-
880-
ready_short = ready_next;
881-
ticks_at_preempt_min = ticks_at_preempt_next;
882-
} while (true);
883-
884-
idx = idx_backup;
858+
} else {
859+
ready = NULL;
885860
}
886861

887862
/* Current event active or another prepare is ready in the pipeline */
@@ -932,6 +907,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
932907
} else {
933908
next = ready;
934909
}
910+
} else if (!idx) {
911+
break;
935912
}
936913

937914
ready = ull_prepare_dequeue_iter(&idx);
@@ -989,6 +966,7 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
989966
*/
990967

991968
/* Find next prepare needing preempt timeout to be setup */
969+
idx = NULL;
992970
next = prepare_dequeue_iter_ready_get(&idx);
993971
if (!next) {
994972
return err;
@@ -1025,14 +1003,20 @@ static inline bool is_done_sync(void)
10251003
#endif /* !CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
10261004
}
10271005

1028-
static inline struct lll_event *prepare_dequeue_iter_ready_get(uint8_t *idx)
1006+
static inline struct lll_event *prepare_dequeue_iter_ready_get(void **idx)
10291007
{
10301008
struct lll_event *ready;
10311009

1032-
do {
1010+
ready = ull_prepare_dequeue_iter(idx);
1011+
while ((ready != NULL) && ((ready->is_aborted != 0U) || (ready->is_resume != 0U) ||
1012+
(ready->prepare_param.defer != 0U))) {
1013+
if (!*idx) {
1014+
ready = NULL;
1015+
break;
1016+
}
1017+
10331018
ready = ull_prepare_dequeue_iter(idx);
1034-
} while ((ready != NULL) && ((ready->is_aborted != 0U) || (ready->is_resume != 0U) ||
1035-
(ready->prepare_param.defer != 0U)));
1019+
}
10361020

10371021
return ready;
10381022
}
@@ -1223,17 +1207,16 @@ static void preempt(void *param)
12231207
{
12241208
lll_prepare_cb_t resume_cb;
12251209
struct lll_event *ready;
1226-
uint8_t idx;
1210+
void *idx;
12271211
int err;
12281212

12291213
/* No event to abort */
12301214
if (!event.curr.abort_cb || !event.curr.param) {
12311215
return;
12321216
}
12331217

1234-
preempt_find_preemptor:
12351218
/* Find a prepare that is ready and not a resume */
1236-
idx = UINT8_MAX;
1219+
idx = NULL;
12371220
ready = prepare_dequeue_iter_ready_get(&idx);
12381221
if (!ready) {
12391222
/* No ready prepare */
@@ -1242,87 +1225,14 @@ static void preempt(void *param)
12421225

12431226
/* Preemptor not in pipeline */
12441227
if (ready->prepare_param.param != param) {
1245-
uint32_t ticks_at_preempt_min = ready->prepare_param.ticks_at_expire;
1246-
struct lll_event *ready_short = NULL;
1247-
struct lll_event *ready_next = NULL;
1248-
struct lll_event *preemptor;
1249-
1250-
/* Find if the short prepare request in the pipeline */
1251-
do {
1252-
uint32_t ticks_at_preempt_next;
1253-
uint32_t diff;
1254-
1255-
preemptor = prepare_dequeue_iter_ready_get(&idx);
1256-
if (!preemptor) {
1257-
break;
1258-
}
1259-
1260-
if (!ready_next) {
1261-
ready_next = preemptor;
1262-
}
1263-
1264-
if (preemptor->prepare_param.param == param) {
1265-
break;
1266-
}
1267-
1268-
ticks_at_preempt_next = preemptor->prepare_param.ticks_at_expire;
1269-
diff = ticker_ticks_diff_get(ticks_at_preempt_next,
1270-
ticks_at_preempt_min);
1271-
if ((diff & BIT(HAL_TICKER_CNTR_MSBIT)) == 0U) {
1272-
continue;
1273-
}
1274-
1275-
ready_short = preemptor;
1276-
ticks_at_preempt_min = ticks_at_preempt_next;
1277-
} while (true);
1278-
1279-
/* "The" short prepare we were looking for is not in pipeline */
1280-
if (!preemptor) {
1281-
uint32_t ret;
1282-
1283-
/* Find any short prepare */
1284-
if (ready_short) {
1285-
ready = ready_short;
1286-
}
1287-
1288-
/* Start the preempt timeout for (short) ready event */
1289-
ret = preempt_ticker_start(ready, NULL, ready);
1290-
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
1291-
(ret == TICKER_STATUS_BUSY));
1292-
1293-
return;
1294-
}
1295-
1296-
/* FIXME: Prepare pipeline is not a ordered list implementation,
1297-
* and for short prepare being enqueued, ideally the
1298-
* pipeline has to be implemented as ordered list.
1299-
* Until then a workaround to abort a prepare present
1300-
* before the short prepare being enqueued is implemented
1301-
* below.
1302-
* A proper solution will be to re-design the pipeline
1303-
* as a ordered list, instead of the current FIFO.
1304-
*/
1305-
1306-
/* Abort the prepare that is present before the short prepare */
1307-
ready->is_aborted = 1;
1308-
ready->abort_cb(&ready->prepare_param, ready->prepare_param.param);
1309-
1310-
/* Abort all events in pipeline before the short prepare */
1311-
if (preemptor != ready_next) {
1312-
goto preempt_find_preemptor;
1313-
}
1228+
uint32_t ret;
13141229

1315-
/* As the prepare queue has been refreshed due to the call of
1316-
* abort_cb which invokes the lll_done, find the latest prepare
1317-
*/
1318-
idx = UINT8_MAX;
1319-
ready = prepare_dequeue_iter_ready_get(&idx);
1320-
if (!ready) {
1321-
/* No ready prepare */
1322-
return;
1323-
}
1230+
/* Start the preempt timeout for ready event */
1231+
ret = preempt_ticker_start(ready, NULL, ready);
1232+
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
1233+
(ret == TICKER_STATUS_BUSY));
13241234

1325-
LL_ASSERT(ready->prepare_param.param == param);
1235+
return;
13261236
}
13271237

13281238
/* Check if current event want to continue */
@@ -1366,8 +1276,8 @@ static void preempt(void *param)
13661276
lll_abort_cb_t abort_cb;
13671277
uint8_t is_resume_abort;
13681278
struct lll_event *iter;
1369-
uint8_t iter_idx;
13701279
void *curr_param;
1280+
void *iter_idx;
13711281

13721282
/* Remove parameter assignment from currently active radio event so that done event
13731283
* is not generated.
@@ -1385,8 +1295,8 @@ static void preempt(void *param)
13851295
is_resume_abort = 0U;
13861296

13871297
preempt_abort_resume:
1388-
/* Abort any duplicate non-resume, that they get dequeued */
1389-
iter_idx = UINT8_MAX;
1298+
/* Abort any duplicates so that they get dequeued */
1299+
iter_idx = NULL;
13901300
iter = ull_prepare_dequeue_iter(&iter_idx);
13911301
while (iter) {
13921302
if (!iter->is_aborted &&
@@ -1401,8 +1311,10 @@ static void preempt(void *param)
14011311
* the prepare pipeline hence re-iterate
14021312
* through the prepare pipeline.
14031313
*/
1404-
iter_idx = UINT8_MAX;
1314+
iter_idx = NULL;
14051315
#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL_DONE */
1316+
} else if (!iter_idx) {
1317+
break;
14061318
}
14071319

14081320
iter = ull_prepare_dequeue_iter(&iter_idx);

0 commit comments

Comments
 (0)