diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c index f0955b0936b..50800caa980 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_chmu.c @@ -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, 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; } else { llcp_rr_set_incompat(conn, INCOMPAT_RESOLVABLE); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c index 619c2045f02..7b3b50eab2a 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_common.c @@ -416,7 +416,7 @@ static void lp_comm_send_req(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t } break; 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; } else { lp_comm_tx(conn, ctx); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c index cb194bd92cf..7773d6cd958 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_conn_upd.c @@ -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, 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; } else { 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, 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; } else { 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, 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; } else { 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, 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; } else { 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, 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; } else { 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, 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; } else { rp_cu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c index bba4fea04a1..11fb731f218 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c @@ -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 */ ctx->rx_opcode = PDU_DATA_LLCTRL_TYPE_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) ? pdu->llctrl.reject_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); break; 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 */ ull_conn_resume_rx_data(conn); ctx->data.enc.error = BT_HCI_ERR_SUCCESS; + + /* Resume possibly paused remote procedure */ + llcp_rr_resume(conn); + lp_enc_complete(conn, ctx, evt, param); break; 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); /* Resume Rx data */ 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 */ ull_conn_resume_rx_data(conn); + /* Resume possibly paused local procedure */ + llcp_lr_resume(conn); + /* Tx Encryption enabled */ 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); /* Pause Rx data */ ull_conn_pause_rx_data(conn); + + /* Pause possibly paused local procedure */ + llcp_lr_pause(conn); + rp_enc_store_m(conn, ctx, param); rp_enc_send_enc_rsp(conn, ctx, evt, param); break; diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h index 10cf74c3b34..4f1a725d8db 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h @@ -415,6 +415,8 @@ void llcp_pdu_decode_terminate_ind(struct proc_ctx *ctx, struct pdu_data *pdu); * LLCP Local Request */ 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_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); @@ -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); bool llcp_rr_get_collision(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_rx(struct ll_conn *conn, struct proc_ctx *ctx, struct node_rx_pdu *rx); void llcp_rr_init(struct ll_conn *conn); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c index e142dd192e6..cf82526acf4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_local.c @@ -112,6 +112,26 @@ struct proc_ctx *llcp_lr_peek(struct ll_conn *conn) 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) { switch (ctx->proc) { diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index 021b2a35cc3..fa108ca05c6 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -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) { - 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; } else { 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, 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; } else { 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, 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; } else { 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) 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; } else { rp_pu_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_PHY_RSP); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c index 9f2ea5e3bea..9516eb5e562 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_remote.c @@ -172,6 +172,27 @@ struct proc_ctx *llcp_rr_peek(struct ll_conn *conn) 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) { switch (ctx->proc) { @@ -352,7 +373,7 @@ static void rr_act_reject(struct ll_conn *conn) 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); } else { rr_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_IND);