diff options
author | Olivier Galibert <galibert@pobox.com> | 2007-02-13 07:26:20 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-02-13 07:26:20 -0500 |
commit | b78673944b22b662b270c8bba5c198f19e4ee4e1 (patch) | |
tree | 3cbbe3808335fc297fb3daf01dcbf26d4243a2db /arch/x86_64 | |
parent | 2e188938ab2358034801938c2329b016ca135823 (diff) |
[PATCH] mmconfig: Share parts of mmconfig code between i386 and x86-64
i386 and x86-64 pci mmconfig code have a lot in common. So share what's
shareable between the two.
Signed-off-by: Olivier Galibert <galibert@pobox.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/pci/Makefile | 3 | ||||
-rw-r--r-- | arch/x86_64/pci/mmconfig.c | 76 |
2 files changed, 14 insertions, 65 deletions
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile index 149aba05a5b8..c9eddc8859c0 100644 --- a/arch/x86_64/pci/Makefile +++ b/arch/x86_64/pci/Makefile | |||
@@ -11,7 +11,7 @@ obj-y += fixup.o init.o | |||
11 | obj-$(CONFIG_ACPI) += acpi.o | 11 | obj-$(CONFIG_ACPI) += acpi.o |
12 | obj-y += legacy.o irq.o common.o early.o | 12 | obj-y += legacy.o irq.o common.o early.o |
13 | # mmconfig has a 64bit special | 13 | # mmconfig has a 64bit special |
14 | obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o | 14 | obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o |
15 | 15 | ||
16 | obj-$(CONFIG_NUMA) += k8-bus.o | 16 | obj-$(CONFIG_NUMA) += k8-bus.o |
17 | 17 | ||
@@ -24,3 +24,4 @@ fixup-y += ../../i386/pci/fixup.o | |||
24 | i386-y += ../../i386/pci/i386.o | 24 | i386-y += ../../i386/pci/i386.o |
25 | init-y += ../../i386/pci/init.o | 25 | init-y += ../../i386/pci/init.o |
26 | early-y += ../../i386/pci/early.o | 26 | early-y += ../../i386/pci/early.o |
27 | mmconfig-shared-y += ../../i386/pci/mmconfig-shared.o | ||
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index faabb6e87f12..0847735bb31e 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
@@ -19,9 +19,7 @@ | |||
19 | 19 | ||
20 | /* Verify the first 16 busses. We assume that systems with more busses | 20 | /* Verify the first 16 busses. We assume that systems with more busses |
21 | get MCFG right. */ | 21 | get MCFG right. */ |
22 | #define MAX_CHECK_BUS 16 | 22 | #define PCI_MMCFG_MAX_CHECK_BUS 16 |
23 | |||
24 | static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS); | ||
25 | 23 | ||
26 | /* Static virtual mapping of the MMCONFIG aperture */ | 24 | /* Static virtual mapping of the MMCONFIG aperture */ |
27 | struct mmcfg_virt { | 25 | struct mmcfg_virt { |
@@ -63,8 +61,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus) | |||
63 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) | 61 | static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) |
64 | { | 62 | { |
65 | char __iomem *addr; | 63 | char __iomem *addr; |
66 | if (seg == 0 && bus < MAX_CHECK_BUS && | 64 | if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS && |
67 | test_bit(32*bus + PCI_SLOT(devfn), fallback_slots)) | 65 | test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots)) |
68 | return NULL; | 66 | return NULL; |
69 | addr = get_virt(seg, bus); | 67 | addr = get_virt(seg, bus); |
70 | if (!addr) | 68 | if (!addr) |
@@ -135,63 +133,16 @@ static struct pci_raw_ops pci_mmcfg = { | |||
135 | .write = pci_mmcfg_write, | 133 | .write = pci_mmcfg_write, |
136 | }; | 134 | }; |
137 | 135 | ||
138 | /* K8 systems have some devices (typically in the builtin northbridge) | 136 | int __init pci_mmcfg_arch_init(void) |
139 | that are only accessible using type1 | ||
140 | Normally this can be expressed in the MCFG by not listing them | ||
141 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
142 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
143 | and fallback for them. */ | ||
144 | static __init void unreachable_devices(void) | ||
145 | { | ||
146 | int i, k; | ||
147 | /* Use the max bus number from ACPI here? */ | ||
148 | for (k = 0; k < MAX_CHECK_BUS; k++) { | ||
149 | for (i = 0; i < 32; i++) { | ||
150 | u32 val1; | ||
151 | char __iomem *addr; | ||
152 | |||
153 | pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1); | ||
154 | if (val1 == 0xffffffff) | ||
155 | continue; | ||
156 | addr = pci_dev_base(0, k, PCI_DEVFN(i, 0)); | ||
157 | if (addr == NULL|| readl(addr) != val1) { | ||
158 | set_bit(i + 32*k, fallback_slots); | ||
159 | printk(KERN_NOTICE "PCI: No mmconfig possible" | ||
160 | " on device %02x:%02x\n", k, i); | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | void __init pci_mmcfg_init(int type) | ||
167 | { | 137 | { |
168 | int i; | 138 | int i; |
169 | 139 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * | |
170 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 140 | pci_mmcfg_config_num, GFP_KERNEL); |
171 | return; | ||
172 | |||
173 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
174 | if ((pci_mmcfg_config_num == 0) || | ||
175 | (pci_mmcfg_config == NULL) || | ||
176 | (pci_mmcfg_config[0].address == 0)) | ||
177 | return; | ||
178 | |||
179 | /* Only do this check when type 1 works. If it doesn't work | ||
180 | assume we run on a Mac and always use MCFG */ | ||
181 | if (type == 1 && !e820_all_mapped(pci_mmcfg_config[0].address, | ||
182 | pci_mmcfg_config[0].address + MMCONFIG_APER_MIN, | ||
183 | E820_RESERVED)) { | ||
184 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not E820-reserved\n", | ||
185 | (unsigned long)pci_mmcfg_config[0].address); | ||
186 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); | ||
191 | if (pci_mmcfg_virt == NULL) { | 141 | if (pci_mmcfg_virt == NULL) { |
192 | printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); | 142 | printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); |
193 | return; | 143 | return 0; |
194 | } | 144 | } |
145 | |||
195 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | 146 | for (i = 0; i < pci_mmcfg_config_num; ++i) { |
196 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; | 147 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; |
197 | pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address, | 148 | pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].address, |
@@ -200,14 +151,11 @@ void __init pci_mmcfg_init(int type) | |||
200 | printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " | 151 | printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " |
201 | "segment %d\n", | 152 | "segment %d\n", |
202 | pci_mmcfg_config[i].pci_segment); | 153 | pci_mmcfg_config[i].pci_segment); |
203 | return; | 154 | return 0; |
204 | } | 155 | } |
205 | printk(KERN_INFO "PCI: Using MMCONFIG at %lx\n", | 156 | printk(KERN_INFO "PCI: Using MMCONFIG at %Lx\n", |
206 | (unsigned long)pci_mmcfg_config[i].address); | 157 | pci_mmcfg_config[i].address); |
207 | } | 158 | } |
208 | |||
209 | unreachable_devices(); | ||
210 | |||
211 | raw_pci_ops = &pci_mmcfg; | 159 | raw_pci_ops = &pci_mmcfg; |
212 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 160 | return 1; |
213 | } | 161 | } |