From 91c901021694ccdd599807d326260420e26aec85 Mon Sep 17 00:00:00 2001 From: chenguo Date: Tue, 12 Dec 2017 16:16:37 +0800 Subject: [PATCH] qcacmn: Fix memory leak for invalid peer error In dp_rx_null_q_desc_handle, if peer is invaild and no need to deliver to the upper layer, the nbuf must be freed before recycle the rx descriptor. CRs-Fixed: 2153932 Change-Id: I1b373d1b5b50da42b896f0b2fd7bbd13b0e2466d --- dp/wifi3.0/dp_rx.c | 53 ++++++++++++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_rx.h | 2 ++ dp/wifi3.0/dp_rx_err.c | 4 ++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index ebbb02a3a28c..d1469caddf40 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -701,11 +701,64 @@ out: return 0; } + +/** + * dp_rx_process_invalid_peer_wrapper(): Function to wrap invalid peer handler + * @soc: DP SOC handle + * @mpdu: mpdu for which peer is invalid + * @mpdu_done: if an mpdu is completed + * + * return: integer type + */ +void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc, + qdf_nbuf_t mpdu, bool mpdu_done) +{ + /* Only trigger the process when mpdu is completed */ + if (mpdu_done) + dp_rx_process_invalid_peer(soc, mpdu); +} #else uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu) { + qdf_nbuf_t curr_nbuf, next_nbuf; + struct dp_pdev *pdev; + uint8_t i; + + curr_nbuf = mpdu; + while (curr_nbuf) { + next_nbuf = qdf_nbuf_next(curr_nbuf); + /* Drop and free packet */ + DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1, + qdf_nbuf_len(curr_nbuf)); + qdf_nbuf_free(curr_nbuf); + curr_nbuf = next_nbuf; + } + + /* reset the head and tail pointers */ + for (i = 0; i < MAX_PDEV_CNT; i++) { + pdev = soc->pdev_list[i]; + if (!pdev) { + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_ERROR, + "PDEV not found"); + continue; + } + + pdev->invalid_peer_head_msdu = NULL; + pdev->invalid_peer_tail_msdu = NULL; + } return 0; } + +void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc, + qdf_nbuf_t mpdu, bool mpdu_done) +{ + /* To avoid compiler warning */ + mpdu_done = mpdu_done; + + /* Process the nbuf */ + dp_rx_process_invalid_peer(soc, mpdu); +} #endif #if defined(FEATURE_LRO) diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 0987b42b2796..0f7ad0f40a3f 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -412,6 +412,8 @@ dp_rx_wds_srcport_learn(struct dp_soc *soc, #endif uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf); +void dp_rx_process_invalid_peer_wrapper(struct dp_soc *soc, + qdf_nbuf_t mpdu, bool mpdu_done); void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr); #define DP_RX_LIST_APPEND(head, tail, elem) \ diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index dc5cfd279722..279d21cd76de 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -458,8 +458,8 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, FL("peer is NULL")); mpdu_done = dp_rx_chain_msdus(soc, nbuf, rx_tlv_hdr, pool_id); - if (mpdu_done) - dp_rx_process_invalid_peer(soc, nbuf); + /* Trigger invalid peer handler wrapper */ + dp_rx_process_invalid_peer_wrapper(soc, nbuf, mpdu_done); return; }