mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/8] drm/msm: Attach a driver to GMU
@ 2026-10-30 17:09 Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 1/8] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen, Haitao Xu

With the introduction of sync_state in the genpd framework, any consumer
device of GCC and GPUCC which is not bound to a driver will result in
bootup warnings like below:

[   24.362666] gcc-kaanapali 100000.clock-controller: sync_state() pending due to 3d37000.gmu
[   24.371210] gxclkctl-kaanapali 3d64000.clock-controller: sync_state() pending due to 3d37000.gmu
[   24.380268] gpucc-kaanapali 3d90000.clock-controller: sync_state() pending due to 3d37000.gmu

To silence these warnings and also to have a proper state in driver core,
attach a driver to the GMU and set it up as a component device for the drm
master device.

The first few patches are preparatory fixes. And the later patches
introduces a driver for GMU device and a couple of minor refactors.

I have ignored most of the T-b/R-b tags as there is significant code
churn in v2 when compared to v1.

Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
Changes in v2:
- Reorder patches to move fixes to the front (Dmitry)
- New patch to remove unused gpu_ops paramer (Dmitry)
- New patch to consolidate msm_gpu_probe into msm_drv_probe
- Drop patch#2 in the v1 series as it doesn't make sense after rebase
- A new patch to pass around DRM private data via devres
- Retrieve GPU data from master's private data during GMU bind
- Move devfreq initialiation post GPU/GMU bind to avoid handling thermal
  mitigation while GMU device is not bound to the driver.
- Ensure GPU is queicent before GMU unbind.
- Link to v1: https://lore.kernel.org/r/20260513-gmu-sync-state-fix-v1-0-6e33e6aa9b4f@oss.qualcomm.com

---
Akhil P Oommen (6):
      drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove()
      drm/msm/adreno/a6xx: Mark cxpd device_link as stateless
      drm/msm: Keep DRM private data separate from GPU drvdata
      drm/msm/adreno: Simplify adreno_probe()
      drm/msm: Always use component model for standalone GPU
      drm/msm: Attach a driver to the GMU

Haitao Xu (2):
      drm/msm: Remove dead gpu_ops parameter from msm_drm_init/uninit
      drm/msm: Consolidate msm_gpu_probe into msm_drv_probe

 drivers/gpu/drm/msm/adreno/a6xx_gmu.c      | 117 +++++++++++++++++++---------
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c      |  19 +----
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h      |   3 -
 drivers/gpu/drm/msm/adreno/adreno_device.c |  40 ++++++----
 drivers/gpu/drm/msm/adreno/adreno_gpu.h    |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c    |   8 +-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c   |   3 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c   |   9 +--
 drivers/gpu/drm/msm/dp/dp_display.c        |   4 +-
 drivers/gpu/drm/msm/dsi/dsi.c              |   4 +-
 drivers/gpu/drm/msm/hdmi/hdmi.c            |   4 +-
 drivers/gpu/drm/msm/msm_drv.c              | 119 +++++++++++++++--------------
 drivers/gpu/drm/msm/msm_drv.h              |   9 ++-
 drivers/gpu/drm/msm/msm_gpu.c              |   3 -
 drivers/gpu/drm/msm/msm_gpu.h              |   1 +
 drivers/gpu/drm/msm/msm_gpu_devfreq.c      |   5 ++
 drivers/gpu/drm/msm/msm_kms.c              |  17 ++---
 17 files changed, 205 insertions(+), 162 deletions(-)
---
base-commit: 5fed66a6fde4dcc6a63ecec6f32e1a331dc4e1a4
change-id: 20260511-gmu-sync-state-fix-bc6b2d809371

Best regards,
-- 
Akhil P Oommen <akhilpo@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/8] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove()
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 2/8] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless Akhil P Oommen
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen

adreno_remove() decides between component_del() and msm_gpu_remove()
based on platform_get_drvdata(pdev), interpreted as a struct
msm_drm_private *. That dereference is wrong because msm_gpu_init()
overwrites the GPU pdev's drvdata with adreno_smmu_priv pointer.
Use an alternate check similar to adreno_probe() that avoids this.

Fixes: 643515a9cd09 ("drm/msm: rework binding of Imageon GPUs")
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 7108d4aa59b5..1798bb12805a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -282,12 +282,13 @@ static int adreno_probe(struct platform_device *pdev)
 
 static void adreno_remove(struct platform_device *pdev)
 {
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct device_node *node = pdev->dev.of_node;
 
-	if (priv->kms_init)
-		component_del(&pdev->dev, &a3xx_ops);
-	else
+	if (of_device_is_compatible(node, "amd,imageon") ||
+	    (msm_separate_gpu_kms_components() && adreno_has_gpu(node)))
 		msm_gpu_remove(pdev, &a3xx_ops);
+	else
+		component_del(&pdev->dev, &a3xx_ops);
 }
 
 static void adreno_shutdown(struct platform_device *pdev)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 2/8] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 1/8] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 3/8] drm/msm: Keep DRM private data separate from GPU drvdata Akhil P Oommen
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen

Since the cxpd virtual device is a driverless device, it has no real
struct device_driver bound to it the way a normal platform device does. So,
the managed lifecycle doesn't map cleanly onto it. Since the lifecycle of
this device_link is managed by the msm driver, pass DL_FLAG_STATELESS
together with the existing DL_FLAG_PM_RUNTIME flag.

This fix is required to avoid the below splat when a driver is attached to
the GMU:

[    9.624509] WARNING: drivers/base/core.c:1383 at dvice_links_driver_bound+0x178/0x330, CPU#6: (udev-worker)/354e
[    9.781167] pc : device_links_driver_bound+0x178/0x330
[    9.786456] lr : device_links_driver_bound+0x158/0x330
[    9.798622] sp : ffff8000827bb820
[    9.802042] x29: ffff8000827bb820 x28: ffff000808915800 x27: 0000000000000044
[    9.809573] x26: ffffb7caf3f983d0 x25: 0000000000000003 x24: ffffb7caf41645a0
[    9.816920] x23: ffffb7caf3f982d8 x22: ffff000801239cb8 x21: ffff000801239c10
[    9.816921] x20: ffff00080b3a8c00 x19: ffff000801239c98 x18: 00000000ffffffff
[    9.816922] x17: 736d5b2073706f5f x16: ffffb7caf1eb5940 x15: ffff8001027bb3b7
[    9.816922] x14: 0000000000000026 x13: ffff00080084c110 x12: 0000000000000000
[    9.816923] x11: ffff0008004a5828 x10: ffff0008004a56d0 x9 : ffffb7caf2227870
[    9.816924] x8 : ffff0008004a56f8 x7 : 0000000000000001 x6 : 0000000000001000ocket.
[    9.816925] x5 : 00000000001a7fbf x4 : ffff0008004a56e8 x3 : ffff000801238cc8
[    9.816926] x2 : ffffb7caf4164000 x1 : ffff000801239c10 x0 : 0000000000000000
[    9.816927] Call trace:
[    9.816927]  device_links_driver_bound+0x178/0x330 (P)
[    9.893492]  driver_bound+0x7c/0xd0
[    9.893493]  really_probe+0x208/0x2a8
[    9.893495]  __driver_probe_device+0x88/0x170
[    9.893496]  driver_probe_device+0x44/0x178
[    9.909639]  __driver_attach+0x9c/0x1b8
[    9.913592]  bus_for_each_dev+0x7c/0xe8System Message Bus Socket.
[    9.925839]  driver_attach+0x2c/0x40
[    9.929733]  bus_add_driver+0xec/0x218
[    9.933609]  driver_register+0x68/0x138
[    9.937555]  __platform_driver_register+0x2c/0x40
[    9.937556]  adreno_gmu_register+0x2c/0x40 [msm]
[    9.947141]  adreno_register+0x3c/0x50 [msm]
[    9.951544]  msm_drm_register+0x50/0x78 [msm]for the API...
[    9.962813]  do_one_initcall+0x4c/0x3e0
[    9.966975]  do_init_module+0x60/0x280
[    9.970849]  load_module+0x1c70/0x1fa0
[    9.974708]  init_module_from_file+0xdc/0x100
[    9.979188]  __arm64_sys_finit_module+0x1c0/0x2e0
[    9.984026]  invoke_syscall+0x5c/0x120
[    9.987882]  el0_svc_common.constprop.0+0xd0/0xf8
[    9.992715]  do_el0_svc+0x28/0x40
[    9.995243] qcom_q6v5_pas 6800000.remoteproc: Handover signaled, but it already happened
[    9.996128]  el0_svc+0x38/0x148
[   10.007672]  el0t_64_sync_handler+0xa0/0xe8
[   10.011975]  el0t_64_sync+0x198/0x1a0

Fixes: ead5d3e5eb37 ("drm/msm/a6xx: Vote for cx gdsc from gpu driver")
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 662f09bec9d5..5d96b55a624a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2291,7 +2291,8 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 		goto err_mmio;
 	}
 
-	if (!device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME)) {
+	if (!device_link_add(gmu->dev, gmu->cxpd,
+			     DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS)) {
 		ret = -ENODEV;
 		goto detach_cxpd;
 	}
@@ -2478,7 +2479,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 		goto err_mmio;
 	}
 
-	cx_link = device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME);
+	cx_link = device_link_add(gmu->dev, gmu->cxpd,
+				  DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
 	if (!cx_link) {
 		ret = -ENODEV;
 		goto detach_cxpd;

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 3/8] drm/msm: Keep DRM private data separate from GPU drvdata
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 1/8] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 2/8] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 4/8] drm/msm/adreno: Simplify adreno_probe() Akhil P Oommen
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen

In separate GPU/KMS mode, the GPU device is also the DRM component
master. msm_drv_probe() stores priv in its drvdata, but msm_gpu_init()
overwrites it with &gpu->adreno_smmu. So, it is better to avoid using
drm priv data in the master's dev->drvdata.

As an alternative, store priv in a devres entry of the drm master and
retrieve it from there during component bind. Update all component
drivers to use the new helpers.

Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c |  6 +++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c    |  6 ++----
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c   |  6 ++----
 drivers/gpu/drm/msm/dp/dp_display.c        |  4 ++--
 drivers/gpu/drm/msm/dsi/dsi.c              |  4 ++--
 drivers/gpu/drm/msm/hdmi/hdmi.c            |  4 ++--
 drivers/gpu/drm/msm/msm_drv.c              | 24 +++++++++++++++++-------
 drivers/gpu/drm/msm/msm_drv.h              |  2 ++
 drivers/gpu/drm/msm/msm_kms.c              | 17 +++++++----------
 9 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 1798bb12805a..cdf26b38b904 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -209,10 +209,10 @@ bool adreno_has_gpu(struct device_node *node)
 
 static int adreno_bind(struct device *dev, struct device *master, void *data)
 {
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 	static struct adreno_platform_config config = {};
-	const struct adreno_info *info;
-	struct msm_drm_private *priv = dev_get_drvdata(master);
 	struct drm_device *drm = priv->dev;
+	const struct adreno_info *info;
 	struct msm_gpu *gpu;
 	int ret;
 
@@ -254,7 +254,7 @@ static int adreno_system_suspend(struct device *dev);
 static void adreno_unbind(struct device *dev, struct device *master,
 		void *data)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 	struct msm_gpu *gpu = dev_to_gpu(dev);
 
 	if (pm_runtime_enabled(dev))
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index da3556eb6ecc..c044d3c9737a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1434,8 +1434,7 @@ static void dpu_dev_remove(struct platform_device *pdev)
 static int __maybe_unused dpu_runtime_suspend(struct device *dev)
 {
 	int i;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
 
 	clk_bulk_disable_unprepare(dpu_kms->num_clocks, dpu_kms->clocks);
@@ -1449,8 +1448,7 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev)
 static int __maybe_unused dpu_runtime_resume(struct device *dev)
 {
 	int rc = -1;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
 	struct drm_encoder *encoder;
 	struct drm_device *ddev;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 3934cd060b27..40b4415c0fba 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -869,8 +869,7 @@ static void mdp5_dev_remove(struct platform_device *pdev)
 
 static __maybe_unused int mdp5_runtime_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
 
 	DBG("");
@@ -880,8 +879,7 @@ static __maybe_unused int mdp5_runtime_suspend(struct device *dev)
 
 static __maybe_unused int mdp5_runtime_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
 
 	DBG("");
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 9299ce616fdb..40ce87d7d252 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -214,7 +214,7 @@ static int msm_dp_display_bind(struct device *dev, struct device *master,
 {
 	int rc = 0;
 	struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 	struct drm_device *drm = priv->dev;
 
 	dp->msm_dp_display.drm_dev = drm;
@@ -237,7 +237,7 @@ static void msm_dp_display_unbind(struct device *dev, struct device *master,
 			      void *data)
 {
 	struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 
 	of_dp_aux_depopulate_bus(dp->aux);
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index c726fc628a08..bc6d470bb191 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -119,7 +119,7 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
 
 static int dsi_bind(struct device *dev, struct device *master, void *data)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 	struct msm_dsi *msm_dsi = dev_get_drvdata(dev);
 
 	/*
@@ -146,7 +146,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
 static void dsi_unbind(struct device *dev, struct device *master,
 		void *data)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 	struct msm_dsi *msm_dsi = dev_get_drvdata(dev);
 
 	msm_dsi_tx_buf_free(msm_dsi->host);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 474006084633..2ca7693773b2 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -236,7 +236,7 @@ static const struct hdmi_platform_config hdmi_tx_8974_config = {
 
 static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 	struct hdmi *hdmi = dev_get_drvdata(dev);
 	int err;
 
@@ -251,7 +251,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
 static void msm_hdmi_unbind(struct device *dev, struct device *master,
 		void *data)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
 
 	if (priv->kms->hdmi) {
 		msm_hdmi_destroy(priv->kms->hdmi);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 5e8f3ce26b32..e25ef578d2b3 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -137,10 +137,19 @@ bool msm_separate_gpu_kms_components(void)
 	}
 }
 
+static void msm_drm_priv_release(struct device *dev, void *res)
+{
+	/* The devres core frees the allocation after this callback. */
+}
+
+struct msm_drm_private *msm_drm_get_priv(struct device *dev)
+{
+	return devres_find(dev, msm_drm_priv_release, NULL, NULL);
+}
+
 static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv->dev;
 
 	/*
@@ -177,7 +186,7 @@ static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_op
 static int msm_drm_init(struct device *dev, const struct drm_driver *drv,
 			const struct component_ops *gpu_ops)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(dev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev;
 	int ret;
 
@@ -1137,13 +1146,14 @@ int msm_drv_probe(struct device *master_dev,
 	struct component_match *match = NULL;
 	int ret;
 
-	priv = devm_kzalloc(master_dev, sizeof(*priv), GFP_KERNEL);
+	priv = devres_alloc(msm_drm_priv_release, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
 	priv->kms = kms;
 	priv->kms_init = kms_init;
-	dev_set_drvdata(master_dev, priv);
+	/* Register before component binding so priv survives unbind/rebind. */
+	devres_add(master_dev, priv);
 
 	/* Add mdp components if we have KMS. */
 	if (kms_init) {
@@ -1178,11 +1188,11 @@ int msm_gpu_probe(struct platform_device *pdev,
 	struct msm_drm_private *priv;
 	int ret;
 
-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	priv = devres_alloc(msm_drm_priv_release, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, priv);
+	devres_add(&pdev->dev, priv);
 
 	/* on all devices that I am aware of, iommu's which can map
 	 * any address the cpu can see are used:
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2840e8a5052d..107d0efb62ce 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -524,6 +524,8 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
 
 extern const struct component_master_ops msm_drm_ops;
 
+struct msm_drm_private *msm_drm_get_priv(struct device *dev);
+
 int msm_kms_pm_prepare(struct device *dev);
 void msm_kms_pm_complete(struct device *dev);
 
diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c
index e5d0ea629448..3597dc276579 100644
--- a/drivers/gpu/drm/msm/msm_kms.c
+++ b/drivers/gpu/drm/msm/msm_kms.c
@@ -218,8 +218,7 @@ struct drm_gpuvm *msm_kms_init_vm(struct drm_device *dev, struct device *mdss_de
 
 void msm_drm_kms_unregister(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv->dev;
 
 	drm_atomic_helper_shutdown(ddev);
@@ -227,8 +226,7 @@ void msm_drm_kms_unregister(struct device *dev)
 
 void msm_drm_kms_uninit(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv->dev;
 	struct msm_kms *kms = priv->kms;
 	int i;
@@ -262,7 +260,7 @@ void msm_drm_kms_uninit(struct device *dev)
 
 int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(dev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv->dev;
 	struct msm_kms *kms = priv->kms;
 	struct drm_crtc *crtc;
@@ -341,7 +339,7 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv)
 
 int msm_kms_pm_prepare(struct device *dev)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(dev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv ? priv->dev : NULL;
 
 	if (!priv || !priv->kms)
@@ -352,7 +350,7 @@ int msm_kms_pm_prepare(struct device *dev)
 
 void msm_kms_pm_complete(struct device *dev)
 {
-	struct msm_drm_private *priv = dev_get_drvdata(dev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv ? priv->dev : NULL;
 
 	if (!priv || !priv->kms)
@@ -363,7 +361,7 @@ void msm_kms_pm_complete(struct device *dev)
 
 void msm_kms_shutdown(struct platform_device *pdev)
 {
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(&pdev->dev);
 	struct drm_device *drm = priv ? priv->dev : NULL;
 
 	/*
@@ -379,8 +377,7 @@ void msm_kms_shutdown(struct platform_device *pdev)
 
 void msm_drm_kms_post_init(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct msm_drm_private *priv = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv->dev;
 
 	drm_kms_helper_poll_init(ddev);

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 4/8] drm/msm/adreno: Simplify adreno_probe()
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
                   ` (2 preceding siblings ...)
  2026-10-30 17:09 ` [PATCH v2 3/8] drm/msm: Keep DRM private data separate from GPU drvdata Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 5/8] drm/msm: Always use component model for standalone GPU Akhil P Oommen
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen

Now that it is possible to auto detect and create separate drm device
for a "GPU + no display" case, drop the special check for "amd,imageon"
compatible string in adreno_probe().

Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 8 ++++----
 drivers/gpu/drm/msm/msm_drv.c              | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index cdf26b38b904..34718adefbfd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -271,12 +271,12 @@ static const struct component_ops a3xx_ops = {
 
 static int adreno_probe(struct platform_device *pdev)
 {
-	struct device_node *node = pdev->dev.of_node;
-
-	if (of_device_is_compatible(node, "amd,imageon") ||
-	    (msm_separate_gpu_kms_components() && adreno_has_gpu(node)))
+	if (msm_separate_gpu_kms_components())
 		return msm_gpu_probe(pdev, &a3xx_ops);
 
+	if (!adreno_has_gpu(pdev->dev.of_node))
+		return -ENODEV;
+
 	return component_add(&pdev->dev, &a3xx_ops);
 }
 
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e25ef578d2b3..e0c0f1248d1b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -115,11 +115,11 @@ static bool msm_separate_gpu_kms_auto(void)
 	int gpus = msm_count_gpus();
 	int display_subsystems = msm_count_mdss() + msm_count_mdp4();
 
-	if (gpus <= 0 || display_subsystems <= 0)
+	/* Single card if there is exactly one GPU and one display subsystem */
+	if (gpus == 1 && display_subsystems == 1)
 		return false;
 
-	/* Single card if there is exactly one GPU and one display subsystem */
-	return gpus > 1 || display_subsystems > 1;
+	return true;
 }
 
 bool msm_separate_gpu_kms_components(void)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 5/8] drm/msm: Always use component model for standalone GPU
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
                   ` (3 preceding siblings ...)
  2026-10-30 17:09 ` [PATCH v2 4/8] drm/msm/adreno: Simplify adreno_probe() Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 6/8] drm/msm: Attach a driver to the GMU Akhil P Oommen
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen

To prepare for adding the GMU as a peer component, turn the GPU pdev into
both a component master and the sole component of itself in this path.
A follow up patch will introduce GMU as a component device.

Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 26 +++++++++++++---------
 drivers/gpu/drm/msm/msm_drv.c              | 35 +++++++++++++++++++++++++-----
 drivers/gpu/drm/msm/msm_drv.h              |  6 ++---
 3 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 34718adefbfd..6b694b8bf8e3 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -271,24 +271,30 @@ static const struct component_ops a3xx_ops = {
 
 static int adreno_probe(struct platform_device *pdev)
 {
-	if (msm_separate_gpu_kms_components())
-		return msm_gpu_probe(pdev, &a3xx_ops);
+	int ret;
+
+	if (!msm_separate_gpu_kms_components())
+		return component_add(&pdev->dev, &a3xx_ops);
 
 	if (!adreno_has_gpu(pdev->dev.of_node))
 		return -ENODEV;
 
-	return component_add(&pdev->dev, &a3xx_ops);
+	ret = msm_gpu_probe(pdev);
+	if (ret)
+		return ret;
+
+	ret = component_add(&pdev->dev, &a3xx_ops);
+	if (ret)
+		msm_gpu_remove(pdev);
+
+	return ret;
 }
 
 static void adreno_remove(struct platform_device *pdev)
 {
-	struct device_node *node = pdev->dev.of_node;
-
-	if (of_device_is_compatible(node, "amd,imageon") ||
-	    (msm_separate_gpu_kms_components() && adreno_has_gpu(node)))
-		msm_gpu_remove(pdev, &a3xx_ops);
-	else
-		component_del(&pdev->dev, &a3xx_ops);
+	component_del(&pdev->dev, &a3xx_ops);
+	if (msm_separate_gpu_kms_components())
+		msm_gpu_remove(pdev);
 }
 
 static void adreno_shutdown(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e0c0f1248d1b..dbb6c70473bf 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1182,10 +1182,25 @@ int msm_drv_probe(struct device *master_dev,
 	return 0;
 }
 
-int msm_gpu_probe(struct platform_device *pdev,
-		  const struct component_ops *ops)
+static int msm_gpu_drm_bind(struct device *dev)
+{
+	return msm_drm_init(dev, &msm_gpu_driver, NULL);
+}
+
+static void msm_gpu_drm_unbind(struct device *dev)
+{
+	msm_drm_uninit(dev, NULL);
+}
+
+static const struct component_master_ops msm_gpu_drm_ops = {
+	.bind = msm_gpu_drm_bind,
+	.unbind = msm_gpu_drm_unbind,
+};
+
+int msm_gpu_probe(struct platform_device *pdev)
 {
 	struct msm_drm_private *priv;
+	struct component_match *match = NULL;
 	int ret;
 
 	priv = devres_alloc(msm_drm_priv_release, sizeof(*priv), GFP_KERNEL);
@@ -1201,13 +1216,21 @@ int msm_gpu_probe(struct platform_device *pdev,
 	if (ret)
 		return ret;
 
-	return msm_drm_init(&pdev->dev, &msm_gpu_driver, ops);
+	/*
+	 * The GPU pdev acts as both the component master and the sole
+	 * component (added by adreno_probe()). Future patches add the
+	 * GMU node as a second component on this same master.
+	 */
+	drm_of_component_match_add(&pdev->dev, &match,
+				   component_compare_of, pdev->dev.of_node);
+
+	return component_master_add_with_match(&pdev->dev, &msm_gpu_drm_ops,
+					       match);
 }
 
-void msm_gpu_remove(struct platform_device *pdev,
-		    const struct component_ops *ops)
+void msm_gpu_remove(struct platform_device *pdev)
 {
-	msm_drm_uninit(&pdev->dev, ops);
+	component_master_del(&pdev->dev, &msm_gpu_drm_ops);
 }
 
 static int __init msm_drm_register(void)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 107d0efb62ce..e70fd617f1e0 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -529,10 +529,8 @@ struct msm_drm_private *msm_drm_get_priv(struct device *dev);
 int msm_kms_pm_prepare(struct device *dev);
 void msm_kms_pm_complete(struct device *dev);
 
-int msm_gpu_probe(struct platform_device *pdev,
-		  const struct component_ops *ops);
-void msm_gpu_remove(struct platform_device *pdev,
-		    const struct component_ops *ops);
+int msm_gpu_probe(struct platform_device *pdev);
+void msm_gpu_remove(struct platform_device *pdev);
 int msm_drv_probe(struct device *dev,
 	int (*kms_init)(struct drm_device *dev),
 	struct msm_kms *kms);

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 6/8] drm/msm: Attach a driver to the GMU
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
                   ` (4 preceding siblings ...)
  2026-10-30 17:09 ` [PATCH v2 5/8] drm/msm: Always use component model for standalone GPU Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 7/8] drm/msm: Remove dead gpu_ops parameter from msm_drm_init/uninit Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 8/8] drm/msm: Consolidate msm_gpu_probe into msm_drv_probe Akhil P Oommen
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen

With the introduction of sync_state in the genpd framework, any consumer
device of GCC and GPUCC which is not bound to a driver will result in
bootup warnings like below:

[   24.362666] gcc-kaanapali 100000.clock-controller: sync_state() pending due to 3d37000.gmu
[   24.371210] gxclkctl-kaanapali 3d64000.clock-controller: sync_state() pending due to 3d37000.gmu
[   24.380268] gpucc-kaanapali 3d90000.clock-controller: sync_state() pending due to 3d37000.gmu

To silence these warnings and also to have a proper state in driver core,
attach a driver to the GMU and set it up as a component device for the drm
master device.

Since both GPU and GMU should be bound to a driver before a
devfreq/thermal mitigation request can be handled, move the devfreq
registration to the bind call of the master device.

Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c      | 111 ++++++++++++++++++++---------
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c      |  19 +----
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h      |   3 -
 drivers/gpu/drm/msm/adreno/adreno_device.c |   5 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h    |   2 +
 drivers/gpu/drm/msm/msm_drv.c              |  39 ++++++----
 drivers/gpu/drm/msm/msm_gpu.c              |   3 -
 drivers/gpu/drm/msm/msm_gpu.h              |   1 +
 drivers/gpu/drm/msm/msm_gpu_devfreq.c      |   5 ++
 9 files changed, 115 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 5d96b55a624a..715d70a51004 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -5,7 +5,7 @@
 #include <linux/clk.h>
 #include <linux/firmware/qcom/qcom_scm.h>
 #include <linux/interconnect.h>
-#include <linux/of_platform.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
@@ -2155,7 +2155,7 @@ void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu, bool force_on)
 	pm_runtime_put(&gpu->pdev->dev);
 }
 
-void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
+static void a6xx_gmu_destroy(struct a6xx_gpu *a6xx_gpu)
 {
 	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
@@ -2200,9 +2200,6 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 		free_irq(gmu->gmu_irq, gmu);
 		free_irq(gmu->hfi_irq, gmu);
 	}
-
-	/* Drop reference taken in of_find_device_by_node */
-	put_device(gmu->dev);
 }
 
 static int cxpd_notifier_cb(struct notifier_block *nb,
@@ -2238,9 +2235,9 @@ static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev, resource_si
 	return ret;
 }
 
-int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
+static int a6xx_gmu_wrapper_pdev_bind(struct a6xx_gpu *a6xx_gpu, struct device *dev)
 {
-	struct platform_device *pdev = of_find_device_by_node(node);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 	struct msm_gpu *gpu = &adreno_gpu->base;
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
@@ -2248,14 +2245,7 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	struct resource *res;
 	int ret;
 
-	if (!pdev)
-		return -ENODEV;
-
-	gmu->dev = &pdev->dev;
-
-	ret = of_dma_configure(gmu->dev, node, true);
-	if (ret)
-		return ret;
+	gmu->dev = dev;
 
 	pm_runtime_enable(gmu->dev);
 
@@ -2265,7 +2255,7 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	/* RGMU requires clocks */
 	ret = devm_clk_bulk_get_all(gmu->dev, &gmu->clocks);
 	if (ret < 0)
-		goto err_clk;
+		return ret;
 
 	gmu->nr_clocks = ret;
 
@@ -2308,6 +2298,8 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 		goto err_mmio;
 	}
 
+	mutex_init(&gmu->lock);
+
 	gmu->initialized = true;
 
 	return 0;
@@ -2318,16 +2310,12 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 err_mmio:
 	iounmap(gmu->mmio);
 
-err_clk:
-	/* Drop reference taken in of_find_device_by_node */
-	put_device(gmu->dev);
-
 	return ret;
 }
 
-int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
+static int a6xx_gmu_pdev_bind(struct a6xx_gpu *a6xx_gpu, struct device *dev)
 {
-	struct platform_device *pdev = of_find_device_by_node(node);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 	struct msm_gpu *gpu = &adreno_gpu->base;
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
@@ -2337,14 +2325,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	struct resource *res;
 	int ret;
 
-	if (!pdev)
-		return -ENODEV;
-
-	gmu->dev = &pdev->dev;
-
-	ret = of_dma_configure(gmu->dev, node, true);
-	if (ret)
-		return ret;
+	gmu->dev = dev;
 
 	/* Set GMU idle level */
 	gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
@@ -2355,11 +2336,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	/* Get the list of clocks */
 	ret = a6xx_gmu_clocks_probe(gmu);
 	if (ret)
-		goto err_put_device;
+		return ret;
 
 	ret = a6xx_gmu_memory_probe(adreno_gpu->base.dev, gmu);
 	if (ret)
-		goto err_put_device;
+		return ret;
 
 
 	/* A660 now requires handling "prealloc requests" in GMU firmware
@@ -2531,6 +2512,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	/* Initialize RPMh */
 	a6xx_gmu_rpmh_init(gmu);
 
+	mutex_init(&gmu->lock);
 	gmu->initialized = true;
 
 	return 0;
@@ -2562,9 +2544,68 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 
 err_memory:
 	a6xx_gmu_memory_free(gmu);
-err_put_device:
-	/* Drop reference taken in of_find_device_by_node */
-	put_device(gmu->dev);
 
 	return ret;
 }
+
+static int a6xx_gmu_bind(struct device *dev, struct device *master, void *data)
+{
+	int (*bind)(struct a6xx_gpu *gpu, struct device *dev) = of_device_get_match_data(dev);
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
+	struct msm_gpu *gpu = dev_to_gpu(&priv->gpu_pdev->dev);
+
+	if (WARN_ON(!gpu))
+		return -ENODEV;
+
+	return bind(to_a6xx_gpu(to_adreno_gpu(gpu)), dev);
+}
+
+static void a6xx_gmu_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct msm_drm_private *priv = msm_drm_get_priv(master);
+	struct msm_gpu *gpu = dev_to_gpu(&priv->gpu_pdev->dev);
+
+	a6xx_gmu_destroy(to_a6xx_gpu(to_adreno_gpu(gpu)));
+}
+
+static const struct component_ops a6xx_gmu_bind_ops = {
+	.bind   = a6xx_gmu_bind,
+	.unbind = a6xx_gmu_unbind,
+};
+
+static int a6xx_gmu_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &a6xx_gmu_bind_ops);
+}
+
+static void a6xx_gmu_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &a6xx_gmu_bind_ops);
+}
+
+static const struct of_device_id a6xx_gmu_dt_match[] = {
+	{ .compatible = "qcom,adreno-gmu", .data = a6xx_gmu_pdev_bind },
+	{ .compatible = "qcom,adreno-rgmu", .data = a6xx_gmu_wrapper_pdev_bind },
+	{ .compatible = "qcom,adreno-gmu-wrapper", .data = a6xx_gmu_wrapper_pdev_bind },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, a6xx_gmu_dt_match);
+
+static struct platform_driver adreno_gmu_driver = {
+	.probe = a6xx_gmu_probe,
+	.remove = a6xx_gmu_remove,
+	.driver = {
+		.name = "adreno_gmu",
+		.of_match_table = a6xx_gmu_dt_match,
+	},
+};
+
+void __init adreno_gmu_register(void)
+{
+	platform_driver_register(&adreno_gmu_driver);
+}
+
+void __exit adreno_gmu_unregister(void)
+{
+	platform_driver_unregister(&adreno_gmu_driver);
+}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 92e8c8abb86d..0bdab662dafa 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2327,8 +2327,6 @@ static void a6xx_destroy(struct msm_gpu *gpu)
 
 	a6xx_llc_slices_destroy(a6xx_gpu);
 
-	a6xx_gmu_remove(a6xx_gpu);
-
 	adreno_gpu_cleanup(adreno_gpu);
 
 	kfree(a6xx_gpu);
@@ -2705,7 +2703,6 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
 		gpu->num_perfcntr_groups = a8xx_num_perfcntr_groups;
 	}
 
-	mutex_init(&a6xx_gpu->gmu.lock);
 	spin_lock_init(&a6xx_gpu->aperture_lock);
 
 	adreno_gpu->registers = NULL;
@@ -2713,10 +2710,9 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
 	/* Check if there is a GMU phandle and set it up */
 	struct device_node *node __free(device_node) =
 		of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0);
-	/* FIXME: How do we gracefully handle this? */
-	BUG_ON(!node);
-
-	adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper");
+	WARN_ON(!node);
+	adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node,
+							     "qcom,adreno-gmu-wrapper");
 
 	adreno_gpu->base.hw_apriv =
 		!!(info->quirks & ADRENO_QUIRK_HAS_HW_APRIV);
@@ -2769,15 +2765,6 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
 	if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu))
 		priv->gpu_clamp_to_idle = true;
 
-	if (adreno_has_gmu_wrapper(adreno_gpu) || adreno_has_rgmu(adreno_gpu))
-		ret = a6xx_gmu_wrapper_init(a6xx_gpu, node);
-	else
-		ret = a6xx_gmu_init(a6xx_gpu, node);
-	if (ret) {
-		a6xx_destroy(&(a6xx_gpu->base.base));
-		return ERR_PTR(ret);
-	}
-
 	adreno_gpu->uche_trap_base = 0x1fffffffff000ull;
 
 	msm_mmu_set_fault_handler(to_msm_vm(gpu->vm)->mmu, gpu,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 79912a33e17c..b308b5bbff80 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -295,9 +295,6 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu);
 int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
 void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
 
-int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
-int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
-void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
 void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu, bool force_on);
 
 void a6xx_preempt_init(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 6b694b8bf8e3..7066be3b8e15 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -250,7 +250,6 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
 	return 0;
 }
 
-static int adreno_system_suspend(struct device *dev);
 static void adreno_unbind(struct device *dev, struct device *master,
 		void *data)
 {
@@ -371,7 +370,7 @@ static void resume_scheduler(struct msm_gpu *gpu)
 	}
 }
 
-static int adreno_system_suspend(struct device *dev)
+int adreno_system_suspend(struct device *dev)
 {
 	struct msm_gpu *gpu = dev_to_gpu(dev);
 	int remaining, ret;
@@ -431,6 +430,7 @@ void __init adreno_register(void)
 		return;
 
 	platform_driver_register(&adreno_driver);
+	adreno_gmu_register();
 }
 
 void __exit adreno_unregister(void)
@@ -438,5 +438,6 @@ void __exit adreno_unregister(void)
 	if (skip_gpu)
 		return;
 
+	adreno_gmu_unregister();
 	platform_driver_unregister(&adreno_driver);
 }
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 4b2156825bdf..9e0d37ec9c15 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -678,6 +678,8 @@ int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state);
 int adreno_gpu_state_put(struct msm_gpu_state *state);
 void adreno_show_object(struct drm_printer *p, void **ptr, int len,
 		bool *encoded);
+void adreno_gmu_register(void);
+void adreno_gmu_unregister(void);
 
 /*
  * Common helper function to initialize the default address space for arm-smmu
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index dbb6c70473bf..9ad2260f4971 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -5,6 +5,7 @@
  * Author: Rob Clark <robdclark@gmail.com>
  */
 
+#include <linux/cleanup.h>
 #include <linux/dma-mapping.h>
 #include <linux/fault-inject.h>
 #include <linux/debugfs.h>
@@ -172,6 +173,14 @@ static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_op
 	if (priv->kms)
 		msm_drm_kms_uninit(dev);
 
+	if (priv->gpu_pdev) {
+		struct device *gpu_dev = &priv->gpu_pdev->dev;
+
+		if (pm_runtime_enabled(gpu_dev))
+			WARN_ON_ONCE(adreno_system_suspend(gpu_dev));
+		msm_devfreq_cleanup(dev_to_gpu(gpu_dev));
+	}
+
 	if (gpu_ops)
 		gpu_ops->unbind(dev, dev, NULL);
 	else
@@ -237,6 +246,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv,
 	if (ret)
 		goto err_put_dev;
 
+	/* Devfreq callbacks require the GPU and GMU to be initialized. */
+	if (priv->gpu_pdev)
+		msm_devfreq_init(dev_to_gpu(&priv->gpu_pdev->dev));
+
 	ret = msm_gem_shrinker_init(ddev);
 	if (ret)
 		goto err_msm_uninit;
@@ -1103,18 +1116,20 @@ static const struct of_device_id msm_gpu_match[] = {
 };
 
 static int add_gpu_components(struct device *dev,
+			      struct device_node *gpu_np,
 			      struct component_match **matchptr)
 {
-	struct device_node *np;
+	struct device_node *np __free(device_node) = gpu_np ?
+		of_node_get(gpu_np) : of_find_matching_node(NULL, msm_gpu_match);
 
-	np = of_find_matching_node(NULL, msm_gpu_match);
-	if (!np)
+	if (!np || !msm_gpu_node_present(np))
 		return 0;
 
-	if (msm_gpu_node_present(np))
-		drm_of_component_match_add(dev, matchptr, component_compare_of, np);
+	drm_of_component_match_add(dev, matchptr, component_compare_of, np);
 
-	of_node_put(np);
+	struct device_node *gmu_np __free(device_node) = of_parse_phandle(np, "qcom,gmu", 0);
+	if (of_device_is_available(gmu_np))
+		drm_of_component_match_add(dev, matchptr, component_compare_of, gmu_np);
 
 	return 0;
 }
@@ -1163,7 +1178,7 @@ int msm_drv_probe(struct device *master_dev,
 	}
 
 	if (!msm_separate_gpu_kms_components()) {
-		ret = add_gpu_components(master_dev, &match);
+		ret = add_gpu_components(master_dev, NULL, &match);
 		if (ret)
 			return ret;
 	}
@@ -1216,13 +1231,9 @@ int msm_gpu_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	/*
-	 * The GPU pdev acts as both the component master and the sole
-	 * component (added by adreno_probe()). Future patches add the
-	 * GMU node as a second component on this same master.
-	 */
-	drm_of_component_match_add(&pdev->dev, &match,
-				   component_compare_of, pdev->dev.of_node);
+	ret = add_gpu_components(&pdev->dev, pdev->dev.of_node, &match);
+	if (ret)
+		return ret;
 
 	return component_master_add_with_match(&pdev->dev, &msm_gpu_drm_ops,
 					       match);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 0c2c35636251..1b558777e241 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -968,8 +968,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 
 	platform_set_drvdata(pdev, &gpu->adreno_smmu);
 
-	msm_devfreq_init(gpu);
-
 	gpu->vm = gpu->funcs->create_vm(gpu, pdev);
 	if (IS_ERR(gpu->vm)) {
 		ret = PTR_ERR(gpu->vm);
@@ -1062,7 +1060,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
 		kthread_destroy_worker(gpu->worker);
 	}
 
-	msm_devfreq_cleanup(gpu);
 	msm_perfcntr_cleanup(gpu);
 
 	platform_set_drvdata(gpu->pdev, NULL);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index d27d54bdb7a7..d76aa17044ec 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -756,6 +756,7 @@ msm_gpu_create_private_vm(struct msm_gpu *gpu, struct task_struct *task,
 void msm_gpu_cleanup(struct msm_gpu *gpu);
 
 struct msm_gpu *adreno_load_gpu(struct drm_device *dev);
+int adreno_system_suspend(struct device *dev);
 bool adreno_has_gpu(struct device_node *node);
 void __init adreno_register(void);
 void __exit adreno_unregister(void);
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
index 2e1d5c343272..025e608f45b4 100644
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
@@ -221,8 +221,13 @@ void msm_devfreq_cleanup(struct msm_gpu *gpu)
 	if (!has_devfreq(gpu))
 		return;
 
+	cancel_idle_work(df);
+	cancel_boost_work(df);
+
 	devfreq_cooling_unregister(gpu->cooling);
 	dev_pm_qos_remove_request(&df->boost_freq);
+	devm_devfreq_remove_device(&gpu->pdev->dev, df->devfreq);
+	df->devfreq = NULL;
 }
 
 void msm_devfreq_resume(struct msm_gpu *gpu)

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 7/8] drm/msm: Remove dead gpu_ops parameter from msm_drm_init/uninit
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
                   ` (5 preceding siblings ...)
  2026-10-30 17:09 ` [PATCH v2 6/8] drm/msm: Attach a driver to the GMU Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  2026-10-30 17:09 ` [PATCH v2 8/8] drm/msm: Consolidate msm_gpu_probe into msm_drv_probe Akhil P Oommen
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen, Haitao Xu

From: Haitao Xu <haitao.xu@oss.qualcomm.com>

The gpu_ops parameter on msm_drm_init() and msm_drm_uninit() was
introduced as an escape hatch for the standalone GPU path, where
adreno_probe() bypassed the component framework and called the bind/unbind
ops directly instead of going through component_bind_all() /
component_unbind_all().

Now that the standalone GPU path always uses the component model (the GPU
pdev is both master and sole member of its own component aggregate), all
callers pass NULL for gpu_ops, making the conditional dead code.

Drop the parameter and collapse the conditional branches into the
component_bind_all() / component_unbind_all() calls that are now always
taken.

Signed-off-by: Haitao Xu <haitao.xu@oss.qualcomm.com>
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/msm_drv.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9ad2260f4971..c3b6a5f8f54e 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -148,7 +148,7 @@ struct msm_drm_private *msm_drm_get_priv(struct device *dev)
 	return devres_find(dev, msm_drm_priv_release, NULL, NULL);
 }
 
-static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
+static int msm_drm_uninit(struct device *dev)
 {
 	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev = priv->dev;
@@ -181,10 +181,7 @@ static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_op
 		msm_devfreq_cleanup(dev_to_gpu(gpu_dev));
 	}
 
-	if (gpu_ops)
-		gpu_ops->unbind(dev, dev, NULL);
-	else
-		component_unbind_all(dev, ddev);
+	component_unbind_all(dev, ddev);
 
 	ddev->dev_private = NULL;
 	drm_dev_put(ddev);
@@ -192,8 +189,7 @@ static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_op
 	return 0;
 }
 
-static int msm_drm_init(struct device *dev, const struct drm_driver *drv,
-			const struct component_ops *gpu_ops)
+static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
 {
 	struct msm_drm_private *priv = msm_drm_get_priv(dev);
 	struct drm_device *ddev;
@@ -239,10 +235,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv,
 	dma_set_max_seg_size(dev, UINT_MAX);
 
 	/* Bind all our sub-components: */
-	if (gpu_ops)
-		ret = gpu_ops->bind(dev, dev, NULL);
-	else
-		ret = component_bind_all(dev, ddev);
+	ret = component_bind_all(dev, ddev);
 	if (ret)
 		goto err_put_dev;
 
@@ -276,7 +269,7 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv,
 	return 0;
 
 err_msm_uninit:
-	msm_drm_uninit(dev, gpu_ops);
+	msm_drm_uninit(dev);
 
 	return ret;
 
@@ -1139,13 +1132,12 @@ static int msm_drm_bind(struct device *dev)
 	return msm_drm_init(dev,
 			    msm_separate_gpu_kms_components() ?
 				    &msm_kms_driver :
-				    &msm_driver,
-			    NULL);
+				    &msm_driver);
 }
 
 static void msm_drm_unbind(struct device *dev)
 {
-	msm_drm_uninit(dev, NULL);
+	msm_drm_uninit(dev);
 }
 
 const struct component_master_ops msm_drm_ops = {
@@ -1199,12 +1191,12 @@ int msm_drv_probe(struct device *master_dev,
 
 static int msm_gpu_drm_bind(struct device *dev)
 {
-	return msm_drm_init(dev, &msm_gpu_driver, NULL);
+	return msm_drm_init(dev, &msm_gpu_driver);
 }
 
 static void msm_gpu_drm_unbind(struct device *dev)
 {
-	msm_drm_uninit(dev, NULL);
+	msm_drm_uninit(dev);
 }
 
 static const struct component_master_ops msm_gpu_drm_ops = {

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 8/8] drm/msm: Consolidate msm_gpu_probe into msm_drv_probe
  2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
                   ` (6 preceding siblings ...)
  2026-10-30 17:09 ` [PATCH v2 7/8] drm/msm: Remove dead gpu_ops parameter from msm_drm_init/uninit Akhil P Oommen
@ 2026-10-30 17:09 ` Akhil P Oommen
  7 siblings, 0 replies; 9+ messages in thread
From: Akhil P Oommen @ 2026-10-30 17:09 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
	Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
	Simona Vetter, Neil Armstrong, Ulf Hansson
  Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akisaira,
	Vladyslav Tymoshchuk, Val Packett, Dmitry Baryshkov,
	Akhil P Oommen, Haitao Xu

From: Haitao Xu <haitao.xu@oss.qualcomm.com>

msm_gpu_probe() duplicates the setup already done by msm_drv_probe():
allocating msm_drm_private, setting the DMA mask, scanning for GPU
components, and registering a component master.

Reduce msm_gpu_probe() to delegate to msm_drv_probe(dev, NULL, NULL) and
drop the now-unused msm_gpu_drm_{bind,unbind,ops} helpers. Extend
msm_drm_bind() to select msm_gpu_driver when kms_init is NULL, and relax
the add_gpu_components() guard in msm_drv_probe() to always run for
GPU-only callers.

Signed-off-by: Haitao Xu <haitao.xu@oss.qualcomm.com>
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  |  2 +-
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c |  3 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c |  3 +-
 drivers/gpu/drm/msm/msm_drv.c            | 61 +++++++++-----------------------
 drivers/gpu/drm/msm/msm_drv.h            |  1 +
 5 files changed, 22 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index c044d3c9737a..4e5ba85317f6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1423,7 +1423,7 @@ static int dpu_dev_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	return msm_drv_probe(&pdev->dev, dpu_kms_init, &dpu_kms->base);
+	return msm_drv_probe(&pdev->dev, NULL, dpu_kms_init, &dpu_kms->base);
 }
 
 static void dpu_dev_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index c299fef1a400..ad08a040982f 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -553,7 +553,8 @@ static int mdp4_probe(struct platform_device *pdev)
 	if (IS_ERR(mdp4_kms->lut_clk))
 		return dev_err_probe(dev, PTR_ERR(mdp4_kms->lut_clk), "failed to get lut_clk\n");
 
-	return msm_drv_probe(&pdev->dev, mdp4_kms_init, &mdp4_kms->base.base);
+	return msm_drv_probe(&pdev->dev, NULL, mdp4_kms_init,
+			     &mdp4_kms->base.base);
 }
 
 static void mdp4_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 40b4415c0fba..067e23fb9649 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -858,7 +858,8 @@ static int mdp5_dev_probe(struct platform_device *pdev)
 
 	mdp5_kms->base.base.irq = irq;
 
-	return msm_drv_probe(&pdev->dev, mdp5_kms_init, &mdp5_kms->base.base);
+	return msm_drv_probe(&pdev->dev, NULL, mdp5_kms_init,
+			     &mdp5_kms->base.base);
 }
 
 static void mdp5_dev_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c3b6a5f8f54e..9eb5d182eaed 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1129,10 +1129,17 @@ static int add_gpu_components(struct device *dev,
 
 static int msm_drm_bind(struct device *dev)
 {
-	return msm_drm_init(dev,
-			    msm_separate_gpu_kms_components() ?
-				    &msm_kms_driver :
-				    &msm_driver);
+	struct msm_drm_private *priv = msm_drm_get_priv(dev);
+	const struct drm_driver *drv;
+
+	if (!priv->kms_init)
+		drv = &msm_gpu_driver;
+	else if (msm_separate_gpu_kms_components())
+		drv = &msm_kms_driver;
+	else
+		drv = &msm_driver;
+
+	return msm_drm_init(dev, drv);
 }
 
 static void msm_drm_unbind(struct device *dev)
@@ -1146,6 +1153,7 @@ const struct component_master_ops msm_drm_ops = {
 };
 
 int msm_drv_probe(struct device *master_dev,
+	struct device_node *gpu_np,
 	int (*kms_init)(struct drm_device *dev),
 	struct msm_kms *kms)
 {
@@ -1169,8 +1177,8 @@ int msm_drv_probe(struct device *master_dev,
 			return ret;
 	}
 
-	if (!msm_separate_gpu_kms_components()) {
-		ret = add_gpu_components(master_dev, NULL, &match);
+	if (!kms_init || !msm_separate_gpu_kms_components()) {
+		ret = add_gpu_components(master_dev, gpu_np, &match);
 		if (ret)
 			return ret;
 	}
@@ -1189,51 +1197,14 @@ int msm_drv_probe(struct device *master_dev,
 	return 0;
 }
 
-static int msm_gpu_drm_bind(struct device *dev)
-{
-	return msm_drm_init(dev, &msm_gpu_driver);
-}
-
-static void msm_gpu_drm_unbind(struct device *dev)
-{
-	msm_drm_uninit(dev);
-}
-
-static const struct component_master_ops msm_gpu_drm_ops = {
-	.bind = msm_gpu_drm_bind,
-	.unbind = msm_gpu_drm_unbind,
-};
-
 int msm_gpu_probe(struct platform_device *pdev)
 {
-	struct msm_drm_private *priv;
-	struct component_match *match = NULL;
-	int ret;
-
-	priv = devres_alloc(msm_drm_priv_release, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	devres_add(&pdev->dev, priv);
-
-	/* on all devices that I am aware of, iommu's which can map
-	 * any address the cpu can see are used:
-	 */
-	ret = dma_set_mask_and_coherent(&pdev->dev, ~0);
-	if (ret)
-		return ret;
-
-	ret = add_gpu_components(&pdev->dev, pdev->dev.of_node, &match);
-	if (ret)
-		return ret;
-
-	return component_master_add_with_match(&pdev->dev, &msm_gpu_drm_ops,
-					       match);
+	return msm_drv_probe(&pdev->dev, pdev->dev.of_node, NULL, NULL);
 }
 
 void msm_gpu_remove(struct platform_device *pdev)
 {
-	component_master_del(&pdev->dev, &msm_gpu_drm_ops);
+	component_master_del(&pdev->dev, &msm_drm_ops);
 }
 
 static int __init msm_drm_register(void)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e70fd617f1e0..b65702ac0140 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -532,6 +532,7 @@ void msm_kms_pm_complete(struct device *dev);
 int msm_gpu_probe(struct platform_device *pdev);
 void msm_gpu_remove(struct platform_device *pdev);
 int msm_drv_probe(struct device *dev,
+	struct device_node *gpu_np,
 	int (*kms_init)(struct drm_device *dev),
 	struct msm_kms *kms);
 void msm_kms_shutdown(struct platform_device *pdev);

-- 
2.55.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-10-30 17:10 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 17:09 [PATCH v2 0/8] drm/msm: Attach a driver to GMU Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 1/8] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 2/8] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 3/8] drm/msm: Keep DRM private data separate from GPU drvdata Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 4/8] drm/msm/adreno: Simplify adreno_probe() Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 5/8] drm/msm: Always use component model for standalone GPU Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 6/8] drm/msm: Attach a driver to the GMU Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 7/8] drm/msm: Remove dead gpu_ops parameter from msm_drm_init/uninit Akhil P Oommen
2026-10-30 17:09 ` [PATCH v2 8/8] drm/msm: Consolidate msm_gpu_probe into msm_drv_probe Akhil P Oommen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®