Skip to content

Commit ca44b34

Browse files
cvinayakcarlescufi
authored andcommitted
Bluetooth: Controller: Fix ISO Sync Receiver reception abort
Fix ISO Sync Receiver PDU reception to enqueue towards ULL any PDUs that where received before the BIG event in unreserved timespace is aborted due to overlap with other radio events. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent b4538ff commit ca44b34

File tree

1 file changed

+164
-133
lines changed

1 file changed

+164
-133
lines changed

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

Lines changed: 164 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ static int prepare_cb_common(struct lll_prepare_param *p);
4747
static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
4848
static void isr_rx_estab(void *param);
4949
static void isr_rx(void *param);
50+
static void isr_rx_done(void *param);
51+
static void isr_done(void *param);
5052
static void next_chan_calc(struct lll_sync_iso *lll, uint16_t event_counter,
5153
uint16_t data_chan_id);
5254
static void isr_rx_iso_data_valid(const struct lll_sync_iso *const lll,
@@ -398,7 +400,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
398400

399401
/* NOTE: This is not a prepare being cancelled */
400402
if (!prepare_param) {
401-
radio_isr_set(lll_isr_done, param);
403+
radio_isr_set(isr_done, param);
402404
radio_disable();
403405
return;
404406
}
@@ -480,7 +482,6 @@ static void isr_rx(void *param)
480482
{
481483
struct lll_sync_iso_stream *stream;
482484
struct node_rx_pdu *node_rx;
483-
struct event_done_extra *e;
484485
struct lll_sync_iso *lll;
485486
uint8_t access_addr[4];
486487
uint16_t data_chan_id;
@@ -497,7 +498,6 @@ static void isr_rx(void *param)
497498
uint32_t hcto;
498499
uint8_t bis;
499500
uint8_t nse;
500-
uint8_t bn;
501501

502502
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
503503
lll_prof_latency_capture();
@@ -813,136 +813,7 @@ static void isr_rx(void *param)
813813
goto isr_rx_next_subevent;
814814
}
815815

816-
/* Enqueue PDUs to ULL */
817-
node_rx = NULL;
818-
lll->stream_curr = 0U;
819-
payload_index = lll->payload_tail;
820-
for (bis_idx = 0U; bis_idx < lll->num_bis; bis_idx++) {
821-
struct lll_sync_iso_stream *stream;
822-
uint8_t payload_tail;
823-
uint8_t stream_curr;
824-
uint16_t stream_handle;
825-
826-
stream_handle = lll->stream_handle[lll->stream_curr];
827-
stream = ull_sync_iso_lll_stream_get(stream_handle);
828-
/* Skip BIS indices not synchronized. bis_index is 0x01 to 0x1F,
829-
* where as bis_idx is 0 indexed.
830-
*/
831-
if ((bis_idx + 1U) != stream->bis_index) {
832-
continue;
833-
}
834-
835-
payload_tail = lll->payload_tail;
836-
bn = lll->bn;
837-
while (bn--) {
838-
if (lll->payload[bis_idx][payload_tail]) {
839-
node_rx =
840-
lll->payload[bis_idx][payload_tail];
841-
lll->payload[bis_idx][payload_tail] = NULL;
842-
843-
iso_rx_put(node_rx->hdr.link, node_rx);
844-
} else {
845-
/* Check if there are 2 free rx buffers, one
846-
* will be consumed to generate PDU with invalid
847-
* status, and the other is to ensure a PDU can
848-
* be setup for the radio DMA to receive in the
849-
* next sub_interval/iso_interval.
850-
*/
851-
node_rx = ull_iso_pdu_rx_alloc_peek(2U);
852-
if (node_rx) {
853-
struct pdu_bis *pdu;
854-
uint16_t handle;
855-
856-
ull_iso_pdu_rx_alloc();
857-
858-
pdu = (void *)node_rx->pdu;
859-
pdu->ll_id = PDU_BIS_LLID_COMPLETE_END;
860-
pdu->len = 0U;
861-
862-
handle = LL_BIS_SYNC_HANDLE_FROM_IDX(stream_handle);
863-
isr_rx_iso_data_invalid(lll, bn, handle,
864-
node_rx);
865-
866-
iso_rx_put(node_rx->hdr.link, node_rx);
867-
}
868-
}
869-
870-
payload_index = payload_tail + 1U;
871-
if (payload_index >= lll->payload_count_max) {
872-
payload_index = 0U;
873-
}
874-
payload_tail = payload_index;
875-
}
876-
877-
stream_curr = lll->stream_curr + 1U;
878-
if (stream_curr < lll->stream_count) {
879-
lll->stream_curr = stream_curr;
880-
}
881-
}
882-
lll->payload_tail = payload_index;
883-
884-
#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
885-
if (node_rx) {
886-
iso_rx_sched();
887-
}
888-
#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
889-
890-
e = ull_event_done_extra_get();
891-
LL_ASSERT(e);
892-
893-
/* Check if BIG terminate procedure received */
894-
if (lll->term_reason) {
895-
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_TERMINATE;
896-
897-
lll_isr_cleanup(param);
898-
899-
return;
900-
901-
/* Check if BIG Channel Map Update */
902-
} else if (lll->chm_chan_count) {
903-
const uint16_t event_counter = lll->payload_count / lll->bn;
904-
905-
/* Bluetooth Core Specification v5.3 Vol 6, Part B,
906-
* Section 5.5.2 BIG Control Procedures
907-
*
908-
* When a Synchronized Receiver receives such a PDU where
909-
* (instant - bigEventCounter) mod 65536 is greater than or
910-
* equal to 32767 (because the instant is in the past), the
911-
* the Link Layer may stop synchronization with the BIG.
912-
*/
913-
914-
/* Note: We are not validating whether the control PDU was
915-
* received after the instant but apply the new channel map.
916-
* If the channel map was new at or after the instant and the
917-
* the channel at the event counter did not match then the
918-
* control PDU would not have been received.
919-
*/
920-
if (((event_counter - lll->ctrl_instant) & 0xFFFF) <= 0x7FFF) {
921-
(void)memcpy(lll->data_chan_map, lll->chm_chan_map,
922-
sizeof(lll->data_chan_map));
923-
lll->data_chan_count = lll->chm_chan_count;
924-
lll->chm_chan_count = 0U;
925-
}
926-
}
927-
928-
/* Calculate and place the drift information in done event */
929-
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO;
930-
e->trx_cnt = trx_cnt;
931-
e->crc_valid = crc_ok_anchor;
932-
933-
if (trx_cnt) {
934-
e->drift.preamble_to_addr_us = addr_us_get(lll->phy);
935-
e->drift.start_to_address_actual_us =
936-
radio_tmr_aa_restore() - radio_tmr_ready_restore();
937-
e->drift.window_widening_event_us =
938-
lll->window_widening_event_us;
939-
940-
/* Reset window widening, as anchor point sync-ed */
941-
lll->window_widening_event_us = 0U;
942-
lll->window_size_event_us = 0U;
943-
}
944-
945-
lll_isr_cleanup(param);
816+
isr_rx_done(param);
946817

947818
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
948819
lll_prof_send();
@@ -1149,6 +1020,166 @@ static void isr_rx(void *param)
11491020
}
11501021
}
11511022

1023+
static void isr_rx_done(void *param)
1024+
{
1025+
struct node_rx_pdu *node_rx;
1026+
struct event_done_extra *e;
1027+
struct lll_sync_iso *lll;
1028+
uint8_t payload_index;
1029+
uint8_t bis_idx;
1030+
uint8_t bn;
1031+
1032+
/* Enqueue PDUs to ULL */
1033+
node_rx = NULL;
1034+
lll = param;
1035+
lll->stream_curr = 0U;
1036+
payload_index = lll->payload_tail;
1037+
for (bis_idx = 0U; bis_idx < lll->num_bis; bis_idx++) {
1038+
struct lll_sync_iso_stream *stream;
1039+
uint8_t payload_tail;
1040+
uint8_t stream_curr;
1041+
uint16_t stream_handle;
1042+
1043+
stream_handle = lll->stream_handle[lll->stream_curr];
1044+
stream = ull_sync_iso_lll_stream_get(stream_handle);
1045+
/* Skip BIS indices not synchronized. bis_index is 0x01 to 0x1F,
1046+
* where as bis_idx is 0 indexed.
1047+
*/
1048+
if ((bis_idx + 1U) != stream->bis_index) {
1049+
continue;
1050+
}
1051+
1052+
payload_tail = lll->payload_tail;
1053+
bn = lll->bn;
1054+
while (bn--) {
1055+
if (lll->payload[bis_idx][payload_tail]) {
1056+
node_rx =
1057+
lll->payload[bis_idx][payload_tail];
1058+
lll->payload[bis_idx][payload_tail] = NULL;
1059+
1060+
iso_rx_put(node_rx->hdr.link, node_rx);
1061+
} else {
1062+
/* Check if there are 2 free rx buffers, one
1063+
* will be consumed to generate PDU with invalid
1064+
* status, and the other is to ensure a PDU can
1065+
* be setup for the radio DMA to receive in the
1066+
* next sub_interval/iso_interval.
1067+
*/
1068+
node_rx = ull_iso_pdu_rx_alloc_peek(2U);
1069+
if (node_rx) {
1070+
struct pdu_bis *pdu;
1071+
uint16_t handle;
1072+
1073+
ull_iso_pdu_rx_alloc();
1074+
1075+
pdu = (void *)node_rx->pdu;
1076+
pdu->ll_id = PDU_BIS_LLID_COMPLETE_END;
1077+
pdu->len = 0U;
1078+
1079+
handle = LL_BIS_SYNC_HANDLE_FROM_IDX(stream_handle);
1080+
isr_rx_iso_data_invalid(lll, bn, handle,
1081+
node_rx);
1082+
1083+
iso_rx_put(node_rx->hdr.link, node_rx);
1084+
}
1085+
}
1086+
1087+
payload_index = payload_tail + 1U;
1088+
if (payload_index >= lll->payload_count_max) {
1089+
payload_index = 0U;
1090+
}
1091+
payload_tail = payload_index;
1092+
}
1093+
1094+
stream_curr = lll->stream_curr + 1U;
1095+
if (stream_curr < lll->stream_count) {
1096+
lll->stream_curr = stream_curr;
1097+
}
1098+
}
1099+
lll->payload_tail = payload_index;
1100+
1101+
#if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL)
1102+
if (node_rx) {
1103+
iso_rx_sched();
1104+
}
1105+
#endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */
1106+
1107+
e = ull_event_done_extra_get();
1108+
LL_ASSERT(e);
1109+
1110+
/* Check if BIG terminate procedure received */
1111+
if (lll->term_reason) {
1112+
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_TERMINATE;
1113+
1114+
goto isr_done_cleanup;
1115+
1116+
/* Check if BIG Channel Map Update */
1117+
} else if (lll->chm_chan_count) {
1118+
const uint16_t event_counter = lll->payload_count / lll->bn;
1119+
1120+
/* Bluetooth Core Specification v5.3 Vol 6, Part B,
1121+
* Section 5.5.2 BIG Control Procedures
1122+
*
1123+
* When a Synchronized Receiver receives such a PDU where
1124+
* (instant - bigEventCounter) mod 65536 is greater than or
1125+
* equal to 32767 (because the instant is in the past), the
1126+
* the Link Layer may stop synchronization with the BIG.
1127+
*/
1128+
1129+
/* Note: We are not validating whether the control PDU was
1130+
* received after the instant but apply the new channel map.
1131+
* If the channel map was new at or after the instant and the
1132+
* the channel at the event counter did not match then the
1133+
* control PDU would not have been received.
1134+
*/
1135+
if (((event_counter - lll->ctrl_instant) & 0xFFFF) <= 0x7FFF) {
1136+
(void)memcpy(lll->data_chan_map, lll->chm_chan_map,
1137+
sizeof(lll->data_chan_map));
1138+
lll->data_chan_count = lll->chm_chan_count;
1139+
lll->chm_chan_count = 0U;
1140+
}
1141+
}
1142+
1143+
/* Calculate and place the drift information in done event */
1144+
e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO;
1145+
e->trx_cnt = trx_cnt;
1146+
e->crc_valid = crc_ok_anchor;
1147+
1148+
if (trx_cnt) {
1149+
e->drift.preamble_to_addr_us = addr_us_get(lll->phy);
1150+
e->drift.start_to_address_actual_us =
1151+
radio_tmr_aa_restore() - radio_tmr_ready_restore();
1152+
e->drift.window_widening_event_us =
1153+
lll->window_widening_event_us;
1154+
1155+
/* Reset window widening, as anchor point sync-ed */
1156+
lll->window_widening_event_us = 0U;
1157+
lll->window_size_event_us = 0U;
1158+
}
1159+
1160+
isr_done_cleanup:
1161+
lll_isr_cleanup(param);
1162+
}
1163+
1164+
static void isr_done(void *param)
1165+
{
1166+
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1167+
lll_prof_latency_capture();
1168+
}
1169+
1170+
lll_isr_status_reset();
1171+
1172+
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1173+
lll_prof_cputime_capture();
1174+
}
1175+
1176+
isr_rx_done(param);
1177+
1178+
if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
1179+
lll_prof_send();
1180+
}
1181+
}
1182+
11521183
static void next_chan_calc(struct lll_sync_iso *lll, uint16_t event_counter,
11531184
uint16_t data_chan_id)
11541185
{

0 commit comments

Comments
 (0)