Bluetooth: Controller: Fix incorrect event_count when CIG overlaps

Fix incorrect event_count use in CIG events when the next
CIG interval's prepare overlaps with the current CIG event.
Use separate event_count_prepare variable in ULL and copy
the value in LLL event.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2025-01-28 09:44:06 +01:00 committed by Benjamin Cabé
parent 3bf330855e
commit be91cfedfb
6 changed files with 30 additions and 7 deletions

View File

@ -45,7 +45,8 @@ struct lll_conn_iso_stream {
struct lll_conn_iso_stream_rxtx tx; /* TX parameters */
/* Event and payload counters */
uint64_t event_count:39; /* cisEventCount */
uint64_t event_count_prepare:39; /* cisEventCount in overlapping CIG prepare */
uint64_t event_count:39; /* cisEventCount in current CIG event */
/* Acknowledgment and flow control */
uint8_t sn:1; /* Sequence number */

View File

@ -150,6 +150,9 @@ static int prepare_cb(struct lll_prepare_param *p)
/* Get reference to ACL context */
conn_lll = ull_conn_lll_get(cis_lll->acl_handle);
/* Pick the event_count calculated in the ULL prepare */
cis_lll->event_count = cis_lll->event_count_prepare;
/* Event counter value, 0-15 bit of cisEventCounter */
event_counter = cis_lll->event_count;
@ -357,6 +360,9 @@ static int prepare_cb(struct lll_prepare_param *p)
do {
cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle);
if (cis_lll && cis_lll->active) {
/* Pick the event_count calculated in the ULL prepare */
cis_lll->event_count = cis_lll->event_count_prepare;
/* Adjust sn and nesn for skipped CIG events */
payload_count_lazy_update(cis_lll, cig_lll->latency_event);

View File

@ -164,6 +164,9 @@ static int prepare_cb(struct lll_prepare_param *p)
/* Get reference to ACL context */
conn_lll = ull_conn_lll_get(cis_lll->acl_handle);
/* Pick the event_count calculated in the ULL prepare */
cis_lll->event_count = cis_lll->event_count_prepare;
/* Event counter value, 0-15 bit of cisEventCounter */
event_counter = cis_lll->event_count;
@ -374,6 +377,9 @@ static int prepare_cb(struct lll_prepare_param *p)
break;
}
/* Pick the event_count calculated in the ULL prepare */
cis_lll->event_count = cis_lll->event_count_prepare;
/* Adjust sn and nesn for skipped CIG events */
payload_count_lazy(cis_lll, cig_lll->latency_event);

View File

@ -929,6 +929,11 @@ uint8_t ull_central_iso_setup(uint16_t cis_handle,
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
cis->pkt_seq_num = 0U;
#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
/* It is intentional to initialize to the 39 bit maximum value and rollover to 0 in the
* prepare function, the event counter is pre-incremented in prepare function for the
* current ISO event.
*/
cis->lll.event_count_prepare = LLL_CONN_ISO_EVENT_COUNT_MAX;
cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX;
cis->lll.next_subevent = 0U;
cis->lll.tifs_us = conn->lll.tifs_cis_us;

View File

@ -711,17 +711,17 @@ void ull_conn_iso_ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
* has been reached, and offset calculated.
*/
if (cis->lll.handle != 0xFFFF && cis->lll.active) {
cis->lll.event_count += (lazy + 1U);
cis->lll.event_count_prepare += (lazy + 1U);
#if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
cis->lll.event_count -= cis->lll.lazy_active;
cis->lll.event_count_prepare -= cis->lll.lazy_active;
cis->lll.lazy_active = 0U;
#endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */
leading_event_count = MAX(leading_event_count,
cis->lll.event_count);
cis->lll.event_count_prepare);
ull_iso_lll_event_prepare(cis->lll.handle, cis->lll.event_count);
ull_iso_lll_event_prepare(cis->lll.handle, cis->lll.event_count_prepare);
}
/* Latch datapath validity entering event */
@ -975,7 +975,7 @@ void ull_conn_iso_start(struct ll_conn *conn, uint16_t cis_handle,
cis_offset = cis->offset + iso_interval_us - acl_latency_us;
}
cis->lll.event_count += lost_cig_events;
cis->lll.event_count_prepare += lost_cig_events;
lost_payloads = (lost_cig_events - (cis->lll.rx.ft - 1)) * cis->lll.rx.bn;
cis->lll.rx.payload_count += lost_payloads;
@ -1520,7 +1520,7 @@ void ull_conn_iso_transmit_test_cig_interval(uint16_t handle, uint32_t ticks_at_
* on 64-bit sdu_counter:
* (39 bits x 22 bits (4x10^6 us) = 61 bits / 8 bits (255 us) = 53 bits)
*/
sdu_counter = DIV_ROUND_UP((cis->lll.event_count + 1U) * iso_interval,
sdu_counter = DIV_ROUND_UP((cis->lll.event_count_prepare + 1U) * iso_interval,
sdu_interval);
if (cis->hdr.test_mode.tx.sdu_counter == 0U) {

View File

@ -333,6 +333,11 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind,
#if defined(CONFIG_BT_CTLR_ISOAL_PSN_IGNORE)
cis->pkt_seq_num = 0U;
#endif /* CONFIG_BT_CTLR_ISOAL_PSN_IGNORE */
/* It is intentional to initialize to the 39 bit maximum value and rollover to 0 in the
* prepare function, the event counter is pre-incremented in prepare function for the
* current ISO event.
*/
cis->lll.event_count_prepare = LLL_CONN_ISO_EVENT_COUNT_MAX;
cis->lll.event_count = LLL_CONN_ISO_EVENT_COUNT_MAX;
cis->lll.next_subevent = 0U;
cis->lll.tifs_us = conn->lll.tifs_cis_us;