Add a callback in the source device that returns a boolean indicating whether context save and restore operations are required. The save and restore flow is skipped if the callback returns false.
The ETMv4 driver implements its own version's callback.
Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-core.c | 16 +++++++++++- drivers/hwtracing/coresight/coresight-etm4x-core.c | 30 +++++++++++++++++----- include/linux/coresight.h | 2 ++ 3 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index f944a610c85e9e3fce43497543ccc48ab7c2c0d9..94803cacf1a374ae8a3b9513d7d029d5c77d5925 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -423,6 +423,20 @@ int coresight_resume_source(struct coresight_device *csdev) } EXPORT_SYMBOL_GPL(coresight_resume_source);
+static bool coresight_need_save_restore_source(struct coresight_device *csdev) +{ + if (!csdev) + return false; + + if (source_ops(csdev)->need_context_save_restore) + return source_ops(csdev)->need_context_save_restore(csdev); + + if (coresight_get_mode(csdev)) + return true; + + return false; +} + static int coresight_save_source(struct coresight_device *csdev) { if (csdev && source_ops(csdev)->save) @@ -1597,7 +1611,7 @@ static int coresight_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, unsigned int cpu = smp_processor_id(); struct coresight_device *source = per_cpu(csdev_source, cpu);
- if (!source) + if (!coresight_need_save_restore_source(source)) return NOTIFY_OK;
switch (cmd) { diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c index ec7e8d09ce58d62dac826fba9edafc967504a1a5..66aefdb002f075446572df9c4eed9093da19a066 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c @@ -1839,6 +1839,21 @@ static int etm4_dying_cpu(unsigned int cpu) return 0; }
+static bool etm4_need_context_save_restore(struct coresight_device *csdev) +{ + if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED) + return false; + + /* + * Save and restore the ETM Trace registers only if + * the ETM is active. + */ + if (coresight_get_mode(csdev)) + return true; + + return false; +} + static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) { int ret = 0; @@ -1927,13 +1942,14 @@ static void etm4_cpu_restore(struct coresight_device *csdev) }
static const struct coresight_ops_source etm4_source_ops = { - .cpu_id = etm4_cpu_id, - .enable = etm4_enable, - .disable = etm4_disable, - .resume_perf = etm4_resume_perf, - .pause_perf = etm4_pause_perf, - .save = etm4_cpu_save, - .restore = etm4_cpu_restore, + .cpu_id = etm4_cpu_id, + .enable = etm4_enable, + .disable = etm4_disable, + .resume_perf = etm4_resume_perf, + .pause_perf = etm4_pause_perf, + .save = etm4_cpu_save, + .restore = etm4_cpu_restore, + .need_context_save_restore = etm4_need_context_save_restore, };
static const struct coresight_ops etm4_cs_ops = { diff --git a/include/linux/coresight.h b/include/linux/coresight.h index d0764a9c7692181d2619c277acb83701c6b0115e..39781ba24ee2ad9f3065770409aafb0e5af57fa8 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -400,6 +400,7 @@ struct coresight_ops_link { * @disable: disables tracing for a source. * @resume_perf: resumes tracing for a source in perf session. * @pause_perf: pauses tracing for a source in perf session. + * @need_context_save_restore: if need to save and restore context. * @save: save context for a source. * @restore: restore context for a source. */ @@ -411,6 +412,7 @@ struct coresight_ops_source { struct perf_event *event); int (*resume_perf)(struct coresight_device *csdev); void (*pause_perf)(struct coresight_device *csdev); + bool (*need_context_save_restore)(struct coresight_device *csdev); int (*save)(struct coresight_device *csdev); void (*restore)(struct coresight_device *csdev); };