From: lorenzo.pieralisi@arm.com (Lorenzo Pieralisi)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] drivers: perf: arm: implement CPU_PM notifier
Date: Wed, 24 Feb 2016 17:35:11 +0000 [thread overview]
Message-ID: <20160224173511.GF25385@red-moon> (raw)
In-Reply-To: <CANLsYkzvB0GbPeYHrcLtUz8DMHJh4FA5RVwVZ-UAm3BCznB_3w@mail.gmail.com>
On Wed, Feb 24, 2016 at 09:20:22AM -0700, Mathieu Poirier wrote:
> On 23 February 2016 at 11:22, Lorenzo Pieralisi
[...]
> > +static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
> > + void *v)
> > +{
> > + struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
> > + struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
> > + int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
> > +
> > + if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
> > + return NOTIFY_DONE;
> > +
> > + /*
> > + * Always reset the PMU registers on power-up even if
> > + * there are no events running.
> > + */
> > + if (cmd == CPU_PM_EXIT && armpmu->reset)
> > + armpmu->reset(armpmu);
>
> I think this patch does the right thing but I can't get the above
> reset. Wouldn't it be better to do the reset as part of the
> CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
> go back down before the event is enabled, wasting the cycle needed to
> reset the PMU.
The logic goes, if the cpu is woken up and it has no events enabled,
if we do not reset it (mind, ->reset here sets the PMU register values
to a sane default, some of them are architecturally UNKNOWN on reset, it
does NOT reset the PMU) _and_ we subsequently install an event on it we
do have a problem, that's why whenever a core gets out of low-power we
have to reset its pmu.
Does it make sense ?
Thanks,
Lorenzo
>
> Thanks,
> Mathieu
>
> > +
> > + if (!enabled)
> > + return NOTIFY_OK;
> > +
> > + switch (cmd) {
> > + case CPU_PM_ENTER:
> > + armpmu->stop(armpmu);
> > + cpu_pm_pmu_setup(armpmu, cmd);
> > + break;
> > + case CPU_PM_EXIT:
> > + cpu_pm_pmu_setup(armpmu, cmd);
> > + case CPU_PM_ENTER_FAILED:
> > + armpmu->start(armpmu);
> > + break;
> > + default:
> > + return NOTIFY_DONE;
> > + }
> > +
> > + return NOTIFY_OK;
> > +}
> > +
> > +static int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu)
> > +{
> > + cpu_pmu->cpu_pm_nb.notifier_call = cpu_pm_pmu_notify;
> > + return cpu_pm_register_notifier(&cpu_pmu->cpu_pm_nb);
> > +}
> > +
> > +static void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu)
> > +{
> > + cpu_pm_unregister_notifier(&cpu_pmu->cpu_pm_nb);
> > +}
> > +#else
> > +static inline int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu) { return 0; }
> > +static inline void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu) { }
> > +#endif
> > +
> > static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
> > {
> > int err;
> > @@ -725,6 +813,10 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
> > if (err)
> > goto out_hw_events;
> >
> > + err = cpu_pm_pmu_register(cpu_pmu);
> > + if (err)
> > + goto out_unregister;
> > +
> > for_each_possible_cpu(cpu) {
> > struct pmu_hw_events *events = per_cpu_ptr(cpu_hw_events, cpu);
> > raw_spin_lock_init(&events->pmu_lock);
> > @@ -746,6 +838,8 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
> >
> > return 0;
> >
> > +out_unregister:
> > + unregister_cpu_notifier(&cpu_pmu->hotplug_nb);
> > out_hw_events:
> > free_percpu(cpu_hw_events);
> > return err;
> > @@ -753,6 +847,7 @@ out_hw_events:
> >
> > static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
> > {
> > + cpu_pm_pmu_unregister(cpu_pmu);
> > unregister_cpu_notifier(&cpu_pmu->hotplug_nb);
> > free_percpu(cpu_pmu->hw_events);
> > }
> > diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
> > index 83b5e34..9ffa316 100644
> > --- a/include/linux/perf/arm_pmu.h
> > +++ b/include/linux/perf/arm_pmu.h
> > @@ -107,6 +107,7 @@ struct arm_pmu {
> > struct platform_device *plat_device;
> > struct pmu_hw_events __percpu *hw_events;
> > struct notifier_block hotplug_nb;
> > + struct notifier_block cpu_pm_nb;
> > };
> >
> > #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
> > --
> > 2.5.1
> >
>
next prev parent reply other threads:[~2016-02-24 17:35 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-23 18:22 [PATCH] drivers: perf: arm: implement CPU_PM notifier Lorenzo Pieralisi
2016-02-24 16:20 ` Mathieu Poirier
2016-02-24 17:35 ` Lorenzo Pieralisi [this message]
2016-02-24 19:53 ` Ashwin Chaugule
2016-02-24 22:31 ` Lorenzo Pieralisi
2016-02-26 0:22 ` Ashwin Chaugule
2016-02-25 16:37 ` Mathieu Poirier
2016-02-25 1:10 ` Kevin Hilman
2016-02-25 9:44 ` Lorenzo Pieralisi
2016-02-25 16:32 ` Mathieu Poirier
2016-02-25 16:43 ` Will Deacon
2016-02-25 18:46 ` Lorenzo Pieralisi
2016-02-25 21:55 ` Kevin Hilman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160224173511.GF25385@red-moon \
--to=lorenzo.pieralisi@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).