瀏覽代碼

qcacmn: Cancel reap timer during driver unload

In case of driver unload, there can be a race condition
since the timer for processing monitor status ring can run
in parallel to the unload time wow ack response handler,
which is also flushing all the monitor status ring entries.
To avoid this race condition, stop the monitor reap timer
as a part of target suspend, and process all the outstanding
entries in the montior status ring.
This will make sure that the monitor status ring is
processed from only one context at any given time.

Change-Id: If61327c73fdddc414b3957b69ae986f2a26bb803
CRs-Fixed: 2677812
Ananya Gupta 5 年之前
父節點
當前提交
4ef9913568
共有 3 個文件被更改,包括 53 次插入0 次删除
  1. 22 0
      dp/inc/cdp_txrx_bus.h
  2. 3 0
      dp/inc/cdp_txrx_ops.h
  3. 28 0
      dp/wifi3.0/dp_main.c

+ 22 - 0
dp/inc/cdp_txrx_bus.h

@@ -92,4 +92,26 @@ static inline void cdp_process_wow_ack_rsp(ol_txrx_soc_handle soc,
 		return soc->ops->bus_ops->process_wow_ack_rsp(soc, pdev_id);
 }
 
+/**
+ * cdp_process_target_suspend_req() - Process target suspend request
+ * @soc: data path soc handle
+ * @pdev_id: id of dp pdev handle
+ *
+ * Complete the datapath specific work before target suspend
+ *
+ * Return: None
+ */
+static inline void cdp_process_target_suspend_req(ol_txrx_soc_handle soc,
+						  uint8_t pdev_id)
+{
+	if (!soc || !soc->ops || !soc->ops->bus_ops) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
+			  "%s invalid instance", __func__);
+		return;
+	}
+
+	if (soc->ops->bus_ops->process_target_suspend_req)
+		return soc->ops->bus_ops->process_target_suspend_req(soc,
+								     pdev_id);
+}
 #endif /* _CDP_TXRX_BUS_H_ */

+ 3 - 0
dp/inc/cdp_txrx_ops.h

@@ -1551,11 +1551,14 @@ struct cdp_tx_delay_ops {
  * @bus_suspend: handler for bus suspend
  * @bus_resume: handler for bus resume
  * @process_wow_ack_rsp: handler for wow ack response
+ * @process_target_suspend_req: handler for target suspend request
  */
 struct cdp_bus_ops {
 	QDF_STATUS (*bus_suspend)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
 	QDF_STATUS (*bus_resume)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
 	void (*process_wow_ack_rsp)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
+	void (*process_target_suspend_req)(struct cdp_soc_t *soc_hdl,
+					   uint8_t pdev_id);
 };
 #endif
 

+ 28 - 0
dp/wifi3.0/dp_main.c

@@ -10390,10 +10390,38 @@ static void dp_process_wow_ack_rsp(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 	}
 }
 
+/**
+ * dp_process_target_suspend_req() - process target suspend request
+ * @soc_hdl: datapath soc handle
+ * @pdev_id: data path pdev handle id
+ *
+ * Return: none
+ */
+static void dp_process_target_suspend_req(struct cdp_soc_t *soc_hdl,
+					  uint8_t pdev_id)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
+
+	if (qdf_unlikely(!pdev)) {
+		dp_err("pdev is NULL");
+		return;
+	}
+
+	/* Stop monitor reap timer and reap any pending frames in ring */
+	if (((pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED) ||
+	     dp_is_enable_reap_timer_non_pkt(pdev)) &&
+	    soc->reap_timer_init) {
+		qdf_timer_sync_cancel(&soc->mon_reap_timer);
+		dp_service_mon_rings(soc, DP_MON_REAP_BUDGET);
+	}
+}
+
 static struct cdp_bus_ops dp_ops_bus = {
 	.bus_suspend = dp_bus_suspend,
 	.bus_resume = dp_bus_resume,
 	.process_wow_ack_rsp = dp_process_wow_ack_rsp,
+	.process_target_suspend_req = dp_process_target_suspend_req
 };
 #endif