diff options
-rw-r--r-- | arch/x86/kernel/aperture_64.c | 230 |
1 files changed, 139 insertions, 91 deletions
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index c63f8d9fad3e..02f4dbaa4df4 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c | |||
@@ -35,6 +35,18 @@ int fallback_aper_force __initdata; | |||
35 | 35 | ||
36 | int fix_aperture __initdata = 1; | 36 | int fix_aperture __initdata = 1; |
37 | 37 | ||
38 | struct bus_dev_range { | ||
39 | int bus; | ||
40 | int dev_base; | ||
41 | int dev_limit; | ||
42 | }; | ||
43 | |||
44 | static struct bus_dev_range bus_dev_ranges[] __initdata = { | ||
45 | { 0x00, 0x18, 0x20}, | ||
46 | { 0xff, 0x00, 0x20}, | ||
47 | { 0xfe, 0x00, 0x20} | ||
48 | }; | ||
49 | |||
38 | static struct resource gart_resource = { | 50 | static struct resource gart_resource = { |
39 | .name = "GART", | 51 | .name = "GART", |
40 | .flags = IORESOURCE_MEM, | 52 | .flags = IORESOURCE_MEM, |
@@ -120,33 +132,33 @@ static int __init aperture_valid(u64 aper_base, u32 aper_size, u32 min_size) | |||
120 | } | 132 | } |
121 | 133 | ||
122 | /* Find a PCI capability */ | 134 | /* Find a PCI capability */ |
123 | static __u32 __init find_cap(int num, int slot, int func, int cap) | 135 | static __u32 __init find_cap(int bus, int slot, int func, int cap) |
124 | { | 136 | { |
125 | int bytes; | 137 | int bytes; |
126 | u8 pos; | 138 | u8 pos; |
127 | 139 | ||
128 | if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & | 140 | if (!(read_pci_config_16(bus, slot, func, PCI_STATUS) & |
129 | PCI_STATUS_CAP_LIST)) | 141 | PCI_STATUS_CAP_LIST)) |
130 | return 0; | 142 | return 0; |
131 | 143 | ||
132 | pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); | 144 | pos = read_pci_config_byte(bus, slot, func, PCI_CAPABILITY_LIST); |
133 | for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { | 145 | for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { |
134 | u8 id; | 146 | u8 id; |
135 | 147 | ||
136 | pos &= ~3; | 148 | pos &= ~3; |
137 | id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); | 149 | id = read_pci_config_byte(bus, slot, func, pos+PCI_CAP_LIST_ID); |
138 | if (id == 0xff) | 150 | if (id == 0xff) |
139 | break; | 151 | break; |
140 | if (id == cap) | 152 | if (id == cap) |
141 | return pos; | 153 | return pos; |
142 | pos = read_pci_config_byte(num, slot, func, | 154 | pos = read_pci_config_byte(bus, slot, func, |
143 | pos+PCI_CAP_LIST_NEXT); | 155 | pos+PCI_CAP_LIST_NEXT); |
144 | } | 156 | } |
145 | return 0; | 157 | return 0; |
146 | } | 158 | } |
147 | 159 | ||
148 | /* Read a standard AGPv3 bridge header */ | 160 | /* Read a standard AGPv3 bridge header */ |
149 | static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) | 161 | static __u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order) |
150 | { | 162 | { |
151 | u32 apsize; | 163 | u32 apsize; |
152 | u32 apsizereg; | 164 | u32 apsizereg; |
@@ -155,8 +167,8 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) | |||
155 | u64 aper; | 167 | u64 aper; |
156 | u32 old_order; | 168 | u32 old_order; |
157 | 169 | ||
158 | printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", num, slot, func); | 170 | printk(KERN_INFO "AGP bridge at %02x:%02x:%02x\n", bus, slot, func); |
159 | apsizereg = read_pci_config_16(num, slot, func, cap + 0x14); | 171 | apsizereg = read_pci_config_16(bus, slot, func, cap + 0x14); |
160 | if (apsizereg == 0xffffffff) { | 172 | if (apsizereg == 0xffffffff) { |
161 | printk(KERN_ERR "APSIZE in AGP bridge unreadable\n"); | 173 | printk(KERN_ERR "APSIZE in AGP bridge unreadable\n"); |
162 | return 0; | 174 | return 0; |
@@ -174,8 +186,8 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) | |||
174 | if ((int)*order < 0) /* < 32MB */ | 186 | if ((int)*order < 0) /* < 32MB */ |
175 | *order = 0; | 187 | *order = 0; |
176 | 188 | ||
177 | aper_low = read_pci_config(num, slot, func, 0x10); | 189 | aper_low = read_pci_config(bus, slot, func, 0x10); |
178 | aper_hi = read_pci_config(num, slot, func, 0x14); | 190 | aper_hi = read_pci_config(bus, slot, func, 0x14); |
179 | aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); | 191 | aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32); |
180 | 192 | ||
181 | /* | 193 | /* |
@@ -213,15 +225,15 @@ static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order) | |||
213 | */ | 225 | */ |
214 | static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) | 226 | static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) |
215 | { | 227 | { |
216 | int num, slot, func; | 228 | int bus, slot, func; |
217 | 229 | ||
218 | /* Poor man's PCI discovery */ | 230 | /* Poor man's PCI discovery */ |
219 | for (num = 0; num < 256; num++) { | 231 | for (bus = 0; bus < 256; bus++) { |
220 | for (slot = 0; slot < 32; slot++) { | 232 | for (slot = 0; slot < 32; slot++) { |
221 | for (func = 0; func < 8; func++) { | 233 | for (func = 0; func < 8; func++) { |
222 | u32 class, cap; | 234 | u32 class, cap; |
223 | u8 type; | 235 | u8 type; |
224 | class = read_pci_config(num, slot, func, | 236 | class = read_pci_config(bus, slot, func, |
225 | PCI_CLASS_REVISION); | 237 | PCI_CLASS_REVISION); |
226 | if (class == 0xffffffff) | 238 | if (class == 0xffffffff) |
227 | break; | 239 | break; |
@@ -230,17 +242,17 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) | |||
230 | case PCI_CLASS_BRIDGE_HOST: | 242 | case PCI_CLASS_BRIDGE_HOST: |
231 | case PCI_CLASS_BRIDGE_OTHER: /* needed? */ | 243 | case PCI_CLASS_BRIDGE_OTHER: /* needed? */ |
232 | /* AGP bridge? */ | 244 | /* AGP bridge? */ |
233 | cap = find_cap(num, slot, func, | 245 | cap = find_cap(bus, slot, func, |
234 | PCI_CAP_ID_AGP); | 246 | PCI_CAP_ID_AGP); |
235 | if (!cap) | 247 | if (!cap) |
236 | break; | 248 | break; |
237 | *valid_agp = 1; | 249 | *valid_agp = 1; |
238 | return read_agp(num, slot, func, cap, | 250 | return read_agp(bus, slot, func, cap, |
239 | order); | 251 | order); |
240 | } | 252 | } |
241 | 253 | ||
242 | /* No multi-function device? */ | 254 | /* No multi-function device? */ |
243 | type = read_pci_config_byte(num, slot, func, | 255 | type = read_pci_config_byte(bus, slot, func, |
244 | PCI_HEADER_TYPE); | 256 | PCI_HEADER_TYPE); |
245 | if (!(type & 0x80)) | 257 | if (!(type & 0x80)) |
246 | break; | 258 | break; |
@@ -280,38 +292,49 @@ void __init early_gart_iommu_check(void) | |||
280 | * or BIOS forget to put that in reserved. | 292 | * or BIOS forget to put that in reserved. |
281 | * try to update e820 to make that region as reserved. | 293 | * try to update e820 to make that region as reserved. |
282 | */ | 294 | */ |
283 | int fix, num; | 295 | int fix, slot; |
284 | u32 ctl; | 296 | u32 ctl; |
285 | u32 aper_size = 0, aper_order = 0, last_aper_order = 0; | 297 | u32 aper_size = 0, aper_order = 0, last_aper_order = 0; |
286 | u64 aper_base = 0, last_aper_base = 0; | 298 | u64 aper_base = 0, last_aper_base = 0; |
287 | int aper_enabled = 0, last_aper_enabled = 0; | 299 | int aper_enabled = 0, last_aper_enabled = 0; |
300 | int i; | ||
288 | 301 | ||
289 | if (!early_pci_allowed()) | 302 | if (!early_pci_allowed()) |
290 | return; | 303 | return; |
291 | 304 | ||
292 | fix = 0; | 305 | fix = 0; |
293 | for (num = 24; num < 32; num++) { | 306 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { |
294 | if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) | 307 | int bus; |
295 | continue; | 308 | int dev_base, dev_limit; |
296 | 309 | ||
297 | ctl = read_pci_config(0, num, 3, 0x90); | 310 | bus = bus_dev_ranges[i].bus; |
298 | aper_enabled = ctl & 1; | 311 | dev_base = bus_dev_ranges[i].dev_base; |
299 | aper_order = (ctl >> 1) & 7; | 312 | dev_limit = bus_dev_ranges[i].dev_limit; |
300 | aper_size = (32 * 1024 * 1024) << aper_order; | 313 | |
301 | aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; | 314 | for (slot = dev_base; slot < dev_limit; slot++) { |
302 | aper_base <<= 25; | 315 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) |
303 | 316 | continue; | |
304 | if ((last_aper_order && aper_order != last_aper_order) || | 317 | |
305 | (last_aper_base && aper_base != last_aper_base) || | 318 | ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL); |
306 | (last_aper_enabled && aper_enabled != last_aper_enabled)) { | 319 | aper_enabled = ctl & AMD64_GARTEN; |
307 | fix = 1; | 320 | aper_order = (ctl >> 1) & 7; |
308 | break; | 321 | aper_size = (32 * 1024 * 1024) << aper_order; |
322 | aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff; | ||
323 | aper_base <<= 25; | ||
324 | |||
325 | if ((last_aper_order && aper_order != last_aper_order) || | ||
326 | (last_aper_base && aper_base != last_aper_base) || | ||
327 | (last_aper_enabled && aper_enabled != last_aper_enabled)) { | ||
328 | fix = 1; | ||
329 | goto out; | ||
330 | } | ||
331 | last_aper_order = aper_order; | ||
332 | last_aper_base = aper_base; | ||
333 | last_aper_enabled = aper_enabled; | ||
309 | } | 334 | } |
310 | last_aper_order = aper_order; | ||
311 | last_aper_base = aper_base; | ||
312 | last_aper_enabled = aper_enabled; | ||
313 | } | 335 | } |
314 | 336 | ||
337 | out: | ||
315 | if (!fix && !aper_enabled) | 338 | if (!fix && !aper_enabled) |
316 | return; | 339 | return; |
317 | 340 | ||
@@ -330,13 +353,22 @@ void __init early_gart_iommu_check(void) | |||
330 | } | 353 | } |
331 | 354 | ||
332 | /* different nodes have different setting, disable them all at first*/ | 355 | /* different nodes have different setting, disable them all at first*/ |
333 | for (num = 24; num < 32; num++) { | 356 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { |
334 | if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) | 357 | int bus; |
335 | continue; | 358 | int dev_base, dev_limit; |
359 | |||
360 | bus = bus_dev_ranges[i].bus; | ||
361 | dev_base = bus_dev_ranges[i].dev_base; | ||
362 | dev_limit = bus_dev_ranges[i].dev_limit; | ||
336 | 363 | ||
337 | ctl = read_pci_config(0, num, 3, 0x90); | 364 | for (slot = dev_base; slot < dev_limit; slot++) { |
338 | ctl &= ~1; | 365 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) |
339 | write_pci_config(0, num, 3, 0x90, ctl); | 366 | continue; |
367 | |||
368 | ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL); | ||
369 | ctl &= ~AMD64_GARTEN; | ||
370 | write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl); | ||
371 | } | ||
340 | } | 372 | } |
341 | 373 | ||
342 | } | 374 | } |
@@ -348,8 +380,8 @@ void __init gart_iommu_hole_init(void) | |||
348 | u32 agp_aper_base = 0, agp_aper_order = 0; | 380 | u32 agp_aper_base = 0, agp_aper_order = 0; |
349 | u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; | 381 | u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; |
350 | u64 aper_base, last_aper_base = 0; | 382 | u64 aper_base, last_aper_base = 0; |
351 | int fix, num, valid_agp = 0; | 383 | int fix, slot, valid_agp = 0; |
352 | int node; | 384 | int i, node; |
353 | 385 | ||
354 | if (gart_iommu_aperture_disabled || !fix_aperture || | 386 | if (gart_iommu_aperture_disabled || !fix_aperture || |
355 | !early_pci_allowed()) | 387 | !early_pci_allowed()) |
@@ -362,48 +394,58 @@ void __init gart_iommu_hole_init(void) | |||
362 | 394 | ||
363 | fix = 0; | 395 | fix = 0; |
364 | node = 0; | 396 | node = 0; |
365 | for (num = 24; num < 32; num++) { | 397 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { |
366 | if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) | 398 | int bus; |
367 | continue; | 399 | int dev_base, dev_limit; |
368 | 400 | ||
369 | iommu_detected = 1; | 401 | bus = bus_dev_ranges[i].bus; |
370 | gart_iommu_aperture = 1; | 402 | dev_base = bus_dev_ranges[i].dev_base; |
371 | 403 | dev_limit = bus_dev_ranges[i].dev_limit; | |
372 | aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; | 404 | |
373 | aper_size = (32 * 1024 * 1024) << aper_order; | 405 | for (slot = dev_base; slot < dev_limit; slot++) { |
374 | aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; | 406 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) |
375 | aper_base <<= 25; | 407 | continue; |
376 | 408 | ||
377 | printk(KERN_INFO "Node %d: aperture @ %Lx size %u MB\n", | 409 | iommu_detected = 1; |
378 | node, aper_base, aper_size >> 20); | 410 | gart_iommu_aperture = 1; |
379 | node++; | 411 | |
380 | 412 | aper_order = (read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL) >> 1) & 7; | |
381 | if (!aperture_valid(aper_base, aper_size, 64<<20)) { | 413 | aper_size = (32 * 1024 * 1024) << aper_order; |
382 | if (valid_agp && agp_aper_base && | 414 | aper_base = read_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE) & 0x7fff; |
383 | agp_aper_base == aper_base && | 415 | aper_base <<= 25; |
384 | agp_aper_order == aper_order) { | 416 | |
385 | /* the same between two setting from NB and agp */ | 417 | printk(KERN_INFO "Node %d: aperture @ %Lx size %u MB\n", |
386 | if (!no_iommu && end_pfn > MAX_DMA32_PFN && !printed_gart_size_msg) { | 418 | node, aper_base, aper_size >> 20); |
387 | printk(KERN_ERR "you are using iommu with agp, but GART size is less than 64M\n"); | 419 | node++; |
388 | printk(KERN_ERR "please increase GART size in your BIOS setup\n"); | 420 | |
389 | printk(KERN_ERR "if BIOS doesn't have that option, contact your HW vendor!\n"); | 421 | if (!aperture_valid(aper_base, aper_size, 64<<20)) { |
390 | printed_gart_size_msg = 1; | 422 | if (valid_agp && agp_aper_base && |
423 | agp_aper_base == aper_base && | ||
424 | agp_aper_order == aper_order) { | ||
425 | /* the same between two setting from NB and agp */ | ||
426 | if (!no_iommu && end_pfn > MAX_DMA32_PFN && !printed_gart_size_msg) { | ||
427 | printk(KERN_ERR "you are using iommu with agp, but GART size is less than 64M\n"); | ||
428 | printk(KERN_ERR "please increase GART size in your BIOS setup\n"); | ||
429 | printk(KERN_ERR "if BIOS doesn't have that option, contact your HW vendor!\n"); | ||
430 | printed_gart_size_msg = 1; | ||
431 | } | ||
432 | } else { | ||
433 | fix = 1; | ||
434 | goto out; | ||
391 | } | 435 | } |
392 | } else { | ||
393 | fix = 1; | ||
394 | break; | ||
395 | } | 436 | } |
396 | } | ||
397 | 437 | ||
398 | if ((last_aper_order && aper_order != last_aper_order) || | 438 | if ((last_aper_order && aper_order != last_aper_order) || |
399 | (last_aper_base && aper_base != last_aper_base)) { | 439 | (last_aper_base && aper_base != last_aper_base)) { |
400 | fix = 1; | 440 | fix = 1; |
401 | break; | 441 | goto out; |
442 | } | ||
443 | last_aper_order = aper_order; | ||
444 | last_aper_base = aper_base; | ||
402 | } | 445 | } |
403 | last_aper_order = aper_order; | ||
404 | last_aper_base = aper_base; | ||
405 | } | 446 | } |
406 | 447 | ||
448 | out: | ||
407 | if (!fix && !fallback_aper_force) { | 449 | if (!fix && !fallback_aper_force) { |
408 | if (last_aper_base) { | 450 | if (last_aper_base) { |
409 | unsigned long n = (32 * 1024 * 1024) << last_aper_order; | 451 | unsigned long n = (32 * 1024 * 1024) << last_aper_order; |
@@ -452,16 +494,22 @@ void __init gart_iommu_hole_init(void) | |||
452 | } | 494 | } |
453 | 495 | ||
454 | /* Fix up the north bridges */ | 496 | /* Fix up the north bridges */ |
455 | for (num = 24; num < 32; num++) { | 497 | for (i = 0; i < ARRAY_SIZE(bus_dev_ranges); i++) { |
456 | if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) | 498 | int bus; |
457 | continue; | 499 | int dev_base, dev_limit; |
458 | 500 | ||
459 | /* | 501 | bus = bus_dev_ranges[i].bus; |
460 | * Don't enable translation yet. That is done later. | 502 | dev_base = bus_dev_ranges[i].dev_base; |
461 | * Assume this BIOS didn't initialise the GART so | 503 | dev_limit = bus_dev_ranges[i].dev_limit; |
462 | * just overwrite all previous bits | 504 | for (slot = dev_base; slot < dev_limit; slot++) { |
463 | */ | 505 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) |
464 | write_pci_config(0, num, 3, 0x90, aper_order<<1); | 506 | continue; |
465 | write_pci_config(0, num, 3, 0x94, aper_alloc>>25); | 507 | |
508 | /* Don't enable translation yet. That is done later. | ||
509 | Assume this BIOS didn't initialise the GART so | ||
510 | just overwrite all previous bits */ | ||
511 | write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, aper_order << 1); | ||
512 | write_pci_config(bus, slot, 3, AMD64_GARTAPERTUREBASE, aper_alloc >> 25); | ||
513 | } | ||
466 | } | 514 | } |
467 | } | 515 | } |