drm/etnaviv: move runtime PM handling to events
authorLucas Stach <l.stach@pengutronix.de>
Wed, 7 Jun 2023 13:02:18 +0000 (15:02 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Mon, 17 Jul 2023 09:32:13 +0000 (11:32 +0200)
Conceptually events are the right abstraction to handle the GPU
runtime PM state: as long as any event is pending the GPU can not
be idle. Events are also properly freed and reallocated when the
GPU has been reset after a hang.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
drivers/gpu/drm/etnaviv/etnaviv_gem.h
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c

index baa81cb..a42d260 100644 (file)
@@ -97,7 +97,6 @@ struct etnaviv_gem_submit {
        struct list_head node; /* GPU active submit list */
        struct etnaviv_cmdbuf cmdbuf;
        struct pid *pid;       /* submitting process */
-       bool runtime_resumed;
        u32 exec_state;
        u32 flags;
        unsigned int nr_pmrs;
index 45403ea..2416c52 100644 (file)
@@ -362,9 +362,6 @@ static void submit_cleanup(struct kref *kref)
                        container_of(kref, struct etnaviv_gem_submit, refcount);
        unsigned i;
 
-       if (submit->runtime_resumed)
-               pm_runtime_put_autosuspend(submit->gpu->dev);
-
        if (submit->cmdbuf.suballoc)
                etnaviv_cmdbuf_free(&submit->cmdbuf);
 
index e067a27..ba8c43b 100644 (file)
@@ -1147,7 +1147,8 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
        unsigned int *events)
 {
        unsigned long timeout = msecs_to_jiffies(10 * 10000);
-       unsigned i, acquired = 0;
+       unsigned i, acquired = 0, rpm_count = 0;
+       int ret;
 
        for (i = 0; i < nr_events; i++) {
                unsigned long ret;
@@ -1156,6 +1157,7 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
 
                if (!ret) {
                        dev_err(gpu->dev, "wait_for_completion_timeout failed");
+                       ret = -EBUSY;
                        goto out;
                }
 
@@ -1175,13 +1177,23 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events,
 
        spin_unlock(&gpu->event_spinlock);
 
+       for (i = 0; i < nr_events; i++) {
+               ret = pm_runtime_resume_and_get(gpu->dev);
+               if (ret)
+                       goto out_rpm;
+               rpm_count++;
+       }
+
        return 0;
 
+out_rpm:
+       for (i = 0; i < rpm_count; i++)
+               pm_runtime_put_autosuspend(gpu->dev);
 out:
        for (i = 0; i < acquired; i++)
                complete(&gpu->event_free);
 
-       return -EBUSY;
+       return ret;
 }
 
 static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
@@ -1193,6 +1205,8 @@ static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
                clear_bit(event, gpu->event_bitmap);
                complete(&gpu->event_free);
        }
+
+       pm_runtime_put_autosuspend(gpu->dev);
 }
 
 /*
@@ -1335,15 +1349,6 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit)
        unsigned int i, nr_events = 1, event[3];
        int ret;
 
-       if (!submit->runtime_resumed) {
-               ret = pm_runtime_get_sync(gpu->dev);
-               if (ret < 0) {
-                       pm_runtime_put_noidle(gpu->dev);
-                       return NULL;
-               }
-               submit->runtime_resumed = true;
-       }
-
        /*
         * if there are performance monitor requests we need to have
         * - a sync point to re-configure gpu and process ETNA_PM_PROCESS_PRE