diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-23 20:35:56 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-28 00:52:47 -0400 |
commit | 545493917dc90298e1c38f018ad893f5518928e7 (patch) | |
tree | 1c809616d3113785c0f7dd3039ea3b05c99c6440 /arch | |
parent | d18c3db58bc544fce6662ca7edba616ca9788a70 (diff) |
[PATCH] PCI: add proper MCFG table parsing to ACPI core.
This patch is the first step in properly handling the MCFG PCI table.
It defines the structures properly, and saves off the table so that the
pci mmconfig code can access it. It moves the parsing of the table a
little later in the boot process, but still before the information is
needed.
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch')
-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 |
3 files changed, 49 insertions, 20 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 | ||