diff mbox series

[18/26,SRU,U/OEM-5.10] UBUNTU: SAUCE: ath11k: purge rx pktlog when entering suspend

Message ID 20201204152013.195139-19-vicamo.yang@canonical.com
State New
Headers show
Series UBUNTU: SAUCE: Support Killer 500s (QCA6390) WLAN/BT | expand

Commit Message

You-Sheng Yang Dec. 4, 2020, 3:20 p.m. UTC
From: Carl Huang <cjhuang@codeaurora.org>

BugLink: https://bugs.launchpad.net/bugs/1879633

This change is to purge rx pktlog when entering suspend and reap
the mon_status buffer to keep it empty. When leaving suspend, host
restarts the reap timer.

Host also stops CE timer and shadow timer before suspend.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1

Signed-off-by: Carl Huang <cjhuang@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
(cherry picked from commit 6f481de563dd108bd3df616c80e60f308b7a48e3
https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git)
Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
---
 drivers/net/wireless/ath/ath11k/ce.c    |  2 +-
 drivers/net/wireless/ath/ath11k/ce.h    |  2 ++
 drivers/net/wireless/ath/ath11k/core.c  |  8 ++++++-
 drivers/net/wireless/ath/ath11k/dp.c    |  2 +-
 drivers/net/wireless/ath/ath11k/dp.h    |  3 ++-
 drivers/net/wireless/ath/ath11k/dp_rx.c | 23 +++++++++++++++++++
 drivers/net/wireless/ath/ath11k/dp_rx.h |  2 +-
 drivers/net/wireless/ath/ath11k/mac.c   | 30 +++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/mac.h   |  2 ++
 9 files changed, 69 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
index 46c717a344c3..38a710174c87 100644
--- a/drivers/net/wireless/ath/ath11k/ce.c
+++ b/drivers/net/wireless/ath/ath11k/ce.c
@@ -195,7 +195,7 @@  static bool ath11k_ce_need_shadow_fix(int ce_id)
 	return false;
 }
 
-static void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab)
+void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab)
 {
 	int i;
 
diff --git a/drivers/net/wireless/ath/ath11k/ce.h b/drivers/net/wireless/ath/ath11k/ce.h
index 269b599ac0b0..d6eeef919349 100644
--- a/drivers/net/wireless/ath/ath11k/ce.h
+++ b/drivers/net/wireless/ath/ath11k/ce.h
@@ -190,4 +190,6 @@  int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
 int ath11k_ce_attr_attach(struct ath11k_base *ab);
 void ath11k_ce_get_shadow_config(struct ath11k_base *ab,
 				 u32 **shadow_cfg, u32 *shadow_cfg_len);
+void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab);
+
 #endif
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 69ff930cd3e1..af1d1b1e097c 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -952,6 +952,9 @@  int ath11k_core_suspend(struct ath11k_base *ab)
 	int ret = 0;
 
 	if (ab->hw_params.support_suspend) {
+		ath11k_purge_rx_pktlog(ar, true);
+		ath11k_ce_stop_shadow_timers(ab);
+		ath11k_dp_stop_shadow_timers(ab);
 		reinit_completion(&ar->target_suspend);
 		ath11k_wmi_pdev_suspend(ar, 1, 0);
 		ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ);
@@ -963,7 +966,7 @@  int ath11k_core_suspend(struct ath11k_base *ab)
 			ath11k_warn(ab, "suspend failed\n");
 			return -EAGAIN;
 		}
-
+		ath11k_purge_rx_pktlog(ar, false);
 		return ath11k_hif_suspend(ab);
 	}
 	return 0;
@@ -972,8 +975,11 @@  EXPORT_SYMBOL(ath11k_core_suspend);
 
 int ath11k_core_resume(struct ath11k_base *ab)
 {
+	struct ath11k *ar = ab->pdevs[0].ar;
+
 	if (ab->hw_params.support_suspend) {
 		ath11k_hif_resume(ab);
+		ath11k_enable_rx_pktlog(ar);
 		ath11k_wmi_pdev_resume(ab->pdevs[0].ar, 0);
 	}
 
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index b7288dc47199..36ea10fb3945 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -306,7 +306,7 @@  int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
 	return 0;
 }
 
-static void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
+void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
 {
 	int i;
 
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index ee8db812589b..05fd06c20780 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -40,6 +40,7 @@  struct dp_rx_tid {
 
 #define DP_REO_DESC_FREE_THRESHOLD  64
 #define DP_REO_DESC_FREE_TIMEOUT_MS 1000
+#define DP_MON_PURGE_TIMEOUT_MS     100
 #define DP_MON_SERVICE_BUDGET       128
 
 struct dp_reo_cache_flush_elem {
@@ -1640,5 +1641,5 @@  void ath11k_dp_shadow_stop_timer(struct ath11k_base *ab,
 void ath11k_dp_shadow_init_timer(struct ath11k_base *ab,
 				 struct ath11k_hp_update_timer *update_timer,
 				 u32 interval, u32 ring_id);
-
+void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab);
 #endif
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 37e5a408cd62..2bcaf23fa91a 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -274,6 +274,29 @@  static void ath11k_dp_service_mon_ring(struct timer_list *t)
 		  msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
 }
 
+int ath11k_dp_purge_mon_ring(struct ath11k_base *ab)
+{
+	int i, buf_reaped = 0;
+	unsigned long ts = jiffies;
+
+again:
+	for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
+		buf_reaped += ath11k_dp_rx_process_mon_rings(ab, i,
+							     NULL,
+							     DP_MON_SERVICE_BUDGET);
+	}
+
+	/* nothing more to reap */
+	if (buf_reaped < DP_MON_SERVICE_BUDGET)
+		return 0;
+
+	if (time_after(jiffies, ts +
+		       msecs_to_jiffies(DP_MON_PURGE_TIMEOUT_MS)))
+		return -ETIMEDOUT;
+
+	goto again;
+}
+
 /* Returns number of Rx buffers replenished */
 int ath11k_dp_rxbufs_replenish(struct ath11k_base *ab, int mac_id,
 			       struct dp_rxdma_ring *rx_ring,
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.h b/drivers/net/wireless/ath/ath11k/dp_rx.h
index fbea45f79c9b..7d00331cf3e0 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
@@ -90,5 +90,5 @@  int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
 int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar);
 int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar);
 int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id);
-
+int ath11k_dp_purge_mon_ring(struct ath11k_base *ab);
 #endif /* ATH11K_DP_RX_H */
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index a16b5d69b236..32de67d7df08 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -4106,6 +4106,10 @@  static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
 						       &tlv_filter);
 	}
 
+	if (enable && !ar->ab->hw_params.rxdma1_enable)
+		mod_timer(&ar->ab->mon_reap_timer, jiffies +
+			  msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
+
 	return ret;
 }
 
@@ -6437,3 +6441,29 @@  void ath11k_mac_destroy(struct ath11k_base *ab)
 		pdev->ar = NULL;
 	}
 }
+
+int ath11k_purge_rx_pktlog(struct ath11k *ar, bool stop_timer)
+{
+	int ret;
+
+	/* stop timer */
+	if (stop_timer)
+		del_timer_sync(&ar->ab->mon_reap_timer);
+
+	/* reap all the monitor related rings */
+	ret = ath11k_dp_purge_mon_ring(ar->ab);
+	if (ret)
+		ath11k_warn(ar->ab,
+			    "failed to purge mon_buf ring %d\n", ret);
+
+	return ret;
+}
+
+int ath11k_enable_rx_pktlog(struct ath11k *ar)
+{
+	/* start reap timer */
+	mod_timer(&ar->ab->mon_reap_timer, jiffies +
+				  msecs_to_jiffies(ATH11K_MON_TIMER_INTERVAL));
+
+	return 0;
+}
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 0607479774a9..36d812457b75 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -146,4 +146,6 @@  int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
 u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
 enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
 enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
+int ath11k_purge_rx_pktlog(struct ath11k *ar, bool stop_timer);
+int ath11k_enable_rx_pktlog(struct ath11k *ar);
 #endif