diff options
| -rw-r--r-- | arch/i386/kernel/acpi/boot.c | 41 | ||||
| -rw-r--r-- | arch/i386/pci/mmconfig.c | 12 | ||||
| -rw-r--r-- | arch/x86_64/pci/mmconfig.c | 16 | ||||
| -rw-r--r-- | include/linux/acpi.h | 16 |
4 files changed, 62 insertions, 23 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index f5360d88bcf4..b7808a89d945 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
| @@ -159,9 +159,15 @@ char *__acpi_map_table(unsigned long phys, unsigned long size) | |||
| 159 | #endif | 159 | #endif |
| 160 | 160 | ||
| 161 | #ifdef CONFIG_PCI_MMCONFIG | 161 | #ifdef CONFIG_PCI_MMCONFIG |
| 162 | static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | 162 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ |
| 163 | struct acpi_table_mcfg_config *pci_mmcfg_config; | ||
| 164 | int pci_mmcfg_config_num; | ||
| 165 | |||
| 166 | int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | ||
| 163 | { | 167 | { |
| 164 | struct acpi_table_mcfg *mcfg; | 168 | struct acpi_table_mcfg *mcfg; |
| 169 | unsigned long i; | ||
| 170 | int config_size; | ||
| 165 | 171 | ||
| 166 | if (!phys_addr || !size) | 172 | if (!phys_addr || !size) |
| 167 | return -EINVAL; | 173 | return -EINVAL; |
| @@ -172,18 +178,38 @@ static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | |||
| 172 | return -ENODEV; | 178 | return -ENODEV; |
| 173 | } | 179 | } |
| 174 | 180 | ||
| 175 | if (mcfg->base_reserved) { | 181 | /* how many config structures do we have */ |
| 176 | printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); | 182 | pci_mmcfg_config_num = 0; |
| 183 | i = size - sizeof(struct acpi_table_mcfg); | ||
| 184 | while (i >= sizeof(struct acpi_table_mcfg_config)) { | ||
| 185 | ++pci_mmcfg_config_num; | ||
| 186 | i -= sizeof(struct acpi_table_mcfg_config); | ||
| 187 | }; | ||
| 188 | if (pci_mmcfg_config_num == 0) { | ||
| 189 | printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); | ||
| 177 | return -ENODEV; | 190 | return -ENODEV; |
| 178 | } | 191 | } |
| 179 | 192 | ||
| 180 | pci_mmcfg_base_addr = mcfg->base_address; | 193 | config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); |
| 194 | pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); | ||
| 195 | if (!pci_mmcfg_config) { | ||
| 196 | printk(KERN_WARNING PREFIX | ||
| 197 | "No memory for MCFG config tables\n"); | ||
| 198 | return -ENOMEM; | ||
| 199 | } | ||
| 200 | |||
| 201 | memcpy(pci_mmcfg_config, &mcfg->config, config_size); | ||
| 202 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | ||
| 203 | if (mcfg->config[i].base_reserved) { | ||
| 204 | printk(KERN_ERR PREFIX | ||
| 205 | "MMCONFIG not in low 4GB of memory\n"); | ||
| 206 | return -ENODEV; | ||
| 207 | } | ||
| 208 | } | ||
| 181 | 209 | ||
| 182 | return 0; | 210 | return 0; |
| 183 | } | 211 | } |
| 184 | #else | 212 | #endif /* CONFIG_PCI_MMCONFIG */ |
| 185 | #define acpi_parse_mcfg NULL | ||
| 186 | #endif /* !CONFIG_PCI_MMCONFIG */ | ||
| 187 | 213 | ||
| 188 | #ifdef CONFIG_X86_LOCAL_APIC | 214 | #ifdef CONFIG_X86_LOCAL_APIC |
| 189 | static int __init | 215 | static int __init |
| @@ -1139,7 +1165,6 @@ int __init acpi_boot_init(void) | |||
| 1139 | acpi_process_madt(); | 1165 | acpi_process_madt(); |
| 1140 | 1166 | ||
| 1141 | acpi_table_parse(ACPI_HPET, acpi_parse_hpet); | 1167 | acpi_table_parse(ACPI_HPET, acpi_parse_hpet); |
| 1142 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
| 1143 | 1168 | ||
| 1144 | return 0; | 1169 | return 0; |
| 1145 | } | 1170 | } |
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 021a50aa51f4..5fbaa9132258 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
| @@ -11,11 +11,9 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/acpi.h> | ||
| 14 | #include "pci.h" | 15 | #include "pci.h" |
| 15 | 16 | ||
| 16 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | ||
| 17 | u32 pci_mmcfg_base_addr; | ||
| 18 | |||
| 19 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | 17 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
| 20 | 18 | ||
| 21 | /* The base address of the last MMCONFIG device accessed */ | 19 | /* The base address of the last MMCONFIG device accessed */ |
| @@ -27,7 +25,7 @@ static u32 mmcfg_last_accessed_device; | |||
| 27 | 25 | ||
| 28 | static inline void pci_exp_set_dev_base(int bus, int devfn) | 26 | static inline void pci_exp_set_dev_base(int bus, int devfn) |
| 29 | { | 27 | { |
| 30 | u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12); | 28 | u32 dev_base = pci_mmcfg_config[0].base_address | (bus << 20) | (devfn << 12); |
| 31 | if (dev_base != mmcfg_last_accessed_device) { | 29 | if (dev_base != mmcfg_last_accessed_device) { |
| 32 | mmcfg_last_accessed_device = dev_base; | 30 | mmcfg_last_accessed_device = dev_base; |
| 33 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); | 31 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); |
| @@ -101,7 +99,11 @@ static int __init pci_mmcfg_init(void) | |||
| 101 | { | 99 | { |
| 102 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 100 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
| 103 | goto out; | 101 | goto out; |
| 104 | if (!pci_mmcfg_base_addr) | 102 | |
| 103 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
| 104 | if ((pci_mmcfg_config_num == 0) || | ||
| 105 | (pci_mmcfg_config == NULL) || | ||
| 106 | (pci_mmcfg_config[0].base_address == 0)) | ||
| 105 | goto out; | 107 | goto out; |
| 106 | 108 | ||
| 107 | /* Kludge for now. Don't use mmconfig on AMD systems because | 109 | /* Kludge for now. Don't use mmconfig on AMD systems because |
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index b693c232fd07..09cfcc1234b9 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
| @@ -7,15 +7,13 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 10 | #include <linux/acpi.h> | ||
| 10 | #include "pci.h" | 11 | #include "pci.h" |
| 11 | 12 | ||
| 12 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 13 | #define MMCONFIG_APER_SIZE (256*1024*1024) |
| 13 | 14 | ||
| 14 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | ||
| 15 | u32 pci_mmcfg_base_addr; | ||
| 16 | |||
| 17 | /* Static virtual mapping of the MMCONFIG aperture */ | 15 | /* Static virtual mapping of the MMCONFIG aperture */ |
| 18 | char *pci_mmcfg_virt; | 16 | static char *pci_mmcfg_virt; |
| 19 | 17 | ||
| 20 | static inline char *pci_dev_base(unsigned int bus, unsigned int devfn) | 18 | static inline char *pci_dev_base(unsigned int bus, unsigned int devfn) |
| 21 | { | 19 | { |
| @@ -77,7 +75,11 @@ static int __init pci_mmcfg_init(void) | |||
| 77 | { | 75 | { |
| 78 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 76 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
| 79 | return 0; | 77 | return 0; |
| 80 | if (!pci_mmcfg_base_addr) | 78 | |
| 79 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
| 80 | if ((pci_mmcfg_config_num == 0) || | ||
| 81 | (pci_mmcfg_config == NULL) || | ||
| 82 | (pci_mmcfg_config[0].base_address == 0)) | ||
| 81 | return 0; | 83 | return 0; |
| 82 | 84 | ||
| 83 | /* Kludge for now. Don't use mmconfig on AMD systems because | 85 | /* Kludge for now. Don't use mmconfig on AMD systems because |
| @@ -88,13 +90,13 @@ static int __init pci_mmcfg_init(void) | |||
| 88 | return 0; | 90 | return 0; |
| 89 | 91 | ||
| 90 | /* RED-PEN i386 doesn't do _nocache right now */ | 92 | /* RED-PEN i386 doesn't do _nocache right now */ |
| 91 | pci_mmcfg_virt = ioremap_nocache(pci_mmcfg_base_addr, MMCONFIG_APER_SIZE); | 93 | pci_mmcfg_virt = ioremap_nocache(pci_mmcfg_config[0].base_address, MMCONFIG_APER_SIZE); |
| 92 | if (!pci_mmcfg_virt) { | 94 | if (!pci_mmcfg_virt) { |
| 93 | printk("PCI: Cannot map mmconfig aperture\n"); | 95 | printk("PCI: Cannot map mmconfig aperture\n"); |
| 94 | return 0; | 96 | return 0; |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_base_addr); | 99 | printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[0].base_address); |
| 98 | raw_pci_ops = &pci_mmcfg; | 100 | raw_pci_ops = &pci_mmcfg; |
| 99 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 101 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
| 100 | 102 | ||
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f5bc298707e1..ef8483673aa3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -342,11 +342,19 @@ struct acpi_table_ecdt { | |||
| 342 | 342 | ||
| 343 | /* PCI MMCONFIG */ | 343 | /* PCI MMCONFIG */ |
| 344 | 344 | ||
| 345 | /* Defined in PCI Firmware Specification 3.0 */ | ||
| 346 | struct acpi_table_mcfg_config { | ||
| 347 | u32 base_address; | ||
| 348 | u32 base_reserved; | ||
| 349 | u16 pci_segment_group_number; | ||
| 350 | u8 start_bus_number; | ||
| 351 | u8 end_bus_number; | ||
| 352 | u8 reserved[4]; | ||
| 353 | } __attribute__ ((packed)); | ||
| 345 | struct acpi_table_mcfg { | 354 | struct acpi_table_mcfg { |
| 346 | struct acpi_table_header header; | 355 | struct acpi_table_header header; |
| 347 | u8 reserved[8]; | 356 | u8 reserved[8]; |
| 348 | u32 base_address; | 357 | struct acpi_table_mcfg_config config[0]; |
| 349 | u32 base_reserved; | ||
| 350 | } __attribute__ ((packed)); | 358 | } __attribute__ ((packed)); |
| 351 | 359 | ||
| 352 | /* Table Handlers */ | 360 | /* Table Handlers */ |
| @@ -391,6 +399,7 @@ int acpi_table_parse (enum acpi_table_id id, acpi_table_handler handler); | |||
| 391 | int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header); | 399 | int acpi_get_table_header_early (enum acpi_table_id id, struct acpi_table_header **header); |
| 392 | int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); | 400 | int acpi_table_parse_madt (enum acpi_madt_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); |
| 393 | int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); | 401 | int acpi_table_parse_srat (enum acpi_srat_entry_id id, acpi_madt_entry_handler handler, unsigned int max_entries); |
| 402 | int acpi_parse_mcfg (unsigned long phys_addr, unsigned long size); | ||
| 394 | void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr); | 403 | void acpi_table_print (struct acpi_table_header *header, unsigned long phys_addr); |
| 395 | void acpi_table_print_madt_entry (acpi_table_entry_header *madt); | 404 | void acpi_table_print_madt_entry (acpi_table_entry_header *madt); |
| 396 | void acpi_table_print_srat_entry (acpi_table_entry_header *srat); | 405 | void acpi_table_print_srat_entry (acpi_table_entry_header *srat); |
| @@ -412,7 +421,8 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base); | |||
| 412 | 421 | ||
| 413 | extern int acpi_mp_config; | 422 | extern int acpi_mp_config; |
| 414 | 423 | ||
| 415 | extern u32 pci_mmcfg_base_addr; | 424 | extern struct acpi_table_mcfg_config *pci_mmcfg_config; |
| 425 | extern int pci_mmcfg_config_num; | ||
| 416 | 426 | ||
| 417 | extern int sbf_port ; | 427 | extern int sbf_port ; |
| 418 | 428 | ||
