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 <thoh@oticon.com>
This commit is contained in:
parent
d2415fcfd0
commit
d4347339f5
2 changed files with 84 additions and 20 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue