Bluetooth: controller: completing procedure pause handling

Implementing the final parts of procedure pause mechanism
This is needed to bar procedures from generating pdus during encryption
procedure handling

Signed-off-by: Erik Brockhoff <erbr@oticon.com>

wip
This commit is contained in:
Erik Brockhoff 2021-12-14 11:40:51 +01:00 committed by Carles Cufí
commit a148635837
8 changed files with 78 additions and 13 deletions

View file

@ -114,7 +114,7 @@ static void lp_chmu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
static void lp_chmu_send_channel_map_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, static void lp_chmu_send_channel_map_update_ind(struct ll_conn *conn, struct proc_ctx *ctx,
uint8_t evt, void *param) uint8_t evt, void *param)
{ {
if (llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_CHMU_STATE_WAIT_TX_CHAN_MAP_IND; ctx->state = LP_CHMU_STATE_WAIT_TX_CHAN_MAP_IND;
} else { } else {
llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE); llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE);

View file

@ -416,7 +416,7 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
} }
break; break;
case PROC_TERMINATE: case PROC_TERMINATE:
if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) { if (!llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_COMMON_STATE_WAIT_TX; ctx->state = LP_COMMON_STATE_WAIT_TX;
} else { } else {
lp_comm_tx(conn, ctx); lp_comm_tx(conn, ctx);

View file

@ -217,7 +217,7 @@ static void lp_cu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e
static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_CU_STATE_WAIT_TX_CONN_PARAM_REQ; ctx->state = LP_CU_STATE_WAIT_TX_CONN_PARAM_REQ;
} else { } else {
uint16_t event_counter = ull_conn_event_counter(conn); uint16_t event_counter = ull_conn_event_counter(conn);
@ -261,7 +261,7 @@ static void lp_cu_send_conn_param_req(struct ll_conn *conn, struct proc_ctx *ctx
static void lp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void lp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_CU_STATE_WAIT_TX_CONN_UPDATE_IND; ctx->state = LP_CU_STATE_WAIT_TX_CONN_UPDATE_IND;
} else { } else {
ctx->data.cu.win_size = 1U; ctx->data.cu.win_size = 1U;
@ -626,7 +626,7 @@ static void rp_cu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e
static void rp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void rp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND; ctx->state = RP_CU_STATE_WAIT_TX_CONN_UPDATE_IND;
} else { } else {
ctx->data.cu.win_size = 1U; ctx->data.cu.win_size = 1U;
@ -643,7 +643,7 @@ static void rp_cu_send_conn_update_ind(struct ll_conn *conn, struct proc_ctx *ct
static void rp_cu_send_reject_ext_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void rp_cu_send_reject_ext_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_CU_STATE_WAIT_TX_REJECT_EXT_IND; ctx->state = RP_CU_STATE_WAIT_TX_REJECT_EXT_IND;
} else { } else {
rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND); rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND);
@ -655,7 +655,7 @@ static void rp_cu_send_reject_ext_ind(struct ll_conn *conn, struct proc_ctx *ctx
static void rp_cu_send_conn_param_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void rp_cu_send_conn_param_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP; ctx->state = RP_CU_STATE_WAIT_TX_CONN_PARAM_RSP;
} else { } else {
rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP); rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP);
@ -679,7 +679,7 @@ static void rp_cu_send_conn_param_req_ntf(struct ll_conn *conn, struct proc_ctx
static void rp_cu_send_unknown_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void rp_cu_send_unknown_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_CU_STATE_WAIT_TX_UNKNOWN_RSP; ctx->state = RP_CU_STATE_WAIT_TX_UNKNOWN_RSP;
} else { } else {
rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP); rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP);

View file

@ -250,6 +250,10 @@ static void lp_enc_send_enc_req(struct ll_conn *conn, struct proc_ctx *ctx, uint
/* Wait for the LL_ENC_RSP */ /* Wait for the LL_ENC_RSP */
ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_ENC_RSP; ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_ENC_RSP;
ctx->state = LP_ENC_STATE_WAIT_RX_ENC_RSP; ctx->state = LP_ENC_STATE_WAIT_RX_ENC_RSP;
/* Pause possibly ongoing remote procedure */
llcp_rr_pause(conn);
} }
} }
@ -410,6 +414,9 @@ static void lp_enc_st_wait_rx_start_enc_req(struct ll_conn *conn, struct proc_ct
ctx->data.enc.error = (pdu->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_REJECT_IND) ? ctx->data.enc.error = (pdu->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_REJECT_IND) ?
pdu->llctrl.reject_ind.error_code : pdu->llctrl.reject_ind.error_code :
pdu->llctrl.reject_ext_ind.error_code; pdu->llctrl.reject_ext_ind.error_code;
/* Resume possibly paused remote procedure */
llcp_rr_resume(conn);
lp_enc_complete(conn, ctx, evt, param); lp_enc_complete(conn, ctx, evt, param);
break; break;
default: default:
@ -441,6 +448,10 @@ static void lp_enc_st_wait_rx_start_enc_rsp(struct ll_conn *conn, struct proc_ct
/* Resume Rx data */ /* Resume Rx data */
ull_conn_resume_rx_data(conn); ull_conn_resume_rx_data(conn);
ctx->data.enc.error = BT_HCI_ERR_SUCCESS; ctx->data.enc.error = BT_HCI_ERR_SUCCESS;
/* Resume possibly paused remote procedure */
llcp_rr_resume(conn);
lp_enc_complete(conn, ctx, evt, param); lp_enc_complete(conn, ctx, evt, param);
break; break;
default: default:
@ -817,6 +828,8 @@ static void rp_enc_send_reject_ind(struct ll_conn *conn, struct proc_ctx *ctx, u
llcp_tx_resume_data(conn); llcp_tx_resume_data(conn);
/* Resume Rx data */ /* Resume Rx data */
ull_conn_resume_rx_data(conn); ull_conn_resume_rx_data(conn);
/* Resume possibly paused local procedure */
llcp_lr_resume(conn);
} }
} }
@ -835,6 +848,9 @@ static void rp_enc_send_start_enc_rsp(struct ll_conn *conn, struct proc_ctx *ctx
/* Resume Rx data */ /* Resume Rx data */
ull_conn_resume_rx_data(conn); ull_conn_resume_rx_data(conn);
/* Resume possibly paused local procedure */
llcp_lr_resume(conn);
/* Tx Encryption enabled */ /* Tx Encryption enabled */
conn->lll.enc_tx = 1U; conn->lll.enc_tx = 1U;
} }
@ -898,6 +914,10 @@ static void rp_enc_state_wait_rx_enc_req(struct ll_conn *conn, struct proc_ctx *
llcp_tx_flush(conn); llcp_tx_flush(conn);
/* Pause Rx data */ /* Pause Rx data */
ull_conn_pause_rx_data(conn); ull_conn_pause_rx_data(conn);
/* Pause possibly paused local procedure */
llcp_lr_pause(conn);
rp_enc_store_m(conn, ctx, param); rp_enc_store_m(conn, ctx, param);
rp_enc_send_enc_rsp(conn, ctx, evt, param); rp_enc_send_enc_rsp(conn, ctx, evt, param);
break; break;

View file

@ -415,6 +415,8 @@ void llcp_pdu_decode_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu);
* LLCP Local Request * LLCP Local Request
*/ */
struct proc_ctx *llcp_lr_peek(struct ll_conn *conn); struct proc_ctx *llcp_lr_peek(struct ll_conn *conn);
void llcp_lr_pause(struct ll_conn *conn);
void llcp_lr_resume(struct ll_conn *conn);
void llcp_lr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx); void llcp_lr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx);
void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
void llcp_lr_enqueue(struct ll_conn *conn, struct proc_ctx *ctx); void llcp_lr_enqueue(struct ll_conn *conn, struct proc_ctx *ctx);
@ -431,6 +433,8 @@ void llcp_lr_abort(struct ll_conn *conn);
void llcp_rr_set_incompat(struct ll_conn *conn, enum proc_incompat incompat); void llcp_rr_set_incompat(struct ll_conn *conn, enum proc_incompat incompat);
bool llcp_rr_get_collision(struct ll_conn *conn); bool llcp_rr_get_collision(struct ll_conn *conn);
struct proc_ctx *llcp_rr_peek(struct ll_conn *conn); struct proc_ctx *llcp_rr_peek(struct ll_conn *conn);
void llcp_rr_pause(struct ll_conn *conn);
void llcp_rr_resume(struct ll_conn *conn);
void llcp_rr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx); void llcp_rr_tx_ack(struct ll_conn *conn, struct proc_ctx *ctx, struct node_tx *tx);
void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx);
void llcp_rr_init(struct ll_conn *conn); void llcp_rr_init(struct ll_conn *conn);

View file

@ -112,6 +112,26 @@ struct proc_ctx *llcp_lr_peek(struct ll_conn *conn)
return ctx; return ctx;
} }
void llcp_lr_pause(struct ll_conn *conn)
{
struct proc_ctx *ctx;
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list);
if (ctx) {
ctx->pause = 1;
}
}
void llcp_lr_resume(struct ll_conn *conn)
{
struct proc_ctx *ctx;
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.local.pend_proc_list);
if (ctx) {
ctx->pause = 0;
}
}
void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx) void llcp_lr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx)
{ {
switch (ctx->proc) { switch (ctx->proc) {

View file

@ -440,7 +440,7 @@ static void lp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e
static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{ {
if (llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || llcp_rr_get_collision(conn) || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_PU_STATE_WAIT_TX_PHY_REQ; ctx->state = LP_PU_STATE_WAIT_TX_PHY_REQ;
} else { } else {
llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE); llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE);
@ -454,7 +454,7 @@ static void lp_pu_send_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8
static void lp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void lp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = LP_PU_STATE_WAIT_TX_PHY_UPDATE_IND; ctx->state = LP_PU_STATE_WAIT_TX_PHY_UPDATE_IND;
} else { } else {
ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA; ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA;
@ -841,7 +841,7 @@ static void rp_pu_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t e
static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt,
void *param) void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_PU_STATE_WAIT_TX_PHY_UPDATE_IND; ctx->state = RP_PU_STATE_WAIT_TX_PHY_UPDATE_IND;
} else { } else {
ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA; ctx->data.pu.instant = pu_event_counter(conn) + PHY_UPDATE_INSTANT_DELTA;
@ -855,7 +855,7 @@ static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx
#if defined(CONFIG_BT_PERIPHERAL) #if defined(CONFIG_BT_PERIPHERAL)
static void rp_pu_send_phy_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param) static void rp_pu_send_phy_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, void *param)
{ {
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
ctx->state = RP_PU_STATE_WAIT_TX_PHY_RSP; ctx->state = RP_PU_STATE_WAIT_TX_PHY_RSP;
} else { } else {
rp_pu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_PHY_RSP); rp_pu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_PHY_RSP);

View file

@ -172,6 +172,27 @@ struct proc_ctx *llcp_rr_peek(struct ll_conn *conn)
return ctx; return ctx;
} }
void llcp_rr_pause(struct ll_conn *conn)
{
struct proc_ctx *ctx;
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.remote.pend_proc_list);
if (ctx) {
ctx->pause = 1;
}
}
void llcp_rr_resume(struct ll_conn *conn)
{
struct proc_ctx *ctx;
ctx = (struct proc_ctx *)sys_slist_peek_head(&conn->llcp.remote.pend_proc_list);
if (ctx) {
ctx->pause = 0;
}
}
void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx) void llcp_rr_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx)
{ {
switch (ctx->proc) { switch (ctx->proc) {
@ -352,7 +373,7 @@ static void rr_act_reject(struct ll_conn *conn)
LL_ASSERT(ctx != NULL); LL_ASSERT(ctx != NULL);
if (!llcp_tx_alloc_peek(conn, ctx)) { if (ctx->pause || !llcp_tx_alloc_peek(conn, ctx)) {
rr_set_state(conn, RR_STATE_REJECT); rr_set_state(conn, RR_STATE_REJECT);
} else { } else {
rr_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_IND); rr_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_IND);