* [PATCH RFT 1/5] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless
2026-05-12 20:52 [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Akhil P Oommen
@ 2026-05-12 20:52 ` Akhil P Oommen
2026-05-13 0:56 ` Dmitry Baryshkov
2026-05-12 20:52 ` [PATCH RFT 2/5] drm/msm: Centralize the standalone drm device check for GPU Akhil P Oommen
` (4 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-12 20:52 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Since the cxpd virtual device is a driverless device, it has no real
struct device_driver bound 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>
---
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 1b44b9e21ad8..ec13b27feee7 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2196,7 +2196,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;
}
@@ -2377,7 +2378,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
goto err_mmio;
}
- link = device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME);
+ link = device_link_add(gmu->dev, gmu->cxpd,
+ DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
if (!link) {
ret = -ENODEV;
goto detach_cxpd;
--
2.51.0
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 1/5] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless
2026-05-12 20:52 ` [PATCH RFT 1/5] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless Akhil P Oommen
@ 2026-05-13 0:56 ` Dmitry Baryshkov
0 siblings, 0 replies; 15+ messages in thread
From: Dmitry Baryshkov @ 2026-05-13 0:56 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On Wed, May 13, 2026 at 02:22:56AM +0530, Akhil P Oommen wrote:
> Since the cxpd virtual device is a driverless device, it has no real
> struct device_driver bound 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:
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH RFT 2/5] drm/msm: Centralize the standalone drm device check for GPU
2026-05-12 20:52 [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Akhil P Oommen
2026-05-12 20:52 ` [PATCH RFT 1/5] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless Akhil P Oommen
@ 2026-05-12 20:52 ` Akhil P Oommen
2026-05-13 5:41 ` Dmitry Baryshkov
2026-05-12 20:52 ` [PATCH RFT 3/5] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
` (3 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-12 20:52 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
Replace msm_gpu_no_components() with msm_gpu_use_separate_drm_dev() and
move the platform-specific check for "amd,imageon" into the helper so the
policy is centralized and reused by both the core driver and adreno probe
path. No functional change intended.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/adreno_device.c | 3 +--
drivers/gpu/drm/msm/msm_drv.c | 11 +++++++----
drivers/gpu/drm/msm/msm_drv.h | 2 +-
3 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 4edfe80c5be7..3052f3e36de0 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -271,8 +271,7 @@ static const struct component_ops a3xx_ops = {
static int adreno_probe(struct platform_device *pdev)
{
- if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon") ||
- msm_gpu_no_components())
+ if (msm_gpu_use_separate_drm_dev(pdev))
return msm_gpu_probe(pdev, &a3xx_ops);
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 195f40e331e5..b61deafd02c3 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -61,9 +61,12 @@ module_param(separate_gpu_kms, bool, 0400);
DECLARE_FAULT_ATTR(fail_gem_alloc);
DECLARE_FAULT_ATTR(fail_gem_iova);
-bool msm_gpu_no_components(void)
+bool msm_gpu_use_separate_drm_dev(struct platform_device *pdev)
{
- return separate_gpu_kms;
+ if (!pdev)
+ return separate_gpu_kms;
+
+ return of_device_is_compatible(pdev->dev.of_node, "amd,imageon") || separate_gpu_kms;
}
static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
@@ -1035,7 +1038,7 @@ static int add_gpu_components(struct device *dev,
static int msm_drm_bind(struct device *dev)
{
return msm_drm_init(dev,
- msm_gpu_no_components() ?
+ msm_gpu_use_separate_drm_dev(NULL) ?
&msm_kms_driver :
&msm_driver,
NULL);
@@ -1074,7 +1077,7 @@ int msm_drv_probe(struct device *master_dev,
return ret;
}
- if (!msm_gpu_no_components()) {
+ if (!msm_gpu_use_separate_drm_dev(NULL)) {
ret = add_gpu_components(master_dev, &match);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6d847d593f1a..6fcb696ceb7c 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -555,6 +555,6 @@ void msm_kms_shutdown(struct platform_device *pdev);
bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver);
-bool msm_gpu_no_components(void);
+bool msm_gpu_use_separate_drm_dev(struct platform_device *pdev);
#endif /* __MSM_DRV_H__ */
--
2.51.0
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 2/5] drm/msm: Centralize the standalone drm device check for GPU
2026-05-12 20:52 ` [PATCH RFT 2/5] drm/msm: Centralize the standalone drm device check for GPU Akhil P Oommen
@ 2026-05-13 5:41 ` Dmitry Baryshkov
2026-05-13 21:10 ` Akhil P Oommen
0 siblings, 1 reply; 15+ messages in thread
From: Dmitry Baryshkov @ 2026-05-13 5:41 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On Wed, May 13, 2026 at 02:22:57AM +0530, Akhil P Oommen wrote:
> Replace msm_gpu_no_components() with msm_gpu_use_separate_drm_dev() and
> move the platform-specific check for "amd,imageon" into the helper so the
> policy is centralized and reused by both the core driver and adreno probe
> path. No functional change intended.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/adreno_device.c | 3 +--
> drivers/gpu/drm/msm/msm_drv.c | 11 +++++++----
> drivers/gpu/drm/msm/msm_drv.h | 2 +-
> 3 files changed, 9 insertions(+), 7 deletions(-)
For the next iteration please swap this and the next patches (yes,
introducing some code duplication). It's generally not recommended to
have fixes which depend on a non-fix patches.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH RFT 2/5] drm/msm: Centralize the standalone drm device check for GPU
2026-05-13 5:41 ` Dmitry Baryshkov
@ 2026-05-13 21:10 ` Akhil P Oommen
0 siblings, 0 replies; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-13 21:10 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On 5/13/2026 11:11 AM, Dmitry Baryshkov wrote:
> On Wed, May 13, 2026 at 02:22:57AM +0530, Akhil P Oommen wrote:
>> Replace msm_gpu_no_components() with msm_gpu_use_separate_drm_dev() and
>> move the platform-specific check for "amd,imageon" into the helper so the
>> policy is centralized and reused by both the core driver and adreno probe
>> path. No functional change intended.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
>> ---
>> drivers/gpu/drm/msm/adreno/adreno_device.c | 3 +--
>> drivers/gpu/drm/msm/msm_drv.c | 11 +++++++----
>> drivers/gpu/drm/msm/msm_drv.h | 2 +-
>> 3 files changed, 9 insertions(+), 7 deletions(-)
>
> For the next iteration please swap this and the next patches (yes,
> introducing some code duplication). It's generally not recommended to
> have fixes which depend on a non-fix patches.
Ack.
-Akhil.
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH RFT 3/5] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove()
2026-05-12 20:52 [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Akhil P Oommen
2026-05-12 20:52 ` [PATCH RFT 1/5] drm/msm/adreno/a6xx: Mark cxpd device_link as stateless Akhil P Oommen
2026-05-12 20:52 ` [PATCH RFT 2/5] drm/msm: Centralize the standalone drm device check for GPU Akhil P Oommen
@ 2026-05-12 20:52 ` Akhil P Oommen
2026-05-13 5:39 ` Dmitry Baryshkov
2026-05-12 20:52 ` [PATCH RFT 4/5] drm/msm: Always use component model for standalone GPU Akhil P Oommen
` (2 subsequent siblings)
5 siblings, 1 reply; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-12 20:52 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, 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.
Fix this by using msm_gpu_use_separate_drm_dev() instead of relying on
drvdata.
Fixes: 643515a9cd09 ("drm/msm: rework binding of Imageon GPUs")
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/adreno_device.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 3052f3e36de0..66953e551d86 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -279,12 +279,10 @@ 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);
-
- if (priv->kms_init)
- component_del(&pdev->dev, &a3xx_ops);
- else
+ if (msm_gpu_use_separate_drm_dev(pdev))
msm_gpu_remove(pdev, &a3xx_ops);
+ else
+ component_del(&pdev->dev, &a3xx_ops);
}
static void adreno_shutdown(struct platform_device *pdev)
--
2.51.0
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 3/5] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove()
2026-05-12 20:52 ` [PATCH RFT 3/5] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
@ 2026-05-13 5:39 ` Dmitry Baryshkov
0 siblings, 0 replies; 15+ messages in thread
From: Dmitry Baryshkov @ 2026-05-13 5:39 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On Wed, May 13, 2026 at 02:22:58AM +0530, Akhil P Oommen wrote:
> 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.
>
> Fix this by using msm_gpu_use_separate_drm_dev() instead of relying on
> drvdata.
>
> Fixes: 643515a9cd09 ("drm/msm: rework binding of Imageon GPUs")
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/adreno_device.c | 8 +++-----
> 1 file changed, 3 insertions(+), 5 deletions(-)
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH RFT 4/5] drm/msm: Always use component model for standalone GPU
2026-05-12 20:52 [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Akhil P Oommen
` (2 preceding siblings ...)
2026-05-12 20:52 ` [PATCH RFT 3/5] drm/msm/adreno: Fix invalid drvdata typecast in adreno_remove() Akhil P Oommen
@ 2026-05-12 20:52 ` Akhil P Oommen
2026-05-13 11:43 ` Dmitry Baryshkov
2026-05-12 20:53 ` [PATCH RFT 5/5] drm/msm: Attach a driver to the GMU Akhil P Oommen
2026-07-26 5:22 ` [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Val Packett
5 siblings, 1 reply; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-12 20:52 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Akhil P Oommen
When separate_gpu_kms=1 (or the device is compatible with "amd,imageon"),
msm_gpu_no_components() evaluates true and adreno_probe() bypasses the
component framework by calling msm_gpu_probe() directly. In this case,
we skip creating components and directly bind the GPU.
That shortcut makes it impossible to add a second sibling on the GPU
master without introducing ad-hoc plumbing. To prepare for adding the
GMU as a peer component on this master, 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 | 20 ++++++++++++-----
drivers/gpu/drm/msm/msm_drv.c | 35 +++++++++++++++++++++++++-----
drivers/gpu/drm/msm/msm_drv.h | 6 ++---
3 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 66953e551d86..67686424f3a1 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -271,18 +271,26 @@ static const struct component_ops a3xx_ops = {
static int adreno_probe(struct platform_device *pdev)
{
- if (msm_gpu_use_separate_drm_dev(pdev))
- return msm_gpu_probe(pdev, &a3xx_ops);
+ int ret;
- return component_add(&pdev->dev, &a3xx_ops);
+ if (msm_gpu_use_separate_drm_dev(pdev)) {
+ ret = msm_gpu_probe(pdev);
+ if (ret)
+ return ret;
+ }
+
+ ret = component_add(&pdev->dev, &a3xx_ops);
+ if (ret && msm_gpu_use_separate_drm_dev(pdev))
+ msm_gpu_remove(pdev);
+
+ return ret;
}
static void adreno_remove(struct platform_device *pdev)
{
+ component_del(&pdev->dev, &a3xx_ops);
if (msm_gpu_use_separate_drm_dev(pdev))
- msm_gpu_remove(pdev, &a3xx_ops);
- else
- component_del(&pdev->dev, &a3xx_ops);
+ 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 b61deafd02c3..af5aa7ff6179 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1097,10 +1097,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 = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -1116,13 +1131,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 6fcb696ceb7c..6264ff27496f 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -544,10 +544,8 @@ extern const struct component_master_ops msm_drm_ops;
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.51.0
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 4/5] drm/msm: Always use component model for standalone GPU
2026-05-12 20:52 ` [PATCH RFT 4/5] drm/msm: Always use component model for standalone GPU Akhil P Oommen
@ 2026-05-13 11:43 ` Dmitry Baryshkov
2026-05-13 21:09 ` Akhil P Oommen
0 siblings, 1 reply; 15+ messages in thread
From: Dmitry Baryshkov @ 2026-05-13 11:43 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On Wed, May 13, 2026 at 02:22:59AM +0530, Akhil P Oommen wrote:
> When separate_gpu_kms=1 (or the device is compatible with "amd,imageon"),
> msm_gpu_no_components() evaluates true and adreno_probe() bypasses the
> component framework by calling msm_gpu_probe() directly. In this case,
> we skip creating components and directly bind the GPU.
>
> That shortcut makes it impossible to add a second sibling on the GPU
> master without introducing ad-hoc plumbing. To prepare for adding the
> GMU as a peer component on this master, 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 | 20 ++++++++++++-----
> drivers/gpu/drm/msm/msm_drv.c | 35 +++++++++++++++++++++++++-----
> drivers/gpu/drm/msm/msm_drv.h | 6 ++---
> 3 files changed, 45 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 66953e551d86..67686424f3a1 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -271,18 +271,26 @@ static const struct component_ops a3xx_ops = {
>
> static int adreno_probe(struct platform_device *pdev)
> {
> - if (msm_gpu_use_separate_drm_dev(pdev))
> - return msm_gpu_probe(pdev, &a3xx_ops);
> + int ret;
>
> - return component_add(&pdev->dev, &a3xx_ops);
> + if (msm_gpu_use_separate_drm_dev(pdev)) {
> + ret = msm_gpu_probe(pdev);
> + if (ret)
> + return ret;
> + }
> +
> + ret = component_add(&pdev->dev, &a3xx_ops);
> + if (ret && msm_gpu_use_separate_drm_dev(pdev))
> + msm_gpu_remove(pdev);
What about making it more clear:
if (!msm_gpu_use_separate_drm_dev(pdev))
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;
However with this patch in place, maybe it's easier to use the main
msm_drv_probe()? It would need some fixes to handle !kms case as the
GPU-only, but it looks very similar to your new functions.
> +
> + return ret;
> }
>
> static void adreno_remove(struct platform_device *pdev)
> {
> + component_del(&pdev->dev, &a3xx_ops);
> if (msm_gpu_use_separate_drm_dev(pdev))
> - msm_gpu_remove(pdev, &a3xx_ops);
> - else
> - component_del(&pdev->dev, &a3xx_ops);
> + 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 b61deafd02c3..af5aa7ff6179 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -1097,10 +1097,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);
With this patch in place, we can remove the ops argument from
msm_drm_init() and msm_drm_uninit().
> +}
> +
> +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 = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> @@ -1116,13 +1131,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 6fcb696ceb7c..6264ff27496f 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -544,10 +544,8 @@ extern const struct component_master_ops msm_drm_ops;
> 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.51.0
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 4/5] drm/msm: Always use component model for standalone GPU
2026-05-13 11:43 ` Dmitry Baryshkov
@ 2026-05-13 21:09 ` Akhil P Oommen
0 siblings, 0 replies; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-13 21:09 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On 5/13/2026 5:13 PM, Dmitry Baryshkov wrote:
> On Wed, May 13, 2026 at 02:22:59AM +0530, Akhil P Oommen wrote:
>> When separate_gpu_kms=1 (or the device is compatible with "amd,imageon"),
>> msm_gpu_no_components() evaluates true and adreno_probe() bypasses the
>> component framework by calling msm_gpu_probe() directly. In this case,
>> we skip creating components and directly bind the GPU.
>>
>> That shortcut makes it impossible to add a second sibling on the GPU
>> master without introducing ad-hoc plumbing. To prepare for adding the
>> GMU as a peer component on this master, 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 | 20 ++++++++++++-----
>> drivers/gpu/drm/msm/msm_drv.c | 35 +++++++++++++++++++++++++-----
>> drivers/gpu/drm/msm/msm_drv.h | 6 ++---
>> 3 files changed, 45 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
>> index 66953e551d86..67686424f3a1 100644
>> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
>> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
>> @@ -271,18 +271,26 @@ static const struct component_ops a3xx_ops = {
>>
>> static int adreno_probe(struct platform_device *pdev)
>> {
>> - if (msm_gpu_use_separate_drm_dev(pdev))
>> - return msm_gpu_probe(pdev, &a3xx_ops);
>> + int ret;
>>
>> - return component_add(&pdev->dev, &a3xx_ops);
>> + if (msm_gpu_use_separate_drm_dev(pdev)) {
>> + ret = msm_gpu_probe(pdev);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + ret = component_add(&pdev->dev, &a3xx_ops);
>> + if (ret && msm_gpu_use_separate_drm_dev(pdev))
>> + msm_gpu_remove(pdev);
>
> What about making it more clear:
>
> if (!msm_gpu_use_separate_drm_dev(pdev))
> 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;
Ack. this is more readable.
>
> However with this patch in place, maybe it's easier to use the main
> msm_drv_probe()? It would need some fixes to handle !kms case as the
> GPU-only, but it looks very similar to your new functions.
>
Agree. Will do this in a separate patch in the next rev.
>
>> +
>> + return ret;
>> }
>>
>> static void adreno_remove(struct platform_device *pdev)
>> {
>> + component_del(&pdev->dev, &a3xx_ops);
>> if (msm_gpu_use_separate_drm_dev(pdev))
>> - msm_gpu_remove(pdev, &a3xx_ops);
>> - else
>> - component_del(&pdev->dev, &a3xx_ops);
>> + 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 b61deafd02c3..af5aa7ff6179 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.c
>> +++ b/drivers/gpu/drm/msm/msm_drv.c
>> @@ -1097,10 +1097,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);
>
> With this patch in place, we can remove the ops argument from
> msm_drm_init() and msm_drm_uninit().
I didn't notice this. Will drop the unused arg. Thanks.
-Akhil.
>
>> +}
>> +
>> +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 = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
>> @@ -1116,13 +1131,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 6fcb696ceb7c..6264ff27496f 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.h
>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>> @@ -544,10 +544,8 @@ extern const struct component_master_ops msm_drm_ops;
>> 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.51.0
>>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH RFT 5/5] drm/msm: Attach a driver to the GMU
2026-05-12 20:52 [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Akhil P Oommen
` (3 preceding siblings ...)
2026-05-12 20:52 ` [PATCH RFT 4/5] drm/msm: Always use component model for standalone GPU Akhil P Oommen
@ 2026-05-12 20:53 ` Akhil P Oommen
2026-05-13 11:46 ` Dmitry Baryshkov
2026-07-26 5:22 ` [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Val Packett
5 siblings, 1 reply; 15+ messages in thread
From: Akhil P Oommen @ 2026-05-12 20:53 UTC (permalink / raw)
To: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, 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.
Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 70 ++++++++++++++++++++++++++++--
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 +++++--------
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 3 --
drivers/gpu/drm/msm/adreno/adreno_device.c | 2 +
drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 +-
drivers/gpu/drm/msm/msm_drv.c | 17 ++++----
6 files changed, 92 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index ec13b27feee7..71bb621b01f3 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2063,7 +2063,7 @@ void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu)
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;
@@ -2143,7 +2143,7 @@ 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_node *node)
{
struct platform_device *pdev = of_find_device_by_node(node);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
@@ -2213,6 +2213,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;
@@ -2230,7 +2232,7 @@ int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
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_node *node)
{
struct platform_device *pdev = of_find_device_by_node(node);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
@@ -2415,6 +2417,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;
@@ -2444,3 +2447,64 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
return ret;
}
+
+static int a6xx_gmu_bind(struct device *dev, struct device *master, void *data)
+{
+ int (*bind)(struct a6xx_gpu *gpu, struct device_node *node) = of_device_get_match_data(dev);
+ struct a6xx_gpu *a6xx_gpu = dev_get_drvdata(dev);
+
+ if (WARN_ON(!a6xx_gpu))
+ return -ENODEV;
+
+ return bind(a6xx_gpu, dev->of_node);
+}
+
+static void a6xx_gmu_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct a6xx_gpu *a6xx_gpu = dev_get_drvdata(dev);
+
+ a6xx_gmu_destroy(a6xx_gpu);
+ dev_set_drvdata(dev, NULL);
+}
+
+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 d5aba072f44c..b4ae38e1a3d8 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -10,6 +10,7 @@
#include <linux/bitfield.h>
#include <linux/devfreq.h>
+#include <linux/of_platform.h>
#include <linux/pm_domain.h>
#include <linux/soc/qcom/llcc-qcom.h>
@@ -2409,8 +2410,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);
@@ -2622,6 +2621,7 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
struct adreno_platform_config *config = pdev->dev.platform_data;
const struct adreno_info *info = config->info;
struct device_node *node;
+ struct platform_device *gmu_pdev;
struct a6xx_gpu *a6xx_gpu;
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
@@ -2637,17 +2637,14 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
adreno_gpu = &a6xx_gpu->base;
gpu = &adreno_gpu->base;
- mutex_init(&a6xx_gpu->gmu.lock);
spin_lock_init(&a6xx_gpu->aperture_lock);
adreno_gpu->registers = NULL;
- /* Check if there is a GMU phandle and set it up */
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);
@@ -2686,16 +2683,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);
- of_node_put(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,
@@ -2710,6 +2697,13 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
/* Set up the preemption specific bits and pieces for each ringbuffer */
a6xx_preempt_init(gpu);
+ gmu_pdev = of_find_device_by_node(node);
+ of_node_put(node);
+ if (gmu_pdev) {
+ platform_set_drvdata(gmu_pdev, a6xx_gpu);
+ put_device(&gmu_pdev->dev);
+ }
+
return gpu;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index eb431e5e00b1..fe8d68df9944 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -268,9 +268,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);
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 67686424f3a1..d70f98e283d5 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -423,6 +423,7 @@ void __init adreno_register(void)
return;
platform_driver_register(&adreno_driver);
+ adreno_gmu_register();
}
void __exit adreno_unregister(void)
@@ -430,5 +431,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 ec643b84646b..3a05cd98d215 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -642,7 +642,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
* attached targets
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index af5aa7ff6179..426255fd0801 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1021,7 +1021,7 @@ static const struct of_device_id msm_gpu_match[] = {
static int add_gpu_components(struct device *dev,
struct component_match **matchptr)
{
- struct device_node *np;
+ struct device_node *np, *gmu_np;
np = of_find_matching_node(NULL, msm_gpu_match);
if (!np)
@@ -1030,6 +1030,11 @@ static int add_gpu_components(struct device *dev,
if (of_device_is_available(np) && adreno_has_gpu(np))
drm_of_component_match_add(dev, matchptr, component_compare_of, np);
+ gmu_np = 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);
+
+ of_node_put(gmu_np);
of_node_put(np);
return 0;
@@ -1131,13 +1136,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, &match);
+ if (ret)
+ return ret;
return component_master_add_with_match(&pdev->dev, &msm_gpu_drm_ops,
match);
--
2.51.0
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 5/5] drm/msm: Attach a driver to the GMU
2026-05-12 20:53 ` [PATCH RFT 5/5] drm/msm: Attach a driver to the GMU Akhil P Oommen
@ 2026-05-13 11:46 ` Dmitry Baryshkov
0 siblings, 0 replies; 15+ messages in thread
From: Dmitry Baryshkov @ 2026-05-13 11:46 UTC (permalink / raw)
To: Akhil P Oommen
Cc: Rob Clark, Sean Paul, Konrad Dybcio, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, David Airlie,
Simona Vetter, Neil Armstrong, linux-arm-msm, dri-devel,
freedreno, linux-kernel
On Wed, May 13, 2026 at 02:23:00AM +0530, Akhil P Oommen wrote:
> 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.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 70 ++++++++++++++++++++++++++++--
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 +++++--------
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 3 --
> drivers/gpu/drm/msm/adreno/adreno_device.c | 2 +
> drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 +-
> drivers/gpu/drm/msm/msm_drv.c | 17 ++++----
> 6 files changed, 92 insertions(+), 33 deletions(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH RFT 0/5] drm/msm: Attach a driver to GMU
2026-05-12 20:52 [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Akhil P Oommen
` (4 preceding siblings ...)
2026-05-12 20:53 ` [PATCH RFT 5/5] drm/msm: Attach a driver to the GMU Akhil P Oommen
@ 2026-07-26 5:22 ` Val Packett
2026-07-26 16:05 ` Akhil P Oommen
5 siblings, 1 reply; 15+ messages in thread
From: Val Packett @ 2026-07-26 5:22 UTC (permalink / raw)
To: Akhil P Oommen, Rob Clark, Sean Paul, Konrad Dybcio,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Marijn Suijten,
David Airlie, Simona Vetter, Neil Armstrong
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel
On 5/12/26 5:52 PM, Akhil P Oommen wrote:
> 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 refactorings. And the
> final patch introduces a driver for GMU devices.
>
> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com> [..]
For the series:
Tested-by: Val Packett <val@packett.cool> # x1e80100-dell-latitude-7455
When I first saw this series I didn't think this was important, silence
warnings whatever, but since a couple months ago deep suspend started
randomly not completing (bouncing back as soon as everything got
suspended) and I didn't know what it was… just now in #aarch64-laptops
this was brought up again and turns out, yeah. It was bouncing back due
to sync_state not completing for everything. This series actually makes
suspend reliable again!
Thanks,
~val
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH RFT 0/5] drm/msm: Attach a driver to GMU
2026-07-26 5:22 ` [PATCH RFT 0/5] drm/msm: Attach a driver to GMU Val Packett
@ 2026-07-26 16:05 ` Akhil P Oommen
0 siblings, 0 replies; 15+ messages in thread
From: Akhil P Oommen @ 2026-07-26 16:05 UTC (permalink / raw)
To: Val Packett
Cc: linux-arm-msm, dri-devel, freedreno, linux-kernel, Rob Clark,
Sean Paul, Konrad Dybcio, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, David Airlie, Simona Vetter,
Neil Armstrong
On 7/26/2026 10:52 AM, Val Packett wrote:
>
> On 5/12/26 5:52 PM, Akhil P Oommen wrote:
>> 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 refactorings. And the
>> final patch introduces a driver for GMU devices.
>>
>> Signed-off-by: Akhil P Oommen <akhilpo@oss.qualcomm.com> [..]
>
> For the series:
>
> Tested-by: Val Packett <val@packett.cool> # x1e80100-dell-latitude-7455
>
> When I first saw this series I didn't think this was important, silence
> warnings whatever, but since a couple months ago deep suspend started
> randomly not completing (bouncing back as soon as everything got
> suspended) and I didn't know what it was… just now in #aarch64-laptops
> this was brought up again and turns out, yeah. It was bouncing back due
> to sync_state not completing for everything. This series actually makes
> suspend reliable again!
I didn't get a chance to revisit this series after my vacation. I am too
not aware of any impact outside of those dmesg warnings. Any chance this
recent rpmh related fix is helping with the deep sleep instead of this
series:
https://lore.kernel.org/lkml/20260605-assorted-fixes-june-v1-1-2caa04f7287c@oss.qualcomm.com/
I will send a rev 2. Thanks for the T-b tag.
-Akhil.
>
>
> Thanks,
> ~val
>
^ permalink raw reply [flat|nested] 15+ messages in thread