Browse Source

Merge "qcacmn: Stop the monitor reap timer at dp suspend"

Linux Build Service Account 5 years ago
parent
commit
da64f244ea
3 changed files with 104 additions and 16 deletions
  1. 24 1
      dp/inc/cdp_txrx_bus.h
  2. 2 0
      dp/inc/cdp_txrx_ops.h
  3. 78 15
      dp/wifi3.0/dp_main.c

+ 24 - 1
dp/inc/cdp_txrx_bus.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 2019-2020 The Linux Foundation. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -69,4 +69,27 @@ static inline QDF_STATUS cdp_bus_resume(ol_txrx_soc_handle soc,
 	return QDF_STATUS_E_NOSUPPORT;
 	return QDF_STATUS_E_NOSUPPORT;
 }
 }
 
 
+/**
+ * cdp_process_wow_ack() - Process wow ack response
+ * @soc: data path soc handle
+ * @pdev_id: id of dp pdev handle
+ *
+ * Do any required data path operations for target wow ack
+ * suspend response.
+ *
+ * Return: None
+ */
+static inline void cdp_process_wow_ack_rsp(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_wow_ack_rsp)
+		return soc->ops->bus_ops->process_wow_ack_rsp(soc, pdev_id);
+}
+
 #endif /* _CDP_TXRX_BUS_H_ */
 #endif /* _CDP_TXRX_BUS_H_ */

+ 2 - 0
dp/inc/cdp_txrx_ops.h

@@ -1518,10 +1518,12 @@ struct cdp_tx_delay_ops {
  * struct cdp_bus_ops - mcl bus suspend/resume ops
  * struct cdp_bus_ops - mcl bus suspend/resume ops
  * @bus_suspend: handler for bus suspend
  * @bus_suspend: handler for bus suspend
  * @bus_resume: handler for bus resume
  * @bus_resume: handler for bus resume
+ * @process_wow_ack_rsp: handler for wow ack response
  */
  */
 struct cdp_bus_ops {
 struct cdp_bus_ops {
 	QDF_STATUS (*bus_suspend)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id);
 	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);
 	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);
 };
 };
 #endif
 #endif
 
 

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

@@ -201,6 +201,9 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc,
 /* Threshold for peer's cached buf queue beyond which frames are dropped */
 /* Threshold for peer's cached buf queue beyond which frames are dropped */
 #define DP_RX_CACHED_BUFQ_THRESH 64
 #define DP_RX_CACHED_BUFQ_THRESH 64
 
 
+/* Budget to reap monitor status ring */
+#define DP_MON_REAP_BUDGET 1024
+
 /**
 /**
  * default_dscp_tid_map - Default DSCP-TID mapping
  * default_dscp_tid_map - Default DSCP-TID mapping
  *
  *
@@ -338,30 +341,43 @@ uint32_t dp_soc_get_mon_mask_for_interrupt_mode(struct dp_soc *soc, int intr_ctx
 }
 }
 
 
 /*
 /*
- * dp_service_mon_rings()- timer to reap monitor rings
- * reqd as we are not getting ppdu end interrupts
- * @arg: SoC Handle
+ * dp_service_mon_rings()- service monitor rings
+ * @soc: soc dp handle
+ * @quota: number of ring entry that can be serviced
  *
  *
- * Return:
+ * Return: None
  *
  *
  */
  */
-static void dp_service_mon_rings(void *arg)
+static void dp_service_mon_rings(struct  dp_soc *soc, uint32_t quota)
 {
 {
-	struct dp_soc *soc = (struct dp_soc *)arg;
 	int ring = 0, work_done;
 	int ring = 0, work_done;
 	struct dp_pdev *pdev = NULL;
 	struct dp_pdev *pdev = NULL;
 
 
-	for  (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) {
+	for (ring = 0 ; ring < MAX_NUM_LMAC_HW; ring++) {
 		pdev = dp_get_pdev_for_lmac_id(soc, ring);
 		pdev = dp_get_pdev_for_lmac_id(soc, ring);
 		if (!pdev)
 		if (!pdev)
 			continue;
 			continue;
-		work_done = dp_mon_process(soc, ring,
-					   QCA_NAPI_BUDGET);
+		work_done = dp_mon_process(soc, ring, quota);
 
 
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  FL("Reaped %d descs from Monitor rings"),
 			  FL("Reaped %d descs from Monitor rings"),
 			  work_done);
 			  work_done);
 	}
 	}
+}
+
+/*
+ * dp_mon_reap_timer_handler()- timer to reap monitor rings
+ * reqd as we are not getting ppdu end interrupts
+ * @arg: SoC Handle
+ *
+ * Return:
+ *
+ */
+static void dp_mon_reap_timer_handler(void *arg)
+{
+	struct dp_soc *soc = (struct dp_soc *)arg;
+
+	dp_service_mon_rings(soc, QCA_NAPI_BUDGET);
 
 
 	qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS);
 	qdf_timer_mod(&soc->mon_reap_timer, DP_INTR_POLL_TIMER_MS);
 }
 }
@@ -4670,8 +4686,8 @@ static QDF_STATUS dp_rxdma_ring_config(struct dp_soc *soc)
 	 * Needed until we enable ppdu end interrupts
 	 * Needed until we enable ppdu end interrupts
 	 */
 	 */
 	qdf_timer_init(soc->osdev, &soc->mon_reap_timer,
 	qdf_timer_init(soc->osdev, &soc->mon_reap_timer,
-			dp_service_mon_rings, (void *)soc,
-			QDF_TIMER_TYPE_WAKE_APPS);
+		       dp_mon_reap_timer_handler, (void *)soc,
+		       QDF_TIMER_TYPE_WAKE_APPS);
 	soc->reap_timer_init = 1;
 	soc->reap_timer_init = 1;
 	return status;
 	return status;
 }
 }
@@ -10676,8 +10692,7 @@ static struct cdp_ipa_ops dp_ops_ipa = {
 static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 {
 {
 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
-	struct cdp_pdev *pdev = (struct cdp_pdev *)
-		dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
+	struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
 	int timeout = SUSPEND_DRAIN_WAIT;
 	int timeout = SUSPEND_DRAIN_WAIT;
 	int drain_wait_delay = 50; /* 50 ms */
 	int drain_wait_delay = 50; /* 50 ms */
 
 
@@ -10687,7 +10702,7 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 	}
 	}
 
 
 	/* Abort if there are any pending TX packets */
 	/* Abort if there are any pending TX packets */
-	while (dp_get_tx_pending(pdev) > 0) {
+	while (dp_get_tx_pending((struct cdp_pdev *)pdev) > 0) {
 		qdf_sleep(drain_wait_delay);
 		qdf_sleep(drain_wait_delay);
 		if (timeout <= 0) {
 		if (timeout <= 0) {
 			dp_err("TX frames are pending, abort suspend");
 			dp_err("TX frames are pending, abort suspend");
@@ -10699,22 +10714,70 @@ static QDF_STATUS dp_bus_suspend(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 	if (soc->intr_mode == DP_INTR_POLL)
 	if (soc->intr_mode == DP_INTR_POLL)
 		qdf_timer_stop(&soc->int_timer);
 		qdf_timer_stop(&soc->int_timer);
 
 
+	/* Stop monitor reap timer and reap any pending frames in ring */
+	if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
+	    soc->reap_timer_init) {
+		qdf_timer_sync_cancel(&soc->mon_reap_timer);
+		dp_service_mon_rings(soc, DP_MON_REAP_BUDGET);
+	}
+
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
 
 
 static QDF_STATUS dp_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 static QDF_STATUS dp_bus_resume(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
 {
 {
 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
 	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 QDF_STATUS_E_INVAL;
+	}
 
 
 	if (soc->intr_mode == DP_INTR_POLL)
 	if (soc->intr_mode == DP_INTR_POLL)
 		qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
 		qdf_timer_mod(&soc->int_timer, DP_INTR_POLL_TIMER_MS);
 
 
+	/* Start monitor reap timer */
+	if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
+	    soc->reap_timer_init)
+		qdf_timer_mod(&soc->mon_reap_timer,
+			      DP_INTR_POLL_TIMER_MS);
+
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
 
 
+/**
+ * dp_process_wow_ack_rsp() - process wow ack response
+ * @soc_hdl: datapath soc handle
+ * @pdev_id: data path pdev handle id
+ *
+ * Return: none
+ */
+static void dp_process_wow_ack_rsp(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;
+	}
+
+	/*
+	 * As part of wow enable FW disables the mon status ring and in wow ack
+	 * response from FW reap mon status ring to make sure no packets pending
+	 * in the ring.
+	 */
+	if (pdev->rx_pktlog_mode != DP_RX_PKTLOG_DISABLED &&
+	    soc->reap_timer_init) {
+		dp_service_mon_rings(soc, DP_MON_REAP_BUDGET);
+	}
+}
+
 static struct cdp_bus_ops dp_ops_bus = {
 static struct cdp_bus_ops dp_ops_bus = {
 	.bus_suspend = dp_bus_suspend,
 	.bus_suspend = dp_bus_suspend,
-	.bus_resume = dp_bus_resume
+	.bus_resume = dp_bus_resume,
+	.process_wow_ack_rsp = dp_process_wow_ack_rsp,
 };
 };
 #endif
 #endif