Skip to content

Commit 7e4167c

Browse files
committed
drm/msm/gpu: Park scheduler threads for system suspend
In the system suspend path, we don't want to be racing with the scheduler kthreads pushing additional queued up jobs to the hw queue (ringbuffer). So park them first. While we are at it, move the wait for active jobs to complete into the new system- suspend path. Signed-off-by: Rob Clark <robdclark@chromium.org> Link: https://lore.kernel.org/r/20220310234611.424743-3-robdclark@gmail.com
1 parent f7eab1d commit 7e4167c

1 file changed

Lines changed: 64 additions & 4 deletions

File tree

drivers/gpu/drm/msm/adreno/adreno_device.c

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -619,22 +619,82 @@ static int active_submits(struct msm_gpu *gpu)
619619
static int adreno_runtime_suspend(struct device *dev)
620620
{
621621
struct msm_gpu *gpu = dev_to_gpu(dev);
622-
int remaining;
622+
623+
/*
624+
* We should be holding a runpm ref, which will prevent
625+
* runtime suspend. In the system suspend path, we've
626+
* already waited for active jobs to complete.
627+
*/
628+
WARN_ON_ONCE(gpu->active_submits);
629+
630+
return gpu->funcs->pm_suspend(gpu);
631+
}
632+
633+
static void suspend_scheduler(struct msm_gpu *gpu)
634+
{
635+
int i;
636+
637+
/*
638+
* Shut down the scheduler before we force suspend, so that
639+
* suspend isn't racing with scheduler kthread feeding us
640+
* more work.
641+
*
642+
* Note, we just want to park the thread, and let any jobs
643+
* that are already on the hw queue complete normally, as
644+
* opposed to the drm_sched_stop() path used for handling
645+
* faulting/timed-out jobs. We can't really cancel any jobs
646+
* already on the hw queue without racing with the GPU.
647+
*/
648+
for (i = 0; i < gpu->nr_rings; i++) {
649+
struct drm_gpu_scheduler *sched = &gpu->rb[i]->sched;
650+
kthread_park(sched->thread);
651+
}
652+
}
653+
654+
static void resume_scheduler(struct msm_gpu *gpu)
655+
{
656+
int i;
657+
658+
for (i = 0; i < gpu->nr_rings; i++) {
659+
struct drm_gpu_scheduler *sched = &gpu->rb[i]->sched;
660+
kthread_unpark(sched->thread);
661+
}
662+
}
663+
664+
static int adreno_system_suspend(struct device *dev)
665+
{
666+
struct msm_gpu *gpu = dev_to_gpu(dev);
667+
int remaining, ret;
668+
669+
suspend_scheduler(gpu);
623670

624671
remaining = wait_event_timeout(gpu->retire_event,
625672
active_submits(gpu) == 0,
626673
msecs_to_jiffies(1000));
627674
if (remaining == 0) {
628675
dev_err(dev, "Timeout waiting for GPU to suspend\n");
629-
return -EBUSY;
676+
ret = -EBUSY;
677+
goto out;
630678
}
631679

632-
return gpu->funcs->pm_suspend(gpu);
680+
ret = pm_runtime_force_suspend(dev);
681+
out:
682+
if (ret)
683+
resume_scheduler(gpu);
684+
685+
return ret;
633686
}
687+
688+
static int adreno_system_resume(struct device *dev)
689+
{
690+
resume_scheduler(dev_to_gpu(dev));
691+
return pm_runtime_force_resume(dev);
692+
}
693+
634694
#endif
635695

636696
static const struct dev_pm_ops adreno_pm_ops = {
637-
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
697+
SET_SYSTEM_SLEEP_PM_OPS(adreno_system_suspend, adreno_system_resume)
638698
SET_RUNTIME_PM_OPS(adreno_runtime_suspend, adreno_runtime_resume, NULL)
639699
};
640700

0 commit comments

Comments
 (0)