Hi all,
while working on porting an HP DL 145G3 to K10 support with rev C2 Opterons, our team stumbled across the same problem Ward described in his thread. I tried out all errata fixes and the latest microcode patch files - no success. We tracked down the problem to be in the CpuFindCapability function which returns faulty offsets to address the ht phy links. For instance, when link 0 is to be accessed, the function returns A0 as an offset thereby leading function "AMD_checkLinkType" to check for a present and correctly initialized channel on link1. Now, when the AMD_SetHtPhyRegister function hits the function 4 portal of link1, the do/while loop waits for a completion bit to be set on a link that may not even be connected. According to the BKDG, the completion flag will never be set on an uninitialized link, therefore the system hang. Below is a fix of abovementioned function which spits out correct offsets. I am not sure, why this problem did not occur with previous revisions. My guess though is that this defined behaviour is something new to the C2 series. Also, this problem is highly topology dependent. When working with motherboards with all Opteron links properly connected and initialized, the only effect one would see is a missing switch to HT3 frequencies on link0. Hope this helps some people. Best regards,
Maximilian Thuermer
Index: init_cpus.c =================================================================== --- init_cpus.c (revision 4048) +++ init_cpus.c (working copy) @@ -705,37 +705,40 @@ * * Returns the offset of the link register. */ -BOOL AMD_CpuFindCapability (u8 node, u8 cap_count, u8 *offset) +BOOL AMD_CpuFindCapability (u8 node, u8 link_no, u8 *offset) { u32 val; + u8 cap_count = 0;
/* get start of CPU HT Host Capabilities */ val = pci_read_config32(NODE_PCI(node, 0), 0x34); val &= 0xFF;
- cap_count++; - /* Traverse through the capabilities. */ - do { + while((cap_count < link_no) && val) + { val = pci_read_config32(NODE_PCI(node, 0), val); /* Is the capability block a HyperTransport capability block? */ if ((val & 0xFF) == 0x08) /* Is the HT capability block an HT Host Capability? */ if ((val & 0xE0000000) == (1 << 29)) - cap_count--; + cap_count++; val = (val >> 8) & 0xFF; - } while (cap_count && val); + }
*offset = (u8) val;
+ //printk_debug("Offset is 0x%x \n", (u8)val); + /* If requested capability found val != 0 */ - if (!cap_count) + if (val != 0x00) return TRUE; else return FALSE; }