Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 7685/1: delay: use private ticks_per_jiffy field for timer-based delay ops

Commit 70264367a243 ("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>

authored by

Will Deacon and committed by
Russell King
6f3d90e5 93dc6887

+6 -7
+1 -1
arch/arm/include/asm/delay.h
··· 24 24 void (*delay)(unsigned long); 25 25 void (*const_udelay)(unsigned long); 26 26 void (*udelay)(unsigned long); 27 - bool const_clock; 27 + unsigned long ticks_per_jiffy; 28 28 } arm_delay_ops; 29 29 30 30 #define __delay(n) arm_delay_ops.delay(n)
-3
arch/arm/kernel/smp.c
··· 673 673 if (freq->flags & CPUFREQ_CONST_LOOPS) 674 674 return NOTIFY_OK; 675 675 676 - if (arm_delay_ops.const_clock) 677 - return NOTIFY_OK; 678 - 679 676 if (!per_cpu(l_p_j_ref, cpu)) { 680 677 per_cpu(l_p_j_ref, cpu) = 681 678 per_cpu(cpu_data, cpu).loops_per_jiffy;
+5 -3
arch/arm/lib/delay.c
··· 58 58 static void __timer_const_udelay(unsigned long xloops) 59 59 { 60 60 unsigned long long loops = xloops; 61 - loops *= loops_per_jiffy; 61 + loops *= arm_delay_ops.ticks_per_jiffy; 62 62 __timer_delay(loops >> UDELAY_SHIFT); 63 63 } 64 64 ··· 73 73 pr_info("Switching to timer-based delay loop\n"); 74 74 delay_timer = timer; 75 75 lpj_fine = timer->freq / HZ; 76 - loops_per_jiffy = lpj_fine; 76 + 77 + /* cpufreq may scale loops_per_jiffy, so keep a private copy */ 78 + arm_delay_ops.ticks_per_jiffy = lpj_fine; 77 79 arm_delay_ops.delay = __timer_delay; 78 80 arm_delay_ops.const_udelay = __timer_const_udelay; 79 81 arm_delay_ops.udelay = __timer_udelay; 80 - arm_delay_ops.const_clock = true; 82 + 81 83 delay_calibrated = true; 82 84 } else { 83 85 pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");