From 3e0e378dcae7b5eda0ae6e1f5c38e55f165aafc5 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 8 Aug 2019 16:29:09 +0530 Subject: [PATCH] Bluetooth: controller: split: Fix pipeline for continuous events Fix the pipeline prepare-resume implementation to correctly handle multiple continuous events that request resume on being pre-empted. Symptoms of the bug being, when having continuous scanning, and an active peripheral if a directed advertising is started the peripheral event are not scheduled causing link supervision timeout. This is fixed by not having an enqueued resume event prepared if there is an enqueued new non-resume event in the pipeline. Signed-off-by: Vinayak Kariappa Chettimada --- .../controller/ll_sw/nordic/lll/lll.c | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 505bb0a3ef6..d06cc4e33a6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -191,21 +191,9 @@ void lll_resume(void *param) struct lll_event *next = param; int ret; - if (event.curr.abort_cb) { - ret = prepare(next->is_abort_cb, next->abort_cb, - next->prepare_cb, next->prio, - &next->prepare_param, next->is_resume); - LL_ASSERT(!ret || ret == -EINPROGRESS); - - return; - } - - event.curr.is_abort_cb = next->is_abort_cb; - event.curr.abort_cb = next->abort_cb; - event.curr.param = next->prepare_param.param; - - ret = next->prepare_cb(&next->prepare_param); - LL_ASSERT(!ret); + ret = prepare(next->is_abort_cb, next->abort_cb, next->prepare_cb, + next->prio, &next->prepare_param, next->is_resume); + LL_ASSERT(!ret || ret == -EINPROGRESS); } void lll_disable(void *param) @@ -426,12 +414,14 @@ static int prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, struct lll_event *p; u8_t idx = UINT8_MAX; + /* Find the ready prepare in the pipeline */ p = ull_prepare_dequeue_iter(&idx); - while (p && p->is_aborted) { + while (p && (p->is_aborted || p->is_resume)) { p = ull_prepare_dequeue_iter(&idx); } - if (event.curr.abort_cb || p) { + /* Current event active or another prepare is ready in the pipeline */ + if (event.curr.abort_cb || (p && is_resume)) { #if !defined(CONFIG_BT_CTLR_LOW_LAT) u32_t preempt_anchor; struct evt_hdr *evt; @@ -453,11 +443,11 @@ static int prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, prepare_cb, prio, is_resume); LL_ASSERT(!ret); +#if !defined(CONFIG_BT_CTLR_LOW_LAT) if (is_resume) { return -EINPROGRESS; } -#if !defined(CONFIG_BT_CTLR_LOW_LAT) /* Calc the preempt timeout */ evt = HDR_LLL2EVT(prepare_param->param); preempt_anchor = prepare_param->ticks_at_expire; @@ -571,7 +561,7 @@ static void preempt(void *param) return; } - while (next && next->is_resume) { + while (next && (next->is_aborted || next->is_resume)) { next = ull_prepare_dequeue_iter(&idx); }