Commit 908eedc6 authored by KAMEZAWA Hiroyuki's avatar KAMEZAWA Hiroyuki Committed by Linus Torvalds

walk system ram range

Originally, walk_memory_resource() was introduced to traverse all memory
of "System RAM" for detecting memory hotplug/unplug range.  For doing so,
flags of IORESOUCE_MEM|IORESOURCE_BUSY was used and this was enough for
memory hotplug.

But for using other purpose, /proc/kcore, this may includes some firmware
area marked as IORESOURCE_BUSY | IORESOUCE_MEM.  This patch makes the
check strict to find out busy "System RAM".

Note: PPC64 keeps their own walk_memory_resouce(), which walk through
ppc64's lmb informaton.  Because old kclist_add() is called per lmb, this
patch makes no difference in behavior, finally.

And this patch removes CONFIG_MEMORY_HOTPLUG check from this function.
Because pfn_valid() just show "there is memmap or not* and cannot be used
for "there is physical memory or not", this function is useful in generic
to scan physical memory range.
Signed-off-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: WANG Cong <xiyou.wangcong@gmail.com>
Cc: Américo Wang <xiyou.wangcong@gmail.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Roland Dreier <rolandd@cisco.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9492587c
...@@ -143,8 +143,8 @@ int arch_add_memory(int nid, u64 start, u64 size) ...@@ -143,8 +143,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
* memory regions, find holes and callback for contiguous regions. * memory regions, find holes and callback for contiguous regions.
*/ */
int int
walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
int (*func)(unsigned long, unsigned long, void *)) void *arg, int (*func)(unsigned long, unsigned long, void *))
{ {
struct lmb_property res; struct lmb_property res;
unsigned long pfn, len; unsigned long pfn, len;
...@@ -166,7 +166,7 @@ walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, ...@@ -166,7 +166,7 @@ walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg,
} }
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(walk_memory_resource); EXPORT_SYMBOL_GPL(walk_system_ram_range);
/* /*
* Initialize the bootmem system and give it all the memory we * Initialize the bootmem system and give it all the memory we
......
...@@ -2463,7 +2463,7 @@ int ehca_create_busmap(void) ...@@ -2463,7 +2463,7 @@ int ehca_create_busmap(void)
int ret; int ret;
ehca_mr_len = 0; ehca_mr_len = 0;
ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL, ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
ehca_create_busmap_callback); ehca_create_busmap_callback);
return ret; return ret;
} }
......
...@@ -751,7 +751,7 @@ int ehea_create_busmap(void) ...@@ -751,7 +751,7 @@ int ehea_create_busmap(void)
mutex_lock(&ehea_busmap_mutex); mutex_lock(&ehea_busmap_mutex);
ehea_mr_len = 0; ehea_mr_len = 0;
ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL, ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
ehea_create_busmap_callback); ehea_create_busmap_callback);
mutex_unlock(&ehea_busmap_mutex); mutex_unlock(&ehea_busmap_mutex);
return ret; return ret;
......
...@@ -184,5 +184,9 @@ extern void __devm_release_region(struct device *dev, struct resource *parent, ...@@ -184,5 +184,9 @@ extern void __devm_release_region(struct device *dev, struct resource *parent,
extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size); extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size);
extern int iomem_is_exclusive(u64 addr); extern int iomem_is_exclusive(u64 addr);
extern int
walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
void *arg, int (*func)(unsigned long, unsigned long, void *));
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _LINUX_IOPORT_H */ #endif /* _LINUX_IOPORT_H */
...@@ -191,14 +191,6 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat) ...@@ -191,14 +191,6 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
#endif /* ! CONFIG_MEMORY_HOTPLUG */ #endif /* ! CONFIG_MEMORY_HOTPLUG */
/*
* Walk through all memory which is registered as resource.
* arg is (start_pfn, nr_pages, private_arg_pointer)
*/
extern int walk_memory_resource(unsigned long start_pfn,
unsigned long nr_pages, void *arg,
int (*func)(unsigned long, unsigned long, void *));
#ifdef CONFIG_MEMORY_HOTREMOVE #ifdef CONFIG_MEMORY_HOTREMOVE
extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages); extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages);
......
...@@ -223,13 +223,13 @@ int release_resource(struct resource *old) ...@@ -223,13 +223,13 @@ int release_resource(struct resource *old)
EXPORT_SYMBOL(release_resource); EXPORT_SYMBOL(release_resource);
#if defined(CONFIG_MEMORY_HOTPLUG) && !defined(CONFIG_ARCH_HAS_WALK_MEMORY) #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
/* /*
* Finds the lowest memory reosurce exists within [res->start.res->end) * Finds the lowest memory reosurce exists within [res->start.res->end)
* the caller must specify res->start, res->end, res->flags. * the caller must specify res->start, res->end, res->flags and "name".
* If found, returns 0, res is overwritten, if not found, returns -1. * If found, returns 0, res is overwritten, if not found, returns -1.
*/ */
static int find_next_system_ram(struct resource *res) static int find_next_system_ram(struct resource *res, char *name)
{ {
resource_size_t start, end; resource_size_t start, end;
struct resource *p; struct resource *p;
...@@ -245,6 +245,8 @@ static int find_next_system_ram(struct resource *res) ...@@ -245,6 +245,8 @@ static int find_next_system_ram(struct resource *res)
/* system ram is just marked as IORESOURCE_MEM */ /* system ram is just marked as IORESOURCE_MEM */
if (p->flags != res->flags) if (p->flags != res->flags)
continue; continue;
if (name && strcmp(p->name, name))
continue;
if (p->start > end) { if (p->start > end) {
p = NULL; p = NULL;
break; break;
...@@ -262,19 +264,26 @@ static int find_next_system_ram(struct resource *res) ...@@ -262,19 +264,26 @@ static int find_next_system_ram(struct resource *res)
res->end = p->end; res->end = p->end;
return 0; return 0;
} }
int
walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, /*
int (*func)(unsigned long, unsigned long, void *)) * This function calls callback against all memory range of "System RAM"
* which are marked as IORESOURCE_MEM and IORESOUCE_BUSY.
* Now, this function is only for "System RAM".
*/
int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
void *arg, int (*func)(unsigned long, unsigned long, void *))
{ {
struct resource res; struct resource res;
unsigned long pfn, len; unsigned long pfn, len;
u64 orig_end; u64 orig_end;
int ret = -1; int ret = -1;
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_MEM | IORESOURCE_BUSY;
orig_end = res.end; orig_end = res.end;
while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) { while ((res.start < res.end) &&
(find_next_system_ram(&res, "System RAM") >= 0)) {
pfn = (unsigned long)(res.start >> PAGE_SHIFT); pfn = (unsigned long)(res.start >> PAGE_SHIFT);
len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT); len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT);
ret = (*func)(pfn, len, arg); ret = (*func)(pfn, len, arg);
......
...@@ -413,7 +413,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) ...@@ -413,7 +413,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)
if (!populated_zone(zone)) if (!populated_zone(zone))
need_zonelists_rebuild = 1; need_zonelists_rebuild = 1;
ret = walk_memory_resource(pfn, nr_pages, &onlined_pages, ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages,
online_pages_range); online_pages_range);
if (ret) { if (ret) {
printk(KERN_DEBUG "online_pages %lx at %lx failed\n", printk(KERN_DEBUG "online_pages %lx at %lx failed\n",
...@@ -705,7 +705,7 @@ offline_isolated_pages_cb(unsigned long start, unsigned long nr_pages, ...@@ -705,7 +705,7 @@ offline_isolated_pages_cb(unsigned long start, unsigned long nr_pages,
static void static void
offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
{ {
walk_memory_resource(start_pfn, end_pfn - start_pfn, NULL, walk_system_ram_range(start_pfn, end_pfn - start_pfn, NULL,
offline_isolated_pages_cb); offline_isolated_pages_cb);
} }
...@@ -731,7 +731,7 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) ...@@ -731,7 +731,7 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
long offlined = 0; long offlined = 0;
int ret; int ret;
ret = walk_memory_resource(start_pfn, end_pfn - start_pfn, &offlined, ret = walk_system_ram_range(start_pfn, end_pfn - start_pfn, &offlined,
check_pages_isolated_cb); check_pages_isolated_cb);
if (ret < 0) if (ret < 0)
offlined = (long)ret; offlined = (long)ret;
......
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