소스 검색

qcacmn: fix invalid accessing to rx_desc_status pool

crash scenario:
a. pktlog is enabled, the timer mon_reap_timer is active,
   reap mon_status_ring hal desc periodically.
b. rx_desc status pool is freed in dp_rx_pdev_mon_detach() when do
   dp_pdev_deinit() while the mon_reap_timer is still active until
   dp_rxdma_ring_cleanup() free it.
c. during the timeslot between dp_rx_pdev_mon_detach() and
   dp_rxdma_ring_cleanup(), if some hal desc is pending to be
   processed on mon_status_ring, invalid accessing to rx_desc_status
   pool happened.

solution:
  if pktlog is enabled, stop mon_reap_timer ahead of
dp_rx_pdev_mon_detach() in dp_pktlogmod_exit().

Change-Id: I91b16a88a5e4390587925d6eb2840b3ec1ec2187
CRs-Fixed: 2579817
Jinwei Chen 5 년 전
부모
커밋
9012d61d31
1개의 변경된 파일15개의 추가작업 그리고 7개의 파일을 삭제
  1. 15 7
      dp/wifi3.0/dp_main.c

+ 15 - 7
dp/wifi3.0/dp_main.c

@@ -426,22 +426,27 @@ static int dp_get_num_rx_contexts(struct cdp_soc_t *soc_hdl)
 
 /**
  * dp_pktlogmod_exit() - API to cleanup pktlog info
- * @handle: Pdev handle
+ * @pdev: Pdev handle
  *
  * Return: none
  */
-static void dp_pktlogmod_exit(struct dp_pdev *handle)
+static void dp_pktlogmod_exit(struct dp_pdev *pdev)
 {
-	struct hif_opaque_softc *scn = (void *)handle->soc->hif_handle;
+	struct dp_soc *soc = pdev->soc;
+	struct hif_opaque_softc *scn = soc->hif_handle;
 
 	if (!scn) {
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			  "%s: Invalid hif(scn) handle", __func__);
+		dp_err("Invalid hif(scn) handle");
 		return;
 	}
 
+	/* stop mon_reap_timer if it has been started */
+	if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
+	    soc->reap_timer_init)
+		qdf_timer_sync_cancel(&soc->mon_reap_timer);
+
 	pktlogmod_exit(scn);
-	handle->pkt_log_init = false;
+	pdev->pkt_log_init = false;
 }
 #endif
 #else
@@ -3695,7 +3700,10 @@ static void dp_rxdma_ring_cleanup(struct dp_soc *soc,
 		dp_srng_cleanup(soc, &pdev->rx_mac_buf_ring[i],
 			 RXDMA_BUF, 1);
 
-	qdf_timer_free(&soc->mon_reap_timer);
+	if (soc->reap_timer_init) {
+		qdf_timer_free(&soc->mon_reap_timer);
+		soc->reap_timer_init = 0;
+	}
 }
 #else
 static void dp_rxdma_ring_cleanup(struct dp_soc *soc,