When registering a CoreSight device, it first increase the reference counter for the associated device and then allocates sink ID map. The problem happens when the sink ID map allocation fails - the flow misses decreasing the device's reference counter. As a result, the device can never be properly cleaned up after the memory allocation failure.
To fix the issue, the allocation of the sink ID map is moved before increasing the reference counter. With this change, if sink ID map allocation fails, the function can exit without holding a reference to the device. Afterwords, any subsequent failures will invoke coresight_device_release() to release the device's resource, including decrementing the reference counter.
Fixes: 5ad628a76176 ("coresight: Use per-sink trace ID maps for Perf sessions") Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 5632bcb8feb6..3e3823d9f991 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1318,12 +1318,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->dev.parent = desc->dev; csdev->dev.release = coresight_device_release; csdev->dev.bus = &coresight_bustype; - /* - * Hold the reference to our parent device. This will be - * dropped only in coresight_device_release(). - */ - csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev)); - dev_set_name(&csdev->dev, "%s", desc->name);
if (csdev->type == CORESIGHT_DEV_TYPE_SINK || csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) { @@ -1335,6 +1329,14 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) goto err_out; } } + + /* + * Hold the reference to our parent device. This will be + * dropped only in coresight_device_release(). + */ + csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev)); + dev_set_name(&csdev->dev, "%s", desc->name); + /* * Make sure the device registration and the connection fixup * are synchronised, so that we don't see uninitialised devices