From 9f74beac0a5fba54230b050d7d8013a84ac565f9 Mon Sep 17 00:00:00 2001 From: Tao Zhang Date: Mon, 14 Dec 2020 02:11:35 -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. Change-Id: I491293e0b1948f3747d34eb79e7845617ace4244 Signed-off-by: Tingwei Zhang Signed-off-by: Mao Jinlong Signed-off-by: Tao Zhang Signed-off-by: Mao Jinlong --- drivers/hwtracing/coresight/coresight-core.c | 70 +++++++++++++++---- .../hwtracing/coresight/coresight-platform.c | 8 +++ include/linux/coresight.h | 4 +- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 96a83cf25bad..c244014117f7 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2020-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ @@ -60,6 +60,8 @@ static LIST_HEAD(cs_active_paths); const u32 coresight_barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; EXPORT_SYMBOL_GPL(coresight_barrier_pkt); +static struct coresight_device *coresight_get_source(struct list_head *path); + static const struct cti_assoc_op *cti_assoc_ops; static const struct csr_set_atid_op *csr_set_atid_ops; @@ -139,6 +141,31 @@ 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. + */ +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)); +} + static int coresight_reset_sink(struct device *dev, void *data) { struct coresight_device *csdev = to_coresight_device(dev); @@ -157,13 +184,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; } @@ -175,13 +205,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; } @@ -393,7 +426,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 = 0; int link_subtype; @@ -402,8 +436,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 && inport < 0) @@ -428,7 +462,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; @@ -437,8 +472,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) { @@ -592,7 +627,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; @@ -654,7 +689,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; @@ -928,7 +963,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, ret; bool found = false; @@ -940,7 +976,7 @@ static int _coresight_build_path(struct coresight_device *csdev, if (coresight_is_percpu_source(csdev) && coresight_is_percpu_sink(sink) && sink == per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev))) { - if (_coresight_build_path(sink, sink, path) == 0) { + if (_coresight_build_path(sink, sink, path, source) == 0) { found = true; goto out; } @@ -951,8 +987,12 @@ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *child_dev; child_dev = csdev->pdata->conns[i].child_dev; + if (csdev->pdata->conns[i].source_name && + strcmp(csdev->pdata->conns[i].source_name, + dev_name(&source->dev))) + continue; if (child_dev && - _coresight_build_path(child_dev, sink, path) == 0) { + _coresight_build_path(child_dev, sink, path, source) == 0) { found = true; break; } @@ -997,7 +1037,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/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index b24de3445636..3395747e0455 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -235,6 +235,7 @@ static int of_coresight_parse_endpoint(struct device *dev, struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; struct coresight_connection *conn; + struct device_node *sn = NULL; do { /* Parse the local port details */ @@ -279,6 +280,13 @@ static int of_coresight_parse_endpoint(struct device *dev, */ conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; + 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); + } /* Connection record updated */ } while (0); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 9f445f09fcfe..f493def4d69b 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2020-2021, The Linux Foundation. All rights reserved. */ #ifndef _LINUX_CORESIGHT_H @@ -165,6 +165,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. @@ -173,6 +174,7 @@ struct coresight_desc { struct coresight_connection { int outport; int child_port; + const char *source_name; struct fwnode_handle *child_fwnode; struct coresight_device *child_dev; struct coresight_sysfs_link *link;