When a device has multiple power domains, dev->power_domain is left
empty during probe. That didn't cause any issue so far because we are
freeloading on smmu driver's vote on cx gdsc. Instead of that, create
a device_link between cx genpd device and gmu device to keep a vote from
gpu driver.
Before this patch:
localhost ~ # cat /sys/kernel/debug/pm_genpd/pm_genpd_summary
gx_gdsc on 0
/devices/genpd:1:3d6a000.gmu active 0
cx_gdsc on 0
/devices/platform/soc@0/3da0000.iommu active 0
After this patch:
localhost ~ # cat /sys/kernel/debug/pm_genpd/pm_genpd_summary
gx_gdsc on 0
/devices/genpd:1:3d6a000.gmu active 0
cx_gdsc on 0
/devices/platform/soc@0/3da0000.iommu active 0
/devices/genpd:0:3d6a000.gmu active 0
Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com>
---
(no changes since v1)
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 31 +++++++++++++++++++++++++++----
drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 +
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 6484b97c5344..1580d0090f35 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1479,6 +1479,12 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
pm_runtime_force_suspend(gmu->dev);
+ /*
+ * Since cxpd is a virt device, the devlink with gmu-dev will be removed
+ * automatically when we do detach
+ */
+ dev_pm_domain_detach(gmu->cxpd, false);
+
if (!IS_ERR_OR_NULL(gmu->gxpd)) {
pm_runtime_disable(gmu->gxpd);
dev_pm_domain_detach(gmu->gxpd, false);
@@ -1605,8 +1611,10 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
if (adreno_is_a650_family(adreno_gpu)) {
gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc");
- if (IS_ERR(gmu->rscc))
+ if (IS_ERR(gmu->rscc)) {
+ ret = -ENODEV;
goto err_mmio;
+ }
} else {
gmu->rscc = gmu->mmio + 0x23000;
}
@@ -1615,8 +1623,22 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq);
gmu->gmu_irq = a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq);
- if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0)
+ if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0) {
+ ret = -ENODEV;
+ goto err_mmio;
+ }
+
+ gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx");
+ if (IS_ERR(gmu->cxpd)) {
+ ret = PTR_ERR(gmu->cxpd);
goto err_mmio;
+ }
+
+ if (!device_link_add(gmu->dev, gmu->cxpd,
+ DL_FLAG_PM_RUNTIME)) {
+ ret = -ENODEV;
+ goto detach_cxpd;
+ }
/*
* Get a link to the GX power domain to reset the GPU in case of GMU
@@ -1634,6 +1656,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
return 0;
+detach_cxpd:
+ dev_pm_domain_detach(gmu->cxpd, false);
+
err_mmio:
iounmap(gmu->mmio);
if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc"))
@@ -1641,8 +1666,6 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
free_irq(gmu->gmu_irq, gmu);
free_irq(gmu->hfi_irq, gmu);
- ret = -ENODEV;
-
err_memory:
a6xx_gmu_memory_free(gmu);
err_put_device:
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index e034935b3986..5a42dd4dd31f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -56,6 +56,7 @@ struct a6xx_gmu {
int gmu_irq;
struct device *gxpd;
+ struct device *cxpd;
int idle_level;
--
2.7.4
On Wed, 21 Dec 2022 at 18:14, Akhil P Oommen <quic_akhilpo@quicinc.com> wrote: > > When a device has multiple power domains, dev->power_domain is left > empty during probe. That didn't cause any issue so far because we are > freeloading on smmu driver's vote on cx gdsc. Instead of that, create > a device_link between cx genpd device and gmu device to keep a vote from > gpu driver. > > Before this patch: > localhost ~ # cat /sys/kernel/debug/pm_genpd/pm_genpd_summary > gx_gdsc on 0 > /devices/genpd:1:3d6a000.gmu active 0 > cx_gdsc on 0 > /devices/platform/soc@0/3da0000.iommu active 0 > > After this patch: > localhost ~ # cat /sys/kernel/debug/pm_genpd/pm_genpd_summary > gx_gdsc on 0 > /devices/genpd:1:3d6a000.gmu active 0 > cx_gdsc on 0 > /devices/platform/soc@0/3da0000.iommu active 0 > /devices/genpd:0:3d6a000.gmu active 0 > > Signed-off-by: Akhil P Oommen <quic_akhilpo@quicinc.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Kind regards Uffe > --- > > (no changes since v1) > > drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 31 +++++++++++++++++++++++++++---- > drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 1 + > 2 files changed, 28 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > index 6484b97c5344..1580d0090f35 100644 > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > @@ -1479,6 +1479,12 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) > > pm_runtime_force_suspend(gmu->dev); > > + /* > + * Since cxpd is a virt device, the devlink with gmu-dev will be removed > + * automatically when we do detach > + */ > + dev_pm_domain_detach(gmu->cxpd, false); > + > if (!IS_ERR_OR_NULL(gmu->gxpd)) { > pm_runtime_disable(gmu->gxpd); > dev_pm_domain_detach(gmu->gxpd, false); > @@ -1605,8 +1611,10 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) > > if (adreno_is_a650_family(adreno_gpu)) { > gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc"); > - if (IS_ERR(gmu->rscc)) > + if (IS_ERR(gmu->rscc)) { > + ret = -ENODEV; > goto err_mmio; > + } > } else { > gmu->rscc = gmu->mmio + 0x23000; > } > @@ -1615,8 +1623,22 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) > gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq); > gmu->gmu_irq = a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq); > > - if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0) > + if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0) { > + ret = -ENODEV; > + goto err_mmio; > + } > + > + gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx"); > + if (IS_ERR(gmu->cxpd)) { > + ret = PTR_ERR(gmu->cxpd); > goto err_mmio; > + } > + > + if (!device_link_add(gmu->dev, gmu->cxpd, > + DL_FLAG_PM_RUNTIME)) { > + ret = -ENODEV; > + goto detach_cxpd; > + } > > /* > * Get a link to the GX power domain to reset the GPU in case of GMU > @@ -1634,6 +1656,9 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) > > return 0; > > +detach_cxpd: > + dev_pm_domain_detach(gmu->cxpd, false); > + > err_mmio: > iounmap(gmu->mmio); > if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc")) > @@ -1641,8 +1666,6 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) > free_irq(gmu->gmu_irq, gmu); > free_irq(gmu->hfi_irq, gmu); > > - ret = -ENODEV; > - > err_memory: > a6xx_gmu_memory_free(gmu); > err_put_device: > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > index e034935b3986..5a42dd4dd31f 100644 > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > @@ -56,6 +56,7 @@ struct a6xx_gmu { > int gmu_irq; > > struct device *gxpd; > + struct device *cxpd; > > int idle_level; > > -- > 2.7.4 >
© 2016 - 2025 Red Hat, Inc.