aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2009-09-22 19:45:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:41 -0400
commit908eedc6168bd92e89f90d89fa389065a36358fa (patch)
tree612881abb2aae920ab1e62e88990ee7b6a988f51
parent9492587cf35d370db33ef4b38375dfb35a105b61 (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.c6
-rw-r--r--drivers/infiniband/hw/ehca/ehca_mrmw.c2
-rw-r--r--drivers/net/ehea/ehea_qmr.c2
-rw-r--r--include/linux/ioport.h4
-rw-r--r--include/linux/memory_hotplug.h8
-rw-r--r--kernel/resource.c23
-rw-r--r--mm/memory_hotplug.c6
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 */
145int 145int
146walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, 146walk_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}
169EXPORT_SYMBOL_GPL(walk_memory_resource); 169EXPORT_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,
184extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size); 184extern int iomem_map_sanity_check(resource_size_t addr, unsigned long size);
185extern int iomem_is_exclusive(u64 addr); 185extern int iomem_is_exclusive(u64 addr);
186 186
187extern int
188walk_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 */
198extern 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
204extern int is_mem_section_removable(unsigned long pfn, unsigned long nr_pages); 196extern 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
224EXPORT_SYMBOL(release_resource); 224EXPORT_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 */
232static int find_next_system_ram(struct resource *res) 232static 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}
265int 267
266walk_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 */
273int 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,
705static void 705static void
706offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) 706offline_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;