ARM: 7685/1: delay: use private ticks_per_jiffy field for timer-based delay ops
Commit 70264367a2 ("ARM: 7653/2: do not scale loops_per_jiffy when
using a constant delay clock") fixed a problem with our timer-based
delay loop, where loops_per_jiffy is scaled by cpufreq yet used directly
by the timer delay ops.
This patch fixes the problem in a more elegant way by keeping a private
ticks_per_jiffy field in the delay ops, independent of loops_per_jiffy
and therefore not subject to scaling. The loop-based delay continues to
use loops_per_jiffy directly, as it should.
Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
committed by
Russell King
parent
93dc68876b
commit
6f3d90e556
@@ -24,7 +24,7 @@ extern struct arm_delay_ops {
|
|||||||
void (*delay)(unsigned long);
|
void (*delay)(unsigned long);
|
||||||
void (*const_udelay)(unsigned long);
|
void (*const_udelay)(unsigned long);
|
||||||
void (*udelay)(unsigned long);
|
void (*udelay)(unsigned long);
|
||||||
bool const_clock;
|
unsigned long ticks_per_jiffy;
|
||||||
} arm_delay_ops;
|
} arm_delay_ops;
|
||||||
|
|
||||||
#define __delay(n) arm_delay_ops.delay(n)
|
#define __delay(n) arm_delay_ops.delay(n)
|
||||||
|
|||||||
@@ -673,9 +673,6 @@ static int cpufreq_callback(struct notifier_block *nb,
|
|||||||
if (freq->flags & CPUFREQ_CONST_LOOPS)
|
if (freq->flags & CPUFREQ_CONST_LOOPS)
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
|
|
||||||
if (arm_delay_ops.const_clock)
|
|
||||||
return NOTIFY_OK;
|
|
||||||
|
|
||||||
if (!per_cpu(l_p_j_ref, cpu)) {
|
if (!per_cpu(l_p_j_ref, cpu)) {
|
||||||
per_cpu(l_p_j_ref, cpu) =
|
per_cpu(l_p_j_ref, cpu) =
|
||||||
per_cpu(cpu_data, cpu).loops_per_jiffy;
|
per_cpu(cpu_data, cpu).loops_per_jiffy;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ static void __timer_delay(unsigned long cycles)
|
|||||||
static void __timer_const_udelay(unsigned long xloops)
|
static void __timer_const_udelay(unsigned long xloops)
|
||||||
{
|
{
|
||||||
unsigned long long loops = xloops;
|
unsigned long long loops = xloops;
|
||||||
loops *= loops_per_jiffy;
|
loops *= arm_delay_ops.ticks_per_jiffy;
|
||||||
__timer_delay(loops >> UDELAY_SHIFT);
|
__timer_delay(loops >> UDELAY_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,11 +73,13 @@ void __init register_current_timer_delay(const struct delay_timer *timer)
|
|||||||
pr_info("Switching to timer-based delay loop\n");
|
pr_info("Switching to timer-based delay loop\n");
|
||||||
delay_timer = timer;
|
delay_timer = timer;
|
||||||
lpj_fine = timer->freq / HZ;
|
lpj_fine = timer->freq / HZ;
|
||||||
loops_per_jiffy = lpj_fine;
|
|
||||||
|
/* cpufreq may scale loops_per_jiffy, so keep a private copy */
|
||||||
|
arm_delay_ops.ticks_per_jiffy = lpj_fine;
|
||||||
arm_delay_ops.delay = __timer_delay;
|
arm_delay_ops.delay = __timer_delay;
|
||||||
arm_delay_ops.const_udelay = __timer_const_udelay;
|
arm_delay_ops.const_udelay = __timer_const_udelay;
|
||||||
arm_delay_ops.udelay = __timer_udelay;
|
arm_delay_ops.udelay = __timer_udelay;
|
||||||
arm_delay_ops.const_clock = true;
|
|
||||||
delay_calibrated = true;
|
delay_calibrated = true;
|
||||||
} else {
|
} else {
|
||||||
pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
|
pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user