Skip to content

Commit

Permalink
drm/lima: enable runtime pm
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Qiang Yu committed Apr 24, 2020
1 parent 63945d5 commit 50de2e9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 10 deletions.
21 changes: 16 additions & 5 deletions drivers/gpu/drm/lima/lima_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,12 @@ static int lima_pdev_probe(struct platform_device *pdev)
goto err_out2;
}

pm_runtime_set_active(ldev->dev);
pm_runtime_mark_last_busy(ldev->dev);
pm_runtime_set_autosuspend_delay(ldev->dev, 200);
pm_runtime_use_autosuspend(ldev->dev);
pm_runtime_enable(ldev->dev);

/*
* Register the DRM device with the core and the connectors with
* sysfs.
Expand All @@ -412,17 +418,16 @@ static int lima_pdev_probe(struct platform_device *pdev)
if (err < 0)
goto err_out3;

platform_set_drvdata(pdev, ldev);

if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr))
dev_warn(ldev->dev, "fail to create error state sysfs\n");

return 0;

err_out3:
lima_device_fini(ldev);
err_out2:
pm_runtime_disable(ldev->dev);
lima_devfreq_fini(ldev);
err_out2:
lima_device_fini(ldev);
err_out1:
drm_dev_put(ddev);
err_out0:
Expand All @@ -436,10 +441,16 @@ static int lima_pdev_remove(struct platform_device *pdev)
struct drm_device *ddev = ldev->ddev;

sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
platform_set_drvdata(pdev, NULL);

drm_dev_unregister(ddev);

/* stop autosuspend to make sure device is in active state */
pm_runtime_set_autosuspend_delay(ldev->dev, -1);
pm_runtime_disable(ldev->dev);

lima_devfreq_fini(ldev);
lima_device_fini(ldev);

drm_dev_put(ddev);
lima_sched_slab_fini();
return 0;
Expand Down
41 changes: 36 additions & 5 deletions drivers/gpu/drm/lima/lima_sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand All @@ -209,15 +233,20 @@ 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
* may consume the fence before caller use it
*/
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
Expand Down Expand Up @@ -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");
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}
}

0 comments on commit 50de2e9

Please sign in to comment.