diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index ff19a9a2f38..83dfce376e1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -8197,3 +8197,8 @@ uint8_t ull_conn_lll_phy_active(struct ll_conn *conn, uint8_t phys) } #endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ + +uint8_t ull_is_lll_tx_queue_empty(struct ll_conn *conn) +{ + return (memq_peek(conn->lll.memq_tx.head, conn->lll.memq_tx.tail, NULL) == NULL); +} diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index d87e30f421a..bf75d87aeec 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -125,3 +125,8 @@ void ull_conn_pause_rx_data(struct ll_conn *conn); void ull_conn_resume_rx_data(struct ll_conn *conn); #endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */ + +/** + * @brief Check if the lower linked layer transmit queue is empty + */ +uint8_t ull_is_lll_tx_queue_empty(struct ll_conn *conn); diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c index 8e01829b117..47ee96045c4 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c @@ -597,7 +597,7 @@ static void lp_pu_st_wait_tx_ack_phy_req(struct ll_conn *conn, struct proc_ctx * /* Unknown role */ LL_ASSERT(0); } - llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE); + break; default: /* Ignore other evts */ @@ -685,6 +685,7 @@ static void lp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct ctx->data.pu.ntf_pu = ctx->data.pu.host_initiated; lp_pu_complete(conn, ctx, evt, param); } + llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE); break; case LP_PU_EVT_REJECT: llcp_rr_set_incompat(conn, INCOMPAT_NO_COLLISION); @@ -692,6 +693,7 @@ static void lp_pu_st_wait_rx_phy_update_ind(struct ll_conn *conn, struct proc_ct ctx->data.pu.error = ctx->reject_ext_ind.error_code; ctx->data.pu.ntf_pu = 1; lp_pu_complete(conn, ctx, evt, param); + llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE); default: /* Ignore other evts */ break; @@ -919,7 +921,8 @@ static void rp_pu_send_phy_update_ind(struct ll_conn *conn, struct proc_ctx *ctx void *param) { if (llcp_rr_ispaused(conn) || !llcp_tx_alloc_peek(conn, ctx) || - (llcp_rr_get_paused_cmd(conn) == PROC_PHY_UPDATE)) { + (llcp_rr_get_paused_cmd(conn) == PROC_PHY_UPDATE) || + !ull_is_lll_tx_queue_empty(conn)) { ctx->state = RP_PU_STATE_WAIT_TX_PHY_UPDATE_IND; } else { llcp_rr_set_paused_cmd(conn, PROC_CTE_REQ); @@ -965,6 +968,7 @@ static void rp_pu_st_wait_rx_phy_req(struct ll_conn *conn, struct proc_ctx *ctx, /* Combine with the 'Preferred' the phys in conn->phy_pref_?x */ pu_combine_phys(conn, ctx, conn->phy_pref_tx, conn->phy_pref_rx); llcp_tx_pause_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_PHY_UPDATE); + switch (evt) { case RP_PU_EVT_PHY_REQ: switch (conn->lll.role) {