[PATCH v2 2/2] coresight: tnoc: Fix clock refcount imbalance on platform remove
Jie Gan
jie.gan at oss.qualcomm.com
Thu Jul 2 01:54:20 PDT 2026
coresight_get_enable_clocks() enables the programming clock through
devm_clk_get_optional_enabled(), which also registers a devm action to
call clk_disable_unprepare() when the driver detaches.
After probe, pm_runtime_put() allows the device to suspend and the
runtime suspend callback disables the clock. During remove the device is
left runtime suspended, so pm_runtime_disable() freezes it with the
clock already disabled. The devm cleanup that runs afterwards calls
clk_disable_unprepare() a second time, underflowing the clock enable
refcount.
Resume the device with pm_runtime_get_sync() before tearing it down so
the clock is enabled again and balances the devm-managed disable. Then
pm_runtime_set_suspended() and pm_runtime_put_noidle() leave the device
in a coherent runtime PM state (suspended, usage count balanced) once
the devm action has disabled the clock.
Fixes: 1abc1b212eff ("coresight: Appropriately disable programming clocks")
Signed-off-by: Jie Gan <jie.gan at oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-tnoc.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c
index 9e8de4323d28..eddfdcbaa3ec 100644
--- a/drivers/hwtracing/coresight/coresight-tnoc.c
+++ b/drivers/hwtracing/coresight/coresight-tnoc.c
@@ -282,42 +282,50 @@ static int itnoc_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int ret;
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = _tnoc_probe(&pdev->dev, res);
pm_runtime_put(&pdev->dev);
if (ret)
pm_runtime_disable(&pdev->dev);
return ret;
}
static void itnoc_remove(struct platform_device *pdev)
{
struct trace_noc_drvdata *drvdata = platform_get_drvdata(pdev);
+ /*
+ * Resume the device so its clocks are enabled again, balancing the
+ * clk_disable_unprepare() that devm runs when the driver detaches.
+ * Then mark it suspended and drop the usage count taken here.
+ */
+ pm_runtime_get_sync(&pdev->dev);
coresight_unregister(drvdata->csdev);
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
}
#ifdef CONFIG_PM
static int itnoc_runtime_suspend(struct device *dev)
{
struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev);
clk_disable_unprepare(drvdata->pclk);
return 0;
}
static int itnoc_runtime_resume(struct device *dev)
{
struct trace_noc_drvdata *drvdata = dev_get_drvdata(dev);
return clk_prepare_enable(drvdata->pclk);
}
#endif
--
2.34.1
More information about the linux-arm-kernel
mailing list