Move the per-CPU source pointer from ETM perf to the core layer, as this will be used for not only perf session and also for CPU PM notifiers.
Provides coresight_{set|clear|get}_percpu_source() helpers to access the per-CPU source pointer. Add a raw spinlock to protect exclusive access.
Device registration and unregistration call the set and clear helpers for init and teardown the pointers.
Update callers to invoke coresight_get_percpu_source() for retrieving the pointer.
Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-core.c | 32 ++++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-etm-perf.c | 21 +++++++--------- drivers/hwtracing/coresight/coresight-priv.h | 1 + 3 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 5639c8a2124d97148525c3267dacd86510da7a20..df1ea642df7204aeb41c56c2751d0f3a00bbf7a4 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -35,6 +35,9 @@ DEFINE_MUTEX(coresight_mutex); static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
+static DEFINE_RAW_SPINLOCK(coresight_dev_lock); +static DEFINE_PER_CPU(struct coresight_device *, csdev_source); + /** * struct coresight_node - elements of a path, from source to sink * @csdev: Address of an element. @@ -82,6 +85,33 @@ struct coresight_device *coresight_get_percpu_sink(int cpu) } EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
+static void coresight_set_percpu_source(struct coresight_device *csdev) +{ + if (!csdev || !coresight_is_percpu_source(csdev)) + return; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + per_cpu(csdev_source, csdev->cpu) = csdev; +} + +static void coresight_clear_percpu_source(struct coresight_device *csdev) +{ + if (!csdev || !coresight_is_percpu_source(csdev)) + return; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + per_cpu(csdev_source, csdev->cpu) = NULL; +} + +struct coresight_device *coresight_get_percpu_source(int cpu) +{ + if (WARN_ON(cpu < 0)) + return NULL; + + guard(raw_spinlock_irqsave)(&coresight_dev_lock); + return per_cpu(csdev_source, cpu); +} + static struct coresight_device *coresight_get_source(struct coresight_path *path) { struct coresight_device *csdev; @@ -1403,6 +1433,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) if (ret) goto out_unlock;
+ coresight_set_percpu_source(csdev); mutex_unlock(&coresight_mutex);
if (cti_assoc_ops && cti_assoc_ops->add) @@ -1432,6 +1463,7 @@ void coresight_unregister(struct coresight_device *csdev) cti_assoc_ops->remove(csdev);
mutex_lock(&coresight_mutex); + coresight_clear_percpu_source(csdev); etm_perf_del_symlink_sink(csdev); coresight_remove_conns(csdev); coresight_clear_default_sink(csdev); diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index cae6738e9906c35d291e4b0f3feae37306b95c06..a2c1c876099d1f5dacf039d733b78827296d9c2e 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -49,7 +49,6 @@ struct etm_ctxt { };
static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt); -static DEFINE_PER_CPU(struct coresight_device *, csdev_src);
GEN_PMU_FORMAT_ATTR(cycacc); GEN_PMU_FORMAT_ATTR(timestamp); @@ -356,7 +355,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, struct coresight_path *path; struct coresight_device *csdev;
- csdev = per_cpu(csdev_src, cpu); + csdev = coresight_get_percpu_source(cpu); /* * If there is no ETM associated with this CPU clear it from * the mask and continue with the rest. If ever we try to trace @@ -479,10 +478,11 @@ static void etm_event_start(struct perf_event *event, int flags) struct etm_event_data *event_data; struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt); struct perf_output_handle *handle = &ctxt->handle; - struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); + struct coresight_device *sink, *csdev; struct coresight_path *path; u64 hw_id;
+ csdev = coresight_get_percpu_source(cpu); if (!csdev) goto fail;
@@ -630,12 +630,14 @@ static void etm_event_stop(struct perf_event *event, int mode) { int cpu = smp_processor_id(); unsigned long size; - struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); + struct coresight_device *sink, *csdev; struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt); struct perf_output_handle *handle = &ctxt->handle; struct etm_event_data *event_data; struct coresight_path *path;
+ csdev = coresight_get_percpu_source(cpu); + if (mode & PERF_EF_PAUSE) return etm_event_pause(event, csdev, ctxt);
@@ -833,17 +835,12 @@ int etm_perf_symlink(struct coresight_device *csdev, bool link) if (!etm_perf_up) return -EPROBE_DEFER;
- if (link) { + if (link) ret = sysfs_create_link(&pmu_dev->kobj, &cs_dev->kobj, entry); - if (ret) - return ret; - per_cpu(csdev_src, cpu) = csdev; - } else { + else sysfs_remove_link(&pmu_dev->kobj, entry); - per_cpu(csdev_src, cpu) = NULL; - }
- return 0; + return ret; } EXPORT_SYMBOL_GPL(etm_perf_symlink);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 1ea882dffd703b2873e41b4ce0c2564d2ce9bbad..c96d63657f9334be890cca2320abbb8cbd807802 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -248,6 +248,7 @@ void coresight_add_helper(struct coresight_device *csdev,
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); struct coresight_device *coresight_get_percpu_sink(int cpu); +struct coresight_device *coresight_get_percpu_source(int cpu); void coresight_disable_source(struct coresight_device *csdev, void *data); void coresight_pause_source(struct coresight_device *csdev); int coresight_resume_source(struct coresight_device *csdev);