]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/v3d: Allocate all resources before enabling the clock
authorMaíra Canal <mcanal@igalia.com>
Tue, 31 Mar 2026 12:35:52 +0000 (09:35 -0300)
committerMaíra Canal <mcanal@igalia.com>
Sat, 4 Apr 2026 10:41:08 +0000 (07:41 -0300)
Move all resource allocation operations before actually enabling the
clock, as those operations don't require the GPU to be powered on.

This is a preparation for runtime PM support. The next commit will
move all code related to powering on and initiating the GPU into the
runtime PM resume callback and all resource allocation will happen
before resume().

Reviewed-by: Melissa Wen <mwen@igalia.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20260331-v3d-power-management-v9-2-f52ff87bfd36@igalia.com
Signed-off-by: Maíra Canal <mcanal@igalia.com>
drivers/gpu/drm/v3d/v3d_drv.c
drivers/gpu/drm/v3d/v3d_drv.h
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/v3d/v3d_irq.c

index c5e7c778ec7a1a39d81155f7ed2a7ba811b5e3aa..e57b36f4d81a59d15a223afdc4078ae6456de9a9 100644 (file)
@@ -363,14 +363,50 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
                        return ret;
        }
 
+       if (v3d->ver < V3D_GEN_41) {
+               ret = map_regs(v3d, &v3d->gca_regs, "gca");
+               if (ret)
+                       return ret;
+       }
+
+       v3d->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
+       if (IS_ERR(v3d->reset))
+               return dev_err_probe(dev, PTR_ERR(v3d->reset),
+                                    "Failed to get reset control\n");
+
+       if (!v3d->reset) {
+               ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
+               if (ret) {
+                       dev_err(dev, "Failed to get bridge registers\n");
+                       return ret;
+               }
+       }
+
        v3d->clk = devm_clk_get_optional(dev, NULL);
        if (IS_ERR(v3d->clk))
                return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n");
 
+       ret = v3d_irq_init(v3d);
+       if (ret)
+               return ret;
+
+       v3d_perfmon_init(v3d);
+
+       v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr,
+                                       GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
+       if (!v3d->mmu_scratch) {
+               dev_err(dev, "Failed to allocate MMU scratch page\n");
+               return -ENOMEM;
+       }
+
+       ret = v3d_gem_init(drm);
+       if (ret)
+               goto dma_free;
+
        ret = clk_prepare_enable(v3d->clk);
        if (ret) {
                dev_err(&pdev->dev, "Couldn't enable the V3D clock\n");
-               return ret;
+               goto gem_destroy;
        }
 
        v3d_idle_sms(v3d);
@@ -399,44 +435,9 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
        ident3 = V3D_READ(V3D_HUB_IDENT3);
        v3d->rev = V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPREV);
 
-       v3d_perfmon_init(v3d);
-
-       v3d->reset = devm_reset_control_get_optional_exclusive(dev, NULL);
-       if (IS_ERR(v3d->reset)) {
-               ret = dev_err_probe(dev, PTR_ERR(v3d->reset),
-                                   "Failed to get reset control\n");
-               goto clk_disable;
-       }
-
-       if (!v3d->reset) {
-               ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
-               if (ret) {
-                       dev_err(dev, "Failed to get bridge registers\n");
-                       goto clk_disable;
-               }
-       }
-
-       if (v3d->ver < V3D_GEN_41) {
-               ret = map_regs(v3d, &v3d->gca_regs, "gca");
-               if (ret)
-                       goto clk_disable;
-       }
-
-       v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr,
-                                       GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
-       if (!v3d->mmu_scratch) {
-               dev_err(dev, "Failed to allocate MMU scratch page\n");
-               ret = -ENOMEM;
-               goto clk_disable;
-       }
-
-       ret = v3d_gem_init(drm);
-       if (ret)
-               goto dma_free;
-
-       ret = v3d_irq_init(v3d);
-       if (ret)
-               goto gem_destroy;
+       v3d_init_hw_state(v3d);
+       v3d_mmu_set_page_table(v3d);
+       v3d_irq_enable(v3d);
 
        ret = drm_dev_register(drm, 0);
        if (ret)
@@ -452,12 +453,13 @@ drm_unregister:
        drm_dev_unregister(drm);
 irq_disable:
        v3d_irq_disable(v3d);
+clk_disable:
+       v3d_power_off_sms(v3d);
+       clk_disable_unprepare(v3d->clk);
 gem_destroy:
        v3d_gem_destroy(drm);
 dma_free:
        dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr);
-clk_disable:
-       clk_disable_unprepare(v3d->clk);
        return ret;
 }
 
@@ -471,14 +473,13 @@ static void v3d_platform_drm_remove(struct platform_device *pdev)
 
        drm_dev_unregister(drm);
 
-       v3d_gem_destroy(drm);
-
-       dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch,
-                   v3d->mmu_scratch_paddr);
-
        v3d_power_off_sms(v3d);
 
        clk_disable_unprepare(v3d->clk);
+
+       v3d_gem_destroy(drm);
+
+       dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr);
 }
 
 static struct platform_driver v3d_platform_driver = {
index 6a3cad933439812d78da5797749c020a9bf46402..ebf406b615bb52de9cb98ea8efe941a5787fb4bd 100644 (file)
@@ -565,6 +565,7 @@ struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q);
 
 /* v3d_gem.c */
 extern bool super_pages;
+void v3d_init_hw_state(struct v3d_dev *v3d);
 int v3d_gem_init(struct drm_device *dev);
 void v3d_gem_destroy(struct drm_device *dev);
 void v3d_reset_sms(struct v3d_dev *v3d);
index 75d9eccd796664e67277c1f83ad59063f164d1da..1ee3c038d5f6f774147289221e3271826042084e 100644 (file)
@@ -36,13 +36,6 @@ v3d_init_core(struct v3d_dev *v3d, int core)
        V3D_CORE_WRITE(core, V3D_CTL_L2TFLEND, ~0);
 }
 
-/* Sets invariant state for the HW. */
-static void
-v3d_init_hw_state(struct v3d_dev *v3d)
-{
-       v3d_init_core(v3d, 0);
-}
-
 static void
 v3d_idle_axi(struct v3d_dev *v3d, int core)
 {
@@ -259,6 +252,13 @@ v3d_invalidate_caches(struct v3d_dev *v3d)
        v3d_invalidate_slices(v3d, 0);
 }
 
+/* Sets invariant state for the HW. */
+void
+v3d_init_hw_state(struct v3d_dev *v3d)
+{
+       v3d_init_core(v3d, 0);
+}
+
 static void
 v3d_huge_mnt_init(struct v3d_dev *v3d)
 {
@@ -328,9 +328,6 @@ v3d_gem_init(struct drm_device *dev)
                goto err_dma_alloc;
        }
 
-       v3d_init_hw_state(v3d);
-       v3d_mmu_set_page_table(v3d);
-
        v3d_huge_mnt_init(v3d);
 
        ret = v3d_sched_init(v3d);
index c28e74ab5442857031b48bcbd4e43eb48c1e0f07..86efaef2722c3602346b037ba536228b2f368a81 100644 (file)
@@ -248,17 +248,10 @@ v3d_hub_irq(int irq, void *arg)
 int
 v3d_irq_init(struct v3d_dev *v3d)
 {
-       int irq, ret, core;
+       int irq, ret;
 
        INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work);
 
-       /* Clear any pending interrupts someone might have left around
-        * for us.
-        */
-       for (core = 0; core < v3d->cores; core++)
-               V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver));
-       V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver));
-
        irq = platform_get_irq_optional(v3d_to_pdev(v3d), 1);
        if (irq == -EPROBE_DEFER)
                return irq;
@@ -296,7 +289,6 @@ v3d_irq_init(struct v3d_dev *v3d)
                        goto fail;
        }
 
-       v3d_irq_enable(v3d);
        return 0;
 
 fail:
@@ -310,6 +302,11 @@ v3d_irq_enable(struct v3d_dev *v3d)
 {
        int core;
 
+       /* Clear any pending interrupts someone might have left around for us. */
+       for (core = 0; core < v3d->cores; core++)
+               V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver));
+       V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver));
+
        /* Enable our set of interrupts, masking out any others. */
        for (core = 0; core < v3d->cores; core++) {
                V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~V3D_CORE_IRQS(v3d->ver));