From 3e56c2cf16114f3952603dbd553c570edcc25e45 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 7 Jun 2019 16:27:48 +0200 Subject: [PATCH] Bluetooth: controller: split: Fix buffer leak on disconnect Fix pending Tx control buffer leak on supervision timeout. Queued tx buffers in LLL consists of both data and control PDUs but only data buffers got correctly released. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ull.c | 33 +++++++------------ subsys/bluetooth/controller/ll_sw/ull_conn.c | 29 ++++++++++------ .../controller/ll_sw/ull_conn_internal.h | 4 +-- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c index 6dbb147daef..4bd45ffde2d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull.c +++ b/subsys/bluetooth/controller/ll_sw/ull.c @@ -1350,37 +1350,26 @@ static inline void rx_demux_conn_tx_ack(u8_t ack_last, u16_t handle, #if !defined(CONFIG_BT_CTLR_LOW_LAT_ULL) do { #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ + struct ll_conn *conn; + /* Dequeue node */ ull_conn_ack_dequeue(); - if (handle != 0xFFFF) { - struct ll_conn *conn; + /* Process Tx ack */ + conn = ull_conn_tx_ack(handle, link, node_tx); - /* Get the conn instance */ - conn = ll_conn_get(handle); + /* Release link mem */ + ull_conn_link_tx_release(link); - /* Process Tx ack */ - ull_conn_tx_ack(conn, link, node_tx); + /* De-mux 1 tx node from FIFO */ + ull_conn_tx_demux(1); - /* Release link mem */ - ull_conn_link_tx_release(link); - - /* De-mux 1 tx node from FIFO */ - ull_conn_tx_demux(1); - - /* Enqueue towards LLL */ + /* Enqueue towards LLL */ + if (conn) { ull_conn_tx_lll_enqueue(conn, 1); - } else { - /* Pass through Tx ack */ - ll_tx_ack_put(0xFFFF, node_tx); - - /* Release link mem */ - ull_conn_link_tx_release(link); - - /* De-mux 1 tx node from FIFO */ - ull_conn_tx_demux(1); } + /* check for more rx ack */ link = ull_conn_ack_by_last_peek(ack_last, &handle, &node_tx); #if defined(CONFIG_BT_CTLR_LOW_LAT_ULL) diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn.c b/subsys/bluetooth/controller/ll_sw/ull_conn.c index 16583984e66..dabae0181c1 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn.c +++ b/subsys/bluetooth/controller/ll_sw/ull_conn.c @@ -1308,7 +1308,6 @@ void ull_conn_lll_tx_flush(void *param) link = memq_dequeue(lll->memq_tx.tail, &lll->memq_tx.head, (void **)&tx); while (link) { - struct pdu_data *p; struct lll_tx *lll_tx; u8_t idx; @@ -1319,8 +1318,6 @@ void ull_conn_lll_tx_flush(void *param) lll_tx->node = tx; link->next = tx->next; tx->link = link; - p = (void *)tx->pdu; - p->ll_id = PDU_DATA_LLID_RESV; MFIFO_ENQUEUE(conn_ack, idx); @@ -1329,27 +1326,39 @@ void ull_conn_lll_tx_flush(void *param) } } -void ull_conn_tx_ack(struct ll_conn *conn, memq_link_t *link, - struct node_tx *tx) +struct ll_conn *ull_conn_tx_ack(u16_t handle, memq_link_t *link, + struct node_tx *tx) { + struct ll_conn *conn = NULL; struct pdu_data *pdu_tx; pdu_tx = (void *)tx->pdu; LL_ASSERT(pdu_tx->len); if (pdu_tx->ll_id == PDU_DATA_LLID_CTRL) { - ctrl_tx_ack(conn, &tx, pdu_tx); + if (handle != 0xFFFF) { + conn = ll_conn_get(handle); + + ctrl_tx_ack(conn, &tx, pdu_tx); + } /* release mem if points to itself */ if (link->next == (void *)tx) { mem_release(tx, &mem_conn_tx_ctrl.free); - return; + + return conn; } else if (!tx) { - return; + return conn; } + } else if (handle != 0xFFFF) { + conn = ll_conn_get(handle); + } else { + pdu_tx->ll_id = PDU_DATA_LLID_RESV; } - ll_tx_ack_put(conn->lll.handle, tx); + ll_tx_ack_put(handle, tx); + + return conn; } u8_t ull_conn_llcp_req(void *conn) @@ -1564,7 +1573,7 @@ static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx) } /* Update last pointer if ctrl added at end of tx list */ - if (tx->next == 0) { + if (!tx->next) { conn->tx_data_last = tx; } } diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h index a951fe11f71..b31a9616650 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h +++ b/subsys/bluetooth/controller/ll_sw/ull_conn_internal.h @@ -45,6 +45,6 @@ memq_link_t *ull_conn_ack_by_last_peek(u8_t last, u16_t *handle, struct node_tx **tx); void *ull_conn_ack_dequeue(void); void ull_conn_lll_tx_flush(void *param); -void ull_conn_tx_ack(struct ll_conn *conn, memq_link_t *link, - struct node_tx *tx); +struct ll_conn *ull_conn_tx_ack(u16_t handle, memq_link_t *link, + struct node_tx *tx); u8_t ull_conn_llcp_req(void *conn);