From d4347339f51ac645532957b3fc08ac8b293d0876 Mon Sep 17 00:00:00 2001 From: Thomas Ebert Hansen Date: Fri, 2 Oct 2020 13:58:18 +0200 Subject: [PATCH] Bluetooth: controller: Fix enc. setup during PHY update If a PHY update is waiting for the instant to be reached and the master starts the encryption procedure, store the pending PHY update procedure and handle it simultaneously with the encryption setup. This fix prevents the encryption setup from stalling and thereby timing out after 40s, after which the master drops the link. The ll_conn::llcp::encryption can not longer be unioned with the ll_conn::llcp:phy_upd_ind as one would overwrite the other. Signed-off-by: Thomas Ebert Hansen --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 65 ++++++++++++++++++- .../controller/ll_sw/ull_conn_types.h | 39 ++++++----- 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index a91187c2e3e..342e0a3553b 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -995,6 +995,32 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy) } } +#if defined(CONFIG_BT_CTLR_LE_ENC) + /* Run any pending procedure stored while encryption was started */ + if (conn->llcp.encryption.pend_llcp_type != LLCP_NONE) { + switch (conn->llcp.encryption.pend_llcp_type) { +#if defined(CONFIG_BT_CTLR_PHY) + case LLCP_PHY_UPD: + { + struct lll_conn *lll = &conn->lll; + uint16_t event_counter; + + /* Calculate current event counter */ + event_counter = lll->event_counter + + lll->latency_prepare + lazy; + + event_phy_upd_ind_prep(conn, event_counter); + } + break; +#endif /* CONFIG_BT_CTLR_PHY */ + + default: + LL_ASSERT(0); + break; + } + } +#endif /* CONFIG_BT_CTLR_LE_ENC */ + /* Terminate Procedure Request */ if (conn->llcp_terminate.ack != conn->llcp_terminate.req) { struct node_tx *tx; @@ -2776,6 +2802,19 @@ static inline void event_enc_prep(struct ll_conn *conn) /* resume data packet rx and tx */ conn->llcp_enc.pause_rx = 0U; conn->llcp_enc.pause_tx = 0U; + + /* If the encryption procedure interrupted another procedcure, + * continue that procedure + */ + if (conn->llcp.encryption.pend_llcp_type != LLCP_NONE) { + conn->llcp_type = conn->llcp.encryption.pend_llcp_type; + conn->llcp.encryption.pend_llcp_type = LLCP_NONE; + /* return now to prevent the 'procedure request acked', + * below, otherwise the ack/req flow prevents the + * interrupted procedure to run. + */ + return; + } #endif /* !CONFIG_BT_CTLR_FAST_ENC */ } @@ -3682,8 +3721,15 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn, struct node_rx_pdu *rx; uint8_t old_tx, old_rx; - /* procedure request acked */ - conn->llcp_ack = conn->llcp_req; + if (conn->llcp.encryption.pend_llcp_type == LLCP_NONE) { + /* procedure request acked */ + conn->llcp_ack = conn->llcp_req; + } else { + /* PHY Update completed, so clear the + * pending procedure + */ + conn->llcp.encryption.pend_llcp_type = LLCP_NONE; + } /* apply new phy */ old_tx = lll->phy_tx; @@ -5463,6 +5509,21 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, goto ull_conn_rx_unknown_rsp_send; } +#if defined(CONFIG_BT_CTLR_PHY) + /* LL_ENC_REQ was received while LLCP_PHY_UPD was running */ + if (conn->llcp_type == LLCP_PHY_UPD && + conn->llcp_ack != conn->llcp_req) { + /* Adjust ack due to decrement below, to prevent + * failures + */ + conn->llcp_ack += 2U; + /* Remember that LLCP_PHY_UPD was interrupted */ + conn->llcp.encryption.pend_llcp_type = LLCP_PHY_UPD; + } else { + conn->llcp.encryption.pend_llcp_type = LLCP_NONE; + } +#endif /* CONFIG_BT_CTLR_PHY */ + #if defined(CONFIG_BT_CTLR_FAST_ENC) /* TODO: BT Spec. text: may finalize the sending of additional * data channel PDUs queued in the controller. diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h index 012bd799cdf..0ce37e6599e 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_types.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_types.h @@ -96,28 +96,30 @@ struct ll_conn { uint8_t llcp_ack; uint8_t llcp_type; - union { - struct { - uint16_t instant; - uint16_t *pdu_win_offset; - uint32_t ticks_anchor; - } conn_upd; + struct { + union { + struct { + uint16_t instant; + uint16_t *pdu_win_offset; + uint32_t ticks_anchor; + } conn_upd; - struct { - uint8_t initiate:1; - uint8_t chm[5]; - uint16_t instant; - } chan_map; + struct { + uint8_t initiate:1; + uint8_t chm[5]; + uint16_t instant; + } chan_map; #if defined(CONFIG_BT_CTLR_PHY) - struct { - uint8_t initiate:1; - uint8_t cmd:1; - uint8_t tx:3; - uint8_t rx:3; - uint16_t instant; - } phy_upd_ind; + struct { + uint8_t initiate:1; + uint8_t cmd:1; + uint8_t tx:3; + uint8_t rx:3; + uint16_t instant; + } phy_upd_ind; #endif /* CONFIG_BT_CTLR_PHY */ + }; #if defined(CONFIG_BT_CTLR_LE_ENC) struct { @@ -126,6 +128,7 @@ struct ll_conn { LLCP_ENC_STATE_INIT, LLCP_ENC_STATE_LTK_WAIT, } state:2 __packed; + uint8_t pend_llcp_type; uint8_t error_code; uint8_t skd[16]; } encryption;