From 7bdca0463d99a7fdc7c38f340a03ef5a53685dc5 Mon Sep 17 00:00:00 2001 From: Pavan Kumar M Date: Mon, 16 Sep 2024 12:43:04 +0530 Subject: [PATCH] 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: Pavan Kumar M Signed-off-by: Jagadeesh Ponduru --- drivers/platform/msm/ipa/ipa_v3/ipa.c | 69 +++++++++++++++++++++---- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 1 + 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 09f5b1cc2fa5..bce110d193f3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -126,7 +126,7 @@ static void ipa_gsi_notify_cb(struct gsi_per_notify *notify); static int ipa3_attach_to_smmu(void); static int ipa3_alloc_pkt_init(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 @@ -457,17 +457,25 @@ EXPORT_SYMBOL(ipa_smmu_free_sgt); static int ipa_pm_notify(struct notifier_block *b, unsigned long event, void *p) { IPAERR("Entry\n"); +#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION) 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"); } -#endif + break; + case PM_POST_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"); + } break; } +#endif IPAERR("Exit\n"); return NOTIFY_DONE; } @@ -479,7 +487,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 = { @@ -6748,7 +6760,7 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, ipa3_register_to_fmwk(); } -#ifdef CONFIG_DEEPSLEEP +#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION) if (!ipa3_is_ready()) ipa_fmwk_deepsleep_exit_ipa(); #endif @@ -6868,10 +6880,9 @@ static int ipa3_pil_load_ipa_fws(const char *sub_sys) return 0; } -#ifdef CONFIG_DEEPSLEEP +#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION) static int ipa3_pil_unload_ipa_fws(void) { - IPADBG("PIL FW unloading process initiated sub_sys\n"); if (ipa3_ctx->subsystem_get_retval) @@ -6889,7 +6900,7 @@ static void ipa3_load_ipa_fw(struct work_struct *work) IPADBG("Entry\n"); IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - + result = ipa3_attach_to_smmu(); if (result) { IPAERR("IPA attach to smmu failed %d\n", result); @@ -9634,7 +9645,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(); @@ -9648,6 +9659,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 @@ -9674,7 +9725,7 @@ bool ipa3_get_lan_rx_napi(void) } -#ifdef CONFIG_DEEPSLEEP +#if IS_ENABLED(CONFIG_DEEPSLEEP) || IS_ENABLED(CONFIG_HIBERNATION) static void ipa3_deepsleep_suspend(void) { IPADBG("Entry\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index ceb439f729b2..39d5f6be8af8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -3114,6 +3114,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);