All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Metcalf <cmetcalf@tilera.com>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] arch/tile: fix __ndelay etc to work better
Date: Mon, 28 Feb 2011 13:21:52 -0500	[thread overview]
Message-ID: <201103011934.p21JYbNA010298@farm-0010.internal.tilera.com> (raw)
In-Reply-To: <201103011931.p21JVtqp010237@farm-0010.internal.tilera.com>

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>
---
 arch/tile/include/asm/timex.h     |    3 +++
 arch/tile/include/hv/hypervisor.h |    5 +++++
 arch/tile/kernel/entry.S          |    6 ------
 arch/tile/kernel/time.c           |   10 ++++++++++
 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);
-- 
1.6.5.2


  parent reply	other threads:[~2011-03-01 19:42 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-27 23:52 arch/tile: various fixes for 2.6.39 Chris Metcalf
2011-02-27 23:52 ` [PATCH] arch/tile: catch up with section naming convention in 2.6.35 Chris Metcalf
2011-03-01 20:52   ` Sam Ravnborg
2011-03-01 21:17     ` Chris Metcalf
2011-02-28 18:08 ` [PATCH] arch/tile: bug fix: exec'ed task thought it was still single-stepping Chris Metcalf
2011-02-28 18:21 ` Chris Metcalf [this message]
2011-02-28 18:24 ` [PATCH] arch/tile: stop disabling INTCTRL_1 interrupts during hypervisor downcalls Chris Metcalf
2011-02-28 18:32 ` [PATCH] arch/tile: warn and retry if an IPI is not accepted by the target cpu Chris Metcalf
2011-02-28 18:35 ` [PATCH] arch/tile: export <asm/hardwall.h> to userspace Chris Metcalf
2011-02-28 20:01 ` [PATCH] arch/tile: avoid a simulator warning during bootup Chris Metcalf
2011-02-28 20:14 ` [PATCH] arch/tile: fix reversed test of strict_strtol() return value Chris Metcalf
2011-02-28 20:19 ` [PATCH] arch/tile: sync up with <arch/sim.h> and <arch/sim_def.h> changes Chris Metcalf
2011-02-28 20:22 ` [PATCH] arch/tile: use a cleaner technique to enable interrupt for cpu_idle() Chris Metcalf
2011-02-28 20:28 ` [PATCH] arch/tile: use extended assembly to inline __mb_incoherent() Chris Metcalf
2011-02-28 20:30 ` [PATCH] arch/tile: fix two bugs in the backtracer code Chris Metcalf
2011-02-28 20:48 ` [PATCH] arch/tile: enhance existing finv_buffer_remote() routine Chris Metcalf
2011-02-28 20:51 ` [PATCH] arch/tile: export some additional module symbols Chris Metcalf
2011-02-28 20:58 ` [PATCH] arch/tile: fix some comments and whitespace Chris Metcalf
2011-02-28 21:01 ` [PATCH] arch/tile: add some more VMSPLIT options and use consistent naming Chris Metcalf
2011-02-28 21:37 ` [PATCH] arch/tile: support 4KB page size as well as 64KB Chris Metcalf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201103011934.p21JYbNA010298@farm-0010.internal.tilera.com \
    --to=cmetcalf@tilera.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.