diff options
Diffstat (limited to 'arch/i386/pci/mmconfig.c')
-rw-r--r-- | arch/i386/pci/mmconfig.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 972180f738d9..05be8db58a8c 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -151,6 +151,38 @@ static struct pci_raw_ops pci_mmcfg = { | |||
151 | .write = pci_mmcfg_write, | 151 | .write = pci_mmcfg_write, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | |||
155 | static __init void pci_mmcfg_insert_resources(void) | ||
156 | { | ||
157 | #define PCI_MMCFG_RESOURCE_NAME_LEN 19 | ||
158 | int i; | ||
159 | struct resource *res; | ||
160 | char *names; | ||
161 | unsigned num_buses; | ||
162 | |||
163 | res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), | ||
164 | pci_mmcfg_config_num, GFP_KERNEL); | ||
165 | |||
166 | if (!res) { | ||
167 | printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | names = (void *)&res[pci_mmcfg_config_num]; | ||
172 | for (i = 0; i < pci_mmcfg_config_num; i++, res++) { | ||
173 | num_buses = pci_mmcfg_config[i].end_bus_number - | ||
174 | pci_mmcfg_config[i].start_bus_number + 1; | ||
175 | res->name = names; | ||
176 | snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u", | ||
177 | pci_mmcfg_config[i].pci_segment_group_number); | ||
178 | res->start = pci_mmcfg_config[i].base_address; | ||
179 | res->end = res->start + (num_buses << 20) - 1; | ||
180 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
181 | insert_resource(&iomem_resource, res); | ||
182 | names += PCI_MMCFG_RESOURCE_NAME_LEN; | ||
183 | } | ||
184 | } | ||
185 | |||
154 | /* K8 systems have some devices (typically in the builtin northbridge) | 186 | /* K8 systems have some devices (typically in the builtin northbridge) |
155 | that are only accessible using type1 | 187 | that are only accessible using type1 |
156 | Normally this can be expressed in the MCFG by not listing them | 188 | Normally this can be expressed in the MCFG by not listing them |
@@ -187,7 +219,9 @@ static __init void unreachable_devices(void) | |||
187 | } | 219 | } |
188 | } | 220 | } |
189 | 221 | ||
190 | void __init pci_mmcfg_init(void) | 222 | |
223 | |||
224 | void __init pci_mmcfg_init(int type) | ||
191 | { | 225 | { |
192 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 226 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
193 | return; | 227 | return; |
@@ -198,7 +232,9 @@ void __init pci_mmcfg_init(void) | |||
198 | (pci_mmcfg_config[0].base_address == 0)) | 232 | (pci_mmcfg_config[0].base_address == 0)) |
199 | return; | 233 | return; |
200 | 234 | ||
201 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | 235 | /* Only do this check when type 1 works. If it doesn't work |
236 | assume we run on a Mac and always use MCFG */ | ||
237 | if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].base_address, | ||
202 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, | 238 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, |
203 | E820_RESERVED)) { | 239 | E820_RESERVED)) { |
204 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", | 240 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", |
@@ -212,4 +248,5 @@ void __init pci_mmcfg_init(void) | |||
212 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 248 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
213 | 249 | ||
214 | unreachable_devices(); | 250 | unreachable_devices(); |
251 | pci_mmcfg_insert_resources(); | ||
215 | } | 252 | } |