Commit 7fd0da4085d5b012a6bdcbbd63da7ead9fc69ad4
Committed by
Ingo Molnar
1 parent
eee206c3bf
Exists in
master
and in
4 other branches
x86_64: check MSR to get MMCONFIG for AMD Family 10h
so even booting kernel with acpi=off or even MCFG is not there, we still can use MMCONFIG. Signed-off-by: Yinghai Lu <yinghai.lu@sun.com> Cc: Andi Kleen <ak@suse.de> Cc: Greg KH <greg@kroah.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 1 changed file with 69 additions and 6 deletions Side-by-side Diff
arch/x86/pci/mmconfig-shared.c
... | ... | @@ -100,33 +100,96 @@ |
100 | 100 | return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; |
101 | 101 | } |
102 | 102 | |
103 | +static const char __init *pci_mmcfg_amd_fam10h(void) | |
104 | +{ | |
105 | + u32 low, high, address; | |
106 | + u64 base, msr; | |
107 | + int i; | |
108 | + unsigned segnbits = 0, busnbits; | |
109 | + | |
110 | + address = MSR_FAM10H_MMIO_CONF_BASE; | |
111 | + if (rdmsr_safe(address, &low, &high)) | |
112 | + return NULL; | |
113 | + | |
114 | + msr = high; | |
115 | + msr <<= 32; | |
116 | + msr |= low; | |
117 | + | |
118 | + /* mmconfig is not enable */ | |
119 | + if (!(msr & FAM10H_MMIO_CONF_ENABLE)) | |
120 | + return NULL; | |
121 | + | |
122 | + base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); | |
123 | + | |
124 | + busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & | |
125 | + FAM10H_MMIO_CONF_BUSRANGE_MASK; | |
126 | + | |
127 | + /* | |
128 | + * only handle bus 0 ? | |
129 | + * need to skip it | |
130 | + */ | |
131 | + if (!busnbits) | |
132 | + return NULL; | |
133 | + | |
134 | + if (busnbits > 8) { | |
135 | + segnbits = busnbits - 8; | |
136 | + busnbits = 8; | |
137 | + } | |
138 | + | |
139 | + pci_mmcfg_config_num = (1 << segnbits); | |
140 | + pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) * | |
141 | + pci_mmcfg_config_num, GFP_KERNEL); | |
142 | + if (!pci_mmcfg_config) | |
143 | + return NULL; | |
144 | + | |
145 | + for (i = 0; i < (1 << segnbits); i++) { | |
146 | + pci_mmcfg_config[i].address = base + (1<<28) * i; | |
147 | + pci_mmcfg_config[i].pci_segment = i; | |
148 | + pci_mmcfg_config[i].start_bus_number = 0; | |
149 | + pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1; | |
150 | + } | |
151 | + | |
152 | + return "AMD Family 10h NB"; | |
153 | +} | |
154 | + | |
103 | 155 | struct pci_mmcfg_hostbridge_probe { |
156 | + u32 bus; | |
157 | + u32 devfn; | |
104 | 158 | u32 vendor; |
105 | 159 | u32 device; |
106 | 160 | const char *(*probe)(void); |
107 | 161 | }; |
108 | 162 | |
109 | 163 | static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { |
110 | - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, | |
111 | - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, | |
164 | + { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, | |
165 | + PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, | |
166 | + { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, | |
167 | + PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, | |
168 | + { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD, | |
169 | + 0x1200, pci_mmcfg_amd_fam10h }, | |
170 | + { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD, | |
171 | + 0x1200, pci_mmcfg_amd_fam10h }, | |
112 | 172 | }; |
113 | 173 | |
114 | 174 | static int __init pci_mmcfg_check_hostbridge(void) |
115 | 175 | { |
116 | 176 | u32 l; |
177 | + u32 bus, devfn; | |
117 | 178 | u16 vendor, device; |
118 | 179 | int i; |
119 | 180 | const char *name; |
120 | 181 | |
121 | - pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0, 4, &l); | |
122 | - vendor = l & 0xffff; | |
123 | - device = (l >> 16) & 0xffff; | |
124 | - | |
125 | 182 | pci_mmcfg_config_num = 0; |
126 | 183 | pci_mmcfg_config = NULL; |
127 | 184 | name = NULL; |
128 | 185 | |
129 | 186 | for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) { |
187 | + bus = pci_mmcfg_probes[i].bus; | |
188 | + devfn = pci_mmcfg_probes[i].devfn; | |
189 | + pci_direct_conf1.read(0, bus, devfn, 0, 4, &l); | |
190 | + vendor = l & 0xffff; | |
191 | + device = (l >> 16) & 0xffff; | |
192 | + | |
130 | 193 | if (pci_mmcfg_probes[i].vendor == vendor && |
131 | 194 | pci_mmcfg_probes[i].device == device) |
132 | 195 | name = pci_mmcfg_probes[i].probe(); |