Skip to content

Commit 88850f7

Browse files
committed
Merge tag 'coresight-next-v6.12' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next
Suzuki writes: coresight: updates for Linux v6.12 CoreSight/hwtracing subsystem updates targeting Linux v6.12: - Miscellaneous fixes and cleanups - TraceID allocation per sink, allowing system with > 110 cores for perf tracing. Signed-off-by: Suzuki K Poulose <[email protected]> * tag 'coresight-next-v6.12' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux: coresight: Make trace ID map spinlock local to the map coresight: Emit sink ID in the HW_ID packets coresight: Remove pending trace ID release mechanism coresight: Use per-sink trace ID maps for Perf sessions coresight: Make CPU id map a property of a trace ID map coresight: Expose map arguments in trace ID API coresight: Move struct coresight_trace_id_map to common header coresight: Clarify comments around the PID of the sink owner coresight: Remove unused ETM Perf stubs coresight: tmc: sg: Do not leak sg_table Coresight: Set correct cs_mode for dummy source to fix disable issue Coresight: Set correct cs_mode for TPDM to fix disable issue coresight: cti: use device_* to iterate over device child nodes
2 parents f53835f + 988d40a commit 88850f7

17 files changed

+219
-188
lines changed

drivers/hwtracing/coresight/coresight-core.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -487,23 +487,25 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
487487
return csdev;
488488
}
489489

490+
u32 coresight_get_sink_id(struct coresight_device *csdev)
491+
{
492+
if (!csdev->ea)
493+
return 0;
494+
495+
/*
496+
* See function etm_perf_add_symlink_sink() to know where
497+
* this comes from.
498+
*/
499+
return (u32) (unsigned long) csdev->ea->var;
500+
}
501+
490502
static int coresight_sink_by_id(struct device *dev, const void *data)
491503
{
492504
struct coresight_device *csdev = to_coresight_device(dev);
493-
unsigned long hash;
494505

495506
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
496-
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
497-
498-
if (!csdev->ea)
499-
return 0;
500-
/*
501-
* See function etm_perf_add_symlink_sink() to know where
502-
* this comes from.
503-
*/
504-
hash = (unsigned long)csdev->ea->var;
505-
506-
if ((u32)hash == *(u32 *)data)
507+
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
508+
if (coresight_get_sink_id(csdev) == *(u32 *)data)
507509
return 1;
508510
}
509511

@@ -902,6 +904,7 @@ static void coresight_device_release(struct device *dev)
902904
struct coresight_device *csdev = to_coresight_device(dev);
903905

904906
fwnode_handle_put(csdev->dev.fwnode);
907+
free_percpu(csdev->perf_sink_id_map.cpu_map);
905908
kfree(csdev);
906909
}
907910

@@ -1159,6 +1162,16 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
11591162
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
11601163
dev_set_name(&csdev->dev, "%s", desc->name);
11611164

1165+
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
1166+
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
1167+
spin_lock_init(&csdev->perf_sink_id_map.lock);
1168+
csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
1169+
if (!csdev->perf_sink_id_map.cpu_map) {
1170+
kfree(csdev);
1171+
ret = -ENOMEM;
1172+
goto err_out;
1173+
}
1174+
}
11621175
/*
11631176
* Make sure the device registration and the connection fixup
11641177
* are synchronised, so that we don't see uninitialised devices

drivers/hwtracing/coresight/coresight-cti-platform.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -416,20 +416,16 @@ static int cti_plat_create_impdef_connections(struct device *dev,
416416
struct cti_drvdata *drvdata)
417417
{
418418
int rc = 0;
419-
struct fwnode_handle *fwnode = dev_fwnode(dev);
420-
struct fwnode_handle *child = NULL;
421419

422-
if (IS_ERR_OR_NULL(fwnode))
420+
if (IS_ERR_OR_NULL(dev_fwnode(dev)))
423421
return -EINVAL;
424422

425-
fwnode_for_each_child_node(fwnode, child) {
423+
device_for_each_child_node_scoped(dev, child) {
426424
if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
427-
rc = cti_plat_create_connection(dev, drvdata,
428-
child);
425+
rc = cti_plat_create_connection(dev, drvdata, child);
429426
if (rc != 0)
430427
break;
431428
}
432-
fwnode_handle_put(child);
433429

434430
return rc;
435431
}

drivers/hwtracing/coresight/coresight-dummy.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ 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
{
27+
if (!coresight_take_mode(csdev, mode))
28+
return -EBUSY;
29+
2630
dev_dbg(csdev->dev.parent, "Dummy source enabled\n");
2731

2832
return 0;
@@ -31,6 +35,7 @@ static int dummy_source_enable(struct coresight_device *csdev,
3135
static void dummy_source_disable(struct coresight_device *csdev,
3236
struct perf_event *event)
3337
{
38+
coresight_set_mode(csdev, CS_MODE_DISABLED);
3439
dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
3540
}
3641

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

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -229,15 +229,24 @@ 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+
/*
236+
* Mark perf event as done for trace id allocator, but don't call
237+
* coresight_trace_id_put_cpu_id_map() on individual IDs. Perf sessions
238+
* never free trace IDs to ensure that the ID associated with a CPU
239+
* cannot change during their and other's concurrent sessions. Instead,
240+
* a refcount is used so that the last event to call
241+
* coresight_trace_id_perf_stop() frees all IDs.
242+
*/
243+
coresight_trace_id_perf_stop(&sink->perf_sink_id_map);
244+
233245
coresight_release_path(*ppath);
246+
}
234247
*ppath = NULL;
235-
coresight_trace_id_put_cpu_id(cpu);
236248
}
237249

238-
/* mark perf event as done for trace id allocator */
239-
coresight_trace_id_perf_stop();
240-
241250
free_percpu(event_data->path);
242251
kfree(event_data);
243252
}
@@ -325,9 +334,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
325334
sink = user_sink = coresight_get_sink_by_id(id);
326335
}
327336

328-
/* tell the trace ID allocator that a perf event is starting up */
329-
coresight_trace_id_perf_start();
330-
331337
/* check if user wants a coresight configuration selected */
332338
cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
333339
if (cfg_hash) {
@@ -401,13 +407,14 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
401407
}
402408

403409
/* ensure we can allocate a trace ID for this CPU */
404-
trace_id = coresight_trace_id_get_cpu_id(cpu);
410+
trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
405411
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
406412
cpumask_clear_cpu(cpu, mask);
407413
coresight_release_path(path);
408414
continue;
409415
}
410416

417+
coresight_trace_id_perf_start(&sink->perf_sink_id_map);
411418
*etm_event_cpu_path_ptr(event_data, cpu) = path;
412419
}
413420

@@ -453,6 +460,7 @@ static void etm_event_start(struct perf_event *event, int flags)
453460
struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
454461
struct list_head *path;
455462
u64 hw_id;
463+
u8 trace_id;
456464

457465
if (!csdev)
458466
goto fail;
@@ -495,7 +503,8 @@ static void etm_event_start(struct perf_event *event, int flags)
495503
goto fail_end_stop;
496504

497505
/* Finally enable the tracer */
498-
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
506+
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF,
507+
&sink->perf_sink_id_map))
499508
goto fail_disable_path;
500509

501510
/*
@@ -504,10 +513,16 @@ static void etm_event_start(struct perf_event *event, int flags)
504513
*/
505514
if (!cpumask_test_cpu(cpu, &event_data->aux_hwid_done)) {
506515
cpumask_set_cpu(cpu, &event_data->aux_hwid_done);
507-
hw_id = FIELD_PREP(CS_AUX_HW_ID_VERSION_MASK,
508-
CS_AUX_HW_ID_CURR_VERSION);
509-
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK,
510-
coresight_trace_id_read_cpu_id(cpu));
516+
517+
trace_id = coresight_trace_id_read_cpu_id_map(cpu, &sink->perf_sink_id_map);
518+
519+
hw_id = FIELD_PREP(CS_AUX_HW_ID_MAJOR_VERSION_MASK,
520+
CS_AUX_HW_ID_MAJOR_VERSION);
521+
hw_id |= FIELD_PREP(CS_AUX_HW_ID_MINOR_VERSION_MASK,
522+
CS_AUX_HW_ID_MINOR_VERSION);
523+
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, trace_id);
524+
hw_id |= FIELD_PREP(CS_AUX_HW_ID_SINK_ID_MASK, coresight_get_sink_id(sink));
525+
511526
perf_report_aux_output_id(event, hw_id);
512527
}
513528

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ struct etm_event_data {
6262
struct list_head * __percpu *path;
6363
};
6464

65-
#if IS_ENABLED(CONFIG_CORESIGHT)
6665
int etm_perf_symlink(struct coresight_device *csdev, bool link);
6766
int etm_perf_add_symlink_sink(struct coresight_device *csdev);
6867
void etm_perf_del_symlink_sink(struct coresight_device *csdev);
@@ -77,23 +76,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
7776
int etm_perf_add_symlink_cscfg(struct device *dev,
7877
struct cscfg_config_desc *config_desc);
7978
void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc);
80-
#else
81-
static inline int etm_perf_symlink(struct coresight_device *csdev, bool link)
82-
{ return -EINVAL; }
83-
int etm_perf_add_symlink_sink(struct coresight_device *csdev)
84-
{ return -EINVAL; }
85-
void etm_perf_del_symlink_sink(struct coresight_device *csdev) {}
86-
static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
87-
{
88-
return NULL;
89-
}
90-
int etm_perf_add_symlink_cscfg(struct device *dev,
91-
struct cscfg_config_desc *config_desc)
92-
{ return -EINVAL; }
93-
void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc) {}
94-
95-
#endif /* CONFIG_CORESIGHT */
96-
9779
int __init etm_perf_init(void);
9880
void etm_perf_exit(void);
9981

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-priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ int coresight_make_links(struct coresight_device *orig,
148148
struct coresight_device *target);
149149
void coresight_remove_links(struct coresight_device *orig,
150150
struct coresight_connection *conn);
151+
u32 coresight_get_sink_id(struct coresight_device *csdev);
151152

152153
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
153154
extern int etm_readl_cp14(u32 off, unsigned int *val);

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
}

0 commit comments

Comments
 (0)