diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2011-02-28 13:21:52 -0500 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2011-03-01 16:20:04 -0500 |
commit | 13371731487896a6ef158b1cd74297f40a3da4bb (patch) | |
tree | af09fca3fd8811340b373faaddcdb528f8a07669 /arch/tile/kernel | |
parent | 04f7a3f12e10032ee3d44df1a509dbf5b2001fce (diff) |
arch/tile: fix __ndelay etc to work better
The current implementations of __ndelay and __udelay call a hypervisor
service to delay, but the hypervisor service isn't actually implemented
very well, and the consensus is that Linux should handle figuring this
out natively and not use a hypervisor service.
By converting nanoseconds to cycles, and then spinning until the
cycle counter reaches the desired cycle, we get several benefits:
first, we are sensitive to the actual clock speed; second, we use
less power by issuing a slow SPR read once every six cycles while
we delay; and third, we properly handle the case of an interrupt by
exiting at the target time rather than after some number of cycles.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/kernel')
-rw-r--r-- | arch/tile/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/tile/kernel/time.c | 10 |
2 files changed, 10 insertions, 6 deletions
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index fd8dc42abdcb..c3aa0676ed06 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S | |||
@@ -38,12 +38,6 @@ STD_ENTRY(kernel_execve) | |||
38 | jrp lr | 38 | jrp lr |
39 | STD_ENDPROC(kernel_execve) | 39 | STD_ENDPROC(kernel_execve) |
40 | 40 | ||
41 | /* Delay a fixed number of cycles. */ | ||
42 | STD_ENTRY(__delay) | ||
43 | { addi r0, r0, -1; bnzt r0, . } | ||
44 | jrp lr | ||
45 | STD_ENDPROC(__delay) | ||
46 | |||
47 | /* | 41 | /* |
48 | * We don't run this function directly, but instead copy it to a page | 42 | * We don't run this function directly, but instead copy it to a page |
49 | * we map into every user process. See vdso_setup(). | 43 | * we map into every user process. See vdso_setup(). |
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index f2e156e44692..49a605be94c5 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c | |||
@@ -224,3 +224,13 @@ int setup_profiling_timer(unsigned int multiplier) | |||
224 | { | 224 | { |
225 | return -EINVAL; | 225 | return -EINVAL; |
226 | } | 226 | } |
227 | |||
228 | /* | ||
229 | * Use the tile timer to convert nsecs to core clock cycles, relying | ||
230 | * on it having the same frequency as SPR_CYCLE. | ||
231 | */ | ||
232 | cycles_t ns2cycles(unsigned long nsecs) | ||
233 | { | ||
234 | struct clock_event_device *dev = &__get_cpu_var(tile_timer); | ||
235 | return ((u64)nsecs * dev->mult) >> dev->shift; | ||
236 | } | ||