Skip to content

Bluetooth: Controller: Fix LLCP event_counter value used during prepare #92726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion subsys/bluetooth/controller/ll_sw/ull_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2177,6 +2177,11 @@ void ull_conn_resume_rx_data(struct ll_conn *conn)
}
#endif /* CONFIG_BT_CTLR_LE_ENC */

uint16_t ull_conn_event_counter_at_prepare(const struct ll_conn *conn)
{
return conn->lll.event_counter + conn->lll.latency_prepare + conn->llcp.prep.lazy;
}

uint16_t ull_conn_event_counter(struct ll_conn *conn)
{
struct lll_conn *lll;
Expand Down Expand Up @@ -2204,6 +2209,7 @@ uint16_t ull_conn_event_counter(struct ll_conn *conn)

return event_counter;
}

static void ull_conn_update_ticker(struct ll_conn *conn,
uint32_t ticks_win_offset,
uint32_t ticks_slot_overhead,
Expand Down Expand Up @@ -2281,7 +2287,7 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_
lll = &conn->lll;

/* Calculate current event counter */
event_counter = ull_conn_event_counter(conn);
event_counter = ull_conn_event_counter_at_prepare(conn);

instant_latency = (event_counter - instant) & 0xFFFF;

Expand Down
1 change: 1 addition & 0 deletions subsys/bluetooth/controller/ll_sw/ull_conn_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ static inline void cpr_active_reset(void)
void ull_conn_past_sender_offset_request(struct ll_conn *conn);
#endif /* CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER */

uint16_t ull_conn_event_counter_at_prepare(const struct ll_conn *conn);
uint16_t ull_conn_event_counter(struct ll_conn *conn);

void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc,
Expand Down
34 changes: 26 additions & 8 deletions subsys/bluetooth/controller/ll_sw/ull_llcp_cc.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ enum {
RP_CC_EVT_UNKNOWN,
};

static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param);
static void rp_cc_check_instant_rx_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param);

/*
* LLCP Remote Procedure FSM
Expand Down Expand Up @@ -485,7 +485,7 @@ static void rp_cc_state_wait_rx_cis_ind(struct ll_conn *conn, struct proc_ctx *c
llcp_rx_node_retain(ctx);

/* Check if this connection event is where we need to start the CIS */
rp_cc_check_instant(conn, ctx, evt, param);
rp_cc_check_instant_rx_cis_ind(conn, ctx, evt, param);
break;
}
/* If we get to here the CIG_ID referred in req/acquire has become void/invalid */
Expand Down Expand Up @@ -523,13 +523,11 @@ static void rp_cc_state_wait_ntf_avail(struct ll_conn *conn, struct proc_ctx *ct
}


static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
static void rp_cc_check_instant_by_counter(struct ll_conn *conn, struct proc_ctx *ctx,
uint16_t event_counter, uint8_t evt, void *param)
{
uint16_t start_event_count;
uint16_t event_counter;

event_counter = ull_conn_event_counter(conn);
start_event_count = ctx->data.cis_create.conn_event_count;

if (is_instant_reached_or_passed(start_event_count, event_counter)) {
Expand All @@ -546,6 +544,26 @@ static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint
}
}

static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
uint16_t event_counter;

event_counter = ull_conn_event_counter_at_prepare(conn);

rp_cc_check_instant_by_counter(conn, ctx, event_counter, evt, param);
}

static void rp_cc_check_instant_rx_cis_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
uint16_t event_counter;

event_counter = ull_conn_event_counter(conn);

rp_cc_check_instant_by_counter(conn, ctx, event_counter, evt, param);
}

static void rp_cc_state_wait_reply(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
Expand Down Expand Up @@ -1078,7 +1096,7 @@ static void lp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint
uint16_t instant_latency;
uint16_t event_counter;

event_counter = ull_conn_event_counter(conn);
event_counter = ull_conn_event_counter_at_prepare(conn);
start_event_count = ctx->data.cis_create.conn_event_count;

instant_latency = (event_counter - start_event_count) & 0xffff;
Expand Down
7 changes: 4 additions & 3 deletions subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ static void lp_chmu_send_channel_map_update_ind(struct ll_conn *conn, struct pro
} else {
llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE);

ctx->data.chmu.instant = ull_conn_event_counter(conn) + CHMU_INSTANT_DELTA;
ctx->data.chmu.instant = ull_conn_event_counter(conn) + conn->lll.latency +
CHMU_INSTANT_DELTA;
Comment on lines +121 to +122
Copy link
Preview

Copilot AI Jul 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This manual calculation may not match the helper's logic (which adds latency_prepare and lazy). Consider using ull_conn_event_counter_at_prepare(conn) + CHMU_INSTANT_DELTA to keep consistency across instant calculations.

Suggested change
ctx->data.chmu.instant = ull_conn_event_counter(conn) + conn->lll.latency +
CHMU_INSTANT_DELTA;
ctx->data.chmu.instant = ull_conn_event_counter_at_prepare(conn) + CHMU_INSTANT_DELTA;

Copilot uses AI. Check for mistakes.


lp_chmu_tx(conn, ctx);

Expand All @@ -142,7 +143,7 @@ static void lp_chmu_st_wait_tx_chan_map_ind(struct ll_conn *conn, struct proc_ct
static void lp_chmu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
uint16_t event_counter = ull_conn_event_counter(conn);
uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);

if (is_instant_reached_or_passed(ctx->data.chmu.instant, event_counter)) {
llcp_rr_set_incompat(conn, INCOMPAT_NO_COLLISION);
Expand Down Expand Up @@ -257,7 +258,7 @@ static void rp_chmu_st_wait_rx_channel_map_update_ind(struct ll_conn *conn, stru
static void rp_chmu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
uint16_t event_counter = ull_conn_event_counter(conn);
uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);

if (((event_counter - ctx->data.chmu.instant) & 0xFFFF) <= 0x7FFF) {
rp_chmu_complete(conn, ctx, evt, param);
Expand Down
4 changes: 2 additions & 2 deletions subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ static void lp_cu_st_wait_rx_conn_update_ind(struct ll_conn *conn, struct proc_c
static void lp_cu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
uint16_t event_counter = ull_conn_event_counter(conn);
uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);

if (is_instant_reached_or_passed(ctx->data.cu.instant, event_counter)) {
bool notify;
Expand Down Expand Up @@ -1222,7 +1222,7 @@ static void rp_cu_st_wait_tx_conn_update_ind(struct ll_conn *conn, struct proc_c
static void rp_cu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
uint16_t event_counter = ull_conn_event_counter(conn);
uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);

if (is_instant_reached_or_passed(ctx->data.cu.instant, event_counter)) {
bool notify;
Expand Down
8 changes: 6 additions & 2 deletions subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,9 @@ static void lp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct
static void lp_pu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
if (is_instant_reached_or_passed(ctx->data.pu.instant, ull_conn_event_counter(conn))) {
uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);

if (is_instant_reached_or_passed(ctx->data.pu.instant, event_counter)) {
const uint8_t phy_changed = pu_apply_phy_update(conn, ctx);
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
if (phy_changed) {
Expand Down Expand Up @@ -1191,7 +1193,9 @@ static void rp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct
static void rp_pu_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param)
{
if (is_instant_reached_or_passed(ctx->data.pu.instant, ull_conn_event_counter(conn))) {
uint16_t event_counter = ull_conn_event_counter_at_prepare(conn);

if (is_instant_reached_or_passed(ctx->data.pu.instant, event_counter)) {
ctx->data.pu.error = BT_HCI_ERR_SUCCESS;
const uint8_t phy_changed = pu_apply_phy_update(conn, ctx);
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
Expand Down