aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/e820.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-04-16 18:25:12 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:25:12 -0400
commita1e9778203b15b86bc2219e87478d3be9acce735 (patch)
tree15141c5b56a4e39fa8e879812785e957ea720c9b /arch/x86_64/kernel/e820.c
parentcf94b62f7005805be0a3ba02c624cb8cd3595bac (diff)
[PATCH] x86_64: Port over e820 gap detection from i386
Look for gaps in the e820 memory map to put PCI resources in. This hopefully fixes problems with the PCI code assigning 32bit BARs MMIO resources which are >32bit. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/e820.c')
-rw-r--r--arch/x86_64/kernel/e820.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 657003e461e6..56516ac92e5d 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -511,3 +511,62 @@ void __init parse_memopt(char *p, char **from)
511 end_user_pfn >>= PAGE_SHIFT; 511 end_user_pfn >>= PAGE_SHIFT;
512} 512}
513 513
514unsigned long pci_mem_start = 0xaeedbabe;
515
516/*
517 * Search for the biggest gap in the low 32 bits of the e820
518 * memory space. We pass this space to PCI to assign MMIO resources
519 * for hotplug or unconfigured devices in.
520 * Hopefully the BIOS let enough space left.
521 */
522__init void e820_setup_gap(void)
523{
524 unsigned long gapstart, gapsize;
525 unsigned long last;
526 int i;
527 int found = 0;
528
529 last = 0x100000000ull;
530 gapstart = 0x10000000;
531 gapsize = 0x400000;
532 i = e820.nr_map;
533 while (--i >= 0) {
534 unsigned long long start = e820.map[i].addr;
535 unsigned long long end = start + e820.map[i].size;
536
537 /*
538 * Since "last" is at most 4GB, we know we'll
539 * fit in 32 bits if this condition is true
540 */
541 if (last > end) {
542 unsigned long gap = last - end;
543
544 if (gap > gapsize) {
545 gapsize = gap;
546 gapstart = end;
547 found = 1;
548 }
549 }
550 if (start < last)
551 last = start;
552 }
553
554 if (!found) {
555 gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
556 printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit address range\n"
557 KERN_ERR "PCI: Unassigned devices with 32bit resource registers may break!\n");
558 }
559
560 /*
561 * Start allocating dynamic PCI memory a bit into the gap,
562 * aligned up to the nearest megabyte.
563 *
564 * Question: should we try to pad it up a bit (do something
565 * like " + (gapsize >> 3)" in there too?). We now have the
566 * technology.
567 */
568 pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
569
570 printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
571 pci_mem_start, gapstart, gapsize);
572}