Skip to content

Commit 7f727ac

Browse files
cvinayaknashif
authored andcommitted
Bluetooth: controller: Fix regression in ctrl tx queue handling
Fix control Tx buffer leak into data Tx pool that happens after a cross-over control procedure response was paused due to currently active encryption setup procedure, and a new control Tx PDU in addition to the paused one is enqueued thereafter. When the control tx PDUs is resumed but not yet enqueued towards the radio, if there is a new control Tx PDU enqueued then the paused control Tx PDU is not set as the head of the control PDUs in the Tx queue. This caused the paused control Tx PDU to be associated with data Tx pool, hence causing the incorrect release into data Tx pool. Relates to the commit bff76b4 ("Bluetooth: controller: split: Fix control tx queue handling") and to the commit 6991d09 ("Bluetooth: controller: Fix control tx queue handling"). Fixes #32898. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 7d35a8c commit 7f727ac

File tree

1 file changed

+26
-12
lines changed

1 file changed

+26
-12
lines changed

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static inline void event_ch_map_prep(struct ll_conn *conn,
9191
uint16_t event_counter);
9292

9393
#if defined(CONFIG_BT_CTLR_LE_ENC)
94+
static inline void ctrl_tx_check_and_resume(struct ll_conn *conn);
9495
static bool is_enc_req_pause_tx(struct ll_conn *conn);
9596
static inline void event_enc_prep(struct ll_conn *conn);
9697
#if defined(CONFIG_BT_PERIPHERAL)
@@ -1868,18 +1869,11 @@ static void tx_demux(void *param)
18681869

18691870
static struct node_tx *tx_ull_dequeue(struct ll_conn *conn, struct node_tx *tx)
18701871
{
1872+
#if defined(CONFIG_BT_CTLR_LE_ENC)
18711873
if (!conn->tx_ctrl && (conn->tx_head != conn->tx_data)) {
1872-
struct pdu_data *pdu_data_tx;
1873-
1874-
pdu_data_tx = (void *)conn->tx_head->pdu;
1875-
if ((pdu_data_tx->ll_id != PDU_DATA_LLID_CTRL) ||
1876-
((pdu_data_tx->llctrl.opcode !=
1877-
PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
1878-
(pdu_data_tx->llctrl.opcode !=
1879-
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
1880-
conn->tx_ctrl = conn->tx_ctrl_last = conn->tx_head;
1881-
}
1874+
ctrl_tx_check_and_resume(conn);
18821875
}
1876+
#endif /* CONFIG_BT_CTLR_LE_ENC */
18831877

18841878
if (conn->tx_head == conn->tx_ctrl) {
18851879
conn->tx_head = conn->tx_head->next;
@@ -1990,8 +1984,24 @@ static int empty_data_start_release(struct ll_conn *conn, struct node_tx *tx)
19901984
}
19911985
#endif /* CONFIG_BT_CTLR_LLID_DATA_START_EMPTY */
19921986

1993-
static void ctrl_tx_last_enqueue(struct ll_conn *conn,
1994-
struct node_tx *tx)
1987+
#if defined(CONFIG_BT_CTLR_LE_ENC)
1988+
static inline void ctrl_tx_check_and_resume(struct ll_conn *conn)
1989+
{
1990+
struct pdu_data *pdu_data_tx;
1991+
1992+
pdu_data_tx = (void *)conn->tx_head->pdu;
1993+
if ((pdu_data_tx->ll_id != PDU_DATA_LLID_CTRL) ||
1994+
((pdu_data_tx->llctrl.opcode !=
1995+
PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
1996+
(pdu_data_tx->llctrl.opcode !=
1997+
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
1998+
conn->tx_ctrl = conn->tx_ctrl_last = conn->tx_head;
1999+
}
2000+
}
2001+
#endif /* CONFIG_BT_CTLR_LE_ENC */
2002+
2003+
static inline void ctrl_tx_last_enqueue(struct ll_conn *conn,
2004+
struct node_tx *tx)
19952005
{
19962006
tx->next = conn->tx_ctrl_last->next;
19972007
conn->tx_ctrl_last->next = tx;
@@ -2022,6 +2032,10 @@ static inline void ctrl_tx_pause_enqueue(struct ll_conn *conn,
20222032
*/
20232033
if (conn->tx_head == conn->tx_data) {
20242034
conn->tx_data = conn->tx_data->next;
2035+
#if defined(CONFIG_BT_CTLR_LE_ENC)
2036+
} else if (!conn->tx_ctrl) {
2037+
ctrl_tx_check_and_resume(conn);
2038+
#endif /* CONFIG_BT_CTLR_LE_ENC */
20252039
}
20262040

20272041
/* if no ctrl packet already queued, new ctrl added will be

0 commit comments

Comments
 (0)