diff options
-rw-r--r-- | arch/tile/include/asm/timex.h | 3 | ||||
-rw-r--r-- | arch/tile/include/hv/hypervisor.h | 5 | ||||
-rw-r--r-- | arch/tile/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/tile/kernel/time.c | 10 | ||||
-rw-r--r-- | arch/tile/lib/delay.c | 21 |
5 files changed, 34 insertions, 11 deletions
diff --git a/arch/tile/include/asm/timex.h b/arch/tile/include/asm/timex.h index 3baf5fc..29921f0 100644 --- a/arch/tile/include/asm/timex.h +++ b/arch/tile/include/asm/timex.h @@ -38,6 +38,9 @@ static inline cycles_t get_cycles(void) cycles_t get_clock_rate(void); +/* Convert nanoseconds to core clock cycles. */ +cycles_t ns2cycles(unsigned long nsecs); + /* Called at cpu initialization to set some low-level constants. */ void setup_clock(void); diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h index f672544..103986b 100644 --- a/arch/tile/include/hv/hypervisor.h +++ b/arch/tile/include/hv/hypervisor.h @@ -964,6 +964,11 @@ HV_ASIDRange hv_inquire_asid(int idx); /** Waits for at least the specified number of nanoseconds then returns. * + * NOTE: this deprecated function currently assumes a 750 MHz clock, + * and is thus not generally suitable for use. New code should call + * hv_sysconf(HV_SYSCONF_CPU_SPEED), compute a cycle count to wait for, + * and delay by looping while checking the cycle counter SPR. + * * @param nanosecs The number of nanoseconds to sleep. */ void hv_nanosleep(int nanosecs); diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index fd8dc42..c3aa067 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S @@ -38,12 +38,6 @@ STD_ENTRY(kernel_execve) jrp lr STD_ENDPROC(kernel_execve) -/* Delay a fixed number of cycles. */ -STD_ENTRY(__delay) - { addi r0, r0, -1; bnzt r0, . } - jrp lr - STD_ENDPROC(__delay) - /* * We don't run this function directly, but instead copy it to a page * we map into every user process. See vdso_setup(). diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index f2e156e..49a605b 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -224,3 +224,13 @@ int setup_profiling_timer(unsigned int multiplier) { return -EINVAL; } + +/* + * Use the tile timer to convert nsecs to core clock cycles, relying + * on it having the same frequency as SPR_CYCLE. + */ +cycles_t ns2cycles(unsigned long nsecs) +{ + struct clock_event_device *dev = &__get_cpu_var(tile_timer); + return ((u64)nsecs * dev->mult) >> dev->shift; +} diff --git a/arch/tile/lib/delay.c b/arch/tile/lib/delay.c index 5801b03..cdacdd1 100644 --- a/arch/tile/lib/delay.c +++ b/arch/tile/lib/delay.c @@ -15,20 +15,31 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/thread_info.h> -#include <asm/fixmap.h> -#include <hv/hypervisor.h> +#include <asm/timex.h> void __udelay(unsigned long usecs) { - hv_nanosleep(usecs * 1000); + if (usecs > ULONG_MAX / 1000) { + WARN_ON_ONCE(usecs > ULONG_MAX / 1000); + usecs = ULONG_MAX / 1000; + } + __ndelay(usecs * 1000); } EXPORT_SYMBOL(__udelay); void __ndelay(unsigned long nsecs) { - hv_nanosleep(nsecs); + cycles_t target = get_cycles(); + target += ns2cycles(nsecs); + while (get_cycles() < target) + cpu_relax(); } EXPORT_SYMBOL(__ndelay); -/* FIXME: should be declared in a header somewhere. */ +void __delay(unsigned long cycles) +{ + cycles_t target = get_cycles() + cycles; + while (get_cycles() < target) + cpu_relax(); +} EXPORT_SYMBOL(__delay); |