From 6c1cdf307a64952935692f018a759cd62a0b0e64 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Thu, 23 May 2019 19:02:49 +0530 Subject: [PATCH] qcacmn: Fix memory leak in dp pdev attach failure case Currently the failure in dp_rx_pdev_mon_attach, during dp_pdev_attach_wifi3, does not cleanup the rx buffers and hence that memory is leaked. Follow the proper cleanup sequence to avoid leaking the rx buffer memory. CRs-Fixed: 2451982 Change-Id: Idef308e11c46fe3e7ae9199a6fcf05ca83210b6b --- dp/wifi3.0/dp_main.c | 14 ++++- dp/wifi3.0/dp_rx_mon_dest.c | 105 ++++++++++++++++++++++++++++-------- 2 files changed, 94 insertions(+), 25 deletions(-) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 0f910d5dd8..3ffa718467 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -3402,13 +3402,13 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, if (dp_rx_pdev_mon_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_rx_pdev_mon_attach failed"); - goto fail1; + goto rx_mon_attach_fail; } if (dp_wdi_event_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "dp_wdi_evet_attach failed"); - goto fail1; + goto wdi_attach_fail; } /* set the reo destination during initialization */ @@ -3445,6 +3445,16 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, return (struct cdp_pdev *)pdev; +wdi_attach_fail: + /* + * dp_mon_link_desc_pool_cleanup is done in dp_pdev_detach + * and hence need not to be done here. + */ + dp_rx_pdev_mon_detach(pdev); + +rx_mon_attach_fail: + dp_rx_pdev_detach(pdev); + fail1: if (pdev->invalid_peer) qdf_mem_free(pdev->invalid_peer); diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index d2977676e2..8ea1809379 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -1484,6 +1484,78 @@ dp_rx_pdev_mon_buf_detach(struct dp_pdev *pdev, int mac_id) } #endif +/** + * dp_rx_pdev_mon_cmn_detach() - detach dp rx for monitor mode + * @pdev: core txrx pdev context + * @mac_id: mac_id for which deinit is to be done + * + * This function will free DP Rx resources for + * monitor mode + * + * Return: QDF_STATUS_SUCCESS: success + * QDF_STATUS_E_RESOURCES: Error return + */ +static QDF_STATUS +dp_rx_pdev_mon_cmn_detach(struct dp_pdev *pdev, int mac_id) { + struct dp_soc *soc = pdev->soc; + uint8_t pdev_id = pdev->pdev_id; + int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + + dp_mon_link_desc_pool_cleanup(soc, mac_for_pdev); + dp_rx_pdev_mon_status_detach(pdev, mac_for_pdev); + dp_rx_pdev_mon_buf_detach(pdev, mac_for_pdev); + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_rx_pdev_mon_cmn_attach() - attach DP RX for monitor mode + * @pdev: core txrx pdev context + * @mac_id: mac_id for which init is to be done + * + * This function Will allocate dp rx resource and + * initialize resources for monitor mode. + * + * Return: QDF_STATUS_SUCCESS: success + * QDF_STATUS_E_RESOURCES: Error return + */ +static QDF_STATUS +dp_rx_pdev_mon_cmn_attach(struct dp_pdev *pdev, int mac_id) { + struct dp_soc *soc = pdev->soc; + uint8_t pdev_id = pdev->pdev_id; + int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); + QDF_STATUS status; + + status = dp_rx_pdev_mon_buf_attach(pdev, mac_for_pdev); + if (!QDF_IS_STATUS_SUCCESS(status)) { + dp_err("%s: dp_rx_pdev_mon_buf_attach() failed\n", __func__); + goto fail; + } + + status = dp_rx_pdev_mon_status_attach(pdev, mac_for_pdev); + if (!QDF_IS_STATUS_SUCCESS(status)) { + dp_err("%s: dp_rx_pdev_mon_status_attach() failed", __func__); + goto mon_buf_detach; + } + + status = dp_mon_link_desc_pool_setup(soc, mac_for_pdev); + if (!QDF_IS_STATUS_SUCCESS(status)) { + dp_err("%s: dp_mon_link_desc_pool_setup() failed", __func__); + goto mon_status_detach; + } + + return status; + +mon_status_detach: + dp_rx_pdev_mon_status_detach(pdev, mac_for_pdev); + +mon_buf_detach: + dp_rx_pdev_mon_buf_detach(pdev, mac_for_pdev); + +fail: + return status; +} + /** * dp_rx_pdev_mon_attach() - attach DP RX for monitor mode * @pdev: core txrx pdev context @@ -1497,7 +1569,6 @@ dp_rx_pdev_mon_buf_detach(struct dp_pdev *pdev, int mac_id) */ QDF_STATUS dp_rx_pdev_mon_attach(struct dp_pdev *pdev) { - struct dp_soc *soc = pdev->soc; QDF_STATUS status; uint8_t pdev_id = pdev->pdev_id; int mac_id; @@ -1506,37 +1577,25 @@ dp_rx_pdev_mon_attach(struct dp_pdev *pdev) { "%s: pdev attach id=%d", __func__, pdev_id); for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { - int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev_id); - - status = dp_rx_pdev_mon_buf_attach(pdev, mac_for_pdev); + status = dp_rx_pdev_mon_cmn_attach(pdev, mac_id); if (!QDF_IS_STATUS_SUCCESS(status)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: dp_rx_pdev_mon_buf_attach() failed\n", - __func__); - return status; - } - - status = dp_rx_pdev_mon_status_attach(pdev, mac_for_pdev); - if (!QDF_IS_STATUS_SUCCESS(status)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: dp_rx_pdev_mon_status_attach() failed", - __func__); - return status; - } - - status = dp_mon_link_desc_pool_setup(soc, mac_for_pdev); - if (!QDF_IS_STATUS_SUCCESS(status)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: dp_mon_link_desc_pool_setup() failed", - __func__); - return status; + "%s: dp_rx_pdev_mon_cmn_attach(%d) failed\n", + __func__, mac_id); + goto fail; } } pdev->mon_last_linkdesc_paddr = 0; pdev->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1; qdf_spinlock_create(&pdev->mon_lock); return QDF_STATUS_SUCCESS; + +fail: + for (mac_id = mac_id - 1; mac_id >= 0; mac_id--) + dp_rx_pdev_mon_cmn_detach(pdev, mac_id); + + return status; } QDF_STATUS