tree a3f194a2a88810662f3ed55f1046ddb6e1774187
parent 326ef583f8c405b748f37f01a4a4e8e5c2602b3b
author Andi Kleen <[EMAIL PROTECTED]> Tue Apr 12 08:25:43 2005
committer Linus Torvalds <[EMAIL PROTECTED]> Tue Apr 12 08:25:43 2005
[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 <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
arch/x86_64/kernel/e820.c | 59 +++++++++++++++++++++++++++++++++++++++++++++
arch/x86_64/kernel/setup.c | 12 ---------
include/asm-x86_64/e820.h | 1
3 files changed, 61 insertions(+), 11 deletions(-)
Index: arch/x86_64/kernel/e820.c
===================================================================
--- 80413101d457478d456c8a4383fd005ac2e602ab/arch/x86_64/kernel/e820.c
(mode:100644 sha1:73e0051859a99d8d74dc9035d02b135aed9db254)
+++ a3f194a2a88810662f3ed55f1046ddb6e1774187/arch/x86_64/kernel/e820.c
(mode:100644 sha1:03c1f4494d4932668b677825912c725ef3efd16d)
@@ -511,3 +511,62 @@
end_user_pfn >>= PAGE_SHIFT;
}
+unsigned long pci_mem_start = 0xaeedbabe;
+
+/*
+ * Search for the biggest gap in the low 32 bits of the e820
+ * memory space. We pass this space to PCI to assign MMIO resources
+ * for hotplug or unconfigured devices in.
+ * Hopefully the BIOS let enough space left.
+ */
+__init void e820_setup_gap(void)
+{
+ unsigned long gapstart, gapsize;
+ unsigned long last;
+ int i;
+ int found = 0;
+
+ last = 0x100000000ull;
+ gapstart = 0x10000000;
+ gapsize = 0x400000;
+ i = e820.nr_map;
+ while (--i >= 0) {
+ unsigned long long start = e820.map[i].addr;
+ unsigned long long end = start + e820.map[i].size;
+
+ /*
+ * Since "last" is at most 4GB, we know we'll
+ * fit in 32 bits if this condition is true
+ */
+ if (last > end) {
+ unsigned long gap = last - end;
+
+ if (gap > gapsize) {
+ gapsize = gap;
+ gapstart = end;
+ found = 1;
+ }
+ }
+ if (start < last)
+ last = start;
+ }
+
+ if (!found) {
+ gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
+ printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit
address range\n"
+ KERN_ERR "PCI: Unassigned devices with 32bit resource
registers may break!\n");
+ }
+
+ /*
+ * Start allocating dynamic PCI memory a bit into the gap,
+ * aligned up to the nearest megabyte.
+ *
+ * Question: should we try to pad it up a bit (do something
+ * like " + (gapsize >> 3)" in there too?). We now have the
+ * technology.
+ */
+ pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+
+ printk(KERN_INFO "Allocating PCI resources starting at %lx (gap:
%lx:%lx)\n",
+ pci_mem_start, gapstart, gapsize);
+}
Index: arch/x86_64/kernel/setup.c
===================================================================
--- 80413101d457478d456c8a4383fd005ac2e602ab/arch/x86_64/kernel/setup.c
(mode:100644 sha1:aab5afa223cafb0c4218909725f7f39871362d4c)
+++ a3f194a2a88810662f3ed55f1046ddb6e1774187/arch/x86_64/kernel/setup.c
(mode:100644 sha1:02b85fef14ba16c052ce3755bae2f7c6ad17545e)
@@ -76,9 +76,6 @@
int acpi_numa __initdata;
-/* For PCI or other memory-mapped resources */
-unsigned long pci_mem_start = 0x10000000;
-
/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type;
@@ -495,7 +492,6 @@
void __init setup_arch(char **cmdline_p)
{
- unsigned long low_mem_size;
unsigned long kernel_end;
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
@@ -654,13 +650,7 @@
request_resource(&ioport_resource, &standard_io_resources[i]);
}
- /* Will likely break when you have unassigned resources with more
- than 4GB memory and bridges that don't support more than 4GB.
- Doing it properly would require to use pci_alloc_consistent
- in this case. */
- low_mem_size = ((end_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;
- if (low_mem_size > pci_mem_start)
- pci_mem_start = low_mem_size;
+ e820_setup_gap();
#ifdef CONFIG_GART_IOMMU
iommu_hole_init();
Index: include/asm-x86_64/e820.h
===================================================================
--- 80413101d457478d456c8a4383fd005ac2e602ab/include/asm-x86_64/e820.h
(mode:100644 sha1:204d05086e29d9c58745831f0618a04016786c7e)
+++ a3f194a2a88810662f3ed55f1046ddb6e1774187/include/asm-x86_64/e820.h
(mode:100644 sha1:7d43d607f6cd9e31c02d97941cb6fb10707b7c86)
@@ -50,6 +50,7 @@
extern int e820_mapped(unsigned long start, unsigned long end, unsigned type);
extern void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned
long end);
+extern void e820_setup_gap(void);
extern void __init parse_memopt(char *p, char **end);
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html