From bc78211a5e8a92c9c9f479c55c63f31eb216c256 Mon Sep 17 00:00:00 2001 From: Tingwei Zhang Date: Thu, 8 Aug 2019 14:52:59 +0800 Subject: [PATCH] coresight: funnel: add support for multiple output ports Funnel devices are now capable of supporting multiple-inputs and multiple-outputs configuration with in built hardware filtering for TPDM devices. Add software support to this function. Output ports is selected according to the source of the trace path. Add QGKI support. Change-Id: I491293e0b1948f3747d34eb79e7845617ace4244 Signed-off-by: Tingwei Zhang --- .../hwtracing/coresight/coresight-platform.c | 14 +++- drivers/hwtracing/coresight/coresight.c | 76 +++++++++++++++---- include/linux/coresight.h | 4 + 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 3c5bee429105..06d41c7dac9b 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2019 The Linux Foundation. All rights reserved. */ #include @@ -184,6 +184,9 @@ static int of_coresight_parse_endpoint(struct device *dev, struct of_endpoint endpoint, rendpoint; struct device_node *rparent = NULL; struct device_node *rep = NULL; +#ifdef CONFIG_CORESIGHT_QGKI + struct device_node *sn = NULL; +#endif struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; @@ -223,6 +226,15 @@ static int of_coresight_parse_endpoint(struct device *dev, */ conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; +#ifdef CONFIG_CORESIGHT_QGKI + conn->source_name = NULL; + sn = of_parse_phandle(ep, "source", 0); + if (sn) { + ret = of_property_read_string(sn, + "coresight-name", &conn->source_name); + of_node_put(sn); + } +#endif /* Connection record updated */ ret = 1; } while (0); diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 06bcad51e1ac..56ad6c63c394 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -54,6 +54,8 @@ static LIST_HEAD(cs_active_paths); */ const u32 barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; +static struct coresight_device *coresight_get_source(struct list_head *path); + static int coresight_id_match(struct device *dev, void *data) { int trace_id, i_trace_id; @@ -93,6 +95,39 @@ static int coresight_source_is_unique(struct coresight_device *csdev) csdev, coresight_id_match); } +/** + * coresight_source_filter - checks whether the connection matches the source + * of path if connection is binded to specific source. + * @path: The list of devices + * @conn: The connection of one outport + * + * Return zero if the connection doesn't have a source binded or source of the + * path matches the source binds to connection. + */ +#ifdef CONFIG_CORESIGHT_QGKI +static int coresight_source_filter(struct list_head *path, + struct coresight_connection *conn) +{ + int ret = 0; + struct coresight_device *source = NULL; + + if (conn->source_name == NULL) + return ret; + + source = coresight_get_source(path); + if (source == NULL) + return ret; + + return strcmp(conn->source_name, dev_name(&source->dev)); +} +#else +static int coresight_source_filter(struct list_head *path, + struct coresight_connection *conn) +{ + return 0; +} +#endif + static int coresight_reset_sink(struct device *dev, void *data) { struct coresight_device *csdev = to_coresight_device(dev); @@ -111,13 +146,16 @@ static void coresight_reset_all_sink(void) } static int coresight_find_link_inport(struct coresight_device *csdev, - struct coresight_device *parent) + struct coresight_device *parent, + struct list_head *path) { int i; struct coresight_connection *conn; for (i = 0; i < parent->pdata->nr_outport; i++) { conn = &parent->pdata->conns[i]; + if (coresight_source_filter(path, conn)) + continue; if (conn->child_dev == csdev) return conn->child_port; } @@ -129,13 +167,16 @@ static int coresight_find_link_inport(struct coresight_device *csdev, } static int coresight_find_link_outport(struct coresight_device *csdev, - struct coresight_device *child) + struct coresight_device *child, + struct list_head *path) { int i; struct coresight_connection *conn; for (i = 0; i < csdev->pdata->nr_outport; i++) { conn = &csdev->pdata->conns[i]; + if (coresight_source_filter(path, conn)) + continue; if (conn->child_dev == child) return conn->outport; } @@ -268,7 +309,8 @@ static void coresight_disable_sink(struct coresight_device *csdev) static int coresight_enable_link(struct coresight_device *csdev, struct coresight_device *parent, - struct coresight_device *child) + struct coresight_device *child, + struct list_head *path) { int ret; int link_subtype; @@ -277,8 +319,8 @@ static int coresight_enable_link(struct coresight_device *csdev, if (!parent || !child) return -EINVAL; - inport = coresight_find_link_inport(csdev, parent); - outport = coresight_find_link_outport(csdev, child); + inport = coresight_find_link_inport(csdev, parent, path); + outport = coresight_find_link_outport(csdev, child, path); link_subtype = csdev->subtype.link_subtype; if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) @@ -308,7 +350,8 @@ static int coresight_enable_link(struct coresight_device *csdev, static void coresight_disable_link(struct coresight_device *csdev, struct coresight_device *parent, - struct coresight_device *child) + struct coresight_device *child, + struct list_head *path) { int i, nr_conns; int link_subtype; @@ -317,8 +360,8 @@ static void coresight_disable_link(struct coresight_device *csdev, if (!parent || !child) return; - inport = coresight_find_link_inport(csdev, parent); - outport = coresight_find_link_outport(csdev, child); + inport = coresight_find_link_inport(csdev, parent, path); + outport = coresight_find_link_outport(csdev, child, path); link_subtype = csdev->subtype.link_subtype; if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { @@ -430,7 +473,7 @@ static void coresight_disable_path_from(struct list_head *path, case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; - coresight_disable_link(csdev, parent, child); + coresight_disable_link(csdev, parent, child, path); break; default: break; @@ -484,7 +527,7 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data) 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); + ret = coresight_enable_link(csdev, parent, child, path); if (ret) goto err; break; @@ -667,7 +710,8 @@ static void coresight_drop_device(struct coresight_device *csdev) */ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink, - struct list_head *path) + struct list_head *path, + struct coresight_device *source) { int i; bool found = false; @@ -682,8 +726,14 @@ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *child_dev; child_dev = csdev->pdata->conns[i].child_dev; +#ifdef CONFIG_CORESIGHT_QGKI + if (csdev->pdata->conns[i].source_name && + strcmp(csdev->pdata->conns[i].source_name, + dev_name(&source->dev))) + continue; +#endif if (child_dev && - _coresight_build_path(child_dev, sink, path) == 0) { + _coresight_build_path(child_dev, sink, path, source) == 0) { found = true; break; } @@ -725,7 +775,7 @@ struct list_head *coresight_build_path(struct coresight_device *source, INIT_LIST_HEAD(path); - rc = _coresight_build_path(source, sink, path); + rc = _coresight_build_path(source, sink, path, source); if (rc) { kfree(path); return ERR_PTR(rc); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 0377cad72e68..e277b1249224 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -127,6 +127,7 @@ struct coresight_desc { * struct coresight_connection - representation of a single connection * @outport: a connection's output port number. * @child_port: remote component's port number @output is connected to. + * @source_name:source component's name. * @chid_fwnode: remote component's fwnode handle. * @child_dev: a @coresight_device representation of the component connected to @outport. @@ -134,6 +135,9 @@ struct coresight_desc { struct coresight_connection { int outport; int child_port; +#ifdef CONFIG_CORESIGHT_QGKI + const char *source_name; +#endif struct fwnode_handle *child_fwnode; struct coresight_device *child_dev; };