x86: split e820 reserved entries record to late v2
authorYinghai Lu <yhlu.kernel@gmail.com>
Thu, 28 Aug 2008 20:52:25 +0000 (13:52 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 4 Sep 2008 15:37:57 +0000 (08:37 -0700)
so could let BAR res register at first, or even pnp.

v2: insert e820 reserve resources before pnp_system_init

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

arch/x86/kernel/e820.c
arch/x86/pci/i386.c
include/asm-x86/e820.h

index 291e6cd..523d6c5 100644 (file)
@@ -1271,13 +1271,15 @@ static inline const char *e820_type_to_string(int e820_type)
 /*
  * Mark e820 reserved areas as busy for the resource manager.
  */
+struct resource __initdata *e820_res;
 void __init e820_reserve_resources(void)
 {
        int i;
-       struct resource *res;
        u64 end;
+       struct resource *res;
 
        res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
+       e820_res = res;
        for (i = 0; i < e820.nr_map; i++) {
                end = e820.map[i].addr + e820.map[i].size - 1;
 #ifndef CONFIG_RESOURCES_64BIT
@@ -1291,7 +1293,8 @@ void __init e820_reserve_resources(void)
                res->end = end;
 
                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-               insert_resource(&iomem_resource, res);
+               if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20))
+                       insert_resource(&iomem_resource, res);
                res++;
        }
 
@@ -1303,6 +1306,19 @@ void __init e820_reserve_resources(void)
        }
 }
 
+void __init e820_reserve_resources_late(void)
+{
+       int i;
+       struct resource *res;
+
+       res = e820_res;
+       for (i = 0; i < e820.nr_map; i++) {
+               if (e820.map[i].type == E820_RESERVED && res->start >= (1ULL<<20))
+                       insert_resource(&iomem_resource, res);
+               res++;
+       }
+}
+
 char *__init default_machine_specific_memory_setup(void)
 {
        char *who = "BIOS-e820";
index 8791fc5..40811ef 100644 (file)
 #include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/bootmem.h>
+#include <linux/acpi.h>
 
 #include <asm/pat.h>
+#include <asm/hpet.h>
+#include <asm/io_apic.h>
+#include <asm/e820.h>
 
 #include "pci.h"
 
@@ -77,6 +81,77 @@ pcibios_align_resource(void *data, struct resource *res,
 }
 EXPORT_SYMBOL(pcibios_align_resource);
 
+static int check_res_with_valid(struct pci_dev *dev, struct resource *res)
+{
+       unsigned long base;
+       unsigned long size;
+       int i;
+
+       base = res->start;
+       size = (res->start == 0 && res->end == res->start) ? 0 :
+                (res->end - res->start + 1);
+
+       if (!base || !size)
+               return 0;
+
+#ifdef CONFIG_HPET_TIMER
+       /* for hpet */
+       if (base == hpet_address && (res->flags & IORESOURCE_MEM)) {
+               dev_info(&dev->dev, "BAR has HPET at %08lx-%08lx\n",
+                                base, base + size - 1);
+               return 1;
+       }
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+       for (i = 0; i < nr_ioapics; i++) {
+               unsigned long ioapic_phys = mp_ioapics[i].mp_apicaddr;
+
+               if (base == ioapic_phys && (res->flags & IORESOURCE_MEM)) {
+                       dev_info(&dev->dev, "BAR has ioapic at %08lx-%08lx\n",
+                                        base, base + size - 1);
+                       return 1;
+               }
+       }
+#endif
+
+#ifdef CONFIG_PCI_MMCONFIG
+       for (i = 0; i < pci_mmcfg_config_num; i++) {
+               unsigned long addr;
+
+               addr = pci_mmcfg_config[i].address;
+               if (base == addr && (res->flags & IORESOURCE_MEM)) {
+                       dev_info(&dev->dev, "BAR has MMCONFIG at %08lx-%08lx\n",
+                                        base, base + size - 1);
+                       return 1;
+               }
+       }
+#endif
+
+       return 0;
+}
+
+static int check_platform(struct pci_dev *dev, struct resource *res)
+{
+       struct resource *root = NULL;
+
+       /*
+        * forcibly insert it into the
+        * resource tree
+        */
+       if (res->flags & IORESOURCE_MEM)
+               root = &iomem_resource;
+       else if (res->flags & IORESOURCE_IO)
+               root = &ioport_resource;
+
+       if (root && check_res_with_valid(dev, res)) {
+               insert_resource(root, res);
+
+               return 1;
+       }
+
+       return 0;
+}
 /*
  *  Handle resources of PCI devices.  If the world were perfect, we could
  *  just allocate all the resource regions and do nothing more.  It isn't.
@@ -128,6 +203,8 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
                                pr = pci_find_parent_resource(dev, r);
                                if (!r->start || !pr ||
                                    request_resource(pr, r) < 0) {
+                                       if (check_platform(dev, r))
+                                               continue;
                                        dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx);
                                        /*
                                         * Something is wrong with the region.
@@ -169,6 +246,8 @@ static void __init pcibios_allocate_resources(int pass)
                                        r->flags, disabled, pass);
                                pr = pci_find_parent_resource(dev, r);
                                if (!pr || request_resource(pr, r) < 0) {
+                                       if (check_platform(dev, r))
+                                               continue;
                                        dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx);
                                        /* We'll assign a new address later */
                                        r->end -= r->start;
index ca433c3..5abbdec 100644 (file)
@@ -122,6 +122,7 @@ extern void e820_register_active_regions(int nid, unsigned long start_pfn,
 extern u64 e820_hole_size(u64 start, u64 end);
 extern void finish_e820_parsing(void);
 extern void e820_reserve_resources(void);
+extern void e820_reserve_resources_late(void);
 extern void setup_memory_map(void);
 extern char *default_machine_specific_memory_setup(void);
 extern char *machine_specific_memory_setup(void);