Patchwork [U-Boot,15/20] x86: Provide a way to throttle port80 accesses

login
register
mail settings
Submitter Simon Glass
Date Nov. 3, 2012, 9:41 p.m.
Message ID <1351978902-23719-16-git-send-email-sjg@chromium.org>
Download mbox | patch
Permalink /patch/196954/
State Accepted, archived
Delegated to: Simon Glass
Headers show

Comments

Simon Glass - Nov. 3, 2012, 9:41 p.m.
From: Vadim Bendebury <vbendeb@chromium.org>

Some systems (like Google Link device) provide the ability to keep a
history of the target CPU port80 accesses, which is extremely handy
for debugging. The problem is that the EC handling port 80 access is
orders of magnitude slower than the AP. This causes random loss of
trace data.

This change allows to throttle port 80 accesses such that in case the
AP is trying to post faster than the EC can handle, a delay is
introduced to make sure that the post rate is throttled. Experiments
have shown that on Link the delay should be at least 350,000 of tsc
clocks.

Throttling is not being enabled by default: to enable it one would
have to set MIN_PORT80_KCLOCKS_DELAY to something like 400 and rebuild
the u-boot image. With upcoming EC code optimizations this number
could be decreased (new new value should be established
experimentally).

Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
---
 arch/x86/cpu/coreboot/coreboot.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

Patch

diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 59d730e..da722e9 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -69,6 +69,27 @@  int board_early_init_r(void)
 
 void show_boot_progress(int val)
 {
+#if MIN_PORT80_KCLOCKS_DELAY
+	static uint32_t prev_stamp;
+	static uint32_t base;
+
+	/*
+	 * Scale the time counter reading to avoid using 64 bit arithmetics.
+	 * Can't use get_timer() here becuase it could be not yet
+	 * initialized or even implemented.
+	 */
+	if (!prev_stamp) {
+		base = rdtsc() / 1000;
+		prev_stamp = 0;
+	} else {
+		uint32_t now;
+
+		do {
+			now = rdtsc() / 1000 - base;
+		} while (now < (prev_stamp + MIN_PORT80_KCLOCKS_DELAY));
+		prev_stamp = now;
+	}
+#endif
 	outb(val, 0x80);
 }