Pārlūkot izejas kodu

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
Rakesh Pillai 5 gadi atpakaļ
vecāks
revīzija
6c1cdf307a
2 mainītis faili ar 94 papildinājumiem un 25 dzēšanām
  1. 12 2
      dp/wifi3.0/dp_main.c
  2. 82 23
      dp/wifi3.0/dp_rx_mon_dest.c

+ 12 - 2
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)) {
 	if (dp_rx_pdev_mon_attach(pdev)) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 				"dp_rx_pdev_mon_attach failed");
 				"dp_rx_pdev_mon_attach failed");
-		goto fail1;
+		goto rx_mon_attach_fail;
 	}
 	}
 
 
 	if (dp_wdi_event_attach(pdev)) {
 	if (dp_wdi_event_attach(pdev)) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
 				"dp_wdi_evet_attach failed");
 				"dp_wdi_evet_attach failed");
-		goto fail1;
+		goto wdi_attach_fail;
 	}
 	}
 
 
 	/* set the reo destination during initialization */
 	/* 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;
 	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:
 fail1:
 	if (pdev->invalid_peer)
 	if (pdev->invalid_peer)
 		qdf_mem_free(pdev->invalid_peer);
 		qdf_mem_free(pdev->invalid_peer);

+ 82 - 23
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
 #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
  * dp_rx_pdev_mon_attach() - attach DP RX for monitor mode
  * @pdev: core txrx pdev context
  * @pdev: core txrx pdev context
@@ -1497,7 +1569,6 @@ dp_rx_pdev_mon_buf_detach(struct dp_pdev *pdev, int mac_id)
  */
  */
 QDF_STATUS
 QDF_STATUS
 dp_rx_pdev_mon_attach(struct dp_pdev *pdev) {
 dp_rx_pdev_mon_attach(struct dp_pdev *pdev) {
-	struct dp_soc *soc = pdev->soc;
 	QDF_STATUS status;
 	QDF_STATUS status;
 	uint8_t pdev_id = pdev->pdev_id;
 	uint8_t pdev_id = pdev->pdev_id;
 	int mac_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);
 			"%s: pdev attach id=%d", __func__, pdev_id);
 
 
 	for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_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)) {
 		if (!QDF_IS_STATUS_SUCCESS(status)) {
 			QDF_TRACE(QDF_MODULE_ID_DP,
 			QDF_TRACE(QDF_MODULE_ID_DP,
 				  QDF_TRACE_LEVEL_ERROR,
 				  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_linkdesc_paddr = 0;
 	pdev->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
 	pdev->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
 	qdf_spinlock_create(&pdev->mon_lock);
 	qdf_spinlock_create(&pdev->mon_lock);
 	return QDF_STATUS_SUCCESS;
 	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
 QDF_STATUS