Sometimes boot loaders set CPU frequency to a value outside of frequency table
present with cpufreq core. In such cases CPU might be unstable if it has to run
on that frequency for long duration of time and so its better to set it to a
frequency which is specified in freq-table. This also makes cpufreq stats
inconsistent as cpufreq-stats would fail to register because current frequency
of CPU isn't found in freq-table.
Because we don't want this change to effect boot process badly, we go for the
next freq which is >= policy->cur ('cur' must be set by now, otherwise we will
end up setting freq to lowest of the table as 'cur' is initialized to zero).
In case where CPU is already running on one of the frequencies present in
freq-table, this would turn into a dummy call as __cpufreq_driver_target() would
return early.
Reported-by: Carlos Hernandez <ceh(a)ti.com>
Reported-and-tested-by: Nishanth Menon <nm(a)ti.com>
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
V1->V2
- Set to (policy->cur - 1) instead of policy->cur.
- return early in case __cpufreq_driver_target() fails.
drivers/cpufreq/cpufreq.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 02d534d..7be996c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1038,6 +1038,38 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
}
}
+ /*
+ * Sometimes boot loaders set CPU frequency to a value outside of
+ * frequency table present with cpufreq core. In such cases CPU might be
+ * unstable if it has to run on that frequency for long duration of time
+ * and so its better to set it to a frequency which is specified in
+ * freq-table. This also makes cpufreq stats inconsistent as
+ * cpufreq-stats would fail to register because current frequency of CPU
+ * isn't found in freq-table.
+ *
+ * Because we don't want this change to effect boot process badly, we go
+ * for the next freq which is >= policy->cur ('cur' must be set by now,
+ * otherwise we will end up setting freq to lowest of the table as 'cur'
+ * is initialized to zero).
+ *
+ * In case where CPU is already running on one of the frequencies
+ * present in freq-table, this would turn into a dummy call as
+ * __cpufreq_driver_target() would return early.
+ *
+ * We are passing target-freq as "policy->cur - 1" otherwise
+ * __cpufreq_driver_target() would simply fail, as policy->cur will be
+ * equal to target-freq.
+ */
+ if (has_target()) {
+ ret = __cpufreq_driver_target(policy, policy->cur - 1,
+ CPUFREQ_RELATION_L);
+ if (ret) {
+ pr_err("%s: Unable to set frequency from table: %d\n",
+ __func__, ret);
+ goto err_out_unregister;
+ }
+ }
+
/* related cpus should atleast have policy->cpus */
cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
--
1.7.12.rc2.18.g61b472e
I2C IP block expect LE data, but CPU may operate in BE mode.
Need to use endian neutral functions to read/write h/w registers.
I.e instead of __raw_read[lw] and __raw_write[lw] functions code
need to use read[lw]_relaxed and write[lw]_relaxed functions.
If the first simply reads/writes register, the second will byteswap
it if host operates in BE mode.
Changes are trivial sed like replacement of __raw_xxx functions
with xxx_relaxed variant.
Signed-off-by: Taras Kondratiuk <taras.kondratiuk(a)linaro.org>
---
Based on Linus' master tip (b4789b8).
Tested on Keystone2 EVM.
drivers/i2c/busses/i2c-davinci.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 132369f..a629447 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -125,12 +125,12 @@ static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = {
static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev,
int reg, u16 val)
{
- __raw_writew(val, i2c_dev->base + reg);
+ writew_relaxed(val, i2c_dev->base + reg);
}
static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
{
- return __raw_readw(i2c_dev->base + reg);
+ return readw_relaxed(i2c_dev->base + reg);
}
/* Generate a pulse on the i2c clock pin. */
--
1.7.9.5
I've been banging my head on this one for quite a while now. The
problem is that there is very little debug out put available. Could you
see if you get the same?
Mainline kernel (I'm using commit 527d151131 right now but older kernels
are also affected). Most interesting config options:
CONFIG_BL_SWITCHER=n
CONFIG_ARCH_VEXPRESS_TC2_PM=y
CONFIG_ARM_BIG_LITTLE_CPUIDLE=y
CONFIG_ARM_BIG_LITTLE_CPUFREQ=y
CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=y
To crash the kernel within 5 seconds:
#!/bin/bash
echo 0 > /sys/kernel/bL_switcher/active
sleep 1
while true; do
for i in 0 1 2 3
do echo 0 > /sys/devices/system/cpu/cpu$i/online
done
for i in 3 2 1 0
do echo 1 > /sys/devices/system/cpu/cpu$i/online
done
for i in 4 3 2 1
do echo 0 > /sys/devices/system/cpu/cpu$i/online
done
for i in 1 2 3 4
do echo 1 > /sys/devices/system/cpu/cpu$i/online
done
done
What I get is:
[...]
CPU1: Booted secondary processor
CPU0: Booted secondary processor
Unable to handle kernel NULL pointer dereference at virtual address 0000000c
pgd = c0004000
[ the output stops there ]
The last CPU to be booted up is not always the same.
Are you able to reproduce?
Nicolas
Kexec disables outer cache before jumping to reboot code, but it doesn't
flush it explicitly. Flush is done implicitly inside of l2x0_disable().
But some SoC's override default .disable handler and don't flush cache.
This may lead to a corrupted memory during Kexec reboot on these
platforms.
This patch adds cache flush inside of OMAP4 and Highbank outer_cache.disable()
handlers to make it consistent with default l2x0_disable().
Acked-by: Rob Herring <rob.herring(a)calxeda.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar(a)ti.com>
Acked-by: Tony Lindgren <tony(a)atomide.com>
Signed-off-by: Taras Kondratiuk <taras.kondratiuk(a)linaro.org>
---
I was not aware about Russell's patch tracker process, so this patch
was not hooked there. Highbank moved to PSCI since then, so patch
has to be slightly modified.
Rob, are you still ok with this patch?
v1..v2: Removed changes in highbank_suspend_finish since after
commit dd68eb0 "ARM: highbank: adapt to use ARM PSCI calls"
cache is not explicitly disabled there.
v1: http://www.spinics.net/lists/linux-omap/msg98318.html
RFC v2: https://patchwork.kernel.org/patch/2990231/
Make the fix specific to platforms that don't use
l2x0_disable().
RFC v1: https://patchwork.kernel.org/patch/2974431/
Based on v3.13-rc1
---
arch/arm/mach-highbank/highbank.c | 1 +
arch/arm/mach-omap2/omap4-common.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index b3d7e56..ae17150 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -50,6 +50,7 @@ static void __init highbank_scu_map_io(void)
static void highbank_l2x0_disable(void)
{
+ outer_flush_all();
/* Disable PL310 L2 Cache controller */
highbank_smc1(0x102, 0x0);
}
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index b39efd4..c0ab9b2 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -162,6 +162,7 @@ void __iomem *omap4_get_l2cache_base(void)
static void omap4_l2x0_disable(void)
{
+ outer_flush_all();
/* Disable PL310 L2 Cache controller */
omap_smc1(0x102, 0x0);
}
--
1.7.9.5
When I read the runnable load avg code, I found the task's
avg.load_avg_contrib mainly updated in enqueue/dequeue, and the 'curr'
task in sched_tick.
So, if a sleep long time task is waked/added and kept on a cpu, but the
task is never be the 'curr' in sched_tick. Then the task's load contrib
will never be updated and keep small.
what I missed? or Is it really?
--
Thanks
Alex