aboutsummaryrefslogtreecommitdiff
path: root/src/devices
diff options
context:
space:
mode:
authorStefan Reinauer <stepan@openbios.org>2006-04-11 19:23:57 +0000
committerStefan Reinauer <stepan@openbios.org>2006-04-11 19:23:57 +0000
commitcf648c9a99c59f25400f198b99de2f92e57db349 (patch)
treeed7c96e1e7e0ba66185154f597d958ddf45f9760 /src/devices
parentfbce0ffb92d8665c9cef5cb7be4d9fa6646bd7f2 (diff)
this was in my queue since 2005/10/26
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2252 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/hypertransport.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/devices/hypertransport.c b/src/devices/hypertransport.c
index c61efa6c7b..6d37ab5764 100644
--- a/src/devices/hypertransport.c
+++ b/src/devices/hypertransport.c
@@ -278,7 +278,20 @@ static void ht_collapse_early_enumeration(struct bus *bus, unsigned offset_uniti
}
/* Has the link failed? */
if (ctrl & (1 << 4)) {
- return;
+ /*
+ * Either the link has failed, or we have
+ * a CRC error.
+ * Sometimes this can happen due to link
+ * retrain, so lets knock it down and see
+ * if its transient
+ */
+ ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
+ pci_write_config16(prev.dev, prev.pos + prev.ctrl_off, ctrl);
+ ctrl = pci_read_config16(prev.dev, prev.pos + prev.ctrl_off);
+ if (ctrl & ((1 << 4) | (1 << 8))) {
+ printk_alert("Detected error on Hypertransport Link\n");
+ return;
+ }
}
} while((ctrl & (1 << 5)) == 0);
@@ -382,12 +395,25 @@ unsigned int hypertransport_scan_chain(struct bus *bus,
/* Wait until the link initialization is complete */
do {
ctrl = pci_read_config16(prev.dev, prev.pos + prev.ctrl_off);
- /* Is this the end of the hypertransport chain?
- * Has the link failed?
- * If so further scanning is pointless.
- */
- if (ctrl & ((1 << 6) | (1 << 4))) {
- goto end_of_chain;
+
+ if (ctrl & (1 << 6))
+ goto end_of_chain; // End of chain
+
+ if (ctrl & ((1 << 4) | (1 << 8))) {
+ /*
+ * Either the link has failed, or we have
+ * a CRC error.
+ * Sometimes this can happen due to link
+ * retrain, so lets knock it down and see
+ * if its transient
+ */
+ ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
+ pci_write_config16(prev.dev, prev.pos + prev.ctrl_off, ctrl);
+ ctrl = pci_read_config16(prev.dev, prev.pos + prev.ctrl_off);
+ if (ctrl & ((1 << 4) | (1 << 8))) {
+ printk_alert("Detected error on Hypertransport Link\n");
+ goto end_of_chain;
+ }
}
} while((ctrl & (1 << 5)) == 0);