[PATCH 2/3] x86_64: check MSR to get MMCONFIG for AMD Family 10hOpteron
From: Yinghai Lu
Date: Mon Jan 14 2008 - 16:34:22 EST
[PATCH 2/3] x86_64: check MSR to get MMCONFIG for AMD Family 10h Opteron
So even MCFG is not there, we still can use MMCONFIG.
Signed-off-by: Yinghai Lu <yinghai.lu@xxxxxxx>
Index: linux-2.6/arch/x86/pci/mmconfig-shared.c
===================================================================
--- linux-2.6.orig/arch/x86/pci/mmconfig-shared.c
+++ linux-2.6/arch/x86/pci/mmconfig-shared.c
@@ -133,33 +133,84 @@ static const char __init *pci_mmcfg_inte
return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
}
+static const char __init *pci_mmcfg_amd_fam10h(void)
+{
+ u32 low, high, address;
+ u64 base;
+ int i;
+ unsigned segnbits = 0, busnbits;
+
+ address = 0xc0010058;
+ if (rdmsr_safe(address, &low, &high))
+ return NULL;
+
+ /* mmconfig is not enable */
+ if (!(low & 1))
+ return NULL;
+
+ base = high & 0xffff;
+ base <<= 32;
+
+ busnbits = (low >> 2) & 0x0f;
+ if (busnbits > 8) {
+ segnbits = busnbits - 8;
+ busnbits = 8;
+ }
+
+ pci_mmcfg_config_num = (1 << segnbits);
+ pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) *
+ pci_mmcfg_config_num, GFP_KERNEL);
+ if (!pci_mmcfg_config)
+ return NULL;
+
+ for (i = 0; i < (1 << segnbits); i++) {
+ pci_mmcfg_config[i].address = base + (1<<28) * i;
+ pci_mmcfg_config[i].pci_segment = i;
+ pci_mmcfg_config[i].start_bus_number = 0;
+ pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
+ }
+
+ return "AMD Family 10h NB";
+}
+
struct pci_mmcfg_hostbridge_probe {
+ u32 bus;
+ u32 devfn;
u32 vendor;
u32 device;
const char *(*probe)(void);
};
static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+ { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+ { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+ { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
+ 0x1200, pci_mmcfg_amd_fam10h },
+ { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
+ 0x1200, pci_mmcfg_amd_fam10h },
};
static int __init pci_mmcfg_check_hostbridge(void)
{
u32 l;
+ u32 bus, devfn;
u16 vendor, device;
int i;
const char *name;
- pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
- vendor = l & 0xffff;
- device = (l >> 16) & 0xffff;
-
pci_mmcfg_config_num = 0;
pci_mmcfg_config = NULL;
name = NULL;
for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+ bus = pci_mmcfg_probes[i].bus;
+ devfn = pci_mmcfg_probes[i].devfn;
+ pci_conf1_read(0, bus, devfn, 0, 4, &l);
+ vendor = l & 0xffff;
+ device = (l >> 16) & 0xffff;
+
if (pci_mmcfg_probes[i].vendor == vendor &&
pci_mmcfg_probes[i].device == device)
name = pci_mmcfg_probes[i].probe();
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/