Skip to content

Commit 247037b

Browse files
cvinayakfabiobaltieri
authored andcommitted
Bluetooth: Controller: Fix incorrect elapsed events value
Fix incorrect elapsed events value when event prepare are aborted in the pipeline. This caused premature supervision timeouts. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent e21ff70 commit 247037b

File tree

11 files changed

+100
-70
lines changed

11 files changed

+100
-70
lines changed

subsys/bluetooth/controller/ll_sw/lll_conn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct lll_conn {
4848
uint16_t latency;
4949

5050
uint16_t latency_prepare;
51+
uint16_t lazy_prepare;
5152
uint16_t latency_event;
5253
uint16_t event_counter;
5354

subsys/bluetooth/controller/ll_sw/lll_conn_iso.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct lll_conn_iso_group {
9393

9494
/* Accumulates LLL prepare callback latencies */
9595
uint16_t latency_prepare;
96+
uint16_t lazy_prepare;
9697
uint16_t latency_event;
9798

9899
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)

subsys/bluetooth/controller/ll_sw/lll_sync.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct lll_sync {
4242
#endif /* CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */
4343

4444
uint16_t skip_prepare;
45+
uint16_t lazy_prepare;
4546
uint16_t skip_event;
4647
uint16_t event_counter;
4748

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ static int prepare_cb(struct lll_prepare_param *p)
120120
lll_conn_prepare_reset();
121121

122122
/* Calculate the current event latency */
123-
lll->latency_event = lll->latency_prepare + p->lazy;
123+
lll->lazy_prepare = p->lazy;
124+
lll->latency_event = lll->latency_prepare + lll->lazy_prepare;
124125

125126
/* Calculate the current event counter value */
126127
event_counter = lll->event_counter + lll->latency_event;

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,22 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
200200
lll = prepare_param->param;
201201

202202
/* Accumulate the latency as event is aborted while being in pipeline */
203-
lll->latency_prepare += (prepare_param->lazy + 1);
203+
lll->lazy_prepare = prepare_param->lazy;
204+
lll->latency_prepare += (lll->lazy_prepare + 1U);
205+
206+
#if defined(CONFIG_BT_PERIPHERAL)
207+
if (lll->role == BT_HCI_ROLE_PERIPHERAL) {
208+
/* Accumulate window widening */
209+
lll->periph.window_widening_prepare_us +=
210+
lll->periph.window_widening_periodic_us *
211+
(prepare_param->lazy + 1);
212+
if (lll->periph.window_widening_prepare_us >
213+
lll->periph.window_widening_max_us) {
214+
lll->periph.window_widening_prepare_us =
215+
lll->periph.window_widening_max_us;
216+
}
217+
}
218+
#endif /* CONFIG_BT_PERIPHERAL */
204219

205220
/* Extra done event, to check supervision timeout */
206221
e = ull_event_done_extra_get();

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,6 @@ void lll_periph_prepare(void *param)
7979

8080
lll = p->param;
8181

82-
/* Accumulate window widening */
83-
lll->periph.window_widening_prepare_us +=
84-
lll->periph.window_widening_periodic_us * (p->lazy + 1);
85-
if (lll->periph.window_widening_prepare_us >
86-
lll->periph.window_widening_max_us) {
87-
lll->periph.window_widening_prepare_us =
88-
lll->periph.window_widening_max_us;
89-
}
90-
9182
/* Invoke common pipeline handling of prepare */
9283
err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb,
9384
0U, p);
@@ -133,7 +124,8 @@ static int prepare_cb(struct lll_prepare_param *p)
133124
lll_conn_prepare_reset();
134125

135126
/* Calculate the current event latency */
136-
lll->latency_event = lll->latency_prepare + p->lazy;
127+
lll->lazy_prepare = p->lazy;
128+
lll->latency_event = lll->latency_prepare + lll->lazy_prepare;
137129

138130
/* Calculate the current event counter value */
139131
event_counter = lll->event_counter + lll->latency_event;
@@ -161,6 +153,15 @@ static int prepare_cb(struct lll_prepare_param *p)
161153
lll->data_chan_count);
162154
}
163155

156+
/* Accumulate window widening */
157+
lll->periph.window_widening_prepare_us +=
158+
lll->periph.window_widening_periodic_us * (lll->lazy_prepare + 1U);
159+
if (lll->periph.window_widening_prepare_us >
160+
lll->periph.window_widening_max_us) {
161+
lll->periph.window_widening_prepare_us =
162+
lll->periph.window_widening_max_us;
163+
}
164+
164165
/* current window widening */
165166
lll->periph.window_widening_event_us +=
166167
lll->periph.window_widening_prepare_us;

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

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,29 +95,15 @@ void lll_peripheral_iso_prepare(void *param)
9595
{
9696
struct lll_conn_iso_group *cig_lll;
9797
struct lll_prepare_param *p;
98-
uint16_t elapsed;
9998
int err;
10099

101100
/* Initiate HF clock start up */
102101
err = lll_hfclock_on();
103102
LL_ASSERT(err >= 0);
104103

105-
/* Instants elapsed */
106104
p = param;
107-
elapsed = p->lazy + 1U;
108105

109-
/* Save the (latency + 1) for use in event and/or supervision timeout */
110106
cig_lll = p->param;
111-
cig_lll->latency_prepare += elapsed;
112-
113-
/* Accumulate window widening */
114-
cig_lll->window_widening_prepare_us_frac +=
115-
cig_lll->window_widening_periodic_us_frac * elapsed;
116-
if (cig_lll->window_widening_prepare_us_frac >
117-
EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us)) {
118-
cig_lll->window_widening_prepare_us_frac =
119-
EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us);
120-
}
121107

122108
/* Invoke common pipeline handling of prepare */
123109
err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0U, param);
@@ -152,7 +138,6 @@ static int prepare_cb(struct lll_prepare_param *p)
152138
memq_link_t *link;
153139
uint32_t start_us;
154140
uint32_t hcto;
155-
uint16_t lazy;
156141
uint32_t ret;
157142
uint8_t phy;
158143
int err = 0;
@@ -190,14 +175,23 @@ static int prepare_cb(struct lll_prepare_param *p)
190175
&data_chan_prn_s,
191176
&data_chan_remap_idx);
192177

193-
/* Store the current event latency */
194-
cig_lll->latency_event = cig_lll->latency_prepare;
195-
lazy = cig_lll->latency_prepare - 1U;
178+
/* Calculate the current event latency */
179+
cig_lll->lazy_prepare = p->lazy;
180+
cig_lll->latency_event = cig_lll->latency_prepare + cig_lll->lazy_prepare;
196181

197182
/* Reset accumulated latencies */
198183
cig_lll->latency_prepare = 0U;
199184

200-
/* current window widening */
185+
/* Accumulate window widening */
186+
cig_lll->window_widening_prepare_us_frac +=
187+
cig_lll->window_widening_periodic_us_frac * (cig_lll->lazy_prepare + 1U);
188+
if (cig_lll->window_widening_prepare_us_frac >
189+
EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us)) {
190+
cig_lll->window_widening_prepare_us_frac =
191+
EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us);
192+
}
193+
194+
/* Current window widening */
201195
cig_lll->window_widening_event_us_frac +=
202196
cig_lll->window_widening_prepare_us_frac;
203197
cig_lll->window_widening_prepare_us_frac = 0;
@@ -210,7 +204,7 @@ static int prepare_cb(struct lll_prepare_param *p)
210204
se_curr = 1U;
211205

212206
/* Adjust sn and nesn for skipped CIG events */
213-
payload_count_lazy(cis_lll, lazy);
207+
payload_count_lazy(cis_lll, cig_lll->lazy_prepare);
214208

215209
/* Start setting up of Radio h/w */
216210
radio_reset();
@@ -381,7 +375,7 @@ static int prepare_cb(struct lll_prepare_param *p)
381375
}
382376

383377
/* Adjust sn and nesn for skipped CIG events */
384-
payload_count_lazy(cis_lll, lazy);
378+
payload_count_lazy(cis_lll, cig_lll->lazy_prepare);
385379

386380
/* Adjust sn and nesn for canceled events */
387381
if (err) {
@@ -405,13 +399,13 @@ static int prepare_cb(struct lll_prepare_param *p)
405399

406400
static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
407401
{
402+
struct lll_conn_iso_group *cig_lll;
408403
int err;
409404

410405
/* NOTE: This is not a prepare being cancelled */
411406
if (!prepare_param) {
412407
struct lll_conn_iso_stream *next_cis_lll;
413408
struct lll_conn_iso_stream *cis_lll;
414-
struct lll_conn_iso_group *cig_lll;
415409

416410
cis_lll = ull_conn_iso_lll_stream_get(cis_handle_curr);
417411
cig_lll = param;
@@ -442,6 +436,22 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
442436
err = lll_hfclock_off();
443437
LL_ASSERT(err >= 0);
444438

439+
/* Get reference to CIG LLL context */
440+
cig_lll = prepare_param->param;
441+
442+
/* Accumulate the latency as event is aborted while being in pipeline */
443+
cig_lll->lazy_prepare = prepare_param->lazy;
444+
cig_lll->latency_prepare += (cig_lll->lazy_prepare + 1U);
445+
446+
/* Accumulate window widening */
447+
cig_lll->window_widening_prepare_us_frac +=
448+
cig_lll->window_widening_periodic_us_frac * (cig_lll->lazy_prepare + 1U);
449+
if (cig_lll->window_widening_prepare_us_frac >
450+
EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us)) {
451+
cig_lll->window_widening_prepare_us_frac =
452+
EVENT_US_TO_US_FRAC(cig_lll->window_widening_max_us);
453+
}
454+
445455
lll_done(param);
446456
}
447457

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,11 @@ static void prepare(void *param)
132132

133133
lll = p->param;
134134

135+
lll->lazy_prepare = p->lazy;
136+
135137
/* Accumulate window widening */
136138
lll->window_widening_prepare_us += lll->window_widening_periodic_us *
137-
(p->lazy + 1U);
139+
(lll->lazy_prepare + 1U);
138140
if (lll->window_widening_prepare_us > lll->window_widening_max_us) {
139141
lll->window_widening_prepare_us = lll->window_widening_max_us;
140142
}
@@ -272,7 +274,7 @@ static int create_prepare_cb(struct lll_prepare_param *p)
272274
lll = p->param;
273275

274276
/* Calculate the current event latency */
275-
lll->skip_event = lll->skip_prepare + p->lazy;
277+
lll->skip_event = lll->skip_prepare + lll->lazy_prepare;
276278

277279
/* Calculate the current event counter value */
278280
event_counter = lll->event_counter + lll->skip_event;
@@ -360,7 +362,7 @@ static int prepare_cb(struct lll_prepare_param *p)
360362
lll = p->param;
361363

362364
/* Calculate the current event latency */
363-
lll->skip_event = lll->skip_prepare + p->lazy;
365+
lll->skip_event = lll->skip_prepare + lll->lazy_prepare;
364366

365367
/* Calculate the current event counter value */
366368
event_counter = lll->event_counter + lll->skip_event;
@@ -631,7 +633,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
631633

632634
/* Accumulate the latency as event is aborted while being in pipeline */
633635
lll = prepare_param->param;
634-
lll->skip_prepare += (prepare_param->lazy + 1U);
636+
lll->skip_prepare += (lll->lazy_prepare + 1U);
635637

636638
/* Extra done event, to check sync lost */
637639
e = ull_event_done_extra_get();

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,11 +1015,6 @@ void ull_conn_done(struct node_rx_event_done *done)
10151015
#else
10161016
latency_event = lll->latency_event;
10171017
#endif
1018-
if (lll->latency_prepare) {
1019-
elapsed_event = latency_event + lll->latency_prepare;
1020-
} else {
1021-
elapsed_event = latency_event + 1U;
1022-
}
10231018

10241019
/* Peripheral drift compensation calc and new latency or
10251020
* central terminate acked
@@ -1054,6 +1049,8 @@ void ull_conn_done(struct node_rx_event_done *done)
10541049
conn->connect_expire = 0U;
10551050
}
10561051

1052+
elapsed_event = latency_event + lll->lazy_prepare + 1U;
1053+
10571054
/* Reset supervision countdown */
10581055
if (done->extra.crc_valid && !done->extra.is_aborted) {
10591056
conn->supervision_expire = 0U;

subsys/bluetooth/controller/ll_sw/ull_conn_iso.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -489,22 +489,26 @@ void ull_conn_iso_done(struct node_rx_event_done *done)
489489
conn->supervision_timeout * 10U * 1000U,
490490
cig->iso_interval * CONN_INT_UNIT_US);
491491

492-
} else if (cis->event_expire > cig->lll.latency_event) {
493-
cis->event_expire -= cig->lll.latency_event;
494-
495492
} else {
496-
cis->event_expire = 0U;
497-
498-
/* Stop CIS and defer cleanup to after teardown. This will
499-
* only generate a terminate event to the host if CIS has
500-
* been established. If CIS was not established, the
501-
* teardown will send CIS_ESTABLISHED with failure.
502-
*/
503-
ull_conn_iso_cis_stop(cis, NULL,
504-
cis->established ?
505-
BT_HCI_ERR_CONN_TIMEOUT :
506-
BT_HCI_ERR_CONN_FAIL_TO_ESTAB);
507-
493+
uint16_t event_elapsed;
494+
495+
event_elapsed = cig->lll.latency_event +
496+
cig->lll.lazy_prepare + 1U;
497+
if (cis->event_expire > event_elapsed) {
498+
cis->event_expire -= event_elapsed;
499+
} else {
500+
cis->event_expire = 0U;
501+
502+
/* Stop CIS and defer cleanup to after teardown.
503+
* This will only generate a terminate event to the
504+
* host if CIS has been established. If CIS was not
505+
* established, the teardown will send
506+
* CIS_ESTABLISHED with failure.
507+
*/
508+
ull_conn_iso_cis_stop(cis, NULL, cis->established ?
509+
BT_HCI_ERR_CONN_TIMEOUT :
510+
BT_HCI_ERR_CONN_FAIL_TO_ESTAB);
511+
}
508512
}
509513
}
510514
}

0 commit comments

Comments
 (0)