This patch fixes incorrect range check for the number of PMU counters. This
caused the number of counters to be off-by-1.
Signed-off-by: Punit Agrawal <punit.agrawal(a)arm.com>
---
Hi Tixy,
I discovered an embarassing range check issue in the CCI driver. It would allow
only 3 of the 4 CCI PMU counters to be used. This patch fixes the issue.
Thanks,
Punit
drivers/misc/arm-cci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/misc/arm-cci.c b/drivers/misc/arm-cci.c
index 291413e..de50846 100644
--- a/drivers/misc/arm-cci.c
+++ b/drivers/misc/arm-cci.c
@@ -171,7 +171,7 @@ static int cci_pmu_get_event_idx(struct pmu_hw_events *hw, struct perf_event *ev
return CCI400_PMU_CYCLE_COUNTER_IDX;
}
- for (idx = CCI400_PMU_COUNTER0_IDX; idx < CCI400_PMU_COUNTER_LAST(cci_pmu); ++idx) {
+ for (idx = CCI400_PMU_COUNTER0_IDX; idx <= CCI400_PMU_COUNTER_LAST(cci_pmu); ++idx) {
if (!test_and_set_bit(idx, hw->used_mask))
return idx;
}
@@ -239,7 +239,7 @@ static irqreturn_t cci_pmu_handle_irq(int irq_num, void *dev)
/* Iterate over counters and update the corresponding perf events.
This should work regardless of whether we have per-counter overflow
interrupt or a combined overflow interrupt. */
- for (idx = CCI400_PMU_CYCLE_COUNTER_IDX; idx < CCI400_PMU_COUNTER_LAST(cci_pmu); idx++) {
+ for (idx = CCI400_PMU_CYCLE_COUNTER_IDX; idx <= CCI400_PMU_COUNTER_LAST(cci_pmu); idx++) {
struct perf_event *event = events->events[idx];
struct hw_perf_event *hw_counter;
--
1.7.9.5
Hello
As some of you know I created a team of ARM Chromebook hackers on
Launchpad. We concentrate on getting misc things working on those devices.
One is Mali T604 OpenGLES driver. It works but there are some bugs in
it. The problem is: where to report them? As Chromium OS bugtracker is
not proper place as our use cases are different than their.
https://bugs.launchpad.net/chromebook-arm/+bug/1085596 is an example
showing that if you run two applications using OpenGLES then you have
screen artifacts. Or if you run WM with compositing and any OpenGLES
application (glgears-es2 is enough).
Can someone from Linaro Multimedia team or ARM Multimedia team suggest
option?
__cpufreq_remove_dev() is called on multiple occasions: cpufreq_driver
unregister and cpu removals.
Current implementation of this routine is overly complex without much need. If
the cpu to be removed is the policy->cpu, we remove the policy first and add all
other cpus again from policy->cpus and then finally call __cpufreq_remove_dev()
again to remove the cpu to be deleted. Haahhhh..
There exist a simple solution to removal of a cpu:
- Simply use the old policy structure
- update its fields like: policy->cpu, etc.
- notify any users of cpufreq, which depend on changing policy->cpu
Hence this patch, which tries to implement the above theory. It is tested well
by myself on ARM big.LITTLE TC2 SoC, which has 5 cores (2 A15 and 3 A7). Both
A15's share same struct policy and all A7's share same policy structure.
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
Tested-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
Hi Guys,
I am just an beginner in cpufreq stuff, please ignore any foolish mistakes. :)
Yesterday, i reviewed a cpufreq driver that had some ugly code in init()
routine:
http://www.spinics.net/lists/arm-kernel/msg215348.html
It wasn't ugly due to the author of the patch, but the way
__cpufreq_remove_dev() is implemented. And then i thought to simplify it.
[Probably need to simplify cpufreq_add_dev() too, but that can be done as next
step.]
I have rebased this patch over some other cpufreq core fixes i had posted
earlier:
https://lkml.org/lkml/2012/12/16/5
ARM mail servers are broken and hence this patch can't be applied as is. :(
I have pushed this and the dependency patch here:
http://git.linaro.org/gitweb?p=arm/big.LITTLE/mp.git;a=shortlog;h=refs/head…
@Shawn: I believe your driver don't require that ugly code anymore (Though i
know there is a situation for that to happen, if we have two cpus, you remove
second one and then add it back. With this cpufreq_add_dev() would call init()
first and then try to match if there are any managed_policies present. But the
issue you pointed out about unregistering the driver would be solved by this
patch.)
drivers/cpufreq/cpufreq.c | 158 +++++++++++++++++-----------------------
drivers/cpufreq/cpufreq_stats.c | 21 +++++-
drivers/cpufreq/freq_table.c | 10 +++
include/linux/cpufreq.h | 5 ++
4 files changed, 101 insertions(+), 93 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 271d3be..8df41ad 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1036,6 +1036,22 @@ module_out:
return ret;
}
+static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
+{
+ unsigned int old_cpu = policy->cpu;
+ int j;
+
+ policy->cpu = cpu;
+
+ for_each_cpu(j, policy->cpus) {
+ if (!cpu_online(j))
+ continue;
+ per_cpu(cpufreq_policy_cpu, j) = cpu;
+ }
+
+ cpufreq_frequency_table_update_policy_cpu(old_cpu, cpu);
+ cpufreq_stats_update_policy_cpu(old_cpu, cpu);
+}
/**
* __cpufreq_remove_dev - remove a CPU device
@@ -1046,132 +1062,92 @@ module_out:
*/
static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
{
- unsigned int cpu = dev->id;
+ unsigned int cpu = dev->id, ret, cpus;
unsigned long flags;
struct cpufreq_policy *data;
struct kobject *kobj;
struct completion *cmp;
-#ifdef CONFIG_SMP
struct device *cpu_dev;
- unsigned int j;
-#endif
- pr_debug("unregistering CPU %u\n", cpu);
+ pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
spin_lock_irqsave(&cpufreq_driver_lock, flags);
data = per_cpu(cpufreq_cpu_data, cpu);
if (!data) {
+ pr_debug("%s: No cpu_data found\n", __func__);
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
unlock_policy_rwsem_write(cpu);
return -EINVAL;
}
- per_cpu(cpufreq_cpu_data, cpu) = NULL;
-#ifdef CONFIG_SMP
- /* if this isn't the CPU which is the parent of the kobj, we
- * only need to unlink, put and exit
- */
- if (unlikely(cpu != data->cpu)) {
- pr_debug("removing link\n");
+ if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
- cpumask_clear_cpu(cpu, data->cpus);
- spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
- __cpufreq_governor(data, CPUFREQ_GOV_START);
- __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
-
- kobj = &dev->kobj;
- cpufreq_cpu_put(data);
- unlock_policy_rwsem_write(cpu);
- sysfs_remove_link(kobj, "cpufreq");
- return 0;
- }
-#endif
-
-#ifdef CONFIG_SMP
#ifdef CONFIG_HOTPLUG_CPU
strncpy(per_cpu(cpufreq_cpu_governor, cpu), data->governor->name,
CPUFREQ_NAME_LEN);
#endif
- /* if we have other CPUs still registered, we need to unlink them,
- * or else wait_for_completion below will lock up. Clean the
- * per_cpu(cpufreq_cpu_data) while holding the lock, and remove
- * the sysfs links afterwards.
- */
- if (unlikely(cpumask_weight(data->cpus) > 1)) {
- for_each_cpu(j, data->cpus) {
- if (j == cpu)
- continue;
- per_cpu(cpufreq_cpu_data, j) = NULL;
- }
- }
-
- spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ per_cpu(cpufreq_cpu_data, cpu) = NULL;
+ cpus = cpumask_weight(data->cpus);
+ cpumask_clear_cpu(cpu, data->cpus);
- if (unlikely(cpumask_weight(data->cpus) > 1)) {
- for_each_cpu(j, data->cpus) {
- if (j == cpu)
- continue;
- pr_debug("removing link for cpu %u\n", j);
-#ifdef CONFIG_HOTPLUG_CPU
- strncpy(per_cpu(cpufreq_cpu_governor, j),
- data->governor->name, CPUFREQ_NAME_LEN);
-#endif
- cpu_dev = get_cpu_device(j);
- kobj = &cpu_dev->kobj;
+ if (unlikely((cpu == data->cpu) && (cpus > 1))) {
+ /* first sibling now owns the new sysfs dir */
+ cpu_dev = get_cpu_device(cpumask_first(data->cpus));
+ sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
+ ret = kobject_move(&data->kobj, &cpu_dev->kobj);
+ if (ret) {
+ pr_err("%s: Failed to move kobj: %d", __func__, ret);
+ cpumask_set_cpu(cpu, data->cpus);
+ ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj,
+ "cpufreq");
+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
unlock_policy_rwsem_write(cpu);
- sysfs_remove_link(kobj, "cpufreq");
- lock_policy_rwsem_write(cpu);
- cpufreq_cpu_put(data);
+ return -EINVAL;
}
+
+ update_policy_cpu(data, cpu_dev->id);
+ pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
+ __func__, cpu_dev->id, cpu);
}
-#else
- spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
-#endif
- if (cpufreq_driver->target)
- __cpufreq_governor(data, CPUFREQ_GOV_STOP);
+ spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- kobj = &data->kobj;
- cmp = &data->kobj_unregister;
+ pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
+ cpufreq_cpu_put(data);
unlock_policy_rwsem_write(cpu);
- kobject_put(kobj);
+ sysfs_remove_link(&dev->kobj, "cpufreq");
- /* we need to make sure that the underlying kobj is actually
- * not referenced anymore by anybody before we proceed with
- * unloading.
- */
- pr_debug("waiting for dropping of refcount\n");
- wait_for_completion(cmp);
- pr_debug("wait complete\n");
-
- lock_policy_rwsem_write(cpu);
- if (cpufreq_driver->exit)
- cpufreq_driver->exit(data);
- unlock_policy_rwsem_write(cpu);
+ /* If cpu is last user of policy, free policy */
+ if (cpus == 1) {
+ lock_policy_rwsem_write(cpu);
+ kobj = &data->kobj;
+ cmp = &data->kobj_unregister;
+ unlock_policy_rwsem_write(cpu);
+ kobject_put(kobj);
-#ifdef CONFIG_HOTPLUG_CPU
- /* when the CPU which is the parent of the kobj is hotplugged
- * offline, check for siblings, and create cpufreq sysfs interface
- * and symlinks
- */
- if (unlikely(cpumask_weight(data->cpus) > 1)) {
- /* first sibling now owns the new sysfs dir */
- cpumask_clear_cpu(cpu, data->cpus);
- cpufreq_add_dev(get_cpu_device(cpumask_first(data->cpus)), NULL);
+ /* we need to make sure that the underlying kobj is actually
+ * not referenced anymore by anybody before we proceed with
+ * unloading.
+ */
+ pr_debug("waiting for dropping of refcount\n");
+ wait_for_completion(cmp);
+ pr_debug("wait complete\n");
- /* finally remove our own symlink */
lock_policy_rwsem_write(cpu);
- __cpufreq_remove_dev(dev, sif);
- }
-#endif
+ if (cpufreq_driver->exit)
+ cpufreq_driver->exit(data);
+ unlock_policy_rwsem_write(cpu);
- free_cpumask_var(data->related_cpus);
- free_cpumask_var(data->cpus);
- kfree(data);
+ free_cpumask_var(data->related_cpus);
+ free_cpumask_var(data->cpus);
+ kfree(data);
+ } else if (cpufreq_driver->target) {
+ __cpufreq_governor(data, CPUFREQ_GOV_START);
+ __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
+ }
return 0;
}
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index e40e508..0afface 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -170,11 +170,13 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
static void cpufreq_stats_free_table(unsigned int cpu)
{
struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
+
if (stat) {
+ pr_debug("%s: Free stat table\n", __func__);
kfree(stat->time_in_state);
kfree(stat);
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
}
- per_cpu(cpufreq_stats_table, cpu) = NULL;
}
/* must be called early in the CPU removal sequence (before
@@ -183,8 +185,10 @@ static void cpufreq_stats_free_table(unsigned int cpu)
static void cpufreq_stats_free_sysfs(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- if (policy && policy->cpu == cpu)
+ if (policy && (cpumask_weight(policy->cpus) == 1)) {
+ pr_debug("%s: Free sysfs stat\n", __func__);
sysfs_remove_group(&policy->kobj, &stats_attr_group);
+ }
if (policy)
cpufreq_cpu_put(policy);
}
@@ -262,6 +266,19 @@ error_get_fail:
return ret;
}
+void cpufreq_stats_update_policy_cpu(unsigned int old_cpu,
+ unsigned int new_cpu)
+{
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, old_cpu);
+
+ pr_debug("Updating stats_table for new_cpu %u from old_cpu %u\n",
+ new_cpu, old_cpu);
+ per_cpu(cpufreq_stats_table, new_cpu) = per_cpu(cpufreq_stats_table,
+ old_cpu);
+ per_cpu(cpufreq_stats_table, old_cpu) = NULL;
+ stat->cpu = new_cpu;
+}
+
static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
unsigned long val, void *data)
{
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 49cda25..a4b384f 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -227,6 +227,16 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu)
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
+void cpufreq_frequency_table_update_policy_cpu(unsigned int old_cpu,
+ unsigned int new_cpu)
+{
+ pr_debug("Updating show_table for new_cpu %u from old_cpu %u\n",
+ new_cpu, old_cpu);
+ per_cpu(cpufreq_show_table, new_cpu) = per_cpu(cpufreq_show_table,
+ old_cpu);
+ per_cpu(cpufreq_show_table, old_cpu) = NULL;
+}
+
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
{
return per_cpu(cpufreq_show_table, cpu);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index a55b88e..a42aa05 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -405,6 +405,11 @@ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);
+void cpufreq_frequency_table_update_policy_cpu(unsigned int old_cpu,
+ unsigned int new_cpu);
void cpufreq_frequency_table_put_attr(unsigned int cpu);
+
+void cpufreq_stats_update_policy_cpu(unsigned int old_cpu,
+ unsigned int new_cpu);
#endif /* _LINUX_CPUFREQ_H */
--
1.7.12.rc2.18.g61b472e
Calendar Week 2, 2013: Here is test result summary for Linux Linaro ubuntu
Quantal image on following boards:
1) ARM Versatile Express A9;
2) Samsung Origen;
3) TI Panda 4430;
4) TI Panda 4460;
5) ST Ericsson Snowball.
Synopsis: Snowball boots unstable, Device Tree is only supported on Samsung
Origen, and no Internet connection on Samsung Origen board.
1. ARM Versatile Express A9 + Linux Linaro Quantal (Column F):
https://docs.google.com/a/linaro.org/spreadsheet/ccc?key=0AroPySpr4FnEdFNmV…
It keeps exactly same status as last test result: only "Halt" & "Device
Tree" test failed, all other features work well.
2. Samsung Origen + Linux Linaro Quantal (Column F):
https://docs.google.com/a/linaro.org/spreadsheet/ccc?key=0AroPySpr4FnEdEowN…
Reboot works, other features are same as last test result. The most
important thing here is no network connection on the board.
3. TI Panda 4430 + Linux Linaro Quantal (Column F):
https://docs.google.com/a/linaro.org/spreadsheet/ccc?key=0AroPySpr4FnEdEwwZ…
Device Tree directory is empty, and there are some power management test
cases failed. All other features are OK.
4. TI Panda 4460 + Linux Linaro Quantal (Column F):
https://docs.google.com/a/linaro.org/spreadsheet/ccc?key=0AroPySpr4FnEdEwwZ…
Everything works well except Device Tree - the directory is empty, same as
TI Panda 4430.
5. ST Ericsson Snowball + Linux Linaro Quantal (Column F):
https://docs.google.com/a/linaro.org/spreadsheet/ccc?key=0AroPySpr4FnEdFJ4X…
The board can't boot in a reliable way. It can boot into console sometimes,
although system will freeze if wait for a longer time; It also possible to
get kernel panic or system crash if try to boot it again. No HDMI display
all the time.
For the 12.12 release test summary (Calendar week 51), please refer to
attachment.
Thank you.
Best Regards
Botao Sun
Hi, all
Does anybody know status of memory-hotplug feature in arm linux?
Is it currently useable or being used in any of Linaro's builds? Any patches or clue will be appreciated.
Thanks.
Best regards,
Guodong Xu
We should be able to cross compile QEMU for ARM64 host.
This is required for trying out ARM 32-bit guest on ARM64 host using QEMU + KVM ARM64.
Signed-off-by: Anup Patel <anup.patel(a)linaro.org>
---
configure | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/configure b/configure
index fe18ed2..0bfb8bb 100755
--- a/configure
+++ b/configure
@@ -366,6 +366,8 @@ elif check_define __s390__ ; then
fi
elif check_define __arm__ ; then
cpu="arm"
+elif check_define __aarch64__ ; then
+ cpu="arm64"
elif check_define __hppa__ ; then
cpu="hppa"
else
@@ -388,6 +390,9 @@ case "$cpu" in
armv*b|armv*l|arm)
cpu="arm"
;;
+ arm64|aarch64)
+ cpu="arm64"
+ ;;
hppa|parisc|parisc64)
cpu="hppa"
;;
--
1.7.9.5
We should be able to configure QEMU for cross compiling it for ARM64 host.
This patch only tries to make sure that the configure step falls through
and atleast QEMU cross-compilation starts.
The rationale behind cpu=aarch64 naming (as commented by Peter Maydell):
For the target architecture name (ie what comes out in the
qemu-foo and qemu-system-foo binary names) we generally use
the same name that 'uname -m' produces on those machines. In
this case that would be "aarch64".
Signed-off-by: Anup Patel <anup.patel(a)linaro.org>
---
configure | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/configure b/configure
index fe18ed2..0bfb8bb 100755
--- a/configure
+++ b/configure
@@ -366,6 +366,8 @@ elif check_define __s390__ ; then
fi
elif check_define __arm__ ; then
cpu="arm"
+elif check_define __aarch64__ ; then
+ cpu="aarch64"
elif check_define __hppa__ ; then
cpu="hppa"
else
@@ -388,6 +390,9 @@ case "$cpu" in
armv*b|armv*l|arm)
cpu="arm"
;;
+ aarch64)
+ cpu="aarch64"
+ ;;
hppa|parisc|parisc64)
cpu="hppa"
;;
--
1.7.9.5
On 01/07/2013 10:58 PM, Rafael J. Wysocki wrote:
> Hi,
>
> Thanks for the patch!
>
> I'd like Daniel to have a look at it still.
I agree with this patch. I was about to send exactly the same.
Thanks Krzysztof for fixing this.
> On Monday, January 07, 2013 08:12:01 PM Krzysztof Mazur wrote:
>> Commit bf4d1b5ddb78f86078ac6ae0415802d5f0c68f92 (cpuidle: support
>> multiple drivers) changed the number of initialized state kobjects
>> in cpuidle_add_state_sysfs() from device->state_count to drv->state_count,
>> but leaved device->state_count in cpuidle_remove_state_sysfs().
>> Those two values might have different values, causing for instance
>> NULL pointer dereference in cpuidle_remove_state_sysfs().
>>
>> Signed-off-by: Krzysztof Mazur <krzysiek(a)podlesie.net>
Acked-by: Daniel Lezcano <daniel.lezcano(a)linaro.org>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog