Bluetooth: controller: Fix encryption and procedure with instant
Fix implementation to run local peripheral initiated control procedure with instant in parallel with remote initiated encryption procedure. Relates to #28887. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
d4347339f5
commit
8f537de8c4
3 changed files with 83 additions and 38 deletions
|
@ -897,6 +897,7 @@ uint8_t ll_adv_enable(uint8_t enable)
|
|||
conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
|
||||
conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.refresh = 0U;
|
||||
conn->slave.llcp_type = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
|
|
|
@ -863,6 +863,9 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
|||
*/
|
||||
if ((conn->llcp_ack == conn->llcp_req) &&
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
(!conn->lll.role || (conn->slave.llcp_type == LLCP_NONE)) &&
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
!conn->llcp_enc.pause_rx) {
|
||||
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
||||
1) {
|
||||
|
@ -995,10 +998,34 @@ 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_PERIPHERAL) && defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
/* Run any pending local peripheral role initiated procedure stored when
|
||||
* peer central initiated a encryption procedure
|
||||
*/
|
||||
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||
switch (conn->slave.llcp_type) {
|
||||
case LLCP_CONN_UPD:
|
||||
{
|
||||
if (event_conn_upd_prep(conn, lazy,
|
||||
ticks_at_expire) == 0) {
|
||||
return -ECANCELED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LLCP_CHAN_MAP:
|
||||
{
|
||||
struct lll_conn *lll = &conn->lll;
|
||||
uint16_t event_counter;
|
||||
|
||||
/* Calculate current event counter */
|
||||
event_counter = lll->event_counter +
|
||||
lll->latency_prepare + lazy;
|
||||
|
||||
event_ch_map_prep(conn, event_counter);
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
case LLCP_PHY_UPD:
|
||||
{
|
||||
|
@ -1019,7 +1046,7 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
/* Terminate Procedure Request */
|
||||
if (conn->llcp_terminate.ack != conn->llcp_terminate.req) {
|
||||
|
@ -2319,9 +2346,21 @@ static inline int event_conn_upd_prep(struct ll_conn *conn, uint16_t lazy,
|
|||
uint32_t periodic_us;
|
||||
uint16_t latency;
|
||||
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||
/* Local peripheral initiated PHY update completed while
|
||||
* a remote central had initiated encryption procedure
|
||||
*/
|
||||
conn->slave.llcp_type = LLCP_NONE;
|
||||
} else
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
{
|
||||
/* procedure request acked */
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
}
|
||||
|
||||
/* procedure request acked */
|
||||
conn->llcp_cu.ack = conn->llcp_cu.req;
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
if ((conn->llcp_conn_param.req != conn->llcp_conn_param.ack) &&
|
||||
|
@ -2591,8 +2630,18 @@ static inline void event_ch_map_prep(struct ll_conn *conn,
|
|||
<= 0x7FFF) {
|
||||
struct lll_conn *lll = &conn->lll;
|
||||
|
||||
/* procedure request acked */
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||
/* Local peripheral initiated PHY update completed while
|
||||
* a remote central had initiated encryption procedure
|
||||
*/
|
||||
conn->slave.llcp_type = LLCP_NONE;
|
||||
} else
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
{
|
||||
/* procedure request acked */
|
||||
conn->llcp_ack = conn->llcp_req;
|
||||
}
|
||||
|
||||
/* copy to active channel map */
|
||||
memcpy(&lll->data_chan_map[0],
|
||||
|
@ -2802,19 +2851,6 @@ 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 */
|
||||
}
|
||||
|
||||
|
@ -3721,14 +3757,17 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
|
|||
struct node_rx_pdu *rx;
|
||||
uint8_t old_tx, old_rx;
|
||||
|
||||
if (conn->llcp.encryption.pend_llcp_type == LLCP_NONE) {
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||
/* Local peripheral initiated PHY update completed while
|
||||
* a remote central had initiated encryption procedure
|
||||
*/
|
||||
conn->slave.llcp_type = LLCP_NONE;
|
||||
} else
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
{
|
||||
/* 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 */
|
||||
|
@ -5510,17 +5549,19 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
}
|
||||
|
||||
#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
|
||||
*/
|
||||
/* LL_ENC_REQ was received while local peripheral initiated
|
||||
* procedure is in progress.
|
||||
*/
|
||||
if (unlikely(((conn->llcp_req - conn->llcp_ack) & 0x03) ==
|
||||
0x02)) {
|
||||
/* 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;
|
||||
|
||||
/* Store the local peripheral initiated procedure */
|
||||
LL_ASSERT(conn->slave.llcp_type == LLCP_NONE);
|
||||
conn->slave.llcp_type = conn->llcp_type;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
|
|
|
@ -72,6 +72,9 @@ struct ll_conn {
|
|||
#endif /* CONFIG_BT_CTLR_CONN_META */
|
||||
uint8_t latency_cancel:1;
|
||||
uint8_t sca:3;
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
uint8_t llcp_type;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
#if defined(CONFIG_BT_CTLR_CONN_RANDOM_FORCE)
|
||||
uint32_t force;
|
||||
#endif /* CONFIG_BT_CTLR_CONN_RANDOM_FORCE */
|
||||
|
@ -94,6 +97,7 @@ struct ll_conn {
|
|||
|
||||
uint8_t llcp_req;
|
||||
uint8_t llcp_ack;
|
||||
|
||||
uint8_t llcp_type;
|
||||
|
||||
struct {
|
||||
|
@ -128,7 +132,6 @@ 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