Bluetooth: Controller: Fix missing supervision/sync lost
When radio event prepare is cancelled due to preemption by overlapping radio events, the extra done event processing was missing and hence the use of accumulated prepares' skip/latency count. This caused the check for supervision timeout and sync lost not be aware of the elapsed events. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
38905eb0ab
commit
f11fe69450
6 changed files with 73 additions and 5 deletions
|
@ -149,6 +149,7 @@ void lll_conn_prepare_reset(void)
|
|||
|
||||
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||
{
|
||||
struct event_done_extra *e;
|
||||
struct lll_conn *lll;
|
||||
int err;
|
||||
|
||||
|
@ -173,6 +174,17 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
|||
lll = prepare_param->param;
|
||||
lll->latency_prepare += (prepare_param->lazy + 1);
|
||||
|
||||
/* Extra done event, to check supervision timeout */
|
||||
e = ull_event_done_extra_get();
|
||||
LL_ASSERT(e);
|
||||
|
||||
e->type = EVENT_DONE_EXTRA_TYPE_CONN;
|
||||
e->trx_cnt = 0U;
|
||||
e->crc_valid = 0U;
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
e->mic_state = LLL_CONN_MIC_NONE;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
lll_done(param);
|
||||
}
|
||||
|
||||
|
|
|
@ -532,6 +532,7 @@ static int is_abort_cb(void *next, void *curr, lll_prepare_cb_t *resume_cb)
|
|||
|
||||
static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||
{
|
||||
struct event_done_extra *e;
|
||||
struct lll_sync *lll;
|
||||
int err;
|
||||
|
||||
|
@ -557,6 +558,20 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
|||
lll = prepare_param->param;
|
||||
lll->skip_prepare += (prepare_param->lazy + 1U);
|
||||
|
||||
/* Extra done event, to check sync lost */
|
||||
e = ull_event_done_extra_get();
|
||||
LL_ASSERT(e);
|
||||
|
||||
e->type = EVENT_DONE_EXTRA_TYPE_SYNC;
|
||||
e->trx_cnt = 0U;
|
||||
e->crc_valid = 0U;
|
||||
#if defined(CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING) && \
|
||||
defined(CONFIG_BT_CTLR_CTEINLINE_SUPPORT)
|
||||
e->sync_term = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC_CTE_TYPE_FILTERING &&
|
||||
* CONFIG_BT_CTLR_CTEINLINE_SUPPORT
|
||||
*/
|
||||
|
||||
lll_done(param);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ static void prepare_bh(void *param);
|
|||
static int create_prepare_cb(struct lll_prepare_param *p);
|
||||
static int prepare_cb(struct lll_prepare_param *p);
|
||||
static int prepare_cb_common(struct lll_prepare_param *p);
|
||||
static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
|
||||
static void isr_rx_estab(void *param);
|
||||
static void isr_rx(void *param);
|
||||
static void isr_rx_iso_data_valid(const struct lll_sync_iso *const lll,
|
||||
|
@ -131,7 +132,7 @@ static void create_prepare_bh(void *param)
|
|||
int err;
|
||||
|
||||
/* Invoke common pipeline handling of prepare */
|
||||
err = lll_prepare(lll_is_abort_cb, lll_abort_cb, create_prepare_cb, 0U,
|
||||
err = lll_prepare(lll_is_abort_cb, abort_cb, create_prepare_cb, 0U,
|
||||
param);
|
||||
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||
}
|
||||
|
@ -141,7 +142,7 @@ static void prepare_bh(void *param)
|
|||
int err;
|
||||
|
||||
/* Invoke common pipeline handling of prepare */
|
||||
err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0U, param);
|
||||
err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0U, param);
|
||||
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||
}
|
||||
|
||||
|
@ -335,6 +336,34 @@ static int prepare_cb_common(struct lll_prepare_param *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||
{
|
||||
struct event_done_extra *e;
|
||||
int err;
|
||||
|
||||
/* NOTE: This is not a prepare being cancelled */
|
||||
if (!prepare_param) {
|
||||
radio_isr_set(lll_isr_done, param);
|
||||
radio_disable();
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: Else clean the top half preparations of the aborted event
|
||||
* currently in preparation pipeline.
|
||||
*/
|
||||
err = lll_hfclock_off();
|
||||
LL_ASSERT(err >= 0);
|
||||
|
||||
/* Extra done event, to check sync lost */
|
||||
e = ull_event_done_extra_get();
|
||||
LL_ASSERT(e);
|
||||
|
||||
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO;
|
||||
e->trx_cnt = 0U;
|
||||
e->crc_valid = 0U;
|
||||
|
||||
lll_done(param);
|
||||
}
|
||||
|
||||
static void isr_rx_estab(void *param)
|
||||
{
|
||||
|
|
|
@ -1552,7 +1552,11 @@ void ull_conn_done(struct node_rx_event_done *done)
|
|||
#else
|
||||
latency_event = lll->latency_event;
|
||||
#endif
|
||||
elapsed_event = latency_event + 1;
|
||||
if (lll->latency_prepare) {
|
||||
elapsed_event = latency_event + lll->latency_prepare;
|
||||
} else {
|
||||
elapsed_event = latency_event + 1U;
|
||||
}
|
||||
|
||||
/* Peripheral drift compensation calc and new latency or
|
||||
* central terminate acked
|
||||
|
|
|
@ -983,7 +983,11 @@ void ull_sync_done(struct node_rx_event_done *done)
|
|||
|
||||
/* Events elapsed used in timeout checks below */
|
||||
skip_event = lll->skip_event;
|
||||
elapsed_event = skip_event + 1;
|
||||
if (lll->skip_prepare) {
|
||||
elapsed_event = skip_event + lll->skip_prepare;
|
||||
} else {
|
||||
elapsed_event = skip_event + 1U;
|
||||
}
|
||||
|
||||
/* Sync drift compensation and new skip calculation */
|
||||
ticks_drift_plus = 0U;
|
||||
|
|
|
@ -516,7 +516,11 @@ void ull_sync_iso_done(struct node_rx_event_done *done)
|
|||
|
||||
/* Events elapsed used in timeout checks below */
|
||||
latency_event = lll->latency_event;
|
||||
if (lll->latency_prepare) {
|
||||
elapsed_event = latency_event + lll->latency_prepare;
|
||||
} else {
|
||||
elapsed_event = latency_event + 1U;
|
||||
}
|
||||
|
||||
/* Sync drift compensation and new skip calculation
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue