diff options
author | Qiang Yu <yuq825@gmail.com> | 2020-04-21 21:35:51 +0800 |
---|---|---|
committer | Qiang Yu <yuq825@gmail.com> | 2020-04-24 20:51:24 +0800 |
commit | 50de2e9ebbc08e1ca27f9b3f0471d92abaaf834a (patch) | |
tree | fd7f824c060e7385a2b2f9631a3e5622d268df67 /drivers/gpu/drm/lima/lima_sched.c | |
parent | 63945d51490f16aede6d635e785faf56521e5e4a (diff) |
drm/lima: enable runtime pm
Enable runtime pm by default so GPU suspend when idle
for 200ms. This value can be changed by
autosuspend_delay_ms in device's power sysfs dir.
On Allwinner H3 lima_device_resume takes ~40us and
lima_device_suspend takes ~20us.
Tested-by: Bhushan Shah <bshah@kde.org>
Reviewed-by: Vasily Khoruzhick <anarsoul@gmail.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200421133551.31481-11-yuq825@gmail.com
Diffstat (limited to 'drivers/gpu/drm/lima/lima_sched.c')
-rw-r--r-- | drivers/gpu/drm/lima/lima_sched.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index eb46db0717cd..e6cefda00279 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -4,6 +4,7 @@ #include <linux/kthread.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/pm_runtime.h> #include "lima_devfreq.h" #include "lima_drv.h" @@ -194,13 +195,36 @@ static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job, return NULL; } +static int lima_pm_busy(struct lima_device *ldev) +{ + int ret; + + /* resume GPU if it has been suspended by runtime PM */ + ret = pm_runtime_get_sync(ldev->dev); + if (ret < 0) + return ret; + + lima_devfreq_record_busy(&ldev->devfreq); + return 0; +} + +static void lima_pm_idle(struct lima_device *ldev) +{ + lima_devfreq_record_idle(&ldev->devfreq); + + /* GPU can do auto runtime suspend */ + pm_runtime_mark_last_busy(ldev->dev); + pm_runtime_put_autosuspend(ldev->dev); +} + static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) { struct lima_sched_task *task = to_lima_task(job); struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); + struct lima_device *ldev = pipe->ldev; struct lima_fence *fence; struct dma_fence *ret; - int i; + int i, err; /* after GPU reset */ if (job->s_fence->finished.error < 0) @@ -209,6 +233,13 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) fence = lima_fence_create(pipe); if (!fence) return NULL; + + err = lima_pm_busy(ldev); + if (err < 0) { + dma_fence_put(&fence->base); + return NULL; + } + task->fence = &fence->base; /* for caller usage of the fence, otherwise irq handler @@ -216,8 +247,6 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job) */ ret = dma_fence_get(task->fence); - lima_devfreq_record_busy(&pipe->ldev->devfreq); - pipe->current_task = task; /* this is needed for MMU to work correctly, otherwise GP/PP @@ -388,6 +417,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) { struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); struct lima_sched_task *task = to_lima_task(job); + struct lima_device *ldev = pipe->ldev; if (!pipe->error) DRM_ERROR("lima job timeout\n"); @@ -413,7 +443,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job) pipe->current_vm = NULL; pipe->current_task = NULL; - lima_devfreq_record_idle(&pipe->ldev->devfreq); + lima_pm_idle(ldev); drm_sched_resubmit_jobs(&pipe->base); drm_sched_start(&pipe->base, true); @@ -485,6 +515,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) { struct lima_sched_task *task = pipe->current_task; + struct lima_device *ldev = pipe->ldev; if (pipe->error) { if (task && task->recoverable) @@ -495,6 +526,6 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe) pipe->task_fini(pipe); dma_fence_signal(task->fence); - lima_devfreq_record_idle(&pipe->ldev->devfreq); + lima_pm_idle(ldev); } } |