From aa80f7da5f80634dcc57b1cfe7a6d214bb866f61 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Thu, 9 Jun 2022 08:15:41 +0200 Subject: [PATCH] Bluetooth: controller: llcp: fix PHY procedure for conformance test This PR fixes the PHY update procedures for conformance tests when being a Central The problem was that data was in the LLL tx queue and was still being queued before the PHY IND was queued (with a given instant). As a result by the time the PHY IND was transmitted over the air the instant was in the past. The fix is to ensure that the LLL tx queue is empty, and to stop queueing new data before queueing the PHY IND Following tests are fixed: LL/CON/CEN/BV-49-C LL/CON/CEN/BV-50-C LL/CON/CEN/BV-53-C LL/CON/CEN/BV-54-C Signed-off-by: Andries Kruithof --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 5 +++++ subsys/bluetooth/controller/ll_sw/ull_conn_internal.h | 5 +++++ subsys/bluetooth/controller/ll_sw/ull_llcp_phy.c | 8 ++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) 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) {