Bluetooth: controller: Start CIG immediately if instant is next event

To be able to timely start the first CIS/CIG, if the requested instant
is the next connection event, call ull_peripheral_iso_start directly
from rp_cc_state_wait_rx_cis_ind instead of waiting for next time
through the state machine.

To enable ULL/LLL to prevent adding latency when LLCP is waiting for
instant, local- and remote procedures with instant now expose a function
for checking this state.

Fixed event_counter function to prevent one-off in RX path. Unified to
use single function ull_conn_event_counter.

Fixed LLCP unit tests and added new mock function.

Signed-off-by: Morten Priess <mtpr@oticon.com>
This commit is contained in:
Morten Priess 2022-09-07 16:16:27 +02:00 committed by Fabio Baltieri
parent 1af16d896c
commit a982c9f9f6
7 changed files with 77 additions and 31 deletions

View file

@ -8064,12 +8064,25 @@ uint16_t ull_conn_event_counter(struct ll_conn *conn)
struct lll_conn *lll;
uint16_t event_counter;
uint16_t lazy = conn->llcp.prep.lazy;
lll = &conn->lll;
/* Calculate current event counter */
event_counter = lll->event_counter + lll->latency_prepare + lazy;
/* Calculate current event counter. If refcount is non-zero, we have called
* prepare and the LLL implementation has calculated and incremented the event
* counter (RX path). In this case we need to subtract one from the current
* event counter.
* Otherwise we are in the TX path, and we calculate the current event counter
* similar to LLL by taking the expected event counter value plus accumulated
* latency.
*/
if (ull_ref_get(&conn->ull)) {
/* We are in post-prepare (RX path). Event counter is already
* calculated and incremented by 1 for next event.
*/
event_counter = lll->event_counter - 1;
} else {
event_counter = lll->event_counter + lll->latency_prepare +
conn->llcp.prep.lazy;
}
return event_counter;
}

View file

@ -89,22 +89,6 @@ static void cc_ntf_established(struct ll_conn *conn, struct proc_ctx *ctx)
}
#if defined(CONFIG_BT_PERIPHERAL)
static uint16_t cc_event_counter(struct ll_conn *conn)
{
struct lll_conn *lll;
uint16_t event_counter;
uint16_t lazy = conn->llcp.prep.lazy;
/**/
lll = &conn->lll;
/* Calculate current event counter */
event_counter = lll->event_counter + lll->latency_prepare + lazy;
return event_counter;
}
/* LLCP Remote Procedure FSM states */
enum {
/* Establish Procedure */
@ -147,6 +131,9 @@ enum {
RP_CC_EVT_UNKNOWN,
};
static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param);
/*
* LLCP Remote Procedure FSM
*/
@ -162,8 +149,13 @@ static void llcp_rp_cc_tx_rsp(struct ll_conn *conn, struct proc_ctx *ctx)
pdu = (struct pdu_data *)tx->pdu;
/* Postpone if instant is in this or next connection event. This would handle obsolete value
* due to retransmission, as well as incorrect behavior by central.
* We need at least 2 connection events to get ready. First for receiving the indication,
* the second for setting up the CIS.
*/
ctx->data.cis_create.conn_event_count = MAX(ctx->data.cis_create.conn_event_count,
cc_event_counter(conn) + 2);
ull_conn_event_counter(conn) + 2);
llcp_pdu_encode_cis_rsp(ctx, pdu);
ctx->tx_opcode = pdu->llctrl.opcode;
@ -380,19 +372,13 @@ static void rp_cc_state_wait_rx_cis_ind(struct ll_conn *conn, struct proc_ctx *c
case RP_CC_EVT_CIS_IND:
llcp_pdu_decode_cis_ind(ctx, pdu);
if (!ull_peripheral_iso_setup(&pdu->llctrl.cis_ind, ctx->data.cis_create.cig_id,
ctx->data.cis_create.cis_handle)) {
ctx->data.cis_create.cis_handle)) {
/* CIS has been setup, go wait for 'instant' before starting */
ctx->state = RP_CC_STATE_WAIT_INSTANT;
/* Fixme - Implement CIS Supervision timeout
* Spec:
* When establishing a CIS, the Peripheral shall start the CIS supervision
* timer at the start of the next CIS event after receiving the LL_CIS_IND.
* If the CIS supervision timer reaches 6 * ISO_Interval before the CIS is
* established, the CIS shall be considered lost.
*/
/* Check if this connection event is where we need to start the CIS */
rp_cc_check_instant(conn, ctx, evt, param);
break;
}
/* If we get to here the CIG_ID referred in req/acquire has become void/invalid */
@ -454,7 +440,7 @@ static void rp_cc_check_instant(struct ll_conn *conn, struct proc_ctx *ctx, uint
}
if (is_instant_reached_or_passed(start_event_count,
cc_event_counter(conn))) {
ull_conn_event_counter(conn))) {
/* Start CIS */
ull_conn_iso_start(conn, conn->llcp.prep.ticks_at_expire,
ctx->data.cis_create.cis_handle);
@ -625,6 +611,11 @@ void llcp_rp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
{
rp_cc_execute_fsm(conn, ctx, RP_CC_EVT_RUN, param);
}
bool llcp_rp_cc_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == RP_CC_STATE_WAIT_INSTANT);
}
#endif /* CONFIG_BT_PERIPHERAL */
#if defined(CONFIG_BT_CTLR_CENTRAL_ISO)

View file

@ -204,6 +204,10 @@ void llcp_lp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
lp_chmu_execute_fsm(conn, ctx, LP_CHMU_EVT_RUN, param);
}
bool llcp_lp_chmu_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == LP_CHMU_STATE_WAIT_INSTANT);
}
#endif /* CONFIG_BT_CENTRAL */
#if defined(CONFIG_BT_PERIPHERAL)
@ -320,4 +324,9 @@ void llcp_rp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
{
rp_chmu_execute_fsm(conn, ctx, RP_CHMU_EVT_RUN, param);
}
bool llcp_rp_chmu_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == RP_CHMU_STATE_WAIT_INSTANT);
}
#endif /* CONFIG_BT_PERIPHERAL */

View file

@ -1225,6 +1225,16 @@ void llcp_rp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param)
rp_cu_execute_fsm(conn, ctx, RP_CU_EVT_RUN, param);
}
bool llcp_rp_cu_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == RP_CU_STATE_WAIT_INSTANT);
}
bool llcp_lp_cu_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == LP_CU_STATE_WAIT_INSTANT);
}
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
void llcp_rp_conn_param_req_reply(struct ll_conn *conn, struct proc_ctx *ctx)
{

View file

@ -458,6 +458,7 @@ void llcp_lp_pu_init_proc(struct proc_ctx *ctx);
void llcp_lp_pu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
void llcp_lp_pu_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
void llcp_lp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx);
bool llcp_lp_pu_awaiting_instant(struct proc_ctx *ctx);
#endif /* CONFIG_BT_CTLR_PHY */
/*
@ -466,6 +467,7 @@ void llcp_lp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx);
void llcp_lp_cu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
void llcp_lp_cu_init_proc(struct proc_ctx *ctx);
void llcp_lp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
bool llcp_lp_cu_awaiting_instant(struct proc_ctx *ctx);
/*
* LLCP Local Channel Map Update
@ -473,6 +475,7 @@ void llcp_lp_cu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
void llcp_lp_chmu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
void llcp_lp_chmu_init_proc(struct proc_ctx *ctx);
void llcp_lp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
bool llcp_lp_chmu_awaiting_instant(struct proc_ctx *ctx);
#if defined(CONFIG_BT_CTLR_PHY)
/*
@ -483,6 +486,7 @@ void llcp_rp_pu_init_proc(struct proc_ctx *ctx);
void llcp_rp_pu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
void llcp_rp_pu_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
void llcp_rp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx);
bool llcp_rp_pu_awaiting_instant(struct proc_ctx *ctx);
#endif /* CONFIG_BT_CTLR_PHY */
/*
@ -495,6 +499,7 @@ void llcp_rp_conn_param_req_reply(struct ll_conn *conn, struct proc_ctx *ctx);
void llcp_rp_conn_param_req_neg_reply(struct ll_conn *conn, struct proc_ctx *ctx);
bool llcp_rp_conn_param_req_apm_awaiting_reply(struct proc_ctx *ctx);
void llcp_rp_conn_param_req_apm_reply(struct ll_conn *conn, struct proc_ctx *ctx);
bool llcp_rp_cu_awaiting_instant(struct proc_ctx *ctx);
/*
* Terminate Helper
@ -659,6 +664,7 @@ void llcp_pdu_decode_chan_map_update_ind(struct proc_ctx *ctx, struct pdu_data *
void llcp_rp_chmu_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
void llcp_rp_chmu_init_proc(struct proc_ctx *ctx);
void llcp_rp_chmu_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
bool llcp_rp_chmu_awaiting_instant(struct proc_ctx *ctx);
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
/*
@ -712,6 +718,7 @@ void llcp_rp_cc_run(struct ll_conn *conn, struct proc_ctx *ctx, void *param);
bool llcp_rp_cc_awaiting_reply(struct proc_ctx *ctx);
void llcp_rp_cc_accept(struct ll_conn *conn, struct proc_ctx *ctx);
void llcp_rp_cc_reject(struct ll_conn *conn, struct proc_ctx *ctx);
bool llcp_rp_cc_awaiting_instant(struct proc_ctx *ctx);
void llcp_pdu_decode_cis_req(struct proc_ctx *ctx, struct pdu_data *pdu);
void llcp_pdu_encode_cis_rsp(struct proc_ctx *ctx, struct pdu_data *pdu);

View file

@ -892,6 +892,12 @@ void llcp_lp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx)
{
lp_pu_execute_fsm(conn, ctx, LP_PU_EVT_NTF, NULL);
}
bool llcp_lp_pu_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == LP_PU_STATE_WAIT_INSTANT);
}
/*
* LLCP Remote Procedure PHY Update FSM
*/
@ -1318,3 +1324,8 @@ void llcp_rp_pu_tx_ntf(struct ll_conn *conn, struct proc_ctx *ctx)
{
rp_pu_execute_fsm(conn, ctx, RP_PU_EVT_NTF, NULL);
}
bool llcp_rp_pu_awaiting_instant(struct proc_ctx *ctx)
{
return (ctx->state == RP_PU_STATE_WAIT_INSTANT);
}

View file

@ -54,6 +54,11 @@ struct ll_conn_iso_stream *ll_conn_iso_stream_get(uint16_t handle)
return &cis;
}
struct ll_conn_iso_stream *ll_iso_stream_connected_get(uint16_t handle)
{
return &cis;
}
struct ll_conn_iso_group *ll_conn_iso_group_get_by_id(uint8_t id)
{
return &cig;