From: Mark Brown <broonie(a)linaro.org>
Another spin of the arm64 topology work - this should incorporate most
of the feedback from Lorenzo, there's a few things that were still under
discussion the main ones being:
- Should we have a smp_store_cpu_info(); like I say I like the errors
it generates for omitted cores and the reuse of the SMP enumeration
code (and cross-check with that I guess - make sure we don't get
confused about which CPUs are getting enabled).
- Should we update the binding to allow cores in the root cpu_map node
(since it's less effort in code and not a meaningful difference
semantically), warn if we find cores in the cpu_map node or actively
reject such DTs?
In both cases I don't much mind but I think what's there is reasonable
so I've left the code as-is pending further feedback. I also didn't
update the code to get more reuse of the iteration code, like I said I
did look at that when writing the code but couldn't find anything that
actually made things more pleasant but if someone has some ideas...
Everything else raised should be addressed I think.
Mark Brown (4):
arm64: topology: Implement basic CPU topology support
arm64: topology: Add support for topology DT bindings
arm64: topology: Tell the scheduler about the relative power of cores
arm64: topology: Provide relative power numbers for cores
arch/arm64/Kconfig | 24 +++
arch/arm64/include/asm/topology.h | 39 ++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/smp.c | 12 ++
arch/arm64/kernel/topology.c | 384 ++++++++++++++++++++++++++++++++++++++
5 files changed, 460 insertions(+)
create mode 100644 arch/arm64/include/asm/topology.h
create mode 100644 arch/arm64/kernel/topology.c
--
1.8.5.2
Hi Tushar / Samsung,
I am a bit confused on the interrupt number for CNTVIRQ..CNTHPIRQ. Can
you please help here.
As per the exynos5 public manual
What is the difference between  CPU_nCNTHPIRQ[0] and CNTHPIRQ.
While the later has an interrupt ID 26, the former is part of a group
with combined interrupt id as 33 for core 0 and 54 for core 1.
For a timer interrupt which goes to PL2, which id should be used 26 or
33 for core 0 ?
Please clear this confusion.
Many Thanks
There are several problems cpufreq stats in the way it handles
cpufreq_unregister_driver() and suspend/resume..
- We must not loose data collected so far when suspend/resume happens and so
stats directories must not be removed/allocated during these operations, Which
is done currently.
- cpufreq_stat has registered notifiers with both cpufreq and hotplug. It adds
sysfs stats directory with a cpufreq notifier: CPUFREQ_NOTIFY and removes this
directory with a notifier from hotplug core.
In case cpufreq_unregister_driver() is called (on rmmod cpufreq driver), stats
directories per cpu aren't removed as CPUs are still online. The only call
cpufreq_stats gets is cpufreq_stats_update_policy_cpu for all CPUs except the
last of each policy. And pointer to stat information is stored in the entry
for last cpu in per-cpu cpufreq_stats_table. But policy structure would be
freed inside cpufreq core and so that will result in memory leak inside
cpufreq stats (as we are never freeing memory for stats).
Now if we again insert the module cpufreq_register_driver() will be called and
we will again allocate stats data and put it on for first cpu of every policy.
In case we only have a single cpu per policy we will return with a error from
cpufreq_stats_create_table() due to below code:
if (per_cpu(cpufreq_stats_table, cpu))
return -EBUSY;
And so probably cpufreq stats directory would show up anymore (as it was added
inside last policies->kobj which doesn't exist anymore). I haven't tested it
though. Also the values in stats files wouldn't be refreshed as we are using
the earlier stats structure.
- CPUFREQ_NOTIFY is called from cpufreq_set_policy() which is called for
scenarios where we don't really want cpufreq_stat_notifier_policy() to get
called. For example whenever we are changing anything related to a policy:
min/max/current freq, etc.. cpufreq_set_policy() is called and so cpufreq
stats is notified. Where we don't do any useful stuff other than simply
returning with -EBUSY from cpufreq_stats_create_table(). And so this isn't the
right notifier that cpufreq stats..
Due to all above reasons this patch does following changes:
- Add new notifiers CPUFREQ_CREATE_POLICY and CPUFREQ_REMOVE_POLICY, which are
only called when policy is created/destroyed. They aren't called for
suspend/resume paths..
- Use these notifiers in cpufreq_stat_notifier_policy() to create/destory stats
sysfs entries. And so cpufreq_unregister_driver() or suspend/resume shouldn't
be a problem for cpufreq_stats.
- Return early from cpufreq_stat_cpu_callback() for suspend/resume sequence, so
that we don't free stats structure.
Acked-and-tested-by: Nicolas Pitre <nico(a)linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
drivers/cpufreq/cpufreq.c | 5 +++++
drivers/cpufreq/cpufreq_stats.c | 24 +++++++++++++++++-------
include/linux/cpufreq.h | 2 ++
3 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3509ca0..1afbe52 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -943,6 +943,9 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
struct kobject *kobj;
struct completion *cmp;
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_REMOVE_POLICY, policy);
+
down_read(&policy->rwsem);
kobj = &policy->kobj;
cmp = &policy->kobj_unregister;
@@ -1148,6 +1151,8 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
ret = cpufreq_add_dev_interface(policy, dev);
if (ret)
goto err_out_unregister;
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_CREATE_POLICY, policy);
}
write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 4cf0d28..0f71562 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -277,7 +277,7 @@ static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
unsigned long val, void *data)
{
- int ret;
+ int ret = 0;
struct cpufreq_policy *policy = data;
struct cpufreq_frequency_table *table;
unsigned int cpu = policy->cpu;
@@ -287,15 +287,21 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
return 0;
}
- if (val != CPUFREQ_NOTIFY)
- return 0;
table = cpufreq_frequency_get_table(cpu);
if (!table)
return 0;
- ret = cpufreq_stats_create_table(policy, table);
- if (ret)
- return ret;
- return 0;
+
+ if (val == CPUFREQ_CREATE_POLICY)
+ ret = cpufreq_stats_create_table(policy, table);
+ else if (val == CPUFREQ_REMOVE_POLICY) {
+ /* This might already be freed by cpu hotplug notifier */
+ if (per_cpu(cpufreq_stats_table, cpu)) {
+ cpufreq_stats_free_sysfs(cpu);
+ cpufreq_stats_free_table(cpu);
+ }
+ }
+
+ return ret;
}
static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
@@ -340,6 +346,10 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb,
{
unsigned int cpu = (unsigned long)hcpu;
+ /* Don't free/allocate stats during suspend/resume */
+ if (action & CPU_TASKS_FROZEN)
+ return 0;
+
switch (action) {
case CPU_DOWN_PREPARE:
cpufreq_stats_free_sysfs(cpu);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index aaf800e..bb727eb 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -308,6 +308,8 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
#define CPUFREQ_NOTIFY (2)
#define CPUFREQ_START (3)
#define CPUFREQ_UPDATE_POLICY_CPU (4)
+#define CPUFREQ_CREATE_POLICY (5)
+#define CPUFREQ_REMOVE_POLICY (6)
#ifdef CONFIG_CPU_FREQ
int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list);
--
1.7.12.rc2.18.g61b472e
Hi,
While reading the kernel logs for arm64 (as one does) I noticed a few
patches that seemed like candidates for either LTS or LTSI. I've also
had a couple of others mentioned via other routes. What do you think of
these?
4ecf7ccb1973 arm64: spinlock: retry trylock operation if strex fails on free lock
This seems like a correctness fix for spinlocks, though since the
callers should cope with failure it's arguably just an optimisation.
53ae3acd4390 arm64: Only enable local interrupts after the CPU is marked online
82b2f495fba3 arm64: virt: ensure visibility of __boot_cpu_mode
845ad05ec31e arm64: Change kernel stack size to 16K
6db83cea1c97 arm64: fix possible invalid FPSIMD initialization state
7b22c03536a5 arm64: check for number of arguments in syscall_get/set_arguments()
df503ba7f653 arm64: dts: Reserve the memory used for secondary CPU release address
These all look like correctness fixes of one kind or another; the change
to 16K stacks is poorly explained but it looks like it's fixing failures
of some kind.
f0dd718090ae arm64: Remove unused cpu_name ascii in arch/arm64/mm/proc.S
A user was reporting that this caused build failures due to alignment
issues with some of the debug options turned on. I've not fully
investigated yet, this might be a toolchain issue though given how
simple the change is.
0d651e4e65e9 clocksource: arch_timer: use virtual counters
This is as mentioned in the changelog a correctness fix for avoiding
clocks going backwards and has also been found to be required to avoid
boot hangs with CONFIG_PROVE_RCU_DELAY enabled.
There were also a few others that aren't entirely -stable material but
might be a fit for LTSI (and the above might be if not -stable in
themselves):
b5b6c9e9149d arm64: Avoid cache flushing in flush_dcache_page()
7249b79f6b4c arm64: Do not flush the D-cache for anonymous pages
4f00130b70e5 arm64: Use Normal NonCacheable memory for writecombine
These look like simple, localised optimisations.
Thanks,
Mark