Эх сурвалжийг харах

qcacmn: Handle RTPM counter for opt wifi dp

Inorder to keep the PCIe link up during
optional wifi dp transfer the
hif_force_wake_request() is called during
filter addition. This increments the rtpm_get counter.
Now if Wifi is disconnected before releasing the
filters, the corresponding hif_force_wake_release()
call is not made. This causes a mismatch in RTPM GET and
PUT calls and triggers an assert during hdd_wlan_stop_modules().
This change adds a cleanup call to release the force wake
and reduce the rtpm_put counter to prevent the assert.

Change-Id: Idd778275a015922376cf7eb0a7c3d92e75881fe8
CRs-Fixed: 3441186
Namita Nair 2 жил өмнө
parent
commit
42381bb34d

+ 32 - 0
dp/wifi3.0/dp_ipa.c

@@ -1354,6 +1354,36 @@ void dp_rx_alt_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
 { }
 { }
 #endif
 #endif
 
 
+/**
+ * dp_ipa_opt_wifi_dp_cleanup() - Cleanup ipa opt wifi dp filter setup
+ * @soc: data path instance
+ * @pdev: core txrx pdev context
+ *
+ * This function will cleanup filter setup for optional wifi dp.
+ *
+ * Return: none
+ */
+
+#ifdef IPA_OPT_WIFI_DP
+static void dp_ipa_opt_wifi_dp_cleanup(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+	struct hal_soc *hal_soc = (struct hal_soc *)soc->hal_soc;
+	struct hif_softc *hif = (struct hif_softc *)(hal_soc->hif_handle);
+	int count = qdf_atomic_read(&hif->opt_wifi_dp_rtpm_cnt);
+	int i;
+
+	for (i = count; i > 0; i--) {
+		dp_info("opt_dp: cleanup call pcie link down");
+		dp_ipa_pcie_link_down((struct cdp_soc_t *)soc);
+	}
+}
+#else
+static inline
+void dp_opt_wifi_dp(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+}
+#endif
+
 int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
 int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
 {
 {
 	if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
 	if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
@@ -1371,6 +1401,8 @@ int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
 	/* Cleanup 2nd RX pipe resources */
 	/* Cleanup 2nd RX pipe resources */
 	dp_rx_alt_ipa_uc_detach(soc, pdev);
 	dp_rx_alt_ipa_uc_detach(soc, pdev);
 
 
+	dp_ipa_opt_wifi_dp_cleanup(soc, pdev);
+
 	return QDF_STATUS_SUCCESS;	/* success */
 	return QDF_STATUS_SUCCESS;	/* success */
 }
 }
 
 

+ 3 - 0
hif/src/hif_main.h

@@ -347,6 +347,9 @@ struct hif_softc {
 #endif /*defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)*/
 #endif /*defined(HIF_CONFIG_SLUB_DEBUG_ON) || defined(HIF_CE_DEBUG_DATA_BUF)*/
 #ifdef IPA_OFFLOAD
 #ifdef IPA_OFFLOAD
 	qdf_shared_mem_t *ipa_ce_ring;
 	qdf_shared_mem_t *ipa_ce_ring;
+#endif
+#ifdef IPA_OPT_WIFI_DP
+	qdf_atomic_t opt_wifi_dp_rtpm_cnt;
 #endif
 #endif
 	struct hif_cfg ini_cfg;
 	struct hif_cfg ini_cfg;
 #ifdef HIF_CE_LOG_INFO
 #ifdef HIF_CE_LOG_INFO

+ 27 - 2
hif/src/pcie/if_pci.c

@@ -4290,11 +4290,36 @@ void hif_allow_link_low_power_states(struct hif_opaque_softc *hif)
 #ifdef IPA_OPT_WIFI_DP
 #ifdef IPA_OPT_WIFI_DP
 int hif_prevent_l1(struct hif_opaque_softc *hif)
 int hif_prevent_l1(struct hif_opaque_softc *hif)
 {
 {
-	return hif_force_wake_request(hif);
+	struct hif_softc *hif_softc = (struct hif_softc *)hif;
+	int status;
+
+	status = hif_force_wake_request(hif);
+	if (status) {
+		hif_err("Force wake request error");
+		return status;
+	}
+
+	qdf_atomic_inc(&hif_softc->opt_wifi_dp_rtpm_cnt);
+	hif_info("opt_dp: pcie link up count %d",
+		 qdf_atomic_read(&hif_softc->opt_wifi_dp_rtpm_cnt));
+	return status;
 }
 }
 
 
 void hif_allow_l1(struct hif_opaque_softc *hif)
 void hif_allow_l1(struct hif_opaque_softc *hif)
 {
 {
-	hif_force_wake_release(hif);
+	struct hif_softc *hif_softc = (struct hif_softc *)hif;
+	int status;
+
+	if (qdf_atomic_read(&hif_softc->opt_wifi_dp_rtpm_cnt) > 0) {
+		status = hif_force_wake_release(hif);
+		if (status) {
+			hif_err("Force wake release error");
+			return;
+		}
+
+		qdf_atomic_dec(&hif_softc->opt_wifi_dp_rtpm_cnt);
+		hif_info("opt_dp: pcie link down count %d",
+			 qdf_atomic_read(&hif_softc->opt_wifi_dp_rtpm_cnt));
+	}
 }
 }
 #endif
 #endif

+ 39 - 34
ipa/core/src/wlan_ipa_core.c

@@ -4892,7 +4892,25 @@ int wlan_ipa_wdi_opt_dpath_flt_rsrv_cb(
 {
 {
 	struct wifi_dp_flt_setup *dp_flt_params = NULL;
 	struct wifi_dp_flt_setup *dp_flt_params = NULL;
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
-	int i;
+	int i, pdev_id, param_val;
+	struct wlan_objmgr_pdev *pdev;
+	int response = 0;
+
+	pdev = ipa_obj->pdev;
+	pdev_id = ipa_obj->dp_pdev_id;
+	/* Disable Low power features before filter reservation */
+	ipa_info("opt_dp: Disable low power features to reserve filter");
+	param_val = 0;
+	response = cdp_ipa_opt_dp_enable_disable_low_power_mode(pdev, pdev_id,
+								param_val);
+	if (response) {
+		ipa_err("Low power feature disable failed. status %d",
+			response);
+		return QDF_STATUS_FILT_REQ_ERROR;
+	}
+
+	response = cdp_ipa_pcie_link_up(ipa_obj->dp_soc);
+	ipa_info("opt_dp: Pcie link up status %d", response);
 
 
 	ipa_info("opt_dp: Send filter reserve req");
 	ipa_info("opt_dp: Send filter reserve req");
 	dp_flt_params = &(ipa_obj->dp_cce_super_rule_flt_param);
 	dp_flt_params = &(ipa_obj->dp_cce_super_rule_flt_param);
@@ -4912,11 +4930,10 @@ int wlan_ipa_wdi_opt_dpath_flt_add_cb(
 	struct ipa_wdi_opt_dpath_flt_add_cb_params *ipa_flt =
 	struct ipa_wdi_opt_dpath_flt_add_cb_params *ipa_flt =
 			 (struct ipa_wdi_opt_dpath_flt_add_cb_params *)(in_out);
 			 (struct ipa_wdi_opt_dpath_flt_add_cb_params *)(in_out);
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
-	int i, j, flt, param_val, pdev_id;
+	int i, j, flt, response = 0;
 	uint8_t num_flts;
 	uint8_t num_flts;
 	uint32_t src_ip_addr, dst_ip_addr;
 	uint32_t src_ip_addr, dst_ip_addr;
 	uint32_t *host_ipv6;
 	uint32_t *host_ipv6;
-	int response = 0;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_psoc *psoc;
 	struct wifi_dp_flt_setup *dp_flt_param = NULL;
 	struct wifi_dp_flt_setup *dp_flt_param = NULL;
@@ -4924,9 +4941,7 @@ int wlan_ipa_wdi_opt_dpath_flt_add_cb(
 
 
 	pdev = ipa_obj->pdev;
 	pdev = ipa_obj->pdev;
 	psoc = wlan_pdev_get_psoc(pdev);
 	psoc = wlan_pdev_get_psoc(pdev);
-	pdev_id = ipa_obj->dp_pdev_id;
 	num_flts = ipa_flt->num_tuples;
 	num_flts = ipa_flt->num_tuples;
-
 	htc_handle = lmac_get_htc_hdl(psoc);
 	htc_handle = lmac_get_htc_hdl(psoc);
 	if (!htc_handle) {
 	if (!htc_handle) {
 		ipa_err("HTC Handle is null");
 		ipa_err("HTC Handle is null");
@@ -4940,19 +4955,6 @@ int wlan_ipa_wdi_opt_dpath_flt_add_cb(
 		return QDF_STATUS_FILT_REQ_ERROR;
 		return QDF_STATUS_FILT_REQ_ERROR;
 	}
 	}
 
 
-	/* Disable Low power features before filter addition */
-	ipa_info("opt_dp: Disable low power features to add filter param");
-	param_val = 0;
-	response = cdp_ipa_opt_dp_enable_disable_low_power_mode(pdev, pdev_id,
-								param_val);
-	if (response) {
-		ipa_err("Low power feature disable failed. status %d",
-			response);
-		return QDF_STATUS_FILT_REQ_ERROR;
-	}
-	response = cdp_ipa_pcie_link_up(ipa_obj->dp_soc);
-	ipa_info("opt_dp: Pcie link up status %d", response);
-
 	for (flt = 0; flt < num_flts; flt++) {
 	for (flt = 0; flt < num_flts; flt++) {
 		for (i = 0; i < IPA_WDI_MAX_FILTER; i++)
 		for (i = 0; i < IPA_WDI_MAX_FILTER; i++)
 			if (!dp_flt_param->flt_addr_params[i].ipa_flt_in_use)
 			if (!dp_flt_param->flt_addr_params[i].ipa_flt_in_use)
@@ -5063,14 +5065,12 @@ int wlan_ipa_wdi_opt_dpath_flt_rem_cb(
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_psoc *psoc;
-	int pdev_id;
 	uint8_t num_flts;
 	uint8_t num_flts;
-	uint32_t i, j, response = 0, param_val = 0;
+	uint32_t i, j, response = 0;
 	void *htc_handle;
 	void *htc_handle;
 
 
 	pdev = ipa_obj->pdev;
 	pdev = ipa_obj->pdev;
 	psoc = wlan_pdev_get_psoc(pdev);
 	psoc = wlan_pdev_get_psoc(pdev);
-	pdev_id = ipa_obj->dp_pdev_id;
 	num_flts = rem_flt->num_tuples;
 	num_flts = rem_flt->num_tuples;
 
 
 	htc_handle = lmac_get_htc_hdl(psoc);
 	htc_handle = lmac_get_htc_hdl(psoc);
@@ -5078,18 +5078,6 @@ int wlan_ipa_wdi_opt_dpath_flt_rem_cb(
 		ipa_err("HTC Handle is null");
 		ipa_err("HTC Handle is null");
 		return QDF_STATUS_FILT_REQ_ERROR;
 		return QDF_STATUS_FILT_REQ_ERROR;
 	}
 	}
-	/* Enable Low power features before filter deletion */
-	ipa_info("opt_dp: Enable low power features to delete filter param");
-	param_val = 1;
-	response = cdp_ipa_opt_dp_enable_disable_low_power_mode(pdev, pdev_id,
-								param_val);
-	if (response) {
-		ipa_err("Low power feature enable failed. status %d", response);
-		return QDF_STATUS_FILT_REQ_ERROR;
-	}
-
-	response = cdp_ipa_pcie_link_up(ipa_obj->dp_soc);
-	ipa_info("opt_dp: Vote for PCIe link up");
 
 
 	dp_flt_params = &(ipa_obj->dp_cce_super_rule_flt_param);
 	dp_flt_params = &(ipa_obj->dp_cce_super_rule_flt_param);
 	for (i = 0; i < num_flts; i++) {
 	for (i = 0; i < num_flts; i++) {
@@ -5146,8 +5134,25 @@ int wlan_ipa_wdi_opt_dpath_flt_rsrv_rel_cb(void *ipa_ctx)
 {
 {
 	struct wifi_dp_flt_setup *dp_flt_params = NULL;
 	struct wifi_dp_flt_setup *dp_flt_params = NULL;
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
 	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)ipa_ctx;
-	int i;
+	int i, param_val = 0;
+	struct wlan_objmgr_pdev *pdev;
+	int pdev_id;
+	int response = 0;
+
+	pdev = ipa_obj->pdev;
+	pdev_id = ipa_obj->dp_pdev_id;
+	/* Enable Low power features before filter release */
+	ipa_info("opt_dp: Enable low power features to release filter");
+	param_val = 1;
+	response = cdp_ipa_opt_dp_enable_disable_low_power_mode(pdev, pdev_id,
+								param_val);
+	if (response) {
+		ipa_err("Low power feature enable failed. status %d", response);
+		return QDF_STATUS_FILT_REQ_ERROR;
+	}
 
 
+	response = cdp_ipa_pcie_link_down(ipa_obj->dp_soc);
+	ipa_info("opt_dp: Vote for PCIe link down");
 	dp_flt_params = &(ipa_obj->dp_cce_super_rule_flt_param);
 	dp_flt_params = &(ipa_obj->dp_cce_super_rule_flt_param);
 	for (i = 0; i < IPA_WDI_MAX_FILTER; i++)
 	for (i = 0; i < IPA_WDI_MAX_FILTER; i++)
 		 dp_flt_params->flt_addr_params[i].valid = 0;
 		 dp_flt_params->flt_addr_params[i].valid = 0;