Skip to content

Commit 167a668

Browse files
committed
drm/msm/gpu: Wait for idle before suspending
System suspend uses pm_runtime_force_suspend(), which cheekily bypasses the runpm reference counts. This doesn't actually work so well when the GPU is active. So add a reasonable delay waiting for the GPU to become idle. Alternatively we could just return -EBUSY in this case, but that has the disadvantage of causing system suspend to fail. v2: s/ret/remaining [sboyd], and switch to using active_submits count to ensure we aren't racing with submit cleanup (and devfreq idle work getting scheduled, etc) v3: fix inverted logic Signed-off-by: Rob Clark <[email protected]> Reviewed-by: Bjorn Andersson <[email protected]> Reviewed-by: AngeloGioacchino Del Regno <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Rob Clark <[email protected]>
1 parent 5e761a2 commit 167a668

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,9 +608,27 @@ static int adreno_resume(struct device *dev)
608608
return gpu->funcs->pm_resume(gpu);
609609
}
610610

611+
static int active_submits(struct msm_gpu *gpu)
612+
{
613+
int active_submits;
614+
mutex_lock(&gpu->active_lock);
615+
active_submits = gpu->active_submits;
616+
mutex_unlock(&gpu->active_lock);
617+
return active_submits;
618+
}
619+
611620
static int adreno_suspend(struct device *dev)
612621
{
613622
struct msm_gpu *gpu = dev_to_gpu(dev);
623+
int remaining;
624+
625+
remaining = wait_event_timeout(gpu->retire_event,
626+
active_submits(gpu) == 0,
627+
msecs_to_jiffies(1000));
628+
if (remaining == 0) {
629+
dev_err(dev, "Timeout waiting for GPU to suspend\n");
630+
return -EBUSY;
631+
}
614632

615633
return gpu->funcs->pm_suspend(gpu);
616634
}

drivers/gpu/drm/msm/msm_gpu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,8 @@ static void retire_submits(struct msm_gpu *gpu)
703703
}
704704
}
705705
}
706+
707+
wake_up_all(&gpu->retire_event);
706708
}
707709

708710
static void retire_worker(struct kthread_work *work)
@@ -848,6 +850,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
848850
INIT_LIST_HEAD(&gpu->active_list);
849851
mutex_init(&gpu->active_lock);
850852
mutex_init(&gpu->lock);
853+
init_waitqueue_head(&gpu->retire_event);
851854
kthread_init_work(&gpu->retire_work, retire_worker);
852855
kthread_init_work(&gpu->recover_work, recover_worker);
853856
kthread_init_work(&gpu->fault_work, fault_worker);

drivers/gpu/drm/msm/msm_gpu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ struct msm_gpu {
230230
/* work for handling GPU recovery: */
231231
struct kthread_work recover_work;
232232

233+
/** retire_event: notified when submits are retired: */
234+
wait_queue_head_t retire_event;
235+
233236
/* work for handling active-list retiring: */
234237
struct kthread_work retire_work;
235238

0 commit comments

Comments
 (0)