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)
|
void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||||
{
|
{
|
||||||
|
struct event_done_extra *e;
|
||||||
struct lll_conn *lll;
|
struct lll_conn *lll;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -173,6 +174,17 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||||
lll = prepare_param->param;
|
lll = prepare_param->param;
|
||||||
lll->latency_prepare += (prepare_param->lazy + 1);
|
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);
|
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)
|
static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||||
{
|
{
|
||||||
|
struct event_done_extra *e;
|
||||||
struct lll_sync *lll;
|
struct lll_sync *lll;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -557,6 +558,20 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||||
lll = prepare_param->param;
|
lll = prepare_param->param;
|
||||||
lll->skip_prepare += (prepare_param->lazy + 1U);
|
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);
|
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 create_prepare_cb(struct lll_prepare_param *p);
|
||||||
static int 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 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_estab(void *param);
|
||||||
static void isr_rx(void *param);
|
static void isr_rx(void *param);
|
||||||
static void isr_rx_iso_data_valid(const struct lll_sync_iso *const lll,
|
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;
|
int err;
|
||||||
|
|
||||||
/* Invoke common pipeline handling of prepare */
|
/* 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);
|
param);
|
||||||
LL_ASSERT(!err || err == -EINPROGRESS);
|
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,7 @@ static void prepare_bh(void *param)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Invoke common pipeline handling of prepare */
|
/* 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);
|
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +336,34 @@ static int prepare_cb_common(struct lll_prepare_param *p)
|
||||||
return 0;
|
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)
|
static void isr_rx_estab(void *param)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1552,7 +1552,11 @@ void ull_conn_done(struct node_rx_event_done *done)
|
||||||
#else
|
#else
|
||||||
latency_event = lll->latency_event;
|
latency_event = lll->latency_event;
|
||||||
#endif
|
#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
|
/* Peripheral drift compensation calc and new latency or
|
||||||
* central terminate acked
|
* central terminate acked
|
||||||
|
|
|
@ -983,7 +983,11 @@ void ull_sync_done(struct node_rx_event_done *done)
|
||||||
|
|
||||||
/* Events elapsed used in timeout checks below */
|
/* Events elapsed used in timeout checks below */
|
||||||
skip_event = lll->skip_event;
|
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 */
|
/* Sync drift compensation and new skip calculation */
|
||||||
ticks_drift_plus = 0U;
|
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 */
|
/* Events elapsed used in timeout checks below */
|
||||||
latency_event = lll->latency_event;
|
latency_event = lll->latency_event;
|
||||||
elapsed_event = latency_event + 1U;
|
if (lll->latency_prepare) {
|
||||||
|
elapsed_event = latency_event + lll->latency_prepare;
|
||||||
|
} else {
|
||||||
|
elapsed_event = latency_event + 1U;
|
||||||
|
}
|
||||||
|
|
||||||
/* Sync drift compensation and new skip calculation
|
/* Sync drift compensation and new skip calculation
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue