Преглед на файлове

qcacmn: disable EXT grp irqs and drain TXRX during suspend

Any update to the SRNG TP/HP when the device is in low power
state would result in system errors. It is recommended to disable
EXT grp irqs and drain TXRX before sending power save enter command
to the FW. This will ensure that no interrupts are received while
in power save mode and as a result there wont be any HP/TP updates.

Change-Id: Ibf952bbc2c6d13fb3e4ca6b4845bc9cc887fa694
CRs-Fixed: 2883135
Manikanta Pubbisetty преди 4 години
родител
ревизия
14d38b77fb

+ 20 - 0
dp/inc/cdp_txrx_cmn.h

@@ -2632,4 +2632,24 @@ cdp_wds_ext_set_peer_rx(ol_txrx_soc_handle soc, uint8_t vdev_id,
 			(soc, vdev_id, mac, rx, osif_peer);
 }
 #endif /* QCA_SUPPORT_WDS_EXTENDED */
+
+/**
+ * cdp_drain_txrx() - drain TX/RX SRNGs
+ * @soc: opaque soc handle
+ */
+static inline void
+cdp_drain_txrx(ol_txrx_soc_handle soc)
+{
+	if (!soc || !soc->ops) {
+		dp_cdp_debug("Invalid Instance");
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->cmn_drv_ops ||
+	    !soc->ops->cmn_drv_ops->txrx_drain)
+		return;
+
+	return soc->ops->cmn_drv_ops->txrx_drain(soc);
+}
 #endif /* _CDP_TXRX_CMN_H_ */

+ 1 - 0
dp/inc/cdp_txrx_ops.h

@@ -566,6 +566,7 @@ struct cdp_cmn_ops {
 					  ol_txrx_rx_fp rx,
 					  ol_osif_peer_handle osif_peer);
 #endif /* QCA_SUPPORT_WDS_EXTENDED */
+	void (*txrx_drain)(ol_txrx_soc_handle soc);
 };
 
 struct cdp_ctrl_ops {

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

@@ -10391,11 +10391,25 @@ void dp_update_rx_soft_irq_limit_params(struct dp_soc *soc,
 		soc->wlan_cfg_ctx->rx_enable_eol_data_check,
 		soc->wlan_cfg_ctx->rx_hp_oos_update_limit);
 }
+
+static void dp_update_soft_irq_limits(struct dp_soc *soc, uint32_t tx_limit,
+				      uint32_t rx_limit)
+{
+	soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit = tx_limit;
+	soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit = rx_limit;
+}
+
 #else
 static inline
 void dp_update_rx_soft_irq_limit_params(struct dp_soc *soc,
 					struct cdp_config_params *params)
 { }
+
+static inline
+void dp_update_soft_irq_limits(struct dp_soc *soc, uint32_t tx_limit,
+			       uint32_t rx_limit)
+{
+}
 #endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
 
 /**
@@ -11430,6 +11444,32 @@ dp_config_full_mon_mode(struct cdp_soc_t *soc_handle,
 }
 #endif
 
+#if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE)
+static void dp_drain_txrx(struct cdp_soc_t *soc_handle)
+{
+	struct dp_soc *soc = (struct dp_soc *)soc_handle;
+	uint32_t cur_tx_limit, cur_rx_limit;
+	uint32_t budget = 0xffff;
+	int i;
+
+	cur_tx_limit = soc->wlan_cfg_ctx->tx_comp_loop_pkt_limit;
+	cur_rx_limit = soc->wlan_cfg_ctx->rx_reap_loop_pkt_limit;
+
+	/* Temporarily increase soft irq limits when going to drain
+	 * the UMAC/LMAC SRNGs and restore them after polling.
+	 * Though the budget is on higher side, the TX/RX reaping loops
+	 * will not execute longer as both TX and RX would be suspended
+	 * by the time this API is called.
+	 */
+	dp_update_soft_irq_limits(soc, budget, budget);
+
+	for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++)
+		dp_service_srngs(&soc->intr_ctx[i], budget);
+
+	dp_update_soft_irq_limits(soc, cur_tx_limit, cur_rx_limit);
+}
+#endif
+
 static struct cdp_cmn_ops dp_ops_cmn = {
 	.txrx_soc_attach_target = dp_soc_attach_target_wifi3,
 	.txrx_vdev_attach = dp_vdev_attach_wifi3,
@@ -11530,6 +11570,10 @@ static struct cdp_cmn_ops dp_ops_cmn = {
 	.get_wds_ext_peer_id = dp_wds_ext_get_peer_id,
 	.set_wds_ext_peer_rx = dp_wds_ext_set_peer_rx,
 #endif /* QCA_SUPPORT_WDS_EXTENDED */
+
+#if defined(FEATURE_RUNTIME_PM) || defined(DP_POWER_SAVE)
+	.txrx_drain = dp_drain_txrx,
+#endif
 };
 
 static struct cdp_ctrl_ops dp_ops_ctrl = {

+ 32 - 0
hif/inc/hif.h

@@ -1699,4 +1699,36 @@ static inline void hif_config_irq_set_perf_affinity_hint(
 {
 }
 #endif
+
+/**
+ * hif_apps_grp_irqs_enable() - enable ext grp irqs
+ * @hif - HIF opaque context
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+int hif_apps_grp_irqs_enable(struct hif_opaque_softc *hif_ctx);
+
+/**
+ * hif_apps_grp_irqs_disable() - disable ext grp irqs
+ * @hif - HIF opaque context
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+int hif_apps_grp_irqs_disable(struct hif_opaque_softc *hif_ctx);
+
+/**
+ * hif_disable_grp_irqs() - disable ext grp irqs
+ * @hif - HIF opaque context
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+int hif_disable_grp_irqs(struct hif_opaque_softc *scn);
+
+/**
+ * hif_enable_grp_irqs() - enable ext grp irqs
+ * @hif - HIF opaque context
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+int hif_enable_grp_irqs(struct hif_opaque_softc *scn);
 #endif /* _HIF_H_ */

+ 21 - 1
hif/src/dispatcher/dummy.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -413,3 +413,23 @@ bool hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data,
 {
 	return false;
 }
+
+/**
+ * hif_dummy_enable_grp_irqs - dummy call
+ * @scn: hif context
+ * Return: EOPNOTSUPP
+ */
+int hif_dummy_enable_grp_irqs(struct hif_softc *scn)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
+ * hif_dummy_disable_grp_irqs - dummy call
+ * @scn: hif context
+ * Return: EOPNOTSUPP
+ */
+int hif_dummy_disable_grp_irqs(struct hif_softc *scn)
+{
+	return -EOPNOTSUPP;
+}

+ 3 - 1
hif/src/dispatcher/dummy.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -90,3 +90,5 @@ void hif_dummy_config_irq_affinity(struct hif_softc *scn);
 int hif_dummy_config_irq_by_ceid(struct hif_softc *scn, int ce_id);
 bool hif_dummy_log_bus_info(struct hif_softc *scn, uint8_t *data,
 			    unsigned int *offset);
+int hif_dummy_enable_grp_irqs(struct hif_softc *scn);
+int hif_dummy_disable_grp_irqs(struct hif_softc *scn);

+ 20 - 1
hif/src/dispatcher/ipci_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -240,4 +240,23 @@ bool hif_ipci_needs_bmi(struct hif_softc *scn);
  */
 const char *hif_ipci_get_irq_name(int irq_no);
 
+/**
+ * hif_ipci_enable_grp_irqs(): enable grp IRQs
+ * @scn: struct hif_softc
+ *
+ * This function enables grp irqs
+ *
+ * Return: 0 if success, error code if failure
+ */
+int hif_ipci_enable_grp_irqs(struct hif_softc *scn);
+
+/**
+ * hif_ipci_disable_grp_irqs(): disable grp IRQs
+ * @scn: struct hif_softc
+ *
+ * This function disables grp irqs
+ *
+ * Return: 0 if success, error code if failure
+ */
+int hif_ipci_disable_grp_irqs(struct hif_softc *scn);
 #endif /* _IPCI_API_H_ */

+ 60 - 0
hif/src/dispatcher/multibus.c

@@ -61,6 +61,8 @@ static void hif_initialize_default_ops(struct hif_softc *hif_sc)
 	bus_ops->hif_config_irq_affinity =
 		&hif_dummy_config_irq_affinity;
 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
+	bus_ops->hif_enable_grp_irqs = &hif_dummy_enable_grp_irqs;
+	bus_ops->hif_disable_grp_irqs = &hif_dummy_enable_grp_irqs;
 }
 
 #define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *))
@@ -625,3 +627,61 @@ bool hif_log_bus_info(struct hif_softc *hif_sc, uint8_t *data,
 	return false;
 }
 #endif
+
+int hif_apps_grp_irqs_enable(struct hif_opaque_softc *hif_ctx)
+{
+	struct hif_exec_context *hif_exec;
+	struct hif_softc *scn;
+	int i;
+
+	QDF_BUG(hif_ctx);
+	scn = HIF_GET_SOFTC(hif_ctx);
+	if (!scn)
+		return -EINVAL;
+
+	for (i = 0 ; i < HIF_MAX_GROUP; i++) {
+		hif_exec = hif_exec_get_ctx(hif_ctx, i);
+		if (!hif_exec)
+			continue;
+
+		hif_exec->irq_enable(hif_exec);
+	}
+
+	return 0;
+}
+
+int hif_apps_grp_irqs_disable(struct hif_opaque_softc *hif_ctx)
+{
+	struct hif_exec_context *hif_exec;
+	struct hif_softc *scn;
+	int i;
+
+	QDF_BUG(hif_ctx);
+	scn = HIF_GET_SOFTC(hif_ctx);
+	if (!scn)
+		return -EINVAL;
+
+	for (i = 0 ; i < HIF_MAX_GROUP; i++) {
+		hif_exec = hif_exec_get_ctx(hif_ctx, i);
+		if (!hif_exec)
+			continue;
+
+		hif_exec->irq_disable(hif_exec);
+	}
+
+	return 0;
+}
+
+int hif_disable_grp_irqs(struct hif_opaque_softc *scn)
+{
+	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
+
+	return hif_sc->bus_ops.hif_disable_grp_irqs(hif_sc);
+}
+
+int hif_enable_grp_irqs(struct hif_opaque_softc *scn)
+{
+	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
+
+	return hif_sc->bus_ops.hif_enable_grp_irqs(hif_sc);
+}

+ 3 - 1
hif/src/dispatcher/multibus.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -94,6 +94,8 @@ struct hif_bus_ops {
 	int (*hif_config_irq_by_ceid)(struct hif_softc *hif_sc, int ce_id);
 	bool (*hif_log_bus_info)(struct hif_softc *scn, uint8_t *data,
 				 unsigned int *offset);
+	int (*hif_enable_grp_irqs)(struct hif_softc *scn);
+	int (*hif_disable_grp_irqs)(struct hif_softc *scn);
 };
 
 #ifdef HIF_SNOC

+ 3 - 1
hif/src/dispatcher/multibus_ipci.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -81,6 +81,8 @@ QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc)
 		&hif_dummy_config_irq_affinity;
 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
 	bus_ops->hif_log_bus_info = &hif_dummy_log_bus_info;
+	bus_ops->hif_enable_grp_irqs = hif_ipci_enable_grp_irqs;
+	bus_ops->hif_disable_grp_irqs = hif_ipci_disable_grp_irqs;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 10 - 0
hif/src/ipcie/if_ipci.c

@@ -826,3 +826,13 @@ void hif_allow_link_low_power_states(struct hif_opaque_softc *hif)
 {
 }
 #endif
+
+int hif_ipci_enable_grp_irqs(struct hif_softc *scn)
+{
+	return hif_apps_grp_irqs_enable(GET_HIF_OPAQUE_HDL(scn));
+}
+
+int hif_ipci_disable_grp_irqs(struct hif_softc *scn)
+{
+	return hif_apps_grp_irqs_disable(GET_HIF_OPAQUE_HDL(scn));
+}