Implement gtrace_perf_symlink() to let RISC-V Trace encoder link themselves to the gtrace PMU directory as "cpuX" based on their bound CPU. --- drivers/hwtracing/gtrace/gtrace-perf.c | 29 +++++++++++++++++-- .../hwtracing/gtrace/rvtrace-encoder-core.c | 10 +++++++ include/linux/gtrace.h | 2 ++ 3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/gtrace/gtrace-perf.c b/drivers/hwtracing/gtrace/gtrace-perf.c index 2fcfbae9acf6..604b673a29d5 100644 --- a/drivers/hwtracing/gtrace/gtrace-perf.c +++ b/drivers/hwtracing/gtrace/gtrace-perf.c @@ -23,6 +23,7 @@ #define GTRACE_PMU_NAME "gtrace" static struct pmu gtrace_pmu; static struct workqueue_struct *gtrace_wq; +static bool gtrace_perf_up;
/** * struct gtrace_event_data - generic hardware trace perf event data @@ -351,6 +352,27 @@ static const struct attribute_group *gtrace_pmu_attr_groups[] = { NULL, };
+int gtrace_perf_symlink(struct gtrace_component *comp, bool link) +{ + char entry[sizeof("cpu9999999")]; + int ret = 0, cpu = comp->pdata->bound_cpu; + struct device *pmu_dev = gtrace_pmu.dev; + struct device *comp_dev = &comp->dev; + + sprintf(entry, "cpu%d", cpu); + + if (!gtrace_perf_up) + return -EPROBE_DEFER; + + if (link) + ret = sysfs_create_link(&pmu_dev->kobj, &comp_dev->kobj, entry); + else + sysfs_remove_link(&pmu_dev->kobj, entry); + + return ret; +} +EXPORT_SYMBOL_GPL(gtrace_perf_symlink); + int __init gtrace_perf_init(void) { int ret; @@ -373,10 +395,13 @@ int __init gtrace_perf_init(void) return -ENOMEM;
ret = perf_pmu_register(>race_pmu, GTRACE_PMU_NAME, -1); - if (ret) + if (ret) { destroy_workqueue(gtrace_wq); + return ret; + }
- return ret; + gtrace_perf_up = true; + return 0; }
void __exit gtrace_perf_exit(void) diff --git a/drivers/hwtracing/gtrace/rvtrace-encoder-core.c b/drivers/hwtracing/gtrace/rvtrace-encoder-core.c index 817535ff9558..17a3dde1314c 100644 --- a/drivers/hwtracing/gtrace/rvtrace-encoder-core.c +++ b/drivers/hwtracing/gtrace/rvtrace-encoder-core.c @@ -129,6 +129,10 @@ static int rvtrace_encoder_probe(struct gtrace_component *comp) } dev_set_drvdata(&comp->dev, priv);
+ ret = gtrace_perf_symlink(comp, true); + if (ret) + return ret; + if (boot_enable) { ret = gtrace_enable_sysfs(comp); if (ret) { @@ -140,6 +144,11 @@ static int rvtrace_encoder_probe(struct gtrace_component *comp) return 0; }
+static void rvtrace_encoder_remove(struct gtrace_component *comp) +{ + gtrace_perf_symlink(comp, false); +} + static void rvtrace_encoder_parse_event_config(struct rvtrace_encoder_priv *priv, struct perf_event *event) { @@ -240,6 +249,7 @@ static const struct gtrace_component_id rvtrace_encoder_ids[] = { static struct gtrace_driver rvtrace_encoder_driver = { .id_table = rvtrace_encoder_ids, .probe = rvtrace_encoder_probe, + .remove = rvtrace_encoder_remove, .start = rvtrace_encoder_start, .stop = rvtrace_encoder_stop, .driver = { diff --git a/include/linux/gtrace.h b/include/linux/gtrace.h index 3d769b405030..4bbe5ac835ec 100644 --- a/include/linux/gtrace.h +++ b/include/linux/gtrace.h @@ -437,4 +437,6 @@ int gtrace_disable_sysfs(struct gtrace_component *comp); int gtrace_sysfs_add(struct gtrace_component *comp); void gtrace_sysfs_remove(struct gtrace_component *comp);
+int gtrace_perf_symlink(struct gtrace_component *comp, bool link); + #endif /* __LINUX_GTRACE_H__ */