Re: [PATCH v2] coresight: Fix clock refcount imbalance on platform probe failure

From: Jie Gan

Date: Sun Nov 08 2026 - 20:54:13 EST




On 9/10/2026 9:17 AM, Jie Gan wrote:
Each CoreSight platform_driver's probe() enables its clocks via
coresight_get_enable_clocks() -> devm_clk_get_optional_enabled(), which
registers a devm cleanup to run clk_disable_unprepare() on driver
detach. The probe wrapper then unconditionally calls pm_runtime_put()
regardless of whether the inner probe succeeded, so on failure this
also fires runtime_suspend() and disables the same clocks a first
time. The driver core then unwinds the failed probe and runs the devm
cleanup, disabling them a second time and underflowing the refcount:

coresight-etm4x etm0: probe with driver coresight-etm4x failed with error -22
------------[ cut here ]------------
qdss_clk already disabled
WARNING: CPU: 1 PID: 432 at drivers/clk/clk.c:1188 clk_core_disable+0x1d0/0x218
...
------------[ cut here ]------------
Unpreparing enabled qdss_clk
WARNING: CPU: 0 PID: 432 at drivers/clk/clk.c:1061 clk_core_unprepare+0x248/0x268
...

qdss_clk is shared by every CoreSight node, so the extra disable drives
its refcount to 0 while sibling devices still expect it enabled. The
next funnel to probe then touches unclocked hardware and panics:

SError Interrupt on CPU1, code 0x00000000be000000 -- SError
Kernel panic - not syncing: Asynchronous SError Interrupt
...
coresight_clear_self_claim_tag+0x7c/0x1e0 [coresight] (P)
funnel_probe+0x114/0x2e0 [coresight_funnel]
dynamic_funnel_probe+0x24/0x70 [coresight_funnel]

On the failure path, disable runtime PM before releasing the usage
reference: call pm_runtime_disable() first so no further
runtime_suspend() can be scheduled, then pm_runtime_set_suspended() to
explicitly record the suspended state, and finally
pm_runtime_put_noidle() to drop the reference without invoking
runtime_suspend(), leaving the devm cleanup as the sole disabler of
the clocks.

Affects catu, ctcu, etm4x, funnel, replicator, stm, tmc, tpiu and tnoc,
all of which share this probe skeleton.


Gentle ping

Reviewed-by: Leo Yan <leo.yan@xxxxxxx>
Fixes: 1abc1b212eff ("coresight: Appropriately disable programming clocks")
Signed-off-by: Jie Gan <jie.gan@xxxxxxxxxxxxxxxx>
---
Changes in v2:
- update the workflow regarding to Leo's suggestion.
- Link to v1: https://lore.kernel.org/r/20260907-fix-clk-issue-v1-1-efe81fa2b697@xxxxxxxxxxxxxxxx
---
drivers/hwtracing/coresight/coresight-catu.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-ctcu-core.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 11 +++++++----
drivers/hwtracing/coresight/coresight-funnel.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-replicator.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-stm.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-tmc-core.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-tnoc.c | 10 +++++++---
drivers/hwtracing/coresight/coresight-tpiu.c | 10 +++++++---
9 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index ad8dafea7d2f..4e2687e61c9a 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -632,11 +632,15 @@ static int catu_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = __catu_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void catu_platform_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
index 9043cad42f01..5827b6d5844f 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -251,11 +251,15 @@ static int ctcu_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = ctcu_probe(pdev);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void ctcu_platform_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2247ad55d444..48050f86ead5 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -2330,12 +2330,15 @@ static int etm4_probe_platform_dev(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = etm4_probe(&pdev->dev);
+ if (ret) {
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
pm_runtime_put(&pdev->dev);
- if (ret)
- pm_runtime_disable(&pdev->dev);
-
- return ret;
+ return 0;
}
static int etm4_probe_cpu(unsigned int cpu)
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 0abc11f0690c..264964a340ec 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -319,11 +319,15 @@ static int funnel_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = funnel_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void funnel_platform_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 2f382de357ee..93274ab0cfaa 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -298,11 +298,15 @@ static int replicator_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = replicator_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void replicator_platform_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index 4e860519a73f..88726274ebeb 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -1011,11 +1011,15 @@ static int stm_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = __stm_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void stm_platform_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index bc5a133ada3e..c4fe2dde5bf8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -974,11 +974,15 @@ static int tmc_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = __tmc_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void tmc_platform_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c
index 9e8de4323d28..4479d93f352b 100644
--- a/drivers/hwtracing/coresight/coresight-tnoc.c
+++ b/drivers/hwtracing/coresight/coresight-tnoc.c
@@ -288,11 +288,15 @@ static int itnoc_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = _tnoc_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void itnoc_remove(struct platform_device *pdev)
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 7b029d2eb389..3166ed6bc224 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -271,11 +271,15 @@ static int tpiu_platform_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = __tpiu_probe(&pdev->dev, res);
- pm_runtime_put(&pdev->dev);
- if (ret)
+ if (ret) {
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ return ret;
+ }
- return ret;
+ pm_runtime_put(&pdev->dev);
+ return 0;
}
static void tpiu_platform_remove(struct platform_device *pdev)

---
base-commit: af5f12805e5cefa4fe68d6127c7e1fb78cd5535c
change-id: 20260907-fix-clk-issue-51e43c533250

Best regards,