]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
coresight: etm4x: Hook CPU PM callbacks
authorLeo Yan <leo.yan@arm.com>
Fri, 15 May 2026 20:08:19 +0000 (21:08 +0100)
committerSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 18 May 2026 09:18:45 +0000 (10:18 +0100)
Add a helper etm4_pm_save_needed() to detect if need save context for
self-hosted PM mode and hook pm_save_disable() and pm_restore_enable()
callbacks through etm4_cs_pm_ops structure.  With this, ETMv4 PM
save/restore is integrated into the core layer's CPU PM.

Organize etm4_cs_ops and etm4_cs_pm_ops together for more readable.

The CPU PM notifier in the ETMv4 driver is no longer needed, remove it
along with its registration and unregistration code.

Reviewed-by: James Clark <james.clark@linaro.org>
Tested-by: James Clark <james.clark@linaro.org>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Tested-by: Jie Gan <jie.gan@oss.qualcomm.com>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20260515-arm_coresight_path_power_management_improvement-v14-12-f88c4a3ecfe9@arm.com
drivers/hwtracing/coresight/coresight-etm4x-core.c

index 7011a20d20042cfbeaac51797cd8592275bbf1ca..5cd70f0f3710a5ec6406a89c034d30230f782b13 100644 (file)
@@ -1195,11 +1195,6 @@ static const struct coresight_ops_source etm4_source_ops = {
        .pause_perf     = etm4_pause_perf,
 };
 
-static const struct coresight_ops etm4_cs_ops = {
-       .trace_id       = coresight_etm_get_trace_id,
-       .source_ops     = &etm4_source_ops,
-};
-
 static bool cpu_supports_sysreg_trace(void)
 {
        u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
@@ -1853,6 +1848,11 @@ static int etm4_dying_cpu(unsigned int cpu)
        return 0;
 }
 
+static inline bool etm4_pm_save_needed(struct etmv4_drvdata *drvdata)
+{
+       return !!drvdata->save_state;
+}
+
 static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
 {
        int i, ret = 0;
@@ -1995,11 +1995,12 @@ out:
        return ret;
 }
 
-static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
+static int etm4_cpu_save(struct coresight_device *csdev)
 {
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
        int ret = 0;
 
-       if (!drvdata->save_state)
+       if (!etm4_pm_save_needed(drvdata))
                return 0;
 
        /*
@@ -2112,47 +2113,27 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
        etm4_cs_lock(drvdata, csa);
 }
 
-static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
+static void etm4_cpu_restore(struct coresight_device *csdev)
 {
-       if (!drvdata->save_state)
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       if (!etm4_pm_save_needed(drvdata))
                return;
 
        if (coresight_get_mode(drvdata->csdev))
                __etm4_cpu_restore(drvdata);
 }
 
-static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
-                             void *v)
-{
-       struct etmv4_drvdata *drvdata;
-       unsigned int cpu = smp_processor_id();
-
-       if (!etmdrvdata[cpu])
-               return NOTIFY_OK;
-
-       drvdata = etmdrvdata[cpu];
-
-       if (WARN_ON_ONCE(drvdata->cpu != cpu))
-               return NOTIFY_BAD;
-
-       switch (cmd) {
-       case CPU_PM_ENTER:
-               if (etm4_cpu_save(drvdata))
-                       return NOTIFY_BAD;
-               break;
-       case CPU_PM_EXIT:
-       case CPU_PM_ENTER_FAILED:
-               etm4_cpu_restore(drvdata);
-               break;
-       default:
-               return NOTIFY_DONE;
-       }
-
-       return NOTIFY_OK;
-}
+static const struct coresight_ops etm4_cs_ops = {
+       .trace_id       = coresight_etm_get_trace_id,
+       .source_ops     = &etm4_source_ops,
+};
 
-static struct notifier_block etm4_cpu_pm_nb = {
-       .notifier_call = etm4_cpu_pm_notify,
+static const struct coresight_ops etm4_cs_pm_ops = {
+       .trace_id               = coresight_etm_get_trace_id,
+       .source_ops             = &etm4_source_ops,
+       .pm_save_disable        = etm4_cpu_save,
+       .pm_restore_enable      = etm4_cpu_restore,
 };
 
 /* Setup PM. Deals with error conditions and counts */
@@ -2160,16 +2141,12 @@ static int __init etm4_pm_setup(void)
 {
        int ret;
 
-       ret = cpu_pm_register_notifier(&etm4_cpu_pm_nb);
-       if (ret)
-               return ret;
-
        ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
                                        "arm/coresight4:starting",
                                        etm4_starting_cpu, etm4_dying_cpu);
 
        if (ret)
-               goto unregister_notifier;
+               return ret;
 
        ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
                                        "arm/coresight4:online",
@@ -2183,15 +2160,11 @@ static int __init etm4_pm_setup(void)
 
        /* failed dyn state - remove others */
        cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
-
-unregister_notifier:
-       cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
        return ret;
 }
 
 static void etm4_pm_clear(void)
 {
-       cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
        cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
        if (hp_online) {
                cpuhp_remove_state_nocalls(hp_online);
@@ -2270,7 +2243,7 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
 
        desc.type = CORESIGHT_DEV_TYPE_SOURCE;
        desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
-       desc.ops = &etm4_cs_ops;
+       desc.ops = etm4_pm_save_needed(drvdata) ? &etm4_cs_pm_ops : &etm4_cs_ops;
        desc.pdata = pdata;
        desc.dev = dev;
        desc.groups = coresight_etmv4_groups;