Skip to content

Commit 701c560

Browse files
cvinayakcfriedt
authored andcommitted
Bluetooth: Controller: Fix assert on aux LLL scheduled chain reception
Fix asserted in ULL due to incorrect resumption of scan window when auxiliary channel chain PDU is LLL scheduled by a ULL scheduled auxiliary channel PDU reception. The issue is solved by having `is_chain_sched` flag in the auxiliary channel scan context and using the already present `is_aux_sched` in the primary channel scan context to differentiate if the auxiliary PDU Rx ISR is to return back to primary channel scan window or to close the auxiliary chain PDU reception radio event. Relates to #38146. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent b24bbad commit 701c560

File tree

3 files changed

+54
-21
lines changed

3 files changed

+54
-21
lines changed

subsys/bluetooth/controller/ll_sw/lll_scan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct lll_scan_aux {
6262

6363
uint8_t chan:6;
6464
uint8_t state:1;
65+
uint8_t is_chain_sched:1;
6566

6667
uint8_t phy:3;
6768

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

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -586,33 +586,36 @@ void lll_scan_aux_isr_aux_setup(void *param)
586586

587587
static void isr_rx_ull_schedule(void *param)
588588
{
589-
struct lll_scan_aux *lll;
590-
struct lll_scan *scan_lll;
589+
struct lll_scan_aux *lll_aux;
590+
struct lll_scan *lll;
591591

592-
lll = param;
593-
scan_lll = ull_scan_aux_lll_parent_get(lll, NULL);
592+
lll_aux = param;
593+
lll = ull_scan_aux_lll_parent_get(lll_aux, NULL);
594594

595-
isr_rx(scan_lll, lll, lll->phy);
595+
isr_rx(lll, lll_aux, lll_aux->phy);
596596
}
597597

598598
static void isr_rx_lll_schedule(void *param)
599599
{
600-
struct lll_scan_aux *lll;
601600
struct node_rx_pdu *node_rx;
602-
struct lll_scan *scan_lll;
601+
struct lll_scan *lll;
603602
uint8_t phy_aux;
604603

605604
node_rx = param;
606-
scan_lll = node_rx->hdr.rx_ftr.param;
607-
lll = scan_lll->lll_aux;
605+
lll = node_rx->hdr.rx_ftr.param;
606+
phy_aux = node_rx->hdr.rx_ftr.aux_phy; /* PHY remembered in node rx */
608607

609-
if (lll) {
610-
phy_aux = lll->phy;
608+
/* scan context has used LLL scheduling for aux reception */
609+
if (lll->is_aux_sched) {
610+
isr_rx(lll, NULL, phy_aux);
611611
} else {
612-
phy_aux = node_rx->hdr.rx_ftr.aux_phy;
612+
/* `lll->lll_aux` would be allocated in ULL for LLL scheduled
613+
* auxiliary PDU reception by scan context and for case
614+
* where LLL scheduled chain PDU reception by aux context, it
615+
* is assigned with the current aux context's LLL context.
616+
*/
617+
isr_rx(lll, lll->lll_aux, phy_aux);
613618
}
614-
615-
isr_rx(scan_lll, NULL, phy_aux);
616619
}
617620

618621
static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
@@ -710,8 +713,16 @@ static void isr_rx(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
710713
ull_rx_sched();
711714
}
712715

713-
/* Resume scan if scanning ADV_AUX_IND chain */
714-
radio_isr_set(lll_scan_isr_resume, lll);
716+
/* Check if LLL scheduled auxiliary PDU reception by scan
717+
* context or auxiliary PDU reception by aux context
718+
*/
719+
if (lll->is_aux_sched) {
720+
/* Go back to resuming primary channel scanning */
721+
radio_isr_set(lll_scan_isr_resume, lll);
722+
} else {
723+
/* auxiliary channel radio event done */
724+
radio_isr_set(isr_done, NULL);
725+
}
715726
}
716727
radio_disable();
717728
}
@@ -1051,18 +1062,33 @@ static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
10511062
/* Passive scanner or scan responses */
10521063
#if defined(CONFIG_BT_CENTRAL)
10531064
} else if (!lll->conn &&
1054-
lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx)) {
1065+
((lll_aux && lll_aux->is_chain_sched) ||
1066+
(lll->lll_aux && lll->lll_aux->is_chain_sched) ||
1067+
lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx))) {
10551068
#else /* !CONFIG_BT_CENTRAL */
1056-
} else if (lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx)) {
1069+
} else if ((lll_aux && lll_aux->is_chain_sched) ||
1070+
(lll->lll_aux && lll->lll_aux->is_chain_sched) ||
1071+
lll_scan_ext_tgta_check(lll, false, false, pdu, rl_idx)) {
10571072
#endif /* !CONFIG_BT_CENTRAL */
10581073

10591074
ftr = &(node_rx->hdr.rx_ftr);
10601075
if (lll_aux) {
10611076
ftr->param = lll_aux;
10621077
ftr->scan_rsp = lll_aux->state;
1078+
1079+
/* Further auxiliary PDU reception will be chain PDUs */
1080+
lll_aux->is_chain_sched = 1U;
10631081
} else if (lll->lll_aux) {
10641082
ftr->param = lll;
10651083
ftr->scan_rsp = lll->lll_aux->state;
1084+
1085+
/* Auxiliary PDU received by LLL scheduling by scan
1086+
* context.
1087+
*/
1088+
lll->is_aux_sched = 1U;
1089+
1090+
/* Further auxiliary PDU reception will be chain PDUs */
1091+
lll->lll_aux->is_chain_sched = 1U;
10661092
} else {
10671093
/* Return -ECHILD, as ULL execution has not yet assigned
10681094
* an aux context. This can happen only under LLL
@@ -1113,7 +1139,6 @@ static int isr_rx_pdu(struct lll_scan *lll, struct lll_scan_aux *lll_aux,
11131139
* disable so prevent caller from doing it again.
11141140
*/
11151141
if (ftr->aux_lll_sched) {
1116-
lll->is_aux_sched = 1U;
11171142
return 0;
11181143
}
11191144

subsys/bluetooth/controller/ll_sw/ull_scan_aux.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
137137
*/
138138
lll_aux = ftr->param;
139139
aux = HDR_LLL2ULL(lll_aux);
140-
/* FIXME: pick the aux somehow */
140+
141+
/* aux parent will be NULL for periodic sync */
141142
lll = aux->parent;
142143
} else if (ull_scan_is_valid_get(HDR_LLL2ULL(ftr->param))) {
143144
/* Node that does not have valid aux context but has
@@ -157,6 +158,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
157158
*/
158159
lll = NULL;
159160
sync_lll = ftr->param;
161+
160162
lll_aux = sync_lll->lll_aux;
161163
aux = HDR_LLL2ULL(lll_aux);
162164
}
@@ -340,7 +342,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
340342
ull_sync_chm_update(rx->handle, ptr, acad_len);
341343
}
342344

343-
/* Do not ULL scheduling auxiliary PDU reception if not aux pointer
345+
/* Do not ULL schedule auxiliary PDU reception if no aux pointer
344346
* or aux pointer is zero or scannable advertising has erroneous aux
345347
* pointer being present or PHY in the aux pointer is invalid.
346348
*/
@@ -366,6 +368,7 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
366368

367369
aux->rx_head = aux->rx_last = NULL;
368370
lll_aux = &aux->lll;
371+
lll_aux->is_chain_sched = 0U;
369372

370373
ull_hdr_init(&aux->ull);
371374
lll_hdr_init(lll_aux, aux);
@@ -409,6 +412,10 @@ void ull_scan_aux_setup(memq_link_t *link, struct node_rx_hdr *rx)
409412
} else {
410413
lll->lll_aux = lll_aux;
411414
}
415+
416+
/* Reset auxiliary channel PDU scan state which otherwise is
417+
* done in the prepare_cb when ULL scheduling is used.
418+
*/
412419
lll_aux->state = 0U;
413420

414421
return;

0 commit comments

Comments
 (0)