Skip to content

Commit 50de2e9

Browse files
committed
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
1 parent 63945d5 commit 50de2e9

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

drivers/gpu/drm/lima/lima_drv.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,12 @@ static int lima_pdev_probe(struct platform_device *pdev)
404404
goto err_out2;
405405
}
406406

407+
pm_runtime_set_active(ldev->dev);
408+
pm_runtime_mark_last_busy(ldev->dev);
409+
pm_runtime_set_autosuspend_delay(ldev->dev, 200);
410+
pm_runtime_use_autosuspend(ldev->dev);
411+
pm_runtime_enable(ldev->dev);
412+
407413
/*
408414
* Register the DRM device with the core and the connectors with
409415
* sysfs.
@@ -412,17 +418,16 @@ static int lima_pdev_probe(struct platform_device *pdev)
412418
if (err < 0)
413419
goto err_out3;
414420

415-
platform_set_drvdata(pdev, ldev);
416-
417421
if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr))
418422
dev_warn(ldev->dev, "fail to create error state sysfs\n");
419423

420424
return 0;
421425

422426
err_out3:
423-
lima_device_fini(ldev);
424-
err_out2:
427+
pm_runtime_disable(ldev->dev);
425428
lima_devfreq_fini(ldev);
429+
err_out2:
430+
lima_device_fini(ldev);
426431
err_out1:
427432
drm_dev_put(ddev);
428433
err_out0:
@@ -436,10 +441,16 @@ static int lima_pdev_remove(struct platform_device *pdev)
436441
struct drm_device *ddev = ldev->ddev;
437442

438443
sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
439-
platform_set_drvdata(pdev, NULL);
444+
440445
drm_dev_unregister(ddev);
446+
447+
/* stop autosuspend to make sure device is in active state */
448+
pm_runtime_set_autosuspend_delay(ldev->dev, -1);
449+
pm_runtime_disable(ldev->dev);
450+
441451
lima_devfreq_fini(ldev);
442452
lima_device_fini(ldev);
453+
443454
drm_dev_put(ddev);
444455
lima_sched_slab_fini();
445456
return 0;

drivers/gpu/drm/lima/lima_sched.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/kthread.h>
55
#include <linux/slab.h>
66
#include <linux/vmalloc.h>
7+
#include <linux/pm_runtime.h>
78

89
#include "lima_devfreq.h"
910
#include "lima_drv.h"
@@ -194,13 +195,36 @@ static struct dma_fence *lima_sched_dependency(struct drm_sched_job *job,
194195
return NULL;
195196
}
196197

198+
static int lima_pm_busy(struct lima_device *ldev)
199+
{
200+
int ret;
201+
202+
/* resume GPU if it has been suspended by runtime PM */
203+
ret = pm_runtime_get_sync(ldev->dev);
204+
if (ret < 0)
205+
return ret;
206+
207+
lima_devfreq_record_busy(&ldev->devfreq);
208+
return 0;
209+
}
210+
211+
static void lima_pm_idle(struct lima_device *ldev)
212+
{
213+
lima_devfreq_record_idle(&ldev->devfreq);
214+
215+
/* GPU can do auto runtime suspend */
216+
pm_runtime_mark_last_busy(ldev->dev);
217+
pm_runtime_put_autosuspend(ldev->dev);
218+
}
219+
197220
static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
198221
{
199222
struct lima_sched_task *task = to_lima_task(job);
200223
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
224+
struct lima_device *ldev = pipe->ldev;
201225
struct lima_fence *fence;
202226
struct dma_fence *ret;
203-
int i;
227+
int i, err;
204228

205229
/* after GPU reset */
206230
if (job->s_fence->finished.error < 0)
@@ -209,15 +233,20 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
209233
fence = lima_fence_create(pipe);
210234
if (!fence)
211235
return NULL;
236+
237+
err = lima_pm_busy(ldev);
238+
if (err < 0) {
239+
dma_fence_put(&fence->base);
240+
return NULL;
241+
}
242+
212243
task->fence = &fence->base;
213244

214245
/* for caller usage of the fence, otherwise irq handler
215246
* may consume the fence before caller use it
216247
*/
217248
ret = dma_fence_get(task->fence);
218249

219-
lima_devfreq_record_busy(&pipe->ldev->devfreq);
220-
221250
pipe->current_task = task;
222251

223252
/* 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)
388417
{
389418
struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
390419
struct lima_sched_task *task = to_lima_task(job);
420+
struct lima_device *ldev = pipe->ldev;
391421

392422
if (!pipe->error)
393423
DRM_ERROR("lima job timeout\n");
@@ -413,7 +443,7 @@ static void lima_sched_timedout_job(struct drm_sched_job *job)
413443
pipe->current_vm = NULL;
414444
pipe->current_task = NULL;
415445

416-
lima_devfreq_record_idle(&pipe->ldev->devfreq);
446+
lima_pm_idle(ldev);
417447

418448
drm_sched_resubmit_jobs(&pipe->base);
419449
drm_sched_start(&pipe->base, true);
@@ -485,6 +515,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
485515
void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
486516
{
487517
struct lima_sched_task *task = pipe->current_task;
518+
struct lima_device *ldev = pipe->ldev;
488519

489520
if (pipe->error) {
490521
if (task && task->recoverable)
@@ -495,6 +526,6 @@ void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
495526
pipe->task_fini(pipe);
496527
dma_fence_signal(task->fence);
497528

498-
lima_devfreq_record_idle(&pipe->ldev->devfreq);
529+
lima_pm_idle(ldev);
499530
}
500531
}

0 commit comments

Comments
 (0)