Skip to content

Commit 1a93b72

Browse files
committed
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"), and to the commit 7f727ac ("Bluetooth: controller: Fix regression in ctrl tx queue handling"). Fixes #32898. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent af56a6b commit 1a93b72

File tree

1 file changed

+21
-11
lines changed
  • subsys/bluetooth/controller/ll_sw

1 file changed

+21
-11
lines changed

subsys/bluetooth/controller/ll_sw/ctrl.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10082,6 +10082,20 @@ static bool is_enc_req_pause_tx(struct connection *conn)
1008210082
/* Head contains a permitted data or control packet. */
1008310083
return false;
1008410084
}
10085+
10086+
static inline void ctrl_tx_check_and_resume(struct connection *conn)
10087+
{
10088+
struct pdu_data *pdu_data_tx;
10089+
10090+
pdu_data_tx = (void *)conn->pkt_tx_head->pdu_data;
10091+
if ((pdu_data_tx->ll_id != PDU_DATA_LLID_CTRL) ||
10092+
((pdu_data_tx->llctrl.opcode !=
10093+
PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
10094+
(pdu_data_tx->llctrl.opcode !=
10095+
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
10096+
conn->pkt_tx_ctrl = conn->pkt_tx_ctrl_last = conn->pkt_tx_head;
10097+
}
10098+
}
1008510099
#endif /* CONFIG_BT_CTLR_LE_ENC */
1008610100

1008710101
static void prepare_pdu_data_tx(struct connection *conn,
@@ -10194,20 +10208,12 @@ static void prepare_pdu_data_tx(struct connection *conn,
1019410208
_pdu_data_tx->md = 1U;
1019510209
}
1019610210

10211+
#if defined(CONFIG_BT_CTLR_LE_ENC)
1019710212
if (!conn->pkt_tx_ctrl &&
1019810213
(conn->pkt_tx_head != conn->pkt_tx_data)) {
10199-
struct pdu_data *pdu_data_tx;
10200-
10201-
pdu_data_tx = (void *)conn->pkt_tx_head->pdu_data;
10202-
if ((pdu_data_tx->ll_id != PDU_DATA_LLID_CTRL) ||
10203-
((pdu_data_tx->llctrl.opcode !=
10204-
PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
10205-
(pdu_data_tx->llctrl.opcode !=
10206-
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ))) {
10207-
conn->pkt_tx_ctrl = conn->pkt_tx_ctrl_last =
10208-
conn->pkt_tx_head;
10209-
}
10214+
ctrl_tx_check_and_resume(conn);
1021010215
}
10216+
#endif /* CONFIG_BT_CTLR_LE_ENC */
1021110217
}
1021210218

1021310219
_pdu_data_tx->rfu = 0U;
@@ -10249,6 +10255,10 @@ static inline void ctrl_tx_pause_enqueue(struct connection *conn,
1024910255
*/
1025010256
if (conn->pkt_tx_head == conn->pkt_tx_data) {
1025110257
conn->pkt_tx_data = conn->pkt_tx_data->next;
10258+
#if defined(CONFIG_BT_CTLR_LE_ENC)
10259+
} else if (!conn->pkt_tx_ctrl) {
10260+
ctrl_tx_check_and_resume(conn);
10261+
#endif /* CONFIG_BT_CTLR_LE_ENC */
1025210262
}
1025310263

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

0 commit comments

Comments
 (0)