Add a 'principal sink' flag to the CoreSight device structure and the routine to search for it.
In cases where no sink is defined, the coresight_find_principal_sink routine can search from a given source, through the child connections until a sink marked as a principal sink is located.
This allows for default sink to be discovered were none is specified (e.g. perf command line)
Signed-off-by: Mike Leach mike.leach@linaro.org --- drivers/hwtracing/coresight/coresight-priv.h | 2 ++ drivers/hwtracing/coresight/coresight.c | 34 ++++++++++++++++++++ include/linux/coresight.h | 7 ++++ 3 files changed, 43 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 890f9a5c97c6..5cce7a2a8125 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -150,6 +150,8 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data); struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device *coresight_get_enabled_sink(bool reset); struct coresight_device *coresight_get_sink_by_id(u32 id); +struct coresight_device * +coresight_find_principal_sink(struct coresight_device *csdev); struct list_head *coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink); void coresight_release_path(struct list_head *path); diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index c71553c09f8e..9a25bceb4766 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -769,6 +769,40 @@ void coresight_release_path(struct list_head *path) path = NULL; }
+/** + * coresight_get_principal_sink - walk trace connections from source to find + * a principal sink. + * @csdev: source / current device to check. + * + * Checks if the current device is flagged as a principal sink, if not + * recursively checks the children of the device. + * + * This will walk the connection path from a source (etm) till a flagged + * sink is encountered and return that sink to the original caller. + */ +struct coresight_device * +coresight_find_principal_sink(struct coresight_device *csdev) +{ + int i; + + /* A default sink has been found. */ + if (csdev->principal_sink) + return csdev; + + /* Not a sink - recursively explore each port found on this element */ + for (i = 0; i < csdev->pdata->nr_outport; i++) { + struct coresight_device *child_dev, *sink; + + child_dev = csdev->pdata->conns[i].child_dev; + if (child_dev) { + sink = coresight_find_principal_sink(child_dev); + if (sink) + return sink; + } + } + return NULL; +} + /** coresight_validate_source - make sure a source has the right credentials * @csdev: the device structure for a source. * @function: the function this was called from. diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 193cc9dbf448..e361081e5695 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -163,6 +163,11 @@ struct coresight_connection { * activated but not yet enabled. Enabling for a _sink_ * appens when a source has been selected for that it. * @ea: Device attribute for sink representation under PMU directory. + * @principal_sink: 'true' if this sink is the principle sink on a trace path + * from a source. Each source can have a single principle sink on + * a path, which can be chosen by perf if no other sink is + * specified. A device can have multiple principle sinks in + * topologies were not all sources are routed to a single sink. * @ect_dev: Associated cross trigger device. Not part of the trace data * path or connections. */ @@ -180,6 +185,8 @@ struct coresight_device { struct dev_ext_attribute *ea; /* cross trigger handling */ struct coresight_device *ect_dev; + /* mark as a principal sink for a trace path */ + bool principal_sink; };
/*