Przeglądaj źródła

msm: ipa3: supporting hibernate & cleanup unused deepsleep API's

Adding changes to listen for new PM driver events to support
hibernate feature. Also, in 5.15 kernel, deepsleep & hibernate
entry/exit SSR API's are becoming same as regular SSR usecases.
So, cleaning up the unused deepsleep API's accordingly.

Change-Id: Ie8d901f824b586bbb7a5e61a1cdc877cd14eb1d0
Signed-off-by: Jagadeesh Ponduru <[email protected]>
Signed-off-by: Pavan Kumar M <[email protected]>
Pavan Kumar M 1 rok temu
rodzic
commit
b43ef45788

+ 1 - 17
drivers/platform/msm/include/linux/ipa.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _IPA_H_
@@ -1810,12 +1810,6 @@ bool ipa_is_ready(void);
 void ipa_proxy_clk_vote(void);
 void ipa_proxy_clk_unvote(void);
 
-#ifdef CONFIG_DEEPSLEEP
-int ipa_fmwk_deepsleep_entry_ipa(void);
-
-int ipa_fmwk_deepsleep_exit_ipa(void);
-#endif
-
 enum ipa_hw_type ipa_get_hw_type(void);
 
 const struct ipa_gsi_ep_config *ipa_get_gsi_ep_info(
@@ -2209,16 +2203,6 @@ static inline bool ipa_is_ready(void)
 	return false;
 }
 
-static inline int ipa_fmwk_deepsleep_entry_ipa(void)
-{
-	return -EPERM;
-}
-
-static inline int ipa_fmwk_deepsleep_exit_ipa(void)
-{
-	return -EPERM;
-}
-
 static inline enum ipa_hw_type ipa_get_hw_type(void)
 {
 	return IPA_HW_None;

+ 1 - 1
drivers/platform/msm/include/linux/ipa_wdi3.h

@@ -915,7 +915,7 @@ static inline int ipa_wdi_opt_dpath_notify_flt_rlsd_per_inst(ipa_wdi_hdl_t hdl,
 
 static int ipa_wdi_opt_dpath_rsrv_filter_req(
 	struct ipa_wlan_opt_dp_rsrv_filter_req_msg_v01 *req,
-	struct ipa_wlan_opt_dp_rsrv_filter_resp_msg_v01 *resp);
+	struct ipa_wlan_opt_dp_rsrv_filter_resp_msg_v01 *resp)
 {
 	return -EPERM;
 }

+ 71 - 21
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -158,7 +158,7 @@ static int ipa_alloc_pkt_init_ex(void);
 static void ipa3_free_pkt_init(void);
 static void ipa3_free_pkt_init_ex(void);
 
-#ifdef CONFIG_DEEPSLEEP
+#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION)
 static void ipa3_deepsleep_resume(void);
 static void ipa3_deepsleep_suspend(void);
 #endif
@@ -519,19 +519,29 @@ EXPORT_SYMBOL(ipa_smmu_free_sgt);
 
 static int ipa_pm_notify(struct notifier_block *b, unsigned long event, void *p)
 {
-	IPAERR("Entry\n");
+	IPADBG("Entry\n");
 	switch (event) {
-		case PM_POST_SUSPEND:
-#ifdef CONFIG_DEEPSLEEP
-			if (mem_sleep_current == PM_SUSPEND_MEM && ipa3_ctx->deepsleep) {
-				IPADBG("Enter deepsleep resume\n");
-				ipa3_deepsleep_resume();
-				IPADBG("Exit deepsleep resume\n");
-			}
+	case PM_POST_SUSPEND:
+#if IS_ENABLED(CONFIG_DEEPSLEEP)
+		if (mem_sleep_current == PM_SUSPEND_MEM && ipa3_ctx->deepsleep) {
+			IPADBG("Enter deepsleep resume\n");
+			ipa3_deepsleep_resume();
+			IPADBG("Exit deepsleep resume\n");
+		}
 #endif
-			break;
+		break;
+	case PM_POST_HIBERNATION:
+#if IS_ENABLED(CONFIG_HIBERNATION)
+		/*Using the same deepsleep flag to check if freeze happened or not.*/
+		if (ipa3_ctx->deepsleep) {
+			IPADBG("Enter hibernate restore\n");
+			ipa3_deepsleep_resume();
+			IPADBG("Exit hibernate restore\n");
+		}
+#endif
+		break;
 	}
-	IPAERR("Exit\n");
+	IPADBG("Exit\n");
 	return NOTIFY_DONE;
 }
 
@@ -542,7 +552,11 @@ static struct notifier_block ipa_pm_notifier = {
 
 static const struct dev_pm_ops ipa_pm_ops = {
 	.suspend_late = ipa3_ap_suspend,
+#if IS_ENABLED(CONFIG_HIBERNATION)
+	.freeze_late = ipa3_ap_freeze,
+#endif
 	.resume_early = ipa3_ap_resume,
+	.restore_early = ipa3_ap_resume,
 };
 
 static struct platform_driver ipa_plat_drv = {
@@ -8239,10 +8253,6 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p,
 	ipa3_setup_uc_act_tbl();
 	ipa_trigger_ipa_ready_cbs();
 
-#ifdef CONFIG_DEEPSLEEP
-	if (!ipa_is_ready())
-		ipa_fmwk_deepsleep_exit_ipa();
-#endif
 	complete_all(&ipa3_ctx->init_completion_obj);
 
 	ipa_ut_module_init();
@@ -8469,16 +8479,17 @@ static int ipa3_pil_load_ipa_fws(const char *sub_sys)
 }
 #endif /* IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */
 
-#ifdef CONFIG_DEEPSLEEP
+#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION)
 static int ipa3_pil_unload_ipa_fws(void)
 {
-
+#if !IS_ENABLED(CONFIG_QCOM_MDT_LOADER)
 	IPADBG("PIL FW unloading process initiated sub_sys\n");
 
 	if (ipa3_ctx->subsystem_get_retval)
 		subsystem_put(ipa3_ctx->subsystem_get_retval);
 
 	IPADBG("PIL FW unloading process is complete sub_sys\n");
+#endif
 	return 0;
 }
 #endif
@@ -10637,6 +10648,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
 
 	/* Get IPA GSI IRQ number */
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0))
+	irq = 0;
 	resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
 			"gsi-irq");
 	if (!resource) {
@@ -11869,7 +11881,7 @@ int ipa3_ap_suspend(struct device *dev)
 		}
 	}
 
-#ifdef CONFIG_DEEPSLEEP
+#if IS_ENABLED(CONFIG_DEEPSLEEP)
 	if (mem_sleep_current == PM_SUSPEND_MEM) {
 		IPADBG("Enter deepsleep suspend\n");
 		ipa3_deepsleep_suspend();
@@ -11883,6 +11895,46 @@ int ipa3_ap_suspend(struct device *dev)
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_HIBERNATION)
+/**
+ * ipa3_ap_freeze() - hibernate freeze callback for runtime_pm
+ * @dev: pointer to device
+ *
+ * This callback will be invoked by the runtime_pm framework when an AP
+ * hibernate freeze operation is invoked, usually by pressing a hibernate button.
+ *
+ * Returns -EAGAIN to runtime_pm framework in case IPA is in use by AP.
+ * This will postpone the suspend/freeze operation until IPA is no longer used by AP.
+ */
+int ipa3_ap_freeze(struct device *dev)
+{
+	int i;
+
+	IPADBG("Enter\n");
+
+	if (!of_device_is_compatible(dev->of_node, "qcom,ipa"))
+		return 0;
+	/* In case there is a tx/rx handler in polling mode fail to suspend */
+	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
+		if (ipa3_ctx->ep[i].sys &&
+			atomic_read(&ipa3_ctx->ep[i].sys->curr_polling_state)) {
+			IPAERR("EP %d is in polling state, do not suspend\n",
+				i);
+			return -EAGAIN;
+		}
+	}
+
+	IPADBG("Enter hibernate freeze\n");
+	ipa3_deepsleep_suspend();
+	IPADBG("Exit hibernate freeze\n");
+
+	ipa_pm_deactivate_all_deferred();
+
+	IPADBG("Exit\n");
+	return 0;
+}
+#endif
+
 /**
  * ipa3_ap_resume() - resume callback for runtime_pm
  * @dev: pointer to device
@@ -11910,7 +11962,7 @@ bool ipa_get_lan_rx_napi(void)
 EXPORT_SYMBOL(ipa_get_lan_rx_napi);
 
 
-#ifdef CONFIG_DEEPSLEEP
+#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION)
 static void ipa3_deepsleep_suspend(void)
 {
 	IPADBG("Entry\n");
@@ -11944,8 +11996,6 @@ static void ipa3_deepsleep_suspend(void)
 	ipa3_debugfs_remove();
 	/*Unloading IPA FW to allow FW load in resume*/
 	ipa3_pil_unload_ipa_fws();
-	/*Calling framework API to reset IPA ready flag to false*/
-	ipa_fmwk_deepsleep_entry_ipa();
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	IPADBG("Exit\n");
 }

+ 1 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -3548,6 +3548,7 @@ struct iommu_domain *ipa3_get_smmu_domain_by_type
 int ipa3_iommu_map(struct iommu_domain *domain, unsigned long iova,
 	phys_addr_t paddr, size_t size, int prot);
 int ipa3_ap_suspend(struct device *dev);
+int ipa3_ap_freeze(struct device *dev);
 int ipa3_ap_resume(struct device *dev);
 int ipa3_init_interrupts(void);
 struct iommu_domain *ipa3_get_smmu_domain(void);

+ 3 - 2
drivers/platform/msm/ipa/ipa_v3/ipa_pm.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _IPA_PM_H_
@@ -181,12 +182,12 @@ static inline int ipa_pm_exceptions_stat(char *buf, int size)
 	return -EPERM;
 }
 
-static inline int ipa_pm_add_dummy_clients(s8 power_plan);
+static inline int ipa_pm_add_dummy_clients(s8 power_plan)
 {
 	return -EPERM;
 }
 
-static inline int ipa_pm_remove_dummy_clients(void);
+static inline int ipa_pm_remove_dummy_clients(void)
 {
 	return -EPERM;
 }