Commit d37a14bb authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-resources-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull ram resource handling changes from Ingo Molnar:
 "Core kernel resource handling changes to support NVDIMM error
  injection.

  This tree introduces a new I/O resource type, IORESOURCE_SYSTEM_RAM,
  for System RAM while keeping the current IORESOURCE_MEM type bit set
  for all memory-mapped ranges (including System RAM) for backward
  compatibility.

  With this resource flag it no longer takes a strcmp() loop through the
  resource tree to find "System RAM" resources.

  The new resource type is then used to extend ACPI/APEI error injection
  facility to also support NVDIMM"

* 'core-resources-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  ACPI/EINJ: Allow memory error injection to NVDIMM
  resource: Kill walk_iomem_res()
  x86/kexec: Remove walk_iomem_res() call with GART type
  x86, kexec, nvdimm: Use walk_iomem_res_desc() for iomem search
  resource: Add walk_iomem_res_desc()
  memremap: Change region_intersects() to take @flags and @desc
  arm/samsung: Change s3c_pm_run_res() to use System RAM type
  resource: Change walk_system_ram() to use System RAM type
  drivers: Initialize resource entry to zero
  xen, mm: Set IORESOURCE_SYSTEM_RAM to System RAM
  kexec: Set IORESOURCE_SYSTEM_RAM for System RAM
  arch: Set IORESOURCE_SYSTEM_RAM flag for System RAM
  ia64: Set System RAM type and descriptor
  x86/e820: Set System RAM type and descriptor
  resource: Add I/O resource descriptor
  resource: Handle resource flags properly
  resource: Add System RAM resource type
parents b562e44f bc94b996
...@@ -176,13 +176,13 @@ static struct resource mem_res[] = { ...@@ -176,13 +176,13 @@ static struct resource mem_res[] = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM .flags = IORESOURCE_SYSTEM_RAM
}, },
{ {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM .flags = IORESOURCE_SYSTEM_RAM
} }
}; };
...@@ -851,7 +851,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) ...@@ -851,7 +851,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
res->name = "System RAM"; res->name = "System RAM";
res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res); request_resource(&iomem_resource, res);
......
...@@ -53,8 +53,8 @@ static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg) ...@@ -53,8 +53,8 @@ static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
if (ptr->child != NULL) if (ptr->child != NULL)
s3c_pm_run_res(ptr->child, fn, arg); s3c_pm_run_res(ptr->child, fn, arg);
if ((ptr->flags & IORESOURCE_MEM) && if ((ptr->flags & IORESOURCE_SYSTEM_RAM)
strcmp(ptr->name, "System RAM") == 0) { == IORESOURCE_SYSTEM_RAM) {
S3C_PMDBG("Found system RAM at %08lx..%08lx\n", S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
(unsigned long)ptr->start, (unsigned long)ptr->start,
(unsigned long)ptr->end); (unsigned long)ptr->end);
......
...@@ -73,13 +73,13 @@ static struct resource mem_res[] = { ...@@ -73,13 +73,13 @@ static struct resource mem_res[] = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM .flags = IORESOURCE_SYSTEM_RAM
}, },
{ {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM .flags = IORESOURCE_SYSTEM_RAM
} }
}; };
...@@ -210,7 +210,7 @@ static void __init request_standard_resources(void) ...@@ -210,7 +210,7 @@ static void __init request_standard_resources(void)
res->name = "System RAM"; res->name = "System RAM";
res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res); request_resource(&iomem_resource, res);
......
...@@ -49,13 +49,13 @@ static struct resource __initdata kernel_data = { ...@@ -49,13 +49,13 @@ static struct resource __initdata kernel_data = {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_SYSTEM_RAM,
}; };
static struct resource __initdata kernel_code = { static struct resource __initdata kernel_code = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_SYSTEM_RAM,
.sibling = &kernel_data, .sibling = &kernel_data,
}; };
...@@ -134,7 +134,7 @@ add_physical_memory(resource_size_t start, resource_size_t end) ...@@ -134,7 +134,7 @@ add_physical_memory(resource_size_t start, resource_size_t end)
new->start = start; new->start = start;
new->end = end; new->end = end;
new->name = "System RAM"; new->name = "System RAM";
new->flags = IORESOURCE_MEM; new->flags = IORESOURCE_SYSTEM_RAM;
*pprev = new; *pprev = new;
} }
......
...@@ -1178,7 +1178,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, ...@@ -1178,7 +1178,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
efi_memory_desc_t *md; efi_memory_desc_t *md;
u64 efi_desc_size; u64 efi_desc_size;
char *name; char *name;
unsigned long flags; unsigned long flags, desc;
efi_map_start = __va(ia64_boot_param->efi_memmap); efi_map_start = __va(ia64_boot_param->efi_memmap);
efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
...@@ -1193,6 +1193,8 @@ efi_initialize_iomem_resources(struct resource *code_resource, ...@@ -1193,6 +1193,8 @@ efi_initialize_iomem_resources(struct resource *code_resource,
continue; continue;
flags = IORESOURCE_MEM | IORESOURCE_BUSY; flags = IORESOURCE_MEM | IORESOURCE_BUSY;
desc = IORES_DESC_NONE;
switch (md->type) { switch (md->type) {
case EFI_MEMORY_MAPPED_IO: case EFI_MEMORY_MAPPED_IO:
...@@ -1207,14 +1209,17 @@ efi_initialize_iomem_resources(struct resource *code_resource, ...@@ -1207,14 +1209,17 @@ efi_initialize_iomem_resources(struct resource *code_resource,
if (md->attribute & EFI_MEMORY_WP) { if (md->attribute & EFI_MEMORY_WP) {
name = "System ROM"; name = "System ROM";
flags |= IORESOURCE_READONLY; flags |= IORESOURCE_READONLY;
} else if (md->attribute == EFI_MEMORY_UC) } else if (md->attribute == EFI_MEMORY_UC) {
name = "Uncached RAM"; name = "Uncached RAM";
else } else {
name = "System RAM"; name = "System RAM";
flags |= IORESOURCE_SYSRAM;
}
break; break;
case EFI_ACPI_MEMORY_NVS: case EFI_ACPI_MEMORY_NVS:
name = "ACPI Non-volatile Storage"; name = "ACPI Non-volatile Storage";
desc = IORES_DESC_ACPI_NV_STORAGE;
break; break;
case EFI_UNUSABLE_MEMORY: case EFI_UNUSABLE_MEMORY:
...@@ -1224,6 +1229,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, ...@@ -1224,6 +1229,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
case EFI_PERSISTENT_MEMORY: case EFI_PERSISTENT_MEMORY:
name = "Persistent Memory"; name = "Persistent Memory";
desc = IORES_DESC_PERSISTENT_MEMORY;
break; break;
case EFI_RESERVED_TYPE: case EFI_RESERVED_TYPE:
...@@ -1246,6 +1252,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, ...@@ -1246,6 +1252,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
res->start = md->phys_addr; res->start = md->phys_addr;
res->end = md->phys_addr + efi_md_size(md) - 1; res->end = md->phys_addr + efi_md_size(md) - 1;
res->flags = flags; res->flags = flags;
res->desc = desc;
if (insert_resource(&iomem_resource, res) < 0) if (insert_resource(&iomem_resource, res) < 0)
kfree(res); kfree(res);
......
...@@ -80,17 +80,17 @@ unsigned long vga_console_membase; ...@@ -80,17 +80,17 @@ unsigned long vga_console_membase;
static struct resource data_resource = { static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource bss_resource = { static struct resource bss_resource = {
.name = "Kernel bss", .name = "Kernel bss",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
unsigned long ia64_max_cacheline_size; unsigned long ia64_max_cacheline_size;
......
...@@ -70,14 +70,14 @@ static struct resource data_resource = { ...@@ -70,14 +70,14 @@ static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
unsigned long memory_start; unsigned long memory_start;
......
...@@ -732,21 +732,23 @@ static void __init resource_init(void) ...@@ -732,21 +732,23 @@ static void __init resource_init(void)
end = HIGHMEM_START - 1; end = HIGHMEM_START - 1;
res = alloc_bootmem(sizeof(struct resource)); res = alloc_bootmem(sizeof(struct resource));
res->start = start;
res->end = end;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
switch (boot_mem_map.map[i].type) { switch (boot_mem_map.map[i].type) {
case BOOT_MEM_RAM: case BOOT_MEM_RAM:
case BOOT_MEM_INIT_RAM: case BOOT_MEM_INIT_RAM:
case BOOT_MEM_ROM_DATA: case BOOT_MEM_ROM_DATA:
res->name = "System RAM"; res->name = "System RAM";
res->flags |= IORESOURCE_SYSRAM;
break; break;
case BOOT_MEM_RESERVED: case BOOT_MEM_RESERVED:
default: default:
res->name = "reserved"; res->name = "reserved";
} }
res->start = start;
res->end = end;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res); request_resource(&iomem_resource, res);
/* /*
......
...@@ -55,12 +55,12 @@ signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; ...@@ -55,12 +55,12 @@ signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
static struct resource data_resource = { static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource pdcdata_resource = { static struct resource pdcdata_resource = {
...@@ -201,7 +201,7 @@ static void __init setup_bootmem(void) ...@@ -201,7 +201,7 @@ static void __init setup_bootmem(void)
res->name = "System RAM"; res->name = "System RAM";
res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT; res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT;
res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1; res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res); request_resource(&iomem_resource, res);
} }
......
...@@ -541,7 +541,7 @@ static int __init add_system_ram_resources(void) ...@@ -541,7 +541,7 @@ static int __init add_system_ram_resources(void)
res->name = "System RAM"; res->name = "System RAM";
res->start = base; res->start = base;
res->end = base + size - 1; res->end = base + size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
WARN_ON(request_resource(&iomem_resource, res) < 0); WARN_ON(request_resource(&iomem_resource, res) < 0);
} }
} }
......
...@@ -374,17 +374,17 @@ static void __init setup_lowcore(void) ...@@ -374,17 +374,17 @@ static void __init setup_lowcore(void)
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource data_resource = { static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource bss_resource = { static struct resource bss_resource = {
.name = "Kernel bss", .name = "Kernel bss",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource __initdata *standard_resources[] = { static struct resource __initdata *standard_resources[] = {
...@@ -408,7 +408,7 @@ static void __init setup_resources(void) ...@@ -408,7 +408,7 @@ static void __init setup_resources(void)
for_each_memblock(memory, reg) { for_each_memblock(memory, reg) {
res = alloc_bootmem_low(sizeof(*res)); res = alloc_bootmem_low(sizeof(*res));
res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
res->name = "System RAM"; res->name = "System RAM";
res->start = reg->base; res->start = reg->base;
......
...@@ -101,7 +101,7 @@ static void __init resource_init(void) ...@@ -101,7 +101,7 @@ static void __init resource_init(void)
res->name = "System RAM"; res->name = "System RAM";
res->start = MEMORY_START; res->start = MEMORY_START;
res->end = MEMORY_START + MEMORY_SIZE - 1; res->end = MEMORY_START + MEMORY_SIZE - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res); request_resource(&iomem_resource, res);
request_resource(res, &code_resource); request_resource(res, &code_resource);
......
...@@ -78,17 +78,17 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, }; ...@@ -78,17 +78,17 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource data_resource = { static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
static struct resource bss_resource = { static struct resource bss_resource = {
.name = "Kernel bss", .name = "Kernel bss",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM, .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
}; };
unsigned long memory_start; unsigned long memory_start;
...@@ -202,7 +202,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, ...@@ -202,7 +202,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
res->name = "System RAM"; res->name = "System RAM";
res->start = start; res->start = start;
res->end = end - 1; res->end = end - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
if (request_resource(&iomem_resource, res)) { if (request_resource(&iomem_resource, res)) {
pr_err("unable to request memory_resource 0x%lx 0x%lx\n", pr_err("unable to request memory_resource 0x%lx 0x%lx\n",
......
...@@ -2863,17 +2863,17 @@ void hugetlb_setup(struct pt_regs *regs) ...@@ -2863,17 +2863,17 @@ void hugetlb_setup(struct pt_regs *regs)
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource data_resource = { static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource bss_resource = { static struct resource bss_resource = {
.name = "Kernel bss", .name = "Kernel bss",
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static inline resource_size_t compute_kern_paddr(void *addr) static inline resource_size_t compute_kern_paddr(void *addr)
...@@ -2909,7 +2909,7 @@ static int __init report_memory(void) ...@@ -2909,7 +2909,7 @@ static int __init report_memory(void)
res->name = "System RAM"; res->name = "System RAM";
res->start = pavail[i].phys_addr; res->start = pavail[i].phys_addr;
res->end = pavail[i].phys_addr + pavail[i].reg_size - 1; res->end = pavail[i].phys_addr + pavail[i].reg_size - 1;
res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
if (insert_resource(&iomem_resource, res) < 0) { if (insert_resource(&iomem_resource, res) < 0) {
pr_warn("Resource insertion failed.\n"); pr_warn("Resource insertion failed.\n");
......
...@@ -1632,14 +1632,14 @@ static struct resource data_resource = { ...@@ -1632,14 +1632,14 @@ static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
/* /*
...@@ -1673,10 +1673,15 @@ insert_ram_resource(u64 start_pfn, u64 end_pfn, bool reserved) ...@@ -1673,10 +1673,15 @@ insert_ram_resource(u64 start_pfn, u64 end_pfn, bool reserved)
kzalloc(sizeof(struct resource), GFP_ATOMIC); kzalloc(sizeof(struct resource), GFP_ATOMIC);
if (!res) if (!res)
return NULL; return NULL;
res->name = reserved ? "Reserved" : "System RAM";
res->start = start_pfn << PAGE_SHIFT; res->start = start_pfn << PAGE_SHIFT;
res->end = (end_pfn << PAGE_SHIFT) - 1; res->end = (end_pfn << PAGE_SHIFT) - 1;
res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
if (reserved) {
res->name = "Reserved";
} else {
res->name = "System RAM";
res->flags |= IORESOURCE_SYSRAM;
}
if (insert_resource(&iomem_resource, res)) { if (insert_resource(&iomem_resource, res)) {
kfree(res); kfree(res);
return NULL; return NULL;
......
...@@ -72,13 +72,13 @@ static struct resource mem_res[] = { ...@@ -72,13 +72,13 @@ static struct resource mem_res[] = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM .flags = IORESOURCE_SYSTEM_RAM
}, },
{ {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_MEM .flags = IORESOURCE_SYSTEM_RAM
} }
}; };
...@@ -211,7 +211,7 @@ request_standard_resources(struct meminfo *mi) ...@@ -211,7 +211,7 @@ request_standard_resources(struct meminfo *mi)
res->name = "System RAM"; res->name = "System RAM";
res->start = mi->bank[i].start; res->start = mi->bank[i].start;
res->end = mi->bank[i].start + mi->bank[i].size - 1; res->end = mi->bank[i].start + mi->bank[i].size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res); request_resource(&iomem_resource, res);
......
...@@ -57,10 +57,9 @@ struct crash_elf_data { ...@@ -57,10 +57,9 @@ struct crash_elf_data {
struct kimage *image; struct kimage *image;
/* /*
* Total number of ram ranges we have after various adjustments for * Total number of ram ranges we have after various adjustments for
* GART, crash reserved region etc. * crash reserved region, etc.
*/ */
unsigned int max_nr_ranges; unsigned int max_nr_ranges;
unsigned long gart_start, gart_end;
/* Pointer to elf header */ /* Pointer to elf header */
void *ehdr; void *ehdr;
...@@ -201,17 +200,6 @@ static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg) ...@@ -201,17 +200,6 @@ static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg)
return 0; return 0;
} }
static int get_gart_ranges_callback(u64 start, u64 end, void *arg)
{
struct crash_elf_data *ced = arg;
ced->gart_start = start;
ced->gart_end = end;
/* Not expecting more than 1 gart aperture */
return 1;
}
/* Gather all the required information to prepare elf headers for ram regions */ /* Gather all the required information to prepare elf headers for ram regions */
static void fill_up_crash_elf_data(struct crash_elf_data *ced, static void fill_up_crash_elf_data(struct crash_elf_data *ced,
...@@ -226,22 +214,6 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced, ...@@ -226,22 +214,6 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
ced->max_nr_ranges = nr_ranges; ced->max_nr_ranges = nr_ranges;
/*
* We don't create ELF headers for GART aperture as an attempt
* to dump this memory in second kernel leads to hang/crash.
* If gart aperture is present, one needs to exclude that region
* and that could lead to need of extra phdr.
*/
walk_iomem_res("GART", IORESOURCE_MEM, 0, -1,
ced, get_gart_ranges_callback);
/*
* If we have gart region, excluding that could potentially split
* a memory range, resulting in extra header. Account for that.
*/
if (ced->gart_end)
ced->max_nr_ranges++;
/* Exclusion of crash region could split memory ranges */ /* Exclusion of crash region could split memory ranges */
ced->max_nr_ranges++; ced->max_nr_ranges++;
...@@ -350,13 +322,6 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced, ...@@ -350,13 +322,6 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
return ret; return ret;
} }
/* Exclude GART region */
if (ced->gart_end) {
ret = exclude_mem_range(cmem, ced->gart_start, ced->gart_end);
if (ret)
return ret;
}
return ret; return ret;
} }
...@@ -599,12 +564,12 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) ...@@ -599,12 +564,12 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
/* Add ACPI tables */ /* Add ACPI tables */
cmd.type = E820_ACPI; cmd.type = E820_ACPI;
flags = IORESOURCE_MEM | IORESOURCE_BUSY; flags = IORESOURCE_MEM | IORESOURCE_BUSY;
walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd, walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd,
memmap_entry_callback); memmap_entry_callback);
/* Add ACPI Non-volatile Storage */ /* Add ACPI Non-volatile Storage */
cmd.type = E820_NVS; cmd.type = E820_NVS;
walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd, walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd,
memmap_entry_callback); memmap_entry_callback);
/* Add crashk_low_res region */ /* Add crashk_low_res region */
......
...@@ -925,6 +925,41 @@ static const char *e820_type_to_string(int e820_type) ...@@ -925,6 +925,41 @@ static const char *e820_type_to_string(int e820_type)
} }
} }
static unsigned long e820_type_to_iomem_type(int e820_type)
{
switch (e820_type) {
case E820_RESERVED_KERN:
case E820_RAM:
return IORESOURCE_SYSTEM_RAM;
case E820_ACPI:
case E820_NVS:
case E820_UNUSABLE:
case E820_PRAM:
case E820_PMEM:
default:
return IORESOURCE_MEM;
}
}
static unsigned long e820_type_to_iores_desc(int e820_type)
{
switch (e820_type) {
case E820_ACPI:
return IORES_DESC_ACPI_TABLES;
case E820_NVS:
return IORES_DESC_ACPI_NV_STORAGE;
case E820_PMEM:
return IORES_DESC_PERSISTENT_MEMORY;
case E820_PRAM:
return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
case E820_RESERVED_KERN:
case E820_RAM:
case E820_UNUSABLE:
default:
return IORES_DESC_NONE;
}
}
static bool do_mark_busy(u32 type, struct resource *res) static bool do_mark_busy(u32 type, struct resource *res)
{ {
/* this is the legacy bios/dos rom-shadow + mmio region */ /* this is the legacy bios/dos rom-shadow + mmio region */
...@@ -967,7 +1002,8 @@ void __init e820_reserve_resources(void) ...@@ -967,7 +1002,8 @@ void __init e820_reserve_resources(void)
res->start = e820.map[i].addr; res->start = e820.map[i].addr;
res->end = end; res->end = end;
res->flags = IORESOURCE_MEM; res->flags = e820_type_to_iomem_type(e820.map[i].type);
res->desc = e820_type_to_iores_desc(e820.map[i].type);
/* /*
* don't register the region that could be conflicted with * don't register the region that could be conflicted with
......
...@@ -13,11 +13,11 @@ static int found(u64 start, u64 end, void *data) ...@@ -13,11 +13,11 @@ static int found(u64 start, u64 end, void *data)
static __init int register_e820_pmem(void) static __init int register_e820_pmem(void)
{ {
char *pmem = "Persistent Memory (legacy)";
struct platform_device *pdev; struct platform_device *pdev;
int rc; int rc;
rc = walk_iomem_res(pmem, IORESOURCE_MEM, 0, -1, NULL, found); rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
IORESOURCE_MEM, 0, -1, NULL, found);
if (rc <= 0) if (rc <= 0)
return 0; return 0;
......
...@@ -152,21 +152,21 @@ static struct resource data_resource = { ...@@ -152,21 +152,21 @@ static struct resource data_resource = {
.name = "Kernel data", .name = "Kernel data",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource code_resource = { static struct resource code_resource = {
.name = "Kernel code", .name = "Kernel code",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
static struct resource bss_resource = { static struct resource bss_resource = {
.name = "Kernel bss", .name = "Kernel bss",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
}; };
......
...@@ -62,7 +62,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) ...@@ -62,7 +62,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
if (count < 0) { if (count < 0) {
return NULL; return NULL;
} else if (count > 0) { } else if (count > 0) {
resources = kmalloc(count * sizeof(struct resource), resources = kzalloc(count * sizeof(struct resource),
GFP_KERNEL); GFP_KERNEL);
if (!resources) { if (!resources) {
dev_err(&adev->dev, "No memory for resources\n"); dev_err(&adev->dev, "No memory for resources\n");
......
...@@ -519,7 +519,7 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, ...@@ -519,7 +519,7 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
u64 param3, u64 param4) u64 param3, u64 param4)
{ {
int rc; int rc;
unsigned long pfn; u64 base_addr, size;
/* If user manually set "flags", make sure it is legal */ /* If user manually set "flags", make sure it is legal */
if (flags && (flags & if (flags && (flags &
...@@ -545,10 +545,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, ...@@ -545,10 +545,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
/* /*
* Disallow crazy address masks that give BIOS leeway to pick * Disallow crazy address masks that give BIOS leeway to pick
* injection address almost anywhere. Insist on page or * injection address almost anywhere. Insist on page or
* better granularity and that target address is normal RAM. * better granularity and that target address is normal RAM or
* NVDIMM.
*/ */
pfn = PFN_DOWN(param1 & param2); base_addr = param1 & param2;
if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK)) size = ~param2 + 1;
if (((param2 & PAGE_MASK) != PAGE_MASK) ||
((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)
!= REGION_INTERSECTS) &&
(region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY)
!= REGION_INTERSECTS)))
return -EINVAL; return -EINVAL;
inject: inject:
......
...@@ -55,7 +55,7 @@ static int e820_pmem_probe(struct platform_device *pdev) ...@@ -55,7 +55,7 @@ static int e820_pmem_probe(struct platform_device *pdev)
for (p = iomem_resource.child; p ; p = p->sibling) { for (p = iomem_resource.child; p ; p = p->sibling) {
struct nd_region_desc ndr_desc; struct nd_region_desc ndr_desc;
if (strncmp(p->name, "Persistent Memory (legacy)", 26) != 0) if (p->desc != IORES_DESC_PERSISTENT_MEMORY_LEGACY)
continue; continue;
memset(&ndr_desc, 0, sizeof(ndr_desc)); memset(&ndr_desc, 0, sizeof(ndr_desc));
......
...@@ -91,7 +91,7 @@ static int configure_memory(const unsigned char *buf, ...@@ -91,7 +91,7 @@ static int configure_memory(const unsigned char *buf,
for (i=0;i<HPEE_MEMORY_MAX_ENT;i++) { for (i=0;i<HPEE_MEMORY_MAX_ENT;i++) {
c = get_8(buf+len); c = get_8(buf+len);
if (NULL != (res = kmalloc(sizeof(struct resource), GFP_KERNEL))) { if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) {
int result; int result;
res->name = name; res->name = name;
...@@ -183,7 +183,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, ...@@ -183,7 +183,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent,
for (i=0;i<HPEE_PORT_MAX_ENT;i++) { for (i=0;i<HPEE_PORT_MAX_ENT;i++) {
c = get_8(buf+len); c = get_8(buf+len);
if (NULL != (res = kmalloc(sizeof(struct resource), GFP_KERNEL))) { if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) {
res->name = board; res->name = board;
res->start = get_16(buf+len+1); res->start = get_16(buf+len+1);
res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1; res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1;
......
...@@ -117,7 +117,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, ...@@ -117,7 +117,7 @@ int rio_request_inb_mbox(struct rio_mport *mport,
if (mport->ops->open_inb_mbox == NULL) if (mport->ops->open_inb_mbox == NULL)
goto out; goto out;
res = kmalloc(sizeof(struct resource), GFP_KERNEL); res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (res) { if (res) {
rio_init_mbox_res(res, mbox, mbox); rio_init_mbox_res(res, mbox, mbox);
...@@ -185,7 +185,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, ...@@ -185,7 +185,7 @@ int rio_request_outb_mbox(struct rio_mport *mport,
if (mport->ops->open_outb_mbox == NULL) if (mport->ops->open_outb_mbox == NULL)
goto out; goto out;
res = kmalloc(sizeof(struct resource), GFP_KERNEL); res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (res) { if (res) {
rio_init_mbox_res(res, mbox, mbox); rio_init_mbox_res(res, mbox, mbox);
...@@ -285,7 +285,7 @@ int rio_request_inb_dbell(struct rio_mport *mport, ...@@ -285,7 +285,7 @@ int rio_request_inb_dbell(struct rio_mport *mport,
{ {
int rc = 0; int rc = 0;
struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (res) { if (res) {
rio_init_dbell_res(res, start, end); rio_init_dbell_res(res, start, end);
...@@ -360,7 +360,7 @@ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) ...@@ -360,7 +360,7 @@ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end)
struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start,
u16 end) u16 end)
{ {
struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (res) { if (res) {
rio_init_dbell_res(res, start, end); rio_init_dbell_res(res, start, end);
......
...@@ -66,7 +66,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, ...@@ -66,7 +66,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev,
superhyway_read_vcr(dev, base, &dev->vcr); superhyway_read_vcr(dev, base, &dev->vcr);
if (!dev->resource) { if (!dev->resource) {
dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL); dev->resource = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (!dev->resource) { if (!dev->resource) {
kfree(dev); kfree(dev);
return -ENOMEM; return -ENOMEM;
......
...@@ -257,7 +257,7 @@ static struct resource *additional_memory_resource(phys_addr_t size) ...@@ -257,7 +257,7 @@ static struct resource *additional_memory_resource(phys_addr_t size)
return NULL; return NULL;
res->name = "System RAM"; res->name = "System RAM";
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
ret = allocate_resource(&iomem_resource, res, ret = allocate_resource(&iomem_resource, res,
size, 0, -1, size, 0, -1,
......
...@@ -20,6 +20,7 @@ struct resource { ...@@ -20,6 +20,7 @@ struct resource {
resource_size_t end; resource_size_t end;
const char *name; const char *name;
unsigned long flags; unsigned long flags;
unsigned long desc;
struct resource *parent, *sibling, *child; struct resource *parent, *sibling, *child;
}; };
...@@ -49,12 +50,19 @@ struct resource { ...@@ -49,12 +50,19 @@ struct resource {
#define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */
#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */
#define IORESOURCE_EXT_TYPE_BITS 0x01000000 /* Resource extended types */
#define IORESOURCE_SYSRAM 0x01000000 /* System RAM (modifier) */
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
#define IORESOURCE_DISABLED 0x10000000 #define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */ #define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */
#define IORESOURCE_AUTO 0x40000000 #define IORESOURCE_AUTO 0x40000000
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
/* I/O resource extended types */
#define IORESOURCE_SYSTEM_RAM (IORESOURCE_MEM|IORESOURCE_SYSRAM)
/* PnP IRQ specific bits (IORESOURCE_BITS) */ /* PnP IRQ specific bits (IORESOURCE_BITS) */
#define IORESOURCE_IRQ_HIGHEDGE (1<<0) #define IORESOURCE_IRQ_HIGHEDGE (1<<0)
#define IORESOURCE_IRQ_LOWEDGE (1<<1) #define IORESOURCE_IRQ_LOWEDGE (1<<1)
...@@ -105,6 +113,22 @@ struct resource { ...@@ -105,6 +113,22 @@ struct resource {
/* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ /* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */
#define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ #define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */
/*
* I/O Resource Descriptors
*
* Descriptors are used by walk_iomem_res_desc() and region_intersects()
* for searching a specific resource range in the iomem table. Assign
* a new descriptor when a resource range supports the search interfaces.
* Otherwise, resource.desc must be set to IORES_DESC_NONE (0).
*/
enum {
IORES_DESC_NONE = 0,
IORES_DESC_CRASH_KERNEL = 1,
IORES_DESC_ACPI_TABLES = 2,
IORES_DESC_ACPI_NV_STORAGE = 3,
IORES_DESC_PERSISTENT_MEMORY = 4,
IORES_DESC_PERSISTENT_MEMORY_LEGACY = 5,
};
/* helpers to define resources */ /* helpers to define resources */
#define DEFINE_RES_NAMED(_start, _size, _name, _flags) \ #define DEFINE_RES_NAMED(_start, _size, _name, _flags) \
...@@ -113,6 +137,7 @@ struct resource { ...@@ -113,6 +137,7 @@ struct resource {
.end = (_start) + (_size) - 1, \ .end = (_start) + (_size) - 1, \
.name = (_name), \ .name = (_name), \
.flags = (_flags), \ .flags = (_flags), \
.desc = IORES_DESC_NONE, \
} }
#define DEFINE_RES_IO_NAMED(_start, _size, _name) \ #define DEFINE_RES_IO_NAMED(_start, _size, _name) \
...@@ -170,6 +195,10 @@ static inline unsigned long resource_type(const struct resource *res) ...@@ -170,6 +195,10 @@ static inline unsigned long resource_type(const struct resource *res)
{ {
return res->flags & IORESOURCE_TYPE_BITS; return res->flags & IORESOURCE_TYPE_BITS;
} }
static inline unsigned long resource_ext_type(const struct resource *res)
{
return res->flags & IORESOURCE_EXT_TYPE_BITS;
}
/* True iff r1 completely contains r2 */ /* True iff r1 completely contains r2 */
static inline bool resource_contains(struct resource *r1, struct resource *r2) static inline bool resource_contains(struct resource *r1, struct resource *r2)
{ {
...@@ -239,8 +268,8 @@ extern int ...@@ -239,8 +268,8 @@ extern int
walk_system_ram_res(u64 start, u64 end, void *arg, walk_system_ram_res(u64 start, u64 end, void *arg,
int (*func)(u64, u64, void *)); int (*func)(u64, u64, void *));
extern int extern int
walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, void *arg, walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end,
int (*func)(u64, u64, void *)); void *arg, int (*func)(u64, u64, void *));
/* True if any part of r1 overlaps r2 */ /* True if any part of r1 overlaps r2 */
static inline bool resource_overlaps(struct resource *r1, struct resource *r2) static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
......
...@@ -387,7 +387,8 @@ enum { ...@@ -387,7 +387,8 @@ enum {
REGION_MIXED, REGION_MIXED,
}; };
int region_intersects(resource_size_t offset, size_t size, const char *type); int region_intersects(resource_size_t offset, size_t size, unsigned long flags,
unsigned long desc);
/* Support for virtually mapped pages */ /* Support for virtually mapped pages */
struct page *vmalloc_to_page(const void *addr); struct page *vmalloc_to_page(const void *addr);
......
...@@ -66,13 +66,15 @@ struct resource crashk_res = { ...@@ -66,13 +66,15 @@ struct resource crashk_res = {
.name = "Crash kernel", .name = "Crash kernel",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
.desc = IORES_DESC_CRASH_KERNEL
}; };
struct resource crashk_low_res = { struct resource crashk_low_res = {
.name = "Crash kernel", .name = "Crash kernel",
.start = 0, .start = 0,
.end = 0, .end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
.desc = IORES_DESC_CRASH_KERNEL
}; };
int kexec_should_crash(struct task_struct *p) int kexec_should_crash(struct task_struct *p)
...@@ -959,7 +961,7 @@ int crash_shrink_memory(unsigned long new_size) ...@@ -959,7 +961,7 @@ int crash_shrink_memory(unsigned long new_size)
ram_res->start = end; ram_res->start = end;
ram_res->end = crashk_res.end; ram_res->end = crashk_res.end;
ram_res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
ram_res->name = "System RAM"; ram_res->name = "System RAM";
crashk_res.end = end - 1; crashk_res.end = end - 1;
......
...@@ -524,10 +524,10 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, ...@@ -524,10 +524,10 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
/* Walk the RAM ranges and allocate a suitable range for the buffer */ /* Walk the RAM ranges and allocate a suitable range for the buffer */
if (image->type == KEXEC_TYPE_CRASH) if (image->type == KEXEC_TYPE_CRASH)
ret = walk_iomem_res("Crash kernel", ret = walk_iomem_res_desc(crashk_res.desc,
IORESOURCE_MEM | IORESOURCE_BUSY, IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
crashk_res.start, crashk_res.end, kbuf, crashk_res.start, crashk_res.end, kbuf,
locate_mem_hole_callback); locate_mem_hole_callback);
else else
ret = walk_system_ram_res(0, -1, kbuf, ret = walk_system_ram_res(0, -1, kbuf,
locate_mem_hole_callback); locate_mem_hole_callback);
......
...@@ -47,7 +47,7 @@ static void *try_ram_remap(resource_size_t offset, size_t size) ...@@ -47,7 +47,7 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
* being mapped does not have i/o side effects and the __iomem * being mapped does not have i/o side effects and the __iomem
* annotation is not applicable. * annotation is not applicable.
* *
* MEMREMAP_WB - matches the default mapping for "System RAM" on * MEMREMAP_WB - matches the default mapping for System RAM on
* the architecture. This is usually a read-allocate write-back cache. * the architecture. This is usually a read-allocate write-back cache.
* Morever, if MEMREMAP_WB is specified and the requested remap region is RAM * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM
* memremap() will bypass establishing a new mapping and instead return * memremap() will bypass establishing a new mapping and instead return
...@@ -56,11 +56,12 @@ static void *try_ram_remap(resource_size_t offset, size_t size) ...@@ -56,11 +56,12 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
* MEMREMAP_WT - establish a mapping whereby writes either bypass the * MEMREMAP_WT - establish a mapping whereby writes either bypass the
* cache or are written through to memory and never exist in a * cache or are written through to memory and never exist in a
* cache-dirty state with respect to program visibility. Attempts to * cache-dirty state with respect to program visibility. Attempts to
* map "System RAM" with this mapping type will fail. * map System RAM with this mapping type will fail.
*/ */
void *memremap(resource_size_t offset, size_t size, unsigned long flags) void *memremap(resource_size_t offset, size_t size, unsigned long flags)
{ {
int is_ram = region_intersects(offset, size, "System RAM"); int is_ram = region_intersects(offset, size,
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
void *addr = NULL; void *addr = NULL;
if (is_ram == REGION_MIXED) { if (is_ram == REGION_MIXED) {
...@@ -76,7 +77,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags) ...@@ -76,7 +77,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
* MEMREMAP_WB is special in that it can be satisifed * MEMREMAP_WB is special in that it can be satisifed
* from the direct map. Some archs depend on the * from the direct map. Some archs depend on the
* capability of memremap() to autodetect cases where * capability of memremap() to autodetect cases where
* the requested range is potentially in "System RAM" * the requested range is potentially in System RAM.
*/ */
if (is_ram == REGION_INTERSECTS) if (is_ram == REGION_INTERSECTS)
addr = try_ram_remap(offset, size); addr = try_ram_remap(offset, size);
...@@ -88,7 +89,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags) ...@@ -88,7 +89,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
* If we don't have a mapping yet and more request flags are * If we don't have a mapping yet and more request flags are
* pending then we will be attempting to establish a new virtual * pending then we will be attempting to establish a new virtual
* address mapping. Enforce that this mapping is not aliasing * address mapping. Enforce that this mapping is not aliasing
* "System RAM" * System RAM.
*/ */
if (!addr && is_ram == REGION_INTERSECTS && flags) { if (!addr && is_ram == REGION_INTERSECTS && flags) {
WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n", WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
...@@ -279,7 +280,8 @@ void *devm_memremap_pages(struct device *dev, struct resource *res, ...@@ -279,7 +280,8 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
align_start = res->start & ~(SECTION_SIZE - 1); align_start = res->start & ~(SECTION_SIZE - 1);
align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE) align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
- align_start; - align_start;
is_ram = region_intersects(align_start, align_size, "System RAM"); is_ram = region_intersects(align_start, align_size,
IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
if (is_ram == REGION_MIXED) { if (is_ram == REGION_MIXED) {
WARN_ONCE(1, "%s attempted on mixed region %pr\n", WARN_ONCE(1, "%s attempted on mixed region %pr\n",
......
...@@ -333,13 +333,13 @@ int release_resource(struct resource *old) ...@@ -333,13 +333,13 @@ int release_resource(struct resource *old)
EXPORT_SYMBOL(release_resource); EXPORT_SYMBOL(release_resource);
/* /*
* Finds the lowest iomem reosurce exists with-in [res->start.res->end) * Finds the lowest iomem resource existing within [res->start.res->end).
* the caller must specify res->start, res->end, res->flags and "name". * The caller must specify res->start, res->end, res->flags, and optionally
* If found, returns 0, res is overwritten, if not found, returns -1. * desc. If found, returns 0, res is overwritten, if not found, returns -1.
* This walks through whole tree and not just first level children * This function walks the whole tree and not just first level children until
* until and unless first_level_children_only is true. * and unless first_level_children_only is true.
*/ */
static int find_next_iomem_res(struct resource *res, char *name, static int find_next_iomem_res(struct resource *res, unsigned long desc,
bool first_level_children_only) bool first_level_children_only)
{ {
resource_size_t start, end; resource_size_t start, end;
...@@ -358,9 +358,9 @@ static int find_next_iomem_res(struct resource *res, char *name, ...@@ -358,9 +358,9 @@ static int find_next_iomem_res(struct resource *res, char *name,
read_lock(&resource_lock); read_lock(&resource_lock);
for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) { for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) {
if (p->flags != res->flags) if ((p->flags & res->flags) != res->flags)
continue; continue;
if (name && strcmp(p->name, name)) if ((desc != IORES_DESC_NONE) && (desc != p->desc))
continue; continue;
if (p->start > end) { if (p->start > end) {
p = NULL; p = NULL;
...@@ -385,15 +385,18 @@ static int find_next_iomem_res(struct resource *res, char *name, ...@@ -385,15 +385,18 @@ static int find_next_iomem_res(struct resource *res, char *name,
* Walks through iomem resources and calls func() with matching resource * Walks through iomem resources and calls func() with matching resource
* ranges. This walks through whole tree and not just first level children. * ranges. This walks through whole tree and not just first level children.
* All the memory ranges which overlap start,end and also match flags and * All the memory ranges which overlap start,end and also match flags and
* name are valid candidates. * desc are valid candidates.
* *
* @name: name of resource * @desc: I/O resource descriptor. Use IORES_DESC_NONE to skip @desc check.
* @flags: resource flags * @flags: I/O resource flags
* @start: start addr * @start: start addr
* @end: end addr * @end: end addr
*
* NOTE: For a new descriptor search, define a new IORES_DESC in
* <linux/ioport.h> and set it in 'desc' of a target resource entry.
*/ */
int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
void *arg, int (*func)(u64, u64, void *)) u64 end, void *arg, int (*func)(u64, u64, void *))
{ {
struct resource res; struct resource res;
u64 orig_end; u64 orig_end;
...@@ -403,23 +406,27 @@ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, ...@@ -403,23 +406,27 @@ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end,
res.end = end; res.end = end;
res.flags = flags; res.flags = flags;
orig_end = res.end; orig_end = res.end;
while ((res.start < res.end) && while ((res.start < res.end) &&
(!find_next_iomem_res(&res, name, false))) { (!find_next_iomem_res(&res, desc, false))) {
ret = (*func)(res.start, res.end, arg); ret = (*func)(res.start, res.end, arg);
if (ret) if (ret)
break; break;
res.start = res.end + 1; res.start = res.end + 1;
res.end = orig_end; res.end = orig_end;
} }
return ret; return ret;
} }
/* /*
* This function calls callback against all memory range of "System RAM" * This function calls the @func callback against all memory ranges of type
* which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
* Now, this function is only for "System RAM". This function deals with * Now, this function is only for System RAM, it deals with full ranges and
* full ranges and not pfn. If resources are not pfn aligned, dealing * not PFNs. If resources are not PFN-aligned, dealing with PFNs can truncate
* with pfn can truncate ranges. * ranges.
*/ */
int walk_system_ram_res(u64 start, u64 end, void *arg, int walk_system_ram_res(u64 start, u64 end, void *arg,
int (*func)(u64, u64, void *)) int (*func)(u64, u64, void *))
...@@ -430,10 +437,10 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, ...@@ -430,10 +437,10 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
res.start = start; res.start = start;
res.end = end; res.end = end;
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
orig_end = res.end; orig_end = res.end;
while ((res.start < res.end) && while ((res.start < res.end) &&
(!find_next_iomem_res(&res, "System RAM", true))) { (!find_next_iomem_res(&res, IORES_DESC_NONE, true))) {
ret = (*func)(res.start, res.end, arg); ret = (*func)(res.start, res.end, arg);
if (ret) if (ret)
break; break;
...@@ -446,9 +453,9 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, ...@@ -446,9 +453,9 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
#if !defined(CONFIG_ARCH_HAS_WALK_MEMORY) #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
/* /*
* This function calls callback against all memory range of "System RAM" * This function calls the @func callback against all memory ranges of type
* which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
* Now, this function is only for "System RAM". * It is to be used only for System RAM.
*/ */
int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
void *arg, int (*func)(unsigned long, unsigned long, void *)) void *arg, int (*func)(unsigned long, unsigned long, void *))
...@@ -460,10 +467,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, ...@@ -460,10 +467,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
res.start = (u64) start_pfn << PAGE_SHIFT; res.start = (u64) start_pfn << PAGE_SHIFT;
res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1; res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
orig_end = res.end; orig_end = res.end;
while ((res.start < res.end) && while ((res.start < res.end) &&
(find_next_iomem_res(&res, "System RAM", true) >= 0)) { (find_next_iomem_res(&res, IORES_DESC_NONE, true) >= 0)) {
pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
end_pfn = (res.end + 1) >> PAGE_SHIFT; end_pfn = (res.end + 1) >> PAGE_SHIFT;
if (end_pfn > pfn) if (end_pfn > pfn)
...@@ -484,7 +491,7 @@ static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg) ...@@ -484,7 +491,7 @@ static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
} }
/* /*
* This generic page_is_ram() returns true if specified address is * This generic page_is_ram() returns true if specified address is
* registered as "System RAM" in iomem_resource list. * registered as System RAM in iomem_resource list.
*/ */
int __weak page_is_ram(unsigned long pfn) int __weak page_is_ram(unsigned long pfn)
{ {
...@@ -496,30 +503,34 @@ EXPORT_SYMBOL_GPL(page_is_ram); ...@@ -496,30 +503,34 @@ EXPORT_SYMBOL_GPL(page_is_ram);
* region_intersects() - determine intersection of region with known resources * region_intersects() - determine intersection of region with known resources
* @start: region start address * @start: region start address
* @size: size of region * @size: size of region
* @name: name of resource (in iomem_resource) * @flags: flags of resource (in iomem_resource)
* @desc: descriptor of resource (in iomem_resource) or IORES_DESC_NONE
* *
* Check if the specified region partially overlaps or fully eclipses a * Check if the specified region partially overlaps or fully eclipses a
* resource identified by @name. Return REGION_DISJOINT if the region * resource identified by @flags and @desc (optional with IORES_DESC_NONE).
* does not overlap @name, return REGION_MIXED if the region overlaps * Return REGION_DISJOINT if the region does not overlap @flags/@desc,
* @type and another resource, and return REGION_INTERSECTS if the * return REGION_MIXED if the region overlaps @flags/@desc and another
* region overlaps @type and no other defined resource. Note, that * resource, and return REGION_INTERSECTS if the region overlaps @flags/@desc
* REGION_INTERSECTS is also returned in the case when the specified * and no other defined resource. Note that REGION_INTERSECTS is also
* region overlaps RAM and undefined memory holes. * returned in the case when the specified region overlaps RAM and undefined
* memory holes.
* *
* region_intersect() is used by memory remapping functions to ensure * region_intersect() is used by memory remapping functions to ensure
* the user is not remapping RAM and is a vast speed up over walking * the user is not remapping RAM and is a vast speed up over walking
* through the resource table page by page. * through the resource table page by page.
*/ */
int region_intersects(resource_size_t start, size_t size, const char *name) int region_intersects(resource_size_t start, size_t size, unsigned long flags,
unsigned long desc)
{ {
unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
resource_size_t end = start + size - 1; resource_size_t end = start + size - 1;
int type = 0; int other = 0; int type = 0; int other = 0;
struct resource *p; struct resource *p;
read_lock(&resource_lock); read_lock(&resource_lock);
for (p = iomem_resource.child; p ; p = p->sibling) { for (p = iomem_resource.child; p ; p = p->sibling) {
bool is_type = strcmp(p->name, name) == 0 && p->flags == flags; bool is_type = (((p->flags & flags) == flags) &&
((desc == IORES_DESC_NONE) ||
(desc == p->desc)));
if (start >= p->start && start <= p->end) if (start >= p->start && start <= p->end)
is_type ? type++ : other++; is_type ? type++ : other++;
...@@ -538,6 +549,7 @@ int region_intersects(resource_size_t start, size_t size, const char *name) ...@@ -538,6 +549,7 @@ int region_intersects(resource_size_t start, size_t size, const char *name)
return REGION_DISJOINT; return REGION_DISJOINT;
} }
EXPORT_SYMBOL_GPL(region_intersects);
void __weak arch_remove_reservations(struct resource *avail) void __weak arch_remove_reservations(struct resource *avail)
{ {
...@@ -948,6 +960,7 @@ static void __init __reserve_region_with_split(struct resource *root, ...@@ -948,6 +960,7 @@ static void __init __reserve_region_with_split(struct resource *root,
res->start = start; res->start = start;
res->end = end; res->end = end;
res->flags = IORESOURCE_BUSY; res->flags = IORESOURCE_BUSY;
res->desc = IORES_DESC_NONE;
while (1) { while (1) {
...@@ -982,6 +995,7 @@ static void __init __reserve_region_with_split(struct resource *root, ...@@ -982,6 +995,7 @@ static void __init __reserve_region_with_split(struct resource *root,
next_res->start = conflict->end + 1; next_res->start = conflict->end + 1;
next_res->end = end; next_res->end = end;
next_res->flags = IORESOURCE_BUSY; next_res->flags = IORESOURCE_BUSY;
next_res->desc = IORES_DESC_NONE;
} }
} else { } else {
res->start = conflict->end + 1; res->start = conflict->end + 1;
...@@ -1071,8 +1085,9 @@ struct resource * __request_region(struct resource *parent, ...@@ -1071,8 +1085,9 @@ struct resource * __request_region(struct resource *parent,
res->name = name; res->name = name;
res->start = start; res->start = start;
res->end = start + n - 1; res->end = start + n - 1;
res->flags = resource_type(parent); res->flags = resource_type(parent) | resource_ext_type(parent);
res->flags |= IORESOURCE_BUSY | flags; res->flags |= IORESOURCE_BUSY | flags;
res->desc = IORES_DESC_NONE;
write_lock(&resource_lock); write_lock(&resource_lock);
...@@ -1238,6 +1253,7 @@ int release_mem_region_adjustable(struct resource *parent, ...@@ -1238,6 +1253,7 @@ int release_mem_region_adjustable(struct resource *parent,
new_res->start = end + 1; new_res->start = end + 1;
new_res->end = res->end; new_res->end = res->end;
new_res->flags = res->flags; new_res->flags = res->flags;
new_res->desc = res->desc;
new_res->parent = res->parent; new_res->parent = res->parent;
new_res->sibling = res->sibling; new_res->sibling = res->sibling;
new_res->child = NULL; new_res->child = NULL;
...@@ -1413,6 +1429,7 @@ static int __init reserve_setup(char *str) ...@@ -1413,6 +1429,7 @@ static int __init reserve_setup(char *str)
res->start = io_start; res->start = io_start;
res->end = io_start + io_num - 1; res->end = io_start + io_num - 1;
res->flags = IORESOURCE_BUSY; res->flags = IORESOURCE_BUSY;
res->desc = IORES_DESC_NONE;
res->child = NULL; res->child = NULL;
if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0) if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
reserved = x+1; reserved = x+1;
......
...@@ -138,7 +138,7 @@ static struct resource *register_memory_resource(u64 start, u64 size) ...@@ -138,7 +138,7 @@ static struct resource *register_memory_resource(u64 start, u64 size)
res->name = "System RAM"; res->name = "System RAM";
res->start = start; res->start = start;
res->end = start + size - 1; res->end = start + size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
if (request_resource(&iomem_resource, res) < 0) { if (request_resource(&iomem_resource, res) < 0) {
pr_debug("System RAM resource %pR cannot be added\n", res); pr_debug("System RAM resource %pR cannot be added\n", res);
kfree(res); kfree(res);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment