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 <andries.kruithof@nordicsemi.no>
This commit is contained in:
Andries Kruithof 2022-06-09 08:15:41 +02:00 committed by Carles Cufí
commit aa80f7da5f
3 changed files with 16 additions and 2 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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) {