Add parameters @from and @to for path enabling and disabling, allowing finer-grained control of a path. The range is [@from..@to], where both @from and @to are inclusive, introduce coresight_path_nodes_in_order() to validate the given range if is ordered.
The helpers coresight_path_{first|last}_node() are provided for conveniently fetching the first and last nodes on the path.
A minor refactoring removes the local variable "source" from coresight_enable_path_from_to(), deferring reading the source until it is needed.
Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-core.c | 95 ++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 18 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 1d6a4c5b3b97b13d06356b01b5acd161c8d607de..ae75c3ce117db5f194f9debd9b329695e0fb0cde 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -62,6 +62,24 @@ static LIST_HEAD(coresight_dev_idx_list);
static const struct cti_assoc_op *cti_assoc_ops;
+static struct coresight_node * +coresight_path_first_node(struct coresight_path *path) +{ + if (list_empty(&path->path_list)) + return NULL; + + return list_first_entry(&path->path_list, struct coresight_node, link); +} + +static struct coresight_node * +coresight_path_last_node(struct coresight_path *path) +{ + if (list_empty(&path->path_list)) + return NULL; + + return list_last_entry(&path->path_list, struct coresight_node, link); +} + void coresight_set_cti_ops(const struct cti_assoc_op *cti_op) { cti_assoc_ops = cti_op; @@ -448,19 +466,41 @@ int coresight_resume_source(struct coresight_device *csdev) EXPORT_SYMBOL_GPL(coresight_resume_source);
/* - * coresight_disable_path_from : Disable components in the given path beyond - * @nd in the list. If @nd is NULL, all the components, except the SOURCE are - * disabled. + * Callers must fetch nodes from the path and pass @from and @to to the path + * enable/disable functions. Walk the path from @from to locate @to. If @to + * is found, it indicates @from and @to are in order. Otherwise, they are out + * of order. */ -static void coresight_disable_path_from(struct coresight_path *path, - struct coresight_node *nd) +static bool coresight_path_nodes_in_order(struct coresight_path *path, + struct coresight_node *from, + struct coresight_node *to) +{ + struct coresight_node *nd; + + if (WARN_ON_ONCE(!from || !to)) + return false; + + nd = from; + list_for_each_entry_from(nd, &path->path_list, link) { + if (nd == to) + return true; + } + + return false; +} + +static void coresight_disable_path_from_to(struct coresight_path *path, + struct coresight_node *from, + struct coresight_node *to) { u32 type; struct coresight_device *csdev, *parent, *child; + struct coresight_node *nd;
- if (!nd) - nd = list_first_entry(&path->path_list, struct coresight_node, link); + if (!coresight_path_nodes_in_order(path, from, to)) + return;
+ nd = from; list_for_each_entry_from(nd, &path->path_list, link) { csdev = nd->csdev; type = csdev->type; @@ -494,12 +534,18 @@ static void coresight_disable_path_from(struct coresight_path *path,
/* Disable all helpers adjacent along the path last */ coresight_disable_helpers(csdev, path); + + /* Iterate up to and including @to */ + if (nd == to) + break; } }
void coresight_disable_path(struct coresight_path *path) { - coresight_disable_path_from(path, NULL); + coresight_disable_path_from_to(path, + coresight_path_first_node(path), + coresight_path_last_node(path)); } EXPORT_SYMBOL_GPL(coresight_disable_path);
@@ -523,19 +569,20 @@ static int coresight_enable_helpers(struct coresight_device *csdev, return 0; }
-int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) +static int coresight_enable_path_from_to(struct coresight_path *path, + enum cs_mode mode, + struct coresight_node *from, + struct coresight_node *to) { int ret = 0; u32 type; - struct coresight_node *nd, *last; + struct coresight_node *nd; struct coresight_device *csdev, *parent, *child; - struct coresight_device *source;
- source = coresight_get_source(path); - - last = list_last_entry(&path->path_list, struct coresight_node, link); + if (!coresight_path_nodes_in_order(path, from, to)) + return -EINVAL;
- nd = last; + nd = to; list_for_each_entry_from_reverse(nd, &path->path_list, link) { csdev = nd->csdev; type = csdev->type; @@ -575,7 +622,8 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; - ret = coresight_enable_link(csdev, parent, child, source); + ret = coresight_enable_link(csdev, parent, child, + coresight_get_source(path)); if (ret) goto err_disable_helpers; break; @@ -583,6 +631,10 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) ret = -EINVAL; goto err_disable_helpers; } + + /* Iterate down to and including @from */ + if (nd == from) + break; }
out: @@ -591,14 +643,21 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) coresight_disable_helpers(csdev, path); err_disable_path: /* No device is actually enabled */ - if (nd == last) + if (nd == to) goto out;
nd = list_next_entry(nd, link); - coresight_disable_path_from(path, nd); + coresight_disable_path_from_to(path, nd, to); goto out; }
+int coresight_enable_path(struct coresight_path *path, enum cs_mode mode) +{ + return coresight_enable_path_from_to(path, mode, + coresight_path_first_node(path), + coresight_path_last_node(path)); +} + struct coresight_device *coresight_get_sink(struct coresight_path *path) { struct coresight_device *csdev;