]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
coresight: Take a reference on csdev
authorLeo Yan <leo.yan@arm.com>
Fri, 15 May 2026 20:08:15 +0000 (21:08 +0100)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 18 May 2026 09:18:45 +0000 (10:18 +0100)
coresight_get_ref() currently pins the provider module and takes a
reference on the parent device, but it does not pin &csdev->dev. Take a
reference on &csdev->dev when grabbing a CoreSight device and drop it in
coresight_put_ref().

Reorder the sequence to follow child-to-parent dependencies: first take
a reference on csdev, then on the parent device and grab the driver
module. Once the data and module are pinned, take a PM runtime
reference to power on the hardware.

Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: James Clark <james.clark@linaro.org>
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20260515-arm_coresight_path_power_management_improvement-v14-8-f88c4a3ecfe9@arm.com
drivers/hwtracing/coresight/coresight-core.c

index 3fc6a5db778c89acad6ee05fe15ec0b8b8dab6bc..6b098c3cab0b8a710863bceb2c5f9584ad0bd8af 100644 (file)
@@ -651,15 +651,29 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
  */
 static bool coresight_get_ref(struct coresight_device *csdev)
 {
-       struct device *dev = csdev->dev.parent;
+       struct device *dev = &csdev->dev;
+       struct device *parent = csdev->dev.parent;
+       struct device_driver *drv;
 
-       /* Make sure the driver can't be removed */
-       if (!try_module_get(dev->driver->owner))
-               return false;
-       /* Make sure the device can't go away */
+       /* Make sure csdev can't go away */
        get_device(dev);
-       pm_runtime_get_sync(dev);
+
+       /* Make sure parent device can't go away */
+       get_device(parent);
+
+       /* Make sure the driver can't be removed */
+       drv = parent->driver;
+       if (!drv || !try_module_get(drv->owner))
+               goto err_module;
+
+       /* Make sure the device is powered on */
+       pm_runtime_get_sync(parent);
        return true;
+
+err_module:
+       put_device(parent);
+       put_device(dev);
+       return false;
 }
 
 /**
@@ -670,11 +684,15 @@ static bool coresight_get_ref(struct coresight_device *csdev)
  */
 static void coresight_put_ref(struct coresight_device *csdev)
 {
-       struct device *dev = csdev->dev.parent;
+       struct device *dev = &csdev->dev;
+       struct device *parent = csdev->dev.parent;
+       struct device_driver *drv = parent->driver;
 
-       pm_runtime_put(dev);
+       pm_runtime_put(parent);
+       if (drv)
+               module_put(drv->owner);
+       put_device(parent);
        put_device(dev);
-       module_put(dev->driver->owner);
 }
 
 /*