Skip to content

Commit

Permalink
coresight: core: Fix coresight device probe failure issue
Browse files Browse the repository at this point in the history
commit 8c1d3f7 upstream.

It is possibe that probe failure issue happens when the device
and its child_device's probe happens at the same time.
In coresight_make_links, has_conns_grp is true for parent, but
has_conns_grp is false for child device as has_conns_grp is set
to true in coresight_create_conns_sysfs_group. The probe of parent
device will fail at this condition. Add has_conns_grp check for
child device before make the links and make the process from
device_register to connection_create be atomic to avoid this
probe failure issue.

Cc: stable@vger.kernel.org
Suggested-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Suggested-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: Mao Jinlong <quic_jinlmao@quicinc.com>
Link: https://lore.kernel.org/r/20220309142206.15632-1-quic_jinlmao@quicinc.com
[ Added Cc stable ]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Mao Jinlong authored and gregkh committed Jun 9, 2022
1 parent 77692c0 commit 67e3404
Showing 1 changed file with 22 additions and 11 deletions.
33 changes: 22 additions & 11 deletions drivers/hwtracing/coresight/coresight-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,7 @@ static int coresight_fixup_device_conns(struct coresight_device *csdev)
continue;
conn->child_dev =
coresight_find_csdev_by_fwnode(conn->child_fwnode);
if (conn->child_dev) {
if (conn->child_dev && conn->child_dev->has_conns_grp) {
ret = coresight_make_links(csdev, conn,
conn->child_dev);
if (ret)
Expand Down Expand Up @@ -1486,6 +1486,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
int nr_refcnts = 1;
atomic_t *refcnts = NULL;
struct coresight_device *csdev;
bool registered = false;

csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
if (!csdev) {
Expand All @@ -1506,7 +1507,8 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
if (!refcnts) {
ret = -ENOMEM;
goto err_free_csdev;
kfree(csdev);
goto err_out;
}

csdev->refcnt = refcnts;
Expand All @@ -1530,14 +1532,21 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
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
* on the coresight bus while trying to resolve the connections.
*/
mutex_lock(&coresight_mutex);

ret = device_register(&csdev->dev);
if (ret) {
put_device(&csdev->dev);
/*
* All resources are free'd explicitly via
* coresight_device_release(), triggered from put_device().
*/
goto err_out;
goto out_unlock;
}

if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
Expand All @@ -1552,11 +1561,11 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
* from put_device(), which is in turn called from
* function device_unregister().
*/
goto err_out;
goto out_unlock;
}
}

mutex_lock(&coresight_mutex);
/* Device is now registered */
registered = true;

ret = coresight_create_conns_sysfs_group(csdev);
if (!ret)
Expand All @@ -1566,16 +1575,18 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
if (!ret && cti_assoc_ops && cti_assoc_ops->add)
cti_assoc_ops->add(csdev);

out_unlock:
mutex_unlock(&coresight_mutex);
if (ret) {
/* Success */
if (!ret)
return csdev;

/* Unregister the device if needed */
if (registered) {
coresight_unregister(csdev);
return ERR_PTR(ret);
}

return csdev;

err_free_csdev:
kfree(csdev);
err_out:
/* Cleanup the connection information */
coresight_release_platform_data(NULL, desc->pdata);
Expand Down

0 comments on commit 67e3404

Please sign in to comment.