From 385b82dcef890100cc51fb7b610c5a76b40f7f36 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 26 Aug 2019 16:33:47 +0530 Subject: [PATCH] Bluetooth: controller: split: Fix data pause on Enc Req enqueue Fix the controller implementation to handle data packet enqueue being pause on Encryption Request be done early in the ULL when enqueueing packets towards LLL. Fixes #18645. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ull_conn.c | 55 ++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 43c289656e0..3b90a3f705d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -90,6 +90,8 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn, u16_t event_counter); #endif /* CONFIG_BT_CTLR_PHY */ +static inline void ctrl_tx_pre_ack(struct ll_conn *conn, + struct pdu_data *pdu_tx); static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, struct pdu_data *pdu_tx); static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx, @@ -1213,6 +1215,7 @@ void ull_conn_tx_lll_enqueue(struct ll_conn *conn, u8_t count) #endif /* CONFIG_BT_CTLR_LE_ENC */ 1) || (!pause_tx && (conn->tx_head == conn->tx_ctrl))) && count--) { + struct pdu_data *pdu_tx; struct node_tx *tx_lll; memq_link_t *link; @@ -1239,6 +1242,11 @@ void ull_conn_tx_lll_enqueue(struct ll_conn *conn, u8_t count) tx_lll->next = NULL; } + pdu_tx = (void *)tx_lll->pdu; + if (pdu_tx->ll_id == PDU_DATA_LLID_CTRL) { + ctrl_tx_pre_ack(conn, pdu_tx); + } + link = mem_acquire(&mem_link_tx.free); LL_ASSERT(link); @@ -2193,6 +2201,8 @@ static inline void event_enc_prep(struct ll_conn *conn) /* send enc start resp */ start_enc_rsp_send(conn, pdu_ctrl_tx); + + ctrl_tx_enqueue(conn, tx); } /* slave send reject ind or start enc req at control priority */ @@ -2206,6 +2216,8 @@ static inline void event_enc_prep(struct ll_conn *conn) /* place the reject ind packet as next in tx queue */ if (conn->llcp.encryption.error_code) { event_enc_reject_prep(conn, pdu_ctrl_tx); + + ctrl_tx_enqueue(conn, tx); } /* place the start enc req packet as next in tx queue */ else { @@ -2262,21 +2274,22 @@ static inline void event_enc_prep(struct ll_conn *conn) sizeof(struct pdu_data_llctrl_start_enc_req); pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_START_ENC_REQ; + + ctrl_tx_enqueue(conn, tx); } #if !defined(CONFIG_BT_CTLR_FAST_ENC) } else { start_enc_rsp_send(conn, pdu_ctrl_tx); + ctrl_tx_enqueue(conn, tx); + /* resume data packet rx and tx */ conn->llcp_enc.pause_rx = 0U; conn->llcp_enc.pause_tx = 0U; #endif /* !CONFIG_BT_CTLR_FAST_ENC */ - } - ctrl_tx_enqueue(conn, tx); - /* procedure request acked */ conn->llcp_ack = conn->llcp_req; } @@ -4240,6 +4253,42 @@ static inline u8_t phy_upd_ind_recv(struct ll_conn *conn, memq_link_t *link, } #endif /* CONFIG_BT_CTLR_PHY */ +static inline void ctrl_tx_pre_ack(struct ll_conn *conn, + struct pdu_data *pdu_tx) +{ + switch (pdu_tx->llctrl.opcode) { +#if defined(CONFIG_BT_CTLR_LE_ENC) + case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP: + if (!conn->lll.role) { + break; + } + /* Pass Through */ + + case PDU_DATA_LLCTRL_TYPE_ENC_REQ: + case PDU_DATA_LLCTRL_TYPE_ENC_RSP: + case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ: + /* pause data packet tx */ + conn->llcp_enc.pause_tx = 1U; + break; + +#endif /* CONFIG_BT_CTLR_LE_ENC */ + +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) + case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ: + if ((conn->llcp_length.req != conn->llcp_length.ack) && + (conn->llcp_length.state == LLCP_LENGTH_STATE_ACK_WAIT)) { + /* pause data packet tx */ + conn->llcp_length.pause_tx = 1U; + } + break; +#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ + + default: + /* Do nothing for other ctrl packet ack */ + break; + } +} + static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx, struct pdu_data *pdu_tx) {