Bluetooth: Controller: Preempt ticker to use atmost one operation

When there are multiple events in prepare pipeline then fix
the implementation so that only one preempt ticker start
or stop operation is enqueued towards ticker_job for
processing.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2021-08-04 11:47:49 +05:30 committed by Carles Cufí
parent a42890fb39
commit 6cd9ec8c8d

View File

@ -69,10 +69,8 @@ static struct lll_event *resume_enqueue(lll_prepare_cb_t resume_cb);
static void isr_race(void *param);
#if !defined(CONFIG_BT_CTLR_LOW_LAT)
static void ticker_stop_op_cb(uint32_t status, void *param);
static void ticker_start_op_cb(uint32_t status, void *param);
static uint32_t preempt_ticker_start(struct lll_event *event,
ticker_op_func op_cb);
static uint32_t preempt_ticker_start(struct lll_event *event);
static uint32_t preempt_ticker_stop(void);
static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
uint16_t lazy, uint8_t force, void *param);
static void preempt(void *param);
@ -641,9 +639,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
/* Start the preempt timeout */
uint32_t ret;
ret = preempt_ticker_start(next, ticker_start_op_cb);
ret = preempt_ticker_start(next);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_FAILURE) ||
(ret == TICKER_STATUS_BUSY));
#else /* CONFIG_BT_CTLR_LOW_LAT */
@ -693,12 +690,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
uint32_t ret;
/* Stop any scheduled preempt ticker */
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_LLL,
TICKER_ID_LLL_PREEMPT,
ticker_stop_op_cb, NULL);
ret = preempt_ticker_stop();
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_FAILURE) ||
(ret == TICKER_STATUS_BUSY));
/* Find next prepare needing preempt timeout to be setup */
@ -710,9 +703,8 @@ int lll_prepare_resolve(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb,
} while (p->is_aborted || p->is_resume);
/* Start the preempt timeout */
ret = preempt_ticker_start(p, ticker_start_op_cb);
ret = preempt_ticker_start(p);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_FAILURE) ||
(ret == TICKER_STATUS_BUSY));
#endif /* !CONFIG_BT_CTLR_LOW_LAT */
@ -737,30 +729,37 @@ static void isr_race(void *param)
}
#if !defined(CONFIG_BT_CTLR_LOW_LAT)
static uint8_t volatile preempt_start_req;
static uint8_t preempt_start_ack;
static uint8_t volatile preempt_stop_req;
static uint8_t preempt_stop_ack;
static uint8_t preempt_req;
static uint8_t volatile preempt_ack;
static void ticker_stop_op_cb(uint32_t status, void *param)
{
/* NOTE: this callback is present only for addition of debug messages
* when needed, else can be dispensed with.
*/
ARG_UNUSED(param);
ARG_UNUSED(status);
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
(status == TICKER_STATUS_FAILURE));
LL_ASSERT(preempt_stop_req != preempt_stop_ack);
preempt_stop_ack++;
preempt_req = preempt_ack;
}
static void ticker_start_op_cb(uint32_t status, void *param)
{
/* NOTE: this callback is present only for addition of debug messages
* when needed, else can be dispensed with.
*/
ARG_UNUSED(param);
LL_ASSERT(status == TICKER_STATUS_SUCCESS);
LL_ASSERT((status == TICKER_STATUS_SUCCESS) ||
(status == TICKER_STATUS_FAILURE));
LL_ASSERT(preempt_start_req != preempt_start_ack);
preempt_start_ack++;
LL_ASSERT(preempt_req == preempt_ack);
preempt_req++;
}
static uint32_t preempt_ticker_start(struct lll_event *event,
ticker_op_func op_cb)
static uint32_t preempt_ticker_start(struct lll_event *event)
{
struct lll_prepare_param *p;
uint32_t preempt_anchor;
@ -768,6 +767,14 @@ static uint32_t preempt_ticker_start(struct lll_event *event,
uint32_t preempt_to;
uint32_t ret;
/* Do not request to start preempt timeout if already requested */
if ((preempt_start_req != preempt_start_ack) ||
(preempt_req != preempt_ack)) {
return TICKER_STATUS_SUCCESS;
}
preempt_start_req++;
/* Calc the preempt timeout */
p = &event->prepare_param;
ull = HDR_LLL2ULL(p->param);
@ -787,7 +794,31 @@ static uint32_t preempt_ticker_start(struct lll_event *event,
TICKER_NULL_LAZY,
TICKER_NULL_SLOT,
preempt_ticker_cb, event,
op_cb, event);
ticker_start_op_cb, event);
return ret;
}
static uint32_t preempt_ticker_stop(void)
{
uint32_t ret;
/* Do not request to stop preempt timeout if already requested or
* has expired
*/
if ((preempt_stop_req != preempt_stop_ack) ||
(preempt_req == preempt_ack)) {
return TICKER_STATUS_SUCCESS;
}
preempt_stop_req++;
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_LLL,
TICKER_ID_LLL_PREEMPT,
ticker_stop_op_cb, NULL);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_BUSY));
return ret;
}
@ -799,6 +830,9 @@ static void preempt_ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
static struct mayfly mfy = {0, 0, &link, NULL, preempt};
uint32_t ret;
LL_ASSERT(preempt_ack != preempt_req);
preempt_ack++;
mfy.param = param;
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
0, &mfy);
@ -839,9 +873,8 @@ static void preempt(void *param)
uint32_t ret;
/* Start the preempt timeout */
ret = preempt_ticker_start(next, ticker_start_op_cb);
ret = preempt_ticker_start(next);
LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
(ret == TICKER_STATUS_FAILURE) ||
(ret == TICKER_STATUS_BUSY));
return;