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 --- drivers/hwtracing/coresight/coresight-core.c | 36 +++++++++++++++++++++------- 1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 5519d323f21f38d719b9030c7d77a9a61948ba1d..a3a03356c4e3729c530cd274f071500c4ae8d490 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -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); }
/*