Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/coresight/linux.git

This commit is contained in:
Stephen Rothwell 2024-12-20 14:20:02 +11:00
commit 80897984e4
13 changed files with 309 additions and 59 deletions

View File

@ -0,0 +1,15 @@
What: /sys/bus/coresight/devices/dummy_source<N>/enable_source
Date: Dec 2024
KernelVersion: 6.14
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
Description: (RW) Enable/disable tracing of dummy source. A sink should be activated
before enabling the source. The path of coresight components linking
the source to the sink is configured and managed automatically by the
coresight framework.
What: /sys/bus/coresight/devices/dummy_source<N>/traceid
Date: Dec 2024
KernelVersion: 6.14
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
Description: (R) Show the trace ID that will appear in the trace stream
coming from this trace entity.

View File

@ -38,6 +38,12 @@ properties:
enum:
- arm,coresight-dummy-source
arm,static-trace-id:
description: If dummy source needs static id support, use this to set trace id.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 111
out-ports:
$ref: /schemas/graph.yaml#/properties/ports

View File

@ -45,7 +45,22 @@ properties:
patternProperties:
'^port@[01]$':
description: Output connections to CoreSight Trace bus
$ref: /schemas/graph.yaml#/properties/port
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
properties:
endpoint:
$ref: /schemas/graph.yaml#/$defs/endpoint-base
unevaluatedProperties: false
properties:
filter-source:
$ref: /schemas/types.yaml#/definitions/phandle
description:
phandle to the coresight trace source device matching the
hard coded filtering for this port
remote-endpoint: true
required:
- compatible
@ -72,6 +87,7 @@ examples:
reg = <0>;
replicator_out_port0: endpoint {
remote-endpoint = <&etb_in_port>;
filter-source = <&tpdm_video>;
};
};
@ -79,6 +95,7 @@ examples:
reg = <1>;
replicator_out_port1: endpoint {
remote-endpoint = <&tpiu_in_port>;
filter-source = <&tpdm_mdss>;
};
};
};

View File

@ -75,22 +75,54 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
}
EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
static struct coresight_device *coresight_get_source(struct list_head *path)
{
struct coresight_device *csdev;
if (!path)
return NULL;
csdev = list_first_entry(path, struct coresight_node, link)->csdev;
if (!coresight_is_device_source(csdev))
return NULL;
return csdev;
}
/**
* coresight_blocks_source - checks whether the connection matches the source
* of path if connection is bound to specific source.
* @src: The source device of the trace path
* @conn: The connection of one outport
*
* Return false if the connection doesn't have a source binded or source of the
* path matches the source binds to connection.
*/
static bool coresight_blocks_source(struct coresight_device *src,
struct coresight_connection *conn)
{
return conn->filter_src_fwnode && (conn->filter_src_dev != src);
}
static struct coresight_connection *
coresight_find_out_connection(struct coresight_device *src_dev,
struct coresight_device *dest_dev)
coresight_find_out_connection(struct coresight_device *csdev,
struct coresight_device *out_dev,
struct coresight_device *trace_src)
{
int i;
struct coresight_connection *conn;
for (i = 0; i < src_dev->pdata->nr_outconns; i++) {
conn = src_dev->pdata->out_conns[i];
if (conn->dest_dev == dest_dev)
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
conn = csdev->pdata->out_conns[i];
if (coresight_blocks_source(trace_src, conn))
continue;
if (conn->dest_dev == out_dev)
return conn;
}
dev_err(&src_dev->dev,
"couldn't find output connection, src_dev: %s, dest_dev: %s\n",
dev_name(&src_dev->dev), dev_name(&dest_dev->dev));
dev_err(&csdev->dev,
"couldn't find output connection, csdev: %s, out_dev: %s\n",
dev_name(&csdev->dev), dev_name(&out_dev->dev));
return ERR_PTR(-ENODEV);
}
@ -251,7 +283,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 coresight_device *source)
{
int link_subtype;
struct coresight_connection *inconn, *outconn;
@ -259,8 +292,8 @@ static int coresight_enable_link(struct coresight_device *csdev,
if (!parent || !child)
return -EINVAL;
inconn = coresight_find_out_connection(parent, csdev);
outconn = coresight_find_out_connection(csdev, child);
inconn = coresight_find_out_connection(parent, csdev, source);
outconn = coresight_find_out_connection(csdev, child, source);
link_subtype = csdev->subtype.link_subtype;
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR(inconn))
@ -273,15 +306,16 @@ 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 coresight_device *source)
{
struct coresight_connection *inconn, *outconn;
if (!parent || !child)
return;
inconn = coresight_find_out_connection(parent, csdev);
outconn = coresight_find_out_connection(csdev, child);
inconn = coresight_find_out_connection(parent, csdev, source);
outconn = coresight_find_out_connection(csdev, child, source);
link_ops(csdev)->disable(csdev, inconn, outconn);
}
@ -375,7 +409,8 @@ 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,
coresight_get_source(path));
break;
default:
break;
@ -418,7 +453,9 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
u32 type;
struct coresight_node *nd;
struct coresight_device *csdev, *parent, *child;
struct coresight_device *source;
source = coresight_get_source(path);
list_for_each_entry_reverse(nd, path, link) {
csdev = nd->csdev;
type = csdev->type;
@ -456,7 +493,7 @@ int coresight_enable_path(struct list_head *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);
ret = coresight_enable_link(csdev, parent, child, source);
if (ret)
goto err;
break;
@ -619,6 +656,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
/**
* _coresight_build_path - recursively build a path from a @csdev to a sink.
* @csdev: The device to start from.
* @source: The trace source device of the path.
* @sink: The final sink we want in this path.
* @path: The list to add devices to.
*
@ -628,6 +666,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
* the source is the first device and the sink the last one.
*/
static int _coresight_build_path(struct coresight_device *csdev,
struct coresight_device *source,
struct coresight_device *sink,
struct list_head *path)
{
@ -641,7 +680,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, source, sink, path) == 0) {
found = true;
goto out;
}
@ -652,8 +691,12 @@ static int _coresight_build_path(struct coresight_device *csdev,
struct coresight_device *child_dev;
child_dev = csdev->pdata->out_conns[i]->dest_dev;
if (coresight_blocks_source(source, csdev->pdata->out_conns[i]))
continue;
if (child_dev &&
_coresight_build_path(child_dev, sink, path) == 0) {
_coresight_build_path(child_dev, source, sink, path) == 0) {
found = true;
break;
}
@ -698,7 +741,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, source, sink, path);
if (rc) {
kfree(path);
return ERR_PTR(rc);
@ -927,6 +970,16 @@ static int coresight_orphan_match(struct device *dev, void *data)
for (i = 0; i < src_csdev->pdata->nr_outconns; i++) {
conn = src_csdev->pdata->out_conns[i];
/* Fix filter source device before skip the port */
if (conn->filter_src_fwnode && !conn->filter_src_dev) {
if (dst_csdev &&
(conn->filter_src_fwnode == dst_csdev->dev.fwnode) &&
!WARN_ON_ONCE(!coresight_is_device_source(dst_csdev)))
conn->filter_src_dev = dst_csdev;
else
still_orphan = true;
}
/* Skip the port if it's already connected. */
if (conn->dest_dev)
continue;
@ -977,18 +1030,40 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev)
csdev, coresight_orphan_match);
}
static int coresight_clear_filter_source(struct device *dev, void *data)
{
int i;
struct coresight_device *source = data;
struct coresight_device *csdev = to_coresight_device(dev);
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
if (csdev->pdata->out_conns[i]->filter_src_dev == source)
csdev->pdata->out_conns[i]->filter_src_dev = NULL;
}
return 0;
}
/* coresight_remove_conns - Remove other device's references to this device */
static void coresight_remove_conns(struct coresight_device *csdev)
{
int i, j;
struct coresight_connection *conn;
if (coresight_is_device_source(csdev))
bus_for_each_dev(&coresight_bustype, NULL, csdev,
coresight_clear_filter_source);
/*
* Remove the input connection references from the destination device
* for each output connection.
*/
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
conn = csdev->pdata->out_conns[i];
if (conn->filter_src_fwnode) {
conn->filter_src_dev = NULL;
fwnode_handle_put(conn->filter_src_fwnode);
}
if (!conn->dest_dev)
continue;

View File

@ -11,10 +11,12 @@
#include <linux/pm_runtime.h>
#include "coresight-priv.h"
#include "coresight-trace-id.h"
struct dummy_drvdata {
struct device *dev;
struct coresight_device *csdev;
u8 traceid;
};
DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
@ -72,6 +74,32 @@ static const struct coresight_ops dummy_sink_cs_ops = {
.sink_ops = &dummy_sink_ops,
};
/* User can get the trace id of dummy source from this node. */
static ssize_t traceid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned long val;
struct dummy_drvdata *drvdata = dev_get_drvdata(dev->parent);
val = drvdata->traceid;
return sysfs_emit(buf, "%#lx\n", val);
}
static DEVICE_ATTR_RO(traceid);
static struct attribute *coresight_dummy_attrs[] = {
&dev_attr_traceid.attr,
NULL,
};
static const struct attribute_group coresight_dummy_group = {
.attrs = coresight_dummy_attrs,
};
static const struct attribute_group *coresight_dummy_groups[] = {
&coresight_dummy_group,
NULL,
};
static int dummy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -79,6 +107,11 @@ static int dummy_probe(struct platform_device *pdev)
struct coresight_platform_data *pdata;
struct dummy_drvdata *drvdata;
struct coresight_desc desc = { 0 };
int ret = 0, trace_id = 0;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
if (of_device_is_compatible(node, "arm,coresight-dummy-source")) {
@ -90,6 +123,26 @@ static int dummy_probe(struct platform_device *pdev)
desc.subtype.source_subtype =
CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS;
desc.ops = &dummy_source_cs_ops;
desc.groups = coresight_dummy_groups;
ret = coresight_get_static_trace_id(dev, &trace_id);
if (!ret) {
/* Get the static id if id is set in device tree. */
ret = coresight_trace_id_get_static_system_id(trace_id);
if (ret < 0) {
dev_err(dev, "Fail to get static id.\n");
return ret;
}
} else {
/* Get next available id if id is not set in device tree. */
trace_id = coresight_trace_id_get_system_id();
if (trace_id < 0) {
ret = trace_id;
return ret;
}
}
drvdata->traceid = (u8)trace_id;
} else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) {
desc.name = coresight_alloc_device_name(&sink_devs, dev);
if (!desc.name)
@ -104,27 +157,35 @@ static int dummy_probe(struct platform_device *pdev)
}
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
if (IS_ERR(pdata)) {
ret = PTR_ERR(pdata);
goto free_id;
}
pdev->dev.platform_data = pdata;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
desc.pdata = pdev->dev.platform_data;
desc.dev = &pdev->dev;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto free_id;
}
pm_runtime_enable(dev);
dev_dbg(dev, "Dummy device initialized\n");
return 0;
ret = 0;
goto out;
free_id:
if (IS_VALID_CS_TRACE_ID(drvdata->traceid))
coresight_trace_id_put_system_id(drvdata->traceid);
out:
return ret;
}
static void dummy_remove(struct platform_device *pdev)
@ -132,6 +193,8 @@ static void dummy_remove(struct platform_device *pdev)
struct dummy_drvdata *drvdata = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
if (IS_VALID_CS_TRACE_ID(drvdata->traceid))
coresight_trace_id_put_system_id(drvdata->traceid);
pm_runtime_disable(dev);
coresight_unregister(drvdata->csdev);
}

View File

@ -86,14 +86,14 @@ static int funnel_enable(struct coresight_device *csdev,
bool first_enable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
if (atomic_read(&in->dest_refcnt) == 0) {
if (in->dest_refcnt == 0) {
if (drvdata->base)
rc = dynamic_funnel_enable_hw(drvdata, in->dest_port);
if (!rc)
first_enable = true;
}
if (!rc)
atomic_inc(&in->dest_refcnt);
in->dest_refcnt++;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
@ -130,7 +130,7 @@ static void funnel_disable(struct coresight_device *csdev,
bool last_disable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
if (atomic_dec_return(&in->dest_refcnt) == 0) {
if (--in->dest_refcnt == 0) {
if (drvdata->base)
dynamic_funnel_disable_hw(drvdata, in->dest_port);
last_disable = true;

View File

@ -243,6 +243,27 @@ static int of_coresight_parse_endpoint(struct device *dev,
conn.dest_fwnode = fwnode_handle_get(rdev_fwnode);
conn.dest_port = rendpoint.port;
/*
* Get the firmware node of the filter source through the
* reference. This could be used to filter the source in
* building path.
*/
conn.filter_src_fwnode =
fwnode_find_reference(&ep->fwnode, "filter-source", 0);
if (IS_ERR(conn.filter_src_fwnode)) {
conn.filter_src_fwnode = NULL;
} else {
conn.filter_src_dev =
coresight_find_csdev_by_fwnode(conn.filter_src_fwnode);
if (conn.filter_src_dev &&
!coresight_is_device_source(conn.filter_src_dev)) {
dev_warn(dev, "port %d: Filter handle is not a trace source : %s\n",
conn.src_port, dev_name(&conn.filter_src_dev->dev));
conn.filter_src_dev = NULL;
conn.filter_src_fwnode = NULL;
}
}
new_conn = coresight_add_out_conn(dev, pdata, &conn);
if (IS_ERR_VALUE(new_conn)) {
fwnode_handle_put(conn.dest_fwnode);
@ -796,6 +817,12 @@ int coresight_get_cpu(struct device *dev)
}
EXPORT_SYMBOL_GPL(coresight_get_cpu);
int coresight_get_static_trace_id(struct device *dev, u32 *id)
{
return fwnode_property_read_u32(dev_fwnode(dev), "arm,static-trace-id", id);
}
EXPORT_SYMBOL_GPL(coresight_get_static_trace_id);
struct coresight_platform_data *
coresight_get_platform_data(struct device *dev)
{

View File

@ -126,7 +126,7 @@ static int replicator_enable(struct coresight_device *csdev,
bool first_enable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
if (atomic_read(&out->src_refcnt) == 0) {
if (out->src_refcnt == 0) {
if (drvdata->base)
rc = dynamic_replicator_enable(drvdata, in->dest_port,
out->src_port);
@ -134,7 +134,7 @@ static int replicator_enable(struct coresight_device *csdev,
first_enable = true;
}
if (!rc)
atomic_inc(&out->src_refcnt);
out->src_refcnt++;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (first_enable)
@ -180,7 +180,7 @@ static void replicator_disable(struct coresight_device *csdev,
bool last_disable = false;
spin_lock_irqsave(&drvdata->spinlock, flags);
if (atomic_dec_return(&out->src_refcnt) == 0) {
if (--out->src_refcnt == 0) {
if (drvdata->base)
dynamic_replicator_disable(drvdata, in->dest_port,
out->src_port);

View File

@ -24,7 +24,7 @@ DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
static bool coresight_device_is_tpdm(struct coresight_device *csdev)
{
return (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
return (coresight_is_device_source(csdev)) &&
(csdev->subtype.source_subtype ==
CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
}
@ -110,6 +110,16 @@ static int tpda_get_element_size(struct tpda_drvdata *drvdata,
csdev->pdata->in_conns[i]->dest_port != inport)
continue;
/*
* If this port has a hardcoded filter, use the source
* device directly.
*/
if (csdev->pdata->in_conns[i]->filter_src_fwnode) {
in = csdev->pdata->in_conns[i]->filter_src_dev;
if (!in)
continue;
}
if (coresight_device_is_tpdm(in)) {
if (drvdata->dsb_esize || drvdata->cmb_esize)
return -EEXIST;
@ -124,7 +134,6 @@ static int tpda_get_element_size(struct tpda_drvdata *drvdata,
}
}
return rc;
}
@ -190,10 +199,10 @@ static int tpda_enable(struct coresight_device *csdev,
int ret = 0;
spin_lock(&drvdata->spinlock);
if (atomic_read(&in->dest_refcnt) == 0) {
if (in->dest_refcnt == 0) {
ret = __tpda_enable(drvdata, in->dest_port);
if (!ret) {
atomic_inc(&in->dest_refcnt);
in->dest_refcnt++;
csdev->refcnt++;
dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
}
@ -223,7 +232,7 @@ static void tpda_disable(struct coresight_device *csdev,
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
if (atomic_dec_return(&in->dest_refcnt) == 0) {
if (--in->dest_refcnt == 0) {
__tpda_disable(drvdata, in->dest_port);
csdev->refcnt--;
}

View File

@ -640,8 +640,7 @@ static ssize_t dsb_mode_store(struct device *dev,
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if ((kstrtoul(buf, 0, &val)) || (val < 0) ||
(val & ~TPDM_DSB_MODE_MASK))
if ((kstrtoul(buf, 0, &val)) || (val & ~TPDM_DSB_MODE_MASK))
return -EINVAL;
spin_lock(&drvdata->spinlock);
@ -1308,8 +1307,8 @@ static void tpdm_remove(struct amba_device *adev)
*/
static struct amba_id tpdm_ids[] = {
{
.id = 0x000f0e00,
.mask = 0x000fff00,
.id = 0x001f0e00,
.mask = 0x00ffff00,
},
{ 0, 0, NULL },
};

View File

@ -12,6 +12,12 @@
#include "coresight-trace-id.h"
enum trace_id_flags {
TRACE_ID_ANY = 0x0,
TRACE_ID_PREFER_ODD = 0x1,
TRACE_ID_REQ_STATIC = 0x2,
};
/* Default trace ID map. Used in sysfs mode and for system sources */
static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0);
static struct coresight_trace_id_map id_map_default = {
@ -74,21 +80,25 @@ static int coresight_trace_id_find_odd_id(struct coresight_trace_id_map *id_map)
* Otherwise allocate next available ID.
*/
static int coresight_trace_id_alloc_new_id(struct coresight_trace_id_map *id_map,
int preferred_id, bool prefer_odd_id)
int preferred_id, unsigned int flags)
{
int id = 0;
/* for backwards compatibility, cpu IDs may use preferred value */
if (IS_VALID_CS_TRACE_ID(preferred_id) &&
!test_bit(preferred_id, id_map->used_ids)) {
id = preferred_id;
goto trace_id_allocated;
} else if (prefer_odd_id) {
if (IS_VALID_CS_TRACE_ID(preferred_id)) {
if (!test_bit(preferred_id, id_map->used_ids)) {
id = preferred_id;
goto trace_id_allocated;
} else if (flags & TRACE_ID_REQ_STATIC)
return -EBUSY;
} else if (flags & TRACE_ID_PREFER_ODD) {
/* may use odd ids to avoid preferred legacy cpu IDs */
id = coresight_trace_id_find_odd_id(id_map);
if (id)
goto trace_id_allocated;
}
} else if (!IS_VALID_CS_TRACE_ID(preferred_id) &&
(flags & TRACE_ID_REQ_STATIC))
return -EINVAL;
/*
* skip reserved bit 0, look at bitmap length of
@ -153,7 +163,7 @@ static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map
*/
id = coresight_trace_id_alloc_new_id(id_map,
CORESIGHT_LEGACY_CPU_TRACE_ID(cpu),
false);
TRACE_ID_ANY);
if (!IS_VALID_CS_TRACE_ID(id))
goto get_cpu_id_out_unlock;
@ -188,14 +198,14 @@ static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_ma
DUMP_ID_MAP(id_map);
}
static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *id_map)
static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *id_map,
int preferred_id, unsigned int traceid_flags)
{
unsigned long flags;
int id;
spin_lock_irqsave(&id_map->lock, flags);
/* prefer odd IDs for system components to avoid legacy CPU IDS */
id = coresight_trace_id_alloc_new_id(id_map, 0, true);
id = coresight_trace_id_alloc_new_id(id_map, preferred_id, traceid_flags);
spin_unlock_irqrestore(&id_map->lock, flags);
DUMP_ID(id);
@ -255,10 +265,19 @@ EXPORT_SYMBOL_GPL(coresight_trace_id_read_cpu_id_map);
int coresight_trace_id_get_system_id(void)
{
return coresight_trace_id_map_get_system_id(&id_map_default);
/* prefer odd IDs for system components to avoid legacy CPU IDS */
return coresight_trace_id_map_get_system_id(&id_map_default, 0,
TRACE_ID_PREFER_ODD);
}
EXPORT_SYMBOL_GPL(coresight_trace_id_get_system_id);
int coresight_trace_id_get_static_system_id(int trace_id)
{
return coresight_trace_id_map_get_system_id(&id_map_default,
trace_id, TRACE_ID_REQ_STATIC);
}
EXPORT_SYMBOL_GPL(coresight_trace_id_get_static_system_id);
void coresight_trace_id_put_system_id(int id)
{
coresight_trace_id_map_put_system_id(&id_map_default, id);

View File

@ -116,6 +116,15 @@ int coresight_trace_id_read_cpu_id_map(int cpu, struct coresight_trace_id_map *i
*/
int coresight_trace_id_get_system_id(void);
/**
* Allocate a CoreSight static trace ID for a system component.
*
* Used to allocate static IDs for system trace sources such as dummy source.
*
* return: Trace ID or -EINVAL if allocation is impossible.
*/
int coresight_trace_id_get_static_system_id(int id);
/**
* Release an allocated system trace ID.
*

View File

@ -172,6 +172,9 @@ struct coresight_desc {
* @dest_dev: a @coresight_device representation of the component
connected to @src_port. NULL until the device is created
* @link: Representation of the connection as a sysfs link.
* @filter_src_fwnode: filter source component's fwnode handle.
* @filter_src_dev: a @coresight_device representation of the component that
needs to be filtered.
*
* The full connection structure looks like this, where in_conns store
* references to same connection as the source device's out_conns.
@ -200,8 +203,10 @@ struct coresight_connection {
struct coresight_device *dest_dev;
struct coresight_sysfs_link *link;
struct coresight_device *src_dev;
atomic_t src_refcnt;
atomic_t dest_refcnt;
struct fwnode_handle *filter_src_fwnode;
struct coresight_device *filter_src_dev;
int src_refcnt;
int dest_refcnt;
};
/**
@ -588,9 +593,14 @@ static inline void csdev_access_write64(struct csdev_access *csa, u64 val, u32 o
}
#endif /* CONFIG_64BIT */
static inline bool coresight_is_device_source(struct coresight_device *csdev)
{
return csdev && (csdev->type == CORESIGHT_DEV_TYPE_SOURCE);
}
static inline bool coresight_is_percpu_source(struct coresight_device *csdev)
{
return csdev && (csdev->type == CORESIGHT_DEV_TYPE_SOURCE) &&
return csdev && coresight_is_device_source(csdev) &&
(csdev->subtype.source_subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_PROC);
}
@ -662,6 +672,7 @@ void coresight_relaxed_write64(struct coresight_device *csdev,
void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset);
extern int coresight_get_cpu(struct device *dev);
extern int coresight_get_static_trace_id(struct device *dev, u32 *id);
struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
struct coresight_connection *