diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2009-09-22 19:45:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 10:39:41 -0400 |
commit | 908eedc6168bd92e89f90d89fa389065a36358fa (patch) | |
tree | 612881abb2aae920ab1e62e88990ee7b6a988f51 | |
parent | 9492587cf35d370db33ef4b38375dfb35a105b61 (diff) |
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: KAMEZAWA 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: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/powerpc/mm/mem.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_mrmw.c | 2 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_qmr.c | 2 | ||||
-rw-r--r-- | include/linux/ioport.h | 4 | ||||
-rw-r--r-- | include/linux/memory_hotplug.h | 8 | ||||
-rw-r--r-- | kernel/resource.c | 23 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 6 |
7 files changed, 28 insertions, 23 deletions
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 0e5c59b995ef..59736317bf0e 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -143,8 +143,8 @@ int arch_add_memory(int nid, u64 start, u64 size) | |||
143 | * memory regions, find holes and callback for contiguous regions. | 143 | * memory regions, find holes and callback for contiguous regions. |
144 | */ | 144 | */ |
145 | int | 145 | int |
146 | walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, | 146 | walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, |
147 | int (*func)(unsigned long, unsigned long, void *)) | 147 | void *arg, int (*func)(unsigned long, unsigned long, void *)) |
148 | { | 148 | { |
149 | struct lmb_property res; | 149 | struct lmb_property res; |
150 | unsigned long pfn, len; | 150 | unsigned long pfn, len; |
@@ -166,7 +166,7 @@ walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, | |||
166 | } | 166 | } |
167 | return ret; | 167 | return ret; |
168 | } | 168 | } |
169 | EXPORT_SYMBOL_GPL(walk_memory_resource); | 169 | EXPORT_SYMBOL_GPL(walk_system_ram_range); |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * Initialize the bootmem system and give it all the memory we | 172 | * Initialize the bootmem system and give it all the memory we |
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c index 7663a2a9f130..7550a534005c 100644 --- a/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c | |||
@@ -2463,7 +2463,7 @@ int ehca_create_busmap(void) | |||
2463 | int ret; | 2463 | int ret; |
2464 | 2464 | ||
2465 | ehca_mr_len = 0; | 2465 | ehca_mr_len = 0; |
2466 | ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL, | 2466 | ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL, |
2467 | ehca_create_busmap_callback); | 2467 | ehca_create_busmap_callback); |
2468 | return ret; | 2468 | return ret; |
2469 | } | 2469 | } |
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 3747457f5e69..bc7c5b7abb88 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c | |||
@@ -751,7 +751,7 @@ int ehea_create_busmap(void) | |||
751 | 751 | ||
752 | mutex_lock(&ehea_busmap_mutex); | 752 | mutex_lock(&ehea_busmap_mutex); |
753 | ehea_mr_len = 0; | 753 | ehea_mr_len = 0; |
754 | ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL, | 754 | ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL, |
755 | ehea_create_busmap_callback); | 755 | ehea_create_busmap_callback); |
756 | mutex_unlock(&ehea_busmap_mutex); | 756 | mutex_unlock(&ehea_busmap_mutex); |
757 | return ret; | 757 | return ret; |
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 786e7b8cece9..83aa81297ea3 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
@@ -184,5 +184,9 @@ extern void __devm_release_region(struct device *dev, struct resource *parent, | |||
184 | extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size); | 184 | extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size); |
185 | extern int iomem_is_exclusive(u64 addr); | 185 | extern int iomem_is_exclusive(u64 addr); |
186 | 186 | ||
187 | extern int | ||
188 | walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | ||
189 | void *arg, int (*func)(unsigned long, unsigned long, void *)); | ||
190 | |||
187 | #endif /* __ASSEMBLY__ */ | 191 | #endif /* __ASSEMBLY__ */ |
188 | #endif /* _LINUX_IOPORT_H */ | 192 | #endif /* _LINUX_IOPORT_H */ |
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index d95f72e79b82..fed969281a41 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
@@ -191,14 +191,6 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat) | |||
191 | 191 | ||
192 | #endif /* ! CONFIG_MEMORY_HOTPLUG */ | 192 | #endif /* ! CONFIG_MEMORY_HOTPLUG */ |
193 | 193 | ||
194 | /* | ||
195 | * Walk through all memory which is registered as resource. | ||
196 | * arg is (start_pfn, nr_pages, private_arg_pointer) | ||
197 | */ | ||
198 | extern int walk_memory_resource(unsigned long start_pfn, | ||
199 | unsigned long nr_pages, void *arg, | ||
200 | int (*func)(unsigned long, unsigned long, void *)); | ||
201 | |||
202 | #ifdef CONFIG_MEMORY_HOTREMOVE | 194 | #ifdef CONFIG_MEMORY_HOTREMOVE |
203 | 195 | ||
204 | extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages); | 196 | extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages); |
diff --git a/kernel/resource.c b/kernel/resource.c index 78b087221c15..fb11a58b9594 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
@@ -223,13 +223,13 @@ int release_resource(struct resource *old) | |||
223 | 223 | ||
224 | EXPORT_SYMBOL(release_resource); | 224 | EXPORT_SYMBOL(release_resource); |
225 | 225 | ||
226 | #if defined(CONFIG_MEMORY_HOTPLUG) && !defined(CONFIG_ARCH_HAS_WALK_MEMORY) | 226 | #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY) |
227 | /* | 227 | /* |
228 | * Finds the lowest memory reosurce exists within [res->start.res->end) | 228 | * Finds the lowest memory reosurce exists within [res->start.res->end) |
229 | * the caller must specify res->start, res->end, res->flags. | 229 | * the caller must specify res->start, res->end, res->flags and "name". |
230 | * If found, returns 0, res is overwritten, if not found, returns -1. | 230 | * If found, returns 0, res is overwritten, if not found, returns -1. |
231 | */ | 231 | */ |
232 | static int find_next_system_ram(struct resource *res) | 232 | static int find_next_system_ram(struct resource *res, char *name) |
233 | { | 233 | { |
234 | resource_size_t start, end; | 234 | resource_size_t start, end; |
235 | struct resource *p; | 235 | struct resource *p; |
@@ -245,6 +245,8 @@ static int find_next_system_ram(struct resource *res) | |||
245 | /* system ram is just marked as IORESOURCE_MEM */ | 245 | /* system ram is just marked as IORESOURCE_MEM */ |
246 | if (p->flags != res->flags) | 246 | if (p->flags != res->flags) |
247 | continue; | 247 | continue; |
248 | if (name && strcmp(p->name, name)) | ||
249 | continue; | ||
248 | if (p->start > end) { | 250 | if (p->start > end) { |
249 | p = NULL; | 251 | p = NULL; |
250 | break; | 252 | break; |
@@ -262,19 +264,26 @@ static int find_next_system_ram(struct resource *res) | |||
262 | res->end = p->end; | 264 | res->end = p->end; |
263 | return 0; | 265 | return 0; |
264 | } | 266 | } |
265 | int | 267 | |
266 | walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, | 268 | /* |
267 | int (*func)(unsigned long, unsigned long, void *)) | 269 | * This function calls callback against all memory range of "System RAM" |
270 | * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. | ||
271 | * Now, this function is only for "System RAM". | ||
272 | */ | ||
273 | int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | ||
274 | void *arg, int (*func)(unsigned long, unsigned long, void *)) | ||
268 | { | 275 | { |
269 | struct resource res; | 276 | struct resource res; |
270 | unsigned long pfn, len; | 277 | unsigned long pfn, len; |
271 | u64 orig_end; | 278 | u64 orig_end; |
272 | int ret = -1; | 279 | int ret = -1; |
280 | |||
273 | res.start = (u64) start_pfn << PAGE_SHIFT; | 281 | res.start = (u64) start_pfn << PAGE_SHIFT; |
274 | res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1; | 282 | res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1; |
275 | res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 283 | res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
276 | orig_end = res.end; | 284 | orig_end = res.end; |
277 | while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) { | 285 | while ((res.start < res.end) && |
286 | (find_next_system_ram(&res, "System RAM") >= 0)) { | ||
278 | pfn = (unsigned long)(res.start >> PAGE_SHIFT); | 287 | pfn = (unsigned long)(res.start >> PAGE_SHIFT); |
279 | len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT); | 288 | len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT); |
280 | ret = (*func)(pfn, len, arg); | 289 | ret = (*func)(pfn, len, arg); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index efe3e0ec2e61..821dee596377 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -413,7 +413,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
413 | if (!populated_zone(zone)) | 413 | if (!populated_zone(zone)) |
414 | need_zonelists_rebuild = 1; | 414 | need_zonelists_rebuild = 1; |
415 | 415 | ||
416 | ret = walk_memory_resource(pfn, nr_pages, &onlined_pages, | 416 | ret = walk_system_ram_range(pfn, nr_pages, &onlined_pages, |
417 | online_pages_range); | 417 | online_pages_range); |
418 | if (ret) { | 418 | if (ret) { |
419 | printk(KERN_DEBUG "online_pages %lx at %lx failed\n", | 419 | 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 | static void | 705 | static void |
706 | offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) | 706 | offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) |
707 | { | 707 | { |
708 | walk_memory_resource(start_pfn, end_pfn - start_pfn, NULL, | 708 | walk_system_ram_range(start_pfn, end_pfn - start_pfn, NULL, |
709 | offline_isolated_pages_cb); | 709 | offline_isolated_pages_cb); |
710 | } | 710 | } |
711 | 711 | ||
@@ -731,7 +731,7 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) | |||
731 | long offlined = 0; | 731 | long offlined = 0; |
732 | int ret; | 732 | int ret; |
733 | 733 | ||
734 | ret = walk_memory_resource(start_pfn, end_pfn - start_pfn, &offlined, | 734 | ret = walk_system_ram_range(start_pfn, end_pfn - start_pfn, &offlined, |
735 | check_pages_isolated_cb); | 735 | check_pages_isolated_cb); |
736 | if (ret < 0) | 736 | if (ret < 0) |
737 | offlined = (long)ret; | 737 | offlined = (long)ret; |