aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/pci/mmconfig.c
diff options
context:
space:
mode:
authorOlivier Galibert <galibert@pobox.com>2007-02-13 07:26:20 -0500
committerAndi Kleen <andi@basil.nowhere.org>2007-02-13 07:26:20 -0500
commitb78673944b22b662b270c8bba5c198f19e4ee4e1 (patch)
tree3cbbe3808335fc297fb3daf01dcbf26d4243a2db /arch/x86_64/pci/mmconfig.c
parent2e188938ab2358034801938c2329b016ca135823 (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/pci/mmconfig.c')
-rw-r--r--arch/x86_64/pci/mmconfig.c76
1 files changed, 12 insertions, 64 deletions
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index faabb6e87f1..0847735bb31 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
24static 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 */
27struct mmcfg_virt { 25struct mmcfg_virt {
@@ -63,8 +61,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
63static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) 61static 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) 136int __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. */
144static __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
166void __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}