]> git.dujemihanovic.xyz Git - linux.git/commitdiff
drm/tegra: Enable runtime PM during probe
authorMikko Perttunen <mperttunen@nvidia.com>
Tue, 13 Jun 2023 09:52:14 +0000 (12:52 +0300)
committerThierry Reding <treding@nvidia.com>
Thu, 27 Jul 2023 16:41:59 +0000 (18:41 +0200)
Currently, engine drivers only enable runtime PM during the host1x
init callback. This can happen slightly later than the probe, which
can cause the power domain to intermittently not be turned off after
probe.

My hypothesis is that there is a race condition between the post-probe
power domain poweroff that is done from a queued work, and the
pm_runtime_enable call happening in the host1x init callback.
If the pm_runtime_enable call happens first, everything is OK and
the power off work can disable the power domain as PM runtime is
enabled and the device is runtime suspended. If power off work runs
first, PM runtime is still disabled for the device and the domain
must be kept powered.

Resolve the issue by moving the runtime PM enablement to the
probe function.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230613095215.2497004-1-cyndis@kapsi.fi
drivers/gpu/drm/tegra/gr2d.c
drivers/gpu/drm/tegra/gr3d.c
drivers/gpu/drm/tegra/nvdec.c
drivers/gpu/drm/tegra/vic.c

index 4c55133467a0db87f8d629e2f3b744dece419d9c..a160d01f26e1db485704cfac31d216b3df55445e 100644 (file)
@@ -71,22 +71,15 @@ static int gr2d_init(struct host1x_client *client)
                goto free;
        }
 
-       pm_runtime_enable(client->dev);
-       pm_runtime_use_autosuspend(client->dev);
-       pm_runtime_set_autosuspend_delay(client->dev, 200);
-
        err = tegra_drm_register_client(dev->dev_private, drm);
        if (err < 0) {
                dev_err(client->dev, "failed to register client: %d\n", err);
-               goto disable_rpm;
+               goto detach_iommu;
        }
 
        return 0;
 
-disable_rpm:
-       pm_runtime_dont_use_autosuspend(client->dev);
-       pm_runtime_force_suspend(client->dev);
-
+detach_iommu:
        host1x_client_iommu_detach(client);
 free:
        host1x_syncpt_put(client->syncpts[0]);
@@ -300,6 +293,7 @@ static void gr2d_remove(struct platform_device *pdev)
 {
        struct gr2d *gr2d = platform_get_drvdata(pdev);
 
+       pm_runtime_disable(&pdev->dev);
        host1x_client_unregister(&gr2d->client.base);
 }
 
@@ -373,6 +367,10 @@ static int __maybe_unused gr2d_runtime_resume(struct device *dev)
                goto disable_clk;
        }
 
+       pm_runtime_enable(dev);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_set_autosuspend_delay(dev, 500);
+
        return 0;
 
 disable_clk:
index 2768f8f073ed7defe24a54502d0ea1ff2c2c1a5d..00c8564520e70818c2814b9c30261f928a4755b6 100644 (file)
@@ -80,22 +80,15 @@ static int gr3d_init(struct host1x_client *client)
                goto free;
        }
 
-       pm_runtime_enable(client->dev);
-       pm_runtime_use_autosuspend(client->dev);
-       pm_runtime_set_autosuspend_delay(client->dev, 200);
-
        err = tegra_drm_register_client(dev->dev_private, drm);
        if (err < 0) {
                dev_err(client->dev, "failed to register client: %d\n", err);
-               goto disable_rpm;
+               goto detach_iommu;
        }
 
        return 0;
 
-disable_rpm:
-       pm_runtime_dont_use_autosuspend(client->dev);
-       pm_runtime_force_suspend(client->dev);
-
+detach_iommu:
        host1x_client_iommu_detach(client);
 free:
        host1x_syncpt_put(client->syncpts[0]);
@@ -554,6 +547,7 @@ static void gr3d_remove(struct platform_device *pdev)
 {
        struct gr3d *gr3d = platform_get_drvdata(pdev);
 
+       pm_runtime_disable(&pdev->dev);
        host1x_client_unregister(&gr3d->client.base);
 }
 
@@ -607,6 +601,10 @@ static int __maybe_unused gr3d_runtime_resume(struct device *dev)
                goto disable_clk;
        }
 
+       pm_runtime_enable(dev);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_set_autosuspend_delay(dev, 500);
+
        return 0;
 
 disable_clk:
index 9f57968392af60fc0cd18fded0eb3a864fba352f..4860790666af51de98a34942c61856bf3c766c8b 100644 (file)
@@ -175,13 +175,9 @@ static int nvdec_init(struct host1x_client *client)
                goto free_channel;
        }
 
-       pm_runtime_enable(client->dev);
-       pm_runtime_use_autosuspend(client->dev);
-       pm_runtime_set_autosuspend_delay(client->dev, 500);
-
        err = tegra_drm_register_client(tegra, drm);
        if (err < 0)
-               goto disable_rpm;
+               goto free_syncpt;
 
        /*
         * Inherit the DMA parameters (such as maximum segment size) from the
@@ -191,10 +187,7 @@ static int nvdec_init(struct host1x_client *client)
 
        return 0;
 
-disable_rpm:
-       pm_runtime_dont_use_autosuspend(client->dev);
-       pm_runtime_force_suspend(client->dev);
-
+free_syncpt:
        host1x_syncpt_put(client->syncpts[0]);
 free_channel:
        host1x_channel_put(nvdec->channel);
@@ -539,6 +532,10 @@ static int nvdec_probe(struct platform_device *pdev)
                goto exit_falcon;
        }
 
+       pm_runtime_enable(dev);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_set_autosuspend_delay(dev, 500);
+
        return 0;
 
 exit_falcon:
@@ -551,8 +548,8 @@ static void nvdec_remove(struct platform_device *pdev)
 {
        struct nvdec *nvdec = platform_get_drvdata(pdev);
 
+       pm_runtime_disable(&pdev->dev);
        host1x_client_unregister(&nvdec->client.base);
-
        falcon_exit(&nvdec->falcon);
 }
 
index 5da989ac700e7f3d8008ebdc32138feb9daab725..73c356f1c90123d0053b2a4778adb1f870e379b7 100644 (file)
@@ -141,13 +141,9 @@ static int vic_init(struct host1x_client *client)
                goto free_channel;
        }
 
-       pm_runtime_enable(client->dev);
-       pm_runtime_use_autosuspend(client->dev);
-       pm_runtime_set_autosuspend_delay(client->dev, 500);
-
        err = tegra_drm_register_client(tegra, drm);
        if (err < 0)
-               goto disable_rpm;
+               goto free_syncpt;
 
        /*
         * Inherit the DMA parameters (such as maximum segment size) from the
@@ -157,10 +153,7 @@ static int vic_init(struct host1x_client *client)
 
        return 0;
 
-disable_rpm:
-       pm_runtime_dont_use_autosuspend(client->dev);
-       pm_runtime_force_suspend(client->dev);
-
+free_syncpt:
        host1x_syncpt_put(client->syncpts[0]);
 free_channel:
        host1x_channel_put(vic->channel);
@@ -527,6 +520,10 @@ static int vic_probe(struct platform_device *pdev)
                goto exit_falcon;
        }
 
+       pm_runtime_enable(dev);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_set_autosuspend_delay(dev, 500);
+
        return 0;
 
 exit_falcon:
@@ -539,8 +536,8 @@ static void vic_remove(struct platform_device *pdev)
 {
        struct vic *vic = platform_get_drvdata(pdev);
 
+       pm_runtime_disable(&pdev->dev);
        host1x_client_unregister(&vic->client.base);
-
        falcon_exit(&vic->falcon);
 }