direct-io.hg

view patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch @ 12988:e080700efa56

[TOOLS] Fix the build. Clearly demarcate PPC-specific stuff.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Dec 13 10:23:53 2006 +0000 (2006-12-13)
parents 6c2c7ff6265a
children
line source
1 diff -pruN ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c ./arch/i386/pci/mmconfig.c
2 --- ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c 2006-09-12 19:02:10.000000000 +0100
3 +++ ./arch/i386/pci/mmconfig.c 2006-09-21 09:35:27.000000000 +0100
4 @@ -12,14 +12,22 @@
5 #include <linux/pci.h>
6 #include <linux/init.h>
7 #include <linux/acpi.h>
8 +#include <asm/e820.h>
9 #include "pci.h"
11 +/* aperture is up to 256MB but BIOS may reserve less */
12 +#define MMCONFIG_APER_MIN (2 * 1024*1024)
13 +#define MMCONFIG_APER_MAX (256 * 1024*1024)
14 +
15 +/* Assume systems with more busses have correct MCFG */
16 +#define MAX_CHECK_BUS 16
17 +
18 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
20 /* The base address of the last MMCONFIG device accessed */
21 static u32 mmcfg_last_accessed_device;
23 -static DECLARE_BITMAP(fallback_slots, 32);
24 +static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
26 /*
27 * Functions for accessing PCI configuration space with MMCONFIG accesses
28 @@ -29,8 +37,8 @@ static u32 get_base_addr(unsigned int se
29 int cfg_num = -1;
30 struct acpi_table_mcfg_config *cfg;
32 - if (seg == 0 && bus == 0 &&
33 - test_bit(PCI_SLOT(devfn), fallback_slots))
34 + if (seg == 0 && bus < MAX_CHECK_BUS &&
35 + test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
36 return 0;
38 while (1) {
39 @@ -74,8 +82,10 @@ static int pci_mmcfg_read(unsigned int s
40 unsigned long flags;
41 u32 base;
43 - if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
44 + if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
45 + *value = -1;
46 return -EINVAL;
47 + }
49 base = get_base_addr(seg, bus, devfn);
50 if (!base)
51 @@ -146,30 +156,66 @@ static struct pci_raw_ops pci_mmcfg = {
52 Normally this can be expressed in the MCFG by not listing them
53 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
54 Instead try to discover all devices on bus 0 that are unreachable using MM
55 - and fallback for them.
56 - We only do this for bus 0/seg 0 */
57 + and fallback for them. */
58 static __init void unreachable_devices(void)
59 {
60 - int i;
61 + int i, k;
62 unsigned long flags;
64 - for (i = 0; i < 32; i++) {
65 - u32 val1;
66 - u32 addr;
67 + for (k = 0; k < MAX_CHECK_BUS; k++) {
68 + for (i = 0; i < 32; i++) {
69 + u32 val1;
70 + u32 addr;
71 +
72 + pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
73 + if (val1 == 0xffffffff)
74 + continue;
75 +
76 + /* Locking probably not needed, but safer */
77 + spin_lock_irqsave(&pci_config_lock, flags);
78 + addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
79 + if (addr != 0)
80 + pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
81 + if (addr == 0 ||
82 + readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
83 + set_bit(i, fallback_slots);
84 + printk(KERN_NOTICE
85 + "PCI: No mmconfig possible on %x:%x\n", k, i);
86 + }
87 + spin_unlock_irqrestore(&pci_config_lock, flags);
88 + }
89 + }
90 +}
92 - pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
93 - if (val1 == 0xffffffff)
94 +/* NB. Ripped from arch/i386/kernel/setup.c for this Xen bugfix patch. */
95 +#ifdef CONFIG_XEN
96 +extern struct e820map machine_e820;
97 +#define e820 machine_e820
98 +#endif
99 +static int __init
100 +e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
101 +{
102 + u64 start = s;
103 + u64 end = e;
104 + int i;
105 + for (i = 0; i < e820.nr_map; i++) {
106 + struct e820entry *ei = &e820.map[i];
107 + if (type && ei->type != type)
108 continue;
109 -
110 - /* Locking probably not needed, but safer */
111 - spin_lock_irqsave(&pci_config_lock, flags);
112 - addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
113 - if (addr != 0)
114 - pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
115 - if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
116 - set_bit(i, fallback_slots);
117 - spin_unlock_irqrestore(&pci_config_lock, flags);
118 + /* is the region (part) in overlap with the current region ?*/
119 + if (ei->addr >= end || ei->addr + ei->size <= start)
120 + continue;
121 + /* if the region is at the beginning of <start,end> we move
122 + * start to the end of the region since it's ok until there
123 + */
124 + if (ei->addr <= start)
125 + start = ei->addr + ei->size;
126 + /* if start is now at or beyond end, we're done, full
127 + * coverage */
128 + if (start >= end)
129 + return 1; /* we're done */
130 }
131 + return 0;
132 }
134 static int __init pci_mmcfg_init(void)
135 @@ -183,6 +229,15 @@ static int __init pci_mmcfg_init(void)
136 (pci_mmcfg_config[0].base_address == 0))
137 goto out;
139 + if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
140 + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
141 + E820_RESERVED)) {
142 + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
143 + pci_mmcfg_config[0].base_address);
144 + printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
145 + goto out;
146 + }
147 +
148 printk(KERN_INFO "PCI: Using MMCONFIG\n");
149 raw_pci_ops = &pci_mmcfg;
150 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
151 diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c ./arch/x86_64/pci/mmconfig.c
152 --- ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c 2006-09-12 19:02:10.000000000 +0100
153 +++ ./arch/x86_64/pci/mmconfig.c 2006-09-21 09:35:40.000000000 +0100
154 @@ -9,11 +9,19 @@
155 #include <linux/init.h>
156 #include <linux/acpi.h>
157 #include <linux/bitmap.h>
158 +#include <asm/e820.h>
159 +
160 #include "pci.h"
162 -#define MMCONFIG_APER_SIZE (256*1024*1024)
163 +/* aperture is up to 256MB but BIOS may reserve less */
164 +#define MMCONFIG_APER_MIN (2 * 1024*1024)
165 +#define MMCONFIG_APER_MAX (256 * 1024*1024)
166 +
167 +/* Verify the first 16 busses. We assume that systems with more busses
168 + get MCFG right. */
169 +#define MAX_CHECK_BUS 16
171 -static DECLARE_BITMAP(fallback_slots, 32);
172 +static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
174 /* Static virtual mapping of the MMCONFIG aperture */
175 struct mmcfg_virt {
176 @@ -55,7 +63,8 @@ static char __iomem *get_virt(unsigned i
177 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
178 {
179 char __iomem *addr;
180 - if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots))
181 + if (seg == 0 && bus < MAX_CHECK_BUS &&
182 + test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
183 return NULL;
184 addr = get_virt(seg, bus);
185 if (!addr)
186 @@ -69,8 +78,10 @@ static int pci_mmcfg_read(unsigned int s
187 char __iomem *addr;
189 /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
190 - if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
191 + if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
192 + *value = -1;
193 return -EINVAL;
194 + }
196 addr = pci_dev_base(seg, bus, devfn);
197 if (!addr)
198 @@ -129,23 +140,56 @@ static struct pci_raw_ops pci_mmcfg = {
199 Normally this can be expressed in the MCFG by not listing them
200 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
201 Instead try to discover all devices on bus 0 that are unreachable using MM
202 - and fallback for them.
203 - We only do this for bus 0/seg 0 */
204 + and fallback for them. */
205 static __init void unreachable_devices(void)
206 {
207 - int i;
208 - for (i = 0; i < 32; i++) {
209 - u32 val1;
210 - char __iomem *addr;
211 + int i, k;
212 + /* Use the max bus number from ACPI here? */
213 + for (k = 0; k < MAX_CHECK_BUS; k++) {
214 + for (i = 0; i < 32; i++) {
215 + u32 val1;
216 + char __iomem *addr;
217 +
218 + pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
219 + if (val1 == 0xffffffff)
220 + continue;
221 + addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
222 + if (addr == NULL|| readl(addr) != val1) {
223 + set_bit(i + 32*k, fallback_slots);
224 + printk(KERN_NOTICE
225 + "PCI: No mmconfig possible on device %x:%x\n",
226 + k, i);
227 + }
228 + }
229 + }
230 +}
232 - pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
233 - if (val1 == 0xffffffff)
234 +/* NB. Ripped from arch/x86_64/kernel/e820.c for this Xen bugfix patch. */
235 +#ifdef CONFIG_XEN
236 +extern struct e820map machine_e820;
237 +#define e820 machine_e820
238 +#endif
239 +static int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
240 +{
241 + int i;
242 + for (i = 0; i < e820.nr_map; i++) {
243 + struct e820entry *ei = &e820.map[i];
244 + if (type && ei->type != type)
245 continue;
246 - addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
247 - if (addr == NULL|| readl(addr) != val1) {
248 - set_bit(i, &fallback_slots);
249 - }
250 + /* is the region (part) in overlap with the current region ?*/
251 + if (ei->addr >= end || ei->addr + ei->size <= start)
252 + continue;
253 +
254 + /* if the region is at the beginning of <start,end> we move
255 + * start to the end of the region since it's ok until there
256 + */
257 + if (ei->addr <= start)
258 + start = ei->addr + ei->size;
259 + /* if start is now at or beyond end, we're done, full coverage */
260 + if (start >= end)
261 + return 1; /* we're done */
262 }
263 + return 0;
264 }
266 static int __init pci_mmcfg_init(void)
267 @@ -161,6 +205,15 @@ static int __init pci_mmcfg_init(void)
268 (pci_mmcfg_config[0].base_address == 0))
269 return 0;
271 + if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
272 + pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
273 + E820_RESERVED)) {
274 + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
275 + pci_mmcfg_config[0].base_address);
276 + printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
277 + return 0;
278 + }
279 +
280 /* RED-PEN i386 doesn't do _nocache right now */
281 pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
282 if (pci_mmcfg_virt == NULL) {
283 @@ -169,7 +222,8 @@ static int __init pci_mmcfg_init(void)
284 }
285 for (i = 0; i < pci_mmcfg_config_num; ++i) {
286 pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
287 - pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
288 + pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
289 + MMCONFIG_APER_MAX);
290 if (!pci_mmcfg_virt[i].virt) {
291 printk("PCI: Cannot map mmconfig aperture for segment %d\n",
292 pci_mmcfg_config[i].pci_segment_group_number);