@@ -640,7 +640,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
* don't appear on the trace path, they should be handled along with the
* the master device.
*/
-static void coresight_grab_device(struct coresight_device *csdev)
+static int coresight_grab_device(struct coresight_device *csdev)
{
int i;
@@ -648,10 +648,30 @@ static void coresight_grab_device(struct coresight_device *csdev)
struct coresight_device *child;
child = csdev->pdata->conns[i].child_dev;
- if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
+ if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) {
+ if (!try_module_get(child->dev.parent->driver->owner))
+ goto err;
+ get_device(child->dev.parent);
pm_runtime_get_sync(child->dev.parent);
+ }
}
+ if (!try_module_get(csdev->dev.parent->driver->owner))
+ goto err;
+ get_device(csdev->dev.parent);
pm_runtime_get_sync(csdev->dev.parent);
+ return 0;
+err:
+ for (i--; i >= 0; i--) {
+ struct coresight_device *child;
+
+ child = csdev->pdata->conns[i].child_dev;
+ if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) {
+ pm_runtime_put(child->dev.parent);
+ put_device(child->dev.parent);
+ module_put(child->dev.parent->driver->owner);
+ }
+ }
+ return -ENODEV;
}
/*
@@ -663,12 +683,17 @@ static void coresight_drop_device(struct coresight_device *csdev)
int i;
pm_runtime_put(csdev->dev.parent);
+ put_device(csdev->dev.parent);
+ module_put(csdev->dev.parent->driver->owner);
for (i = 0; i < csdev->pdata->nr_outport; i++) {
struct coresight_device *child;
child = csdev->pdata->conns[i].child_dev;
- if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
+ if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) {
pm_runtime_put(child->dev.parent);
+ put_device(child->dev.parent);
+ module_put(child->dev.parent->driver->owner);
+ }
}
}
@@ -687,7 +712,7 @@ static int _coresight_build_path(struct coresight_device *csdev,
struct coresight_device *sink,
struct list_head *path)
{
- int i;
+ int i, ret;
bool found = false;
struct coresight_node *node;
@@ -721,7 +746,11 @@ static int _coresight_build_path(struct coresight_device *csdev,
if (!node)
return -ENOMEM;
- coresight_grab_device(csdev);
+ ret = coresight_grab_device(csdev);
+ if (ret) {
+ kfree(node);
+ return ret;
+ }
node->csdev = csdev;
list_add(&node->link, path);
When coresight device is in an active session, driver module of that device should not be removed. Use try_get_module() in coresight_grab_device() to prevent module to be unloaded. Use get_device()/put_device() to protect device data in the middle of active session. Signed-off-by: Tingwei Zhang <tingwei@codeaurora.org> --- drivers/hwtracing/coresight/coresight.c | 39 +++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-)