From c48aba5efeb41adf053e0dc6c996ca315031a1e7 Mon Sep 17 00:00:00 2001 From: Christoph Rudorff Date: Sun, 15 Oct 2023 08:34:30 +0200 Subject: [PATCH] drm/msm/gpu: fix clk lockup PM suspend/resume handler (v2) testing freq. transitions on MSM8916 Samsung J5 "a3xx": locks up when gpu was on 310MHz: resume handler was setting opp rate that will do clk_set_rate before the clk was enabled. devfreq can do this job if opp-suspend was defined in dt. changed resume so clk gets enabled first and let devfreq setting it changed suspend aswell Signed-off-by: Christoph Rudorff drm/msm/gpu: PM suspend/resume handler hotfix resume Signed-off-by: Christoph Rudorff --- drivers/gpu/drm/msm/msm_gpu.c | 25 +++++++++++++++++++------ drivers/gpu/drm/msm/msm_gpu_devfreq.c | 5 +++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 7f64c66673002f..9fa1a71807be5d 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -57,31 +57,44 @@ static int disable_pwrrail(struct msm_gpu *gpu) static int enable_clk(struct msm_gpu *gpu) { - if (gpu->core_clk && gpu->fast_rate) + int ret; + ret = clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks); + if (ret) + return ret; + /* + devfreq_resume_device() will do set_rate + if an "opp-suspend" exists + */ + if (gpu->core_clk && gpu->fast_rate && + dev_pm_opp_get_suspend_opp_freq(&gpu->pdev->dev) == 0) dev_pm_opp_set_rate(&gpu->pdev->dev, gpu->fast_rate); /* Set the RBBM timer rate to 19.2Mhz */ if (gpu->rbbmtimer_clk) clk_set_rate(gpu->rbbmtimer_clk, 19200000); - return clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks); + return 0; } static int disable_clk(struct msm_gpu *gpu) { - clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks); - /* * Set the clock to a deliberately low rate. On older targets the clock * speed had to be non zero to avoid problems. On newer targets this * will be rounded down to zero anyway so it all works out. + + * skip this if an "opp-suspend" exists: + * devfreq_suspend_device() has done this */ - if (gpu->core_clk) - dev_pm_opp_set_rate(&gpu->pdev->dev, 27000000); + if (gpu->core_clk && + dev_pm_opp_get_suspend_opp_freq(&gpu->pdev->dev) == 0) + dev_pm_opp_set_rate(&gpu->pdev->dev, 1); if (gpu->rbbmtimer_clk) clk_set_rate(gpu->rbbmtimer_clk, 0); + clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks); + return 0; } diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index ea70c1c32d9401..d5e4648261dee1 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -230,6 +230,7 @@ void msm_devfreq_resume(struct msm_gpu *gpu) mutex_lock(&df->lock); df->busy_cycles = gpu->funcs->gpu_busy(gpu, &sample_rate); df->time = ktime_get(); + df->idle_freq = 0; df->suspended = false; mutex_unlock(&df->lock); @@ -247,10 +248,10 @@ void msm_devfreq_suspend(struct msm_gpu *gpu) df->suspended = true; mutex_unlock(&df->lock); - devfreq_suspend_device(df->devfreq); - cancel_idle_work(df); cancel_boost_work(df); + + devfreq_suspend_device(df->devfreq); } static void msm_devfreq_boost_work(struct kthread_work *work)