summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/lima/lima_sched.c
diff options
context:
space:
mode:
authorQiang Yu <yuq825@gmail.com>2020-04-21 21:35:51 +0800
committerQiang Yu <yuq825@gmail.com>2020-04-24 20:51:24 +0800
commit50de2e9ebbc08e1ca27f9b3f0471d92abaaf834a (patch)
treefd7f824c060e7385a2b2f9631a3e5622d268df67 /drivers/gpu/drm/lima/lima_sched.c
parent63945d51490f16aede6d635e785faf56521e5e4a (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.c41
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);
}
}