Skip to content

Commit 5ad628a

Browse files
James-A-ClarkSuzuki K Poulose
authored andcommitted
coresight: Use per-sink trace ID maps for Perf sessions
This will allow sessions with more than CORESIGHT_TRACE_IDS_MAX ETMs as long as there are fewer than that many ETMs connected to each sink. Each sink owns its own trace ID map, and any Perf session connecting to that sink will allocate from it, even if the sink is currently in use by other users. This is similar to the existing behavior where the dynamic trace IDs are constant as long as there is any concurrent Perf session active. It's not completely optimal because slightly more IDs will be used than necessary, but the optimal solution involves tracking the PIDs of each session and allocating ID maps based on the session owner. This is difficult to do with the combination of per-thread and per-cpu modes and some scheduling issues. The complexity of this isn't likely to worth it because even with multiple users they'd just see a difference in the ordering of ID allocations rather than hitting any limits (unless the hardware does have too many ETMs connected to one sink). Signed-off-by: James Clark <[email protected]> Reviewed-by: Mike Leach <[email protected]> Signed-off-by: James Clark <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d53c825 commit 5ad628a

File tree

9 files changed

+40
-18
lines changed

9 files changed

+40
-18
lines changed

drivers/hwtracing/coresight/coresight-core.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,7 @@ static void coresight_device_release(struct device *dev)
902902
struct coresight_device *csdev = to_coresight_device(dev);
903903

904904
fwnode_handle_put(csdev->dev.fwnode);
905+
free_percpu(csdev->perf_sink_id_map.cpu_map);
905906
kfree(csdev);
906907
}
907908

@@ -1159,6 +1160,15 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
11591160
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
11601161
dev_set_name(&csdev->dev, "%s", desc->name);
11611162

1163+
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
1164+
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
1165+
csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
1166+
if (!csdev->perf_sink_id_map.cpu_map) {
1167+
kfree(csdev);
1168+
ret = -ENOMEM;
1169+
goto err_out;
1170+
}
1171+
}
11621172
/*
11631173
* Make sure the device registration and the connection fixup
11641174
* are synchronised, so that we don't see uninitialised devices

drivers/hwtracing/coresight/coresight-dummy.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
2121
DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
2222

2323
static int dummy_source_enable(struct coresight_device *csdev,
24-
struct perf_event *event, enum cs_mode mode)
24+
struct perf_event *event, enum cs_mode mode,
25+
__maybe_unused struct coresight_trace_id_map *id_map)
2526
{
2627
if (!coresight_take_mode(csdev, mode))
2728
return -EBUSY;

drivers/hwtracing/coresight/coresight-etm-perf.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,13 @@ static void free_event_data(struct work_struct *work)
229229
struct list_head **ppath;
230230

231231
ppath = etm_event_cpu_path_ptr(event_data, cpu);
232-
if (!(IS_ERR_OR_NULL(*ppath)))
232+
if (!(IS_ERR_OR_NULL(*ppath))) {
233+
struct coresight_device *sink = coresight_get_sink(*ppath);
234+
235+
coresight_trace_id_put_cpu_id_map(cpu, &sink->perf_sink_id_map);
233236
coresight_release_path(*ppath);
237+
}
234238
*ppath = NULL;
235-
coresight_trace_id_put_cpu_id(cpu);
236239
}
237240

238241
/* mark perf event as done for trace id allocator */
@@ -401,7 +404,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
401404
}
402405

403406
/* ensure we can allocate a trace ID for this CPU */
404-
trace_id = coresight_trace_id_get_cpu_id(cpu);
407+
trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
405408
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
406409
cpumask_clear_cpu(cpu, mask);
407410
coresight_release_path(path);
@@ -495,7 +498,8 @@ static void etm_event_start(struct perf_event *event, int flags)
495498
goto fail_end_stop;
496499

497500
/* Finally enable the tracer */
498-
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
501+
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF,
502+
&sink->perf_sink_id_map))
499503
goto fail_disable_path;
500504

501505
/*
@@ -507,7 +511,8 @@ static void etm_event_start(struct perf_event *event, int flags)
507511
hw_id = FIELD_PREP(CS_AUX_HW_ID_VERSION_MASK,
508512
CS_AUX_HW_ID_CURR_VERSION);
509513
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK,
510-
coresight_trace_id_read_cpu_id(cpu));
514+
coresight_trace_id_read_cpu_id_map(cpu,
515+
&sink->perf_sink_id_map));
511516
perf_report_aux_output_id(event, hw_id);
512517
}
513518

drivers/hwtracing/coresight/coresight-etm3x-core.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ void etm_release_trace_id(struct etm_drvdata *drvdata)
481481
}
482482

483483
static int etm_enable_perf(struct coresight_device *csdev,
484-
struct perf_event *event)
484+
struct perf_event *event,
485+
struct coresight_trace_id_map *id_map)
485486
{
486487
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
487488
int trace_id;
@@ -500,7 +501,7 @@ static int etm_enable_perf(struct coresight_device *csdev,
500501
* with perf locks - we know the ID cannot change until perf shuts down
501502
* the session
502503
*/
503-
trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
504+
trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
504505
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
505506
dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
506507
dev_name(&drvdata->csdev->dev), drvdata->cpu);
@@ -553,7 +554,7 @@ static int etm_enable_sysfs(struct coresight_device *csdev)
553554
}
554555

555556
static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
556-
enum cs_mode mode)
557+
enum cs_mode mode, struct coresight_trace_id_map *id_map)
557558
{
558559
int ret;
559560
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -568,7 +569,7 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
568569
ret = etm_enable_sysfs(csdev);
569570
break;
570571
case CS_MODE_PERF:
571-
ret = etm_enable_perf(csdev, event);
572+
ret = etm_enable_perf(csdev, event, id_map);
572573
break;
573574
default:
574575
ret = -EINVAL;

drivers/hwtracing/coresight/coresight-etm4x-core.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,8 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
752752
}
753753

754754
static int etm4_enable_perf(struct coresight_device *csdev,
755-
struct perf_event *event)
755+
struct perf_event *event,
756+
struct coresight_trace_id_map *id_map)
756757
{
757758
int ret = 0, trace_id;
758759
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -775,7 +776,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
775776
* with perf locks - we know the ID cannot change until perf shuts down
776777
* the session
777778
*/
778-
trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
779+
trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
779780
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
780781
dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
781782
dev_name(&drvdata->csdev->dev), drvdata->cpu);
@@ -837,7 +838,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
837838
}
838839

839840
static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
840-
enum cs_mode mode)
841+
enum cs_mode mode, struct coresight_trace_id_map *id_map)
841842
{
842843
int ret;
843844

@@ -851,7 +852,7 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
851852
ret = etm4_enable_sysfs(csdev);
852853
break;
853854
case CS_MODE_PERF:
854-
ret = etm4_enable_perf(csdev, event);
855+
ret = etm4_enable_perf(csdev, event, id_map);
855856
break;
856857
default:
857858
ret = -EINVAL;

drivers/hwtracing/coresight/coresight-stm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ static void stm_enable_hw(struct stm_drvdata *drvdata)
194194
}
195195

196196
static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
197-
enum cs_mode mode)
197+
enum cs_mode mode,
198+
__maybe_unused struct coresight_trace_id_map *trace_id)
198199
{
199200
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
200201

drivers/hwtracing/coresight/coresight-sysfs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/kernel.h>
1010

1111
#include "coresight-priv.h"
12+
#include "coresight-trace-id.h"
1213

1314
/*
1415
* Use IDR to map the hash of the source's device name
@@ -63,7 +64,7 @@ static int coresight_enable_source_sysfs(struct coresight_device *csdev,
6364
*/
6465
lockdep_assert_held(&coresight_mutex);
6566
if (coresight_get_mode(csdev) != CS_MODE_SYSFS) {
66-
ret = source_ops(csdev)->enable(csdev, data, mode);
67+
ret = source_ops(csdev)->enable(csdev, data, mode, NULL);
6768
if (ret)
6869
return ret;
6970
}

drivers/hwtracing/coresight/coresight-tpdm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,8 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
439439
}
440440

441441
static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
442-
enum cs_mode mode)
442+
enum cs_mode mode,
443+
__maybe_unused struct coresight_trace_id_map *id_map)
443444
{
444445
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
445446

include/linux/coresight.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ struct coresight_device {
290290
bool sysfs_sink_activated;
291291
struct dev_ext_attribute *ea;
292292
struct coresight_device *def_sink;
293+
struct coresight_trace_id_map perf_sink_id_map;
293294
/* sysfs links between components */
294295
int nr_links;
295296
bool has_conns_grp;
@@ -384,7 +385,7 @@ struct coresight_ops_link {
384385
struct coresight_ops_source {
385386
int (*cpu_id)(struct coresight_device *csdev);
386387
int (*enable)(struct coresight_device *csdev, struct perf_event *event,
387-
enum cs_mode mode);
388+
enum cs_mode mode, struct coresight_trace_id_map *id_map);
388389
void (*disable)(struct coresight_device *csdev,
389390
struct perf_event *event);
390391
};

0 commit comments

Comments
 (0)