aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri Sivanich <sivanich@sgi.com>2010-01-22 10:41:40 -0500
committerIngo Molnar <mingo@elte.hu>2010-01-27 05:33:53 -0500
commitaca3bb5910119d4cf6c28568a642582efb4cc14a (patch)
treea6a14bbb8a9ae4b469b506d1c611c41637e311ce
parente0b5f80dd4226a920257c91a3b9070e81149060b (diff)
x86, UV: Fix RTC latency bug by reading replicated cachelines
For SGI UV node controllers (HUB) rev 2.0 or greater, use replicated cachelines to read the RTC timer. This optimization allows faster simulataneous reads from a given socket. Signed-off-by: Dimitri Sivanich <sivanich@sgi.com> Cc: Jack Steiner <steiner@sgi.com> LKML-Reference: <20100122154140.GB4975@sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/uv_time.c13
-rw-r--r--drivers/char/uv_mmtimer.c18
2 files changed, 23 insertions, 8 deletions
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
index 3c84aa001c11..2b75ef638dbc 100644
--- a/arch/x86/kernel/uv_time.c
+++ b/arch/x86/kernel/uv_time.c
@@ -282,10 +282,21 @@ static int uv_rtc_unset_timer(int cpu, int force)
282 282
283/* 283/*
284 * Read the RTC. 284 * Read the RTC.
285 *
286 * Starting with HUB rev 2.0, the UV RTC register is replicated across all
287 * cachelines of it's own page. This allows faster simultaneous reads
288 * from a given socket.
285 */ 289 */
286static cycle_t uv_read_rtc(struct clocksource *cs) 290static cycle_t uv_read_rtc(struct clocksource *cs)
287{ 291{
288 return (cycle_t)uv_read_local_mmr(UVH_RTC); 292 unsigned long offset;
293
294 if (uv_get_min_hub_revision_id() == 1)
295 offset = 0;
296 else
297 offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE;
298
299 return (cycle_t)uv_read_local_mmr(UVH_RTC | offset);
289} 300}
290 301
291/* 302/*
diff --git a/drivers/char/uv_mmtimer.c b/drivers/char/uv_mmtimer.c
index 867b67be9f0a..c7072ba14f48 100644
--- a/drivers/char/uv_mmtimer.c
+++ b/drivers/char/uv_mmtimer.c
@@ -89,13 +89,17 @@ static long uv_mmtimer_ioctl(struct file *file, unsigned int cmd,
89 switch (cmd) { 89 switch (cmd) {
90 case MMTIMER_GETOFFSET: /* offset of the counter */ 90 case MMTIMER_GETOFFSET: /* offset of the counter */
91 /* 91 /*
92 * UV RTC register is on its own page 92 * Starting with HUB rev 2.0, the UV RTC register is
93 * replicated across all cachelines of it's own page.
94 * This allows faster simultaneous reads from a given socket.
95 *
96 * The offset returned is in 64 bit units.
93 */ 97 */
94 if (PAGE_SIZE <= (1 << 16)) 98 if (uv_get_min_hub_revision_id() == 1)
95 ret = ((UV_LOCAL_MMR_BASE | UVH_RTC) & (PAGE_SIZE-1)) 99 ret = 0;
96 / 8;
97 else 100 else
98 ret = -ENOSYS; 101 ret = ((uv_blade_processor_id() * L1_CACHE_BYTES) %
102 PAGE_SIZE) / 8;
99 break; 103 break;
100 104
101 case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */ 105 case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
@@ -115,8 +119,8 @@ static long uv_mmtimer_ioctl(struct file *file, unsigned int cmd,
115 ret = hweight64(UVH_RTC_REAL_TIME_CLOCK_MASK); 119 ret = hweight64(UVH_RTC_REAL_TIME_CLOCK_MASK);
116 break; 120 break;
117 121
118 case MMTIMER_MMAPAVAIL: /* can we mmap the clock into userspace? */ 122 case MMTIMER_MMAPAVAIL:
119 ret = (PAGE_SIZE <= (1 << 16)) ? 1 : 0; 123 ret = 1;
120 break; 124 break;
121 125
122 case MMTIMER_GETCOUNTER: 126 case MMTIMER_GETCOUNTER: