Skip to content

Commit

Permalink
x86: split e820 reserved entries record to late v2
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yinghai Lu authored and H. Peter Anvin committed Sep 4, 2008
1 parent 0ccd8c3 commit 58f7c98
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
20 changes: 18 additions & 2 deletions arch/x86/kernel/e820.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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++;
}

Expand All @@ -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";
Expand Down
79 changes: 79 additions & 0 deletions arch/x86/pci/i386.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@
#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"

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions include/asm-x86/e820.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 58f7c98

Please sign in to comment.