aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/mm.h57
1 files changed, 36 insertions, 21 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d538de901965..ab6e4974f379 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -396,7 +396,9 @@ void split_page(struct page *page, unsigned int order);
396 * We are going to use the flags for the page to node mapping if its in 396 * We are going to use the flags for the page to node mapping if its in
397 * there. This includes the case where there is no node, so it is implicit. 397 * there. This includes the case where there is no node, so it is implicit.
398 */ 398 */
399#define FLAGS_HAS_NODE (NODES_WIDTH > 0 || NODES_SHIFT == 0) 399#if !(NODES_WIDTH > 0 || NODES_SHIFT == 0)
400#define NODE_NOT_IN_PAGE_FLAGS
401#endif
400 402
401#ifndef PFN_SECTION_SHIFT 403#ifndef PFN_SECTION_SHIFT
402#define PFN_SECTION_SHIFT 0 404#define PFN_SECTION_SHIFT 0
@@ -411,13 +413,18 @@ void split_page(struct page *page, unsigned int order);
411#define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0)) 413#define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0))
412#define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0)) 414#define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0))
413 415
414/* NODE:ZONE or SECTION:ZONE is used to lookup the zone from a page. */ 416/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allcator */
415#if FLAGS_HAS_NODE 417#ifdef NODE_NOT_IN_PAGEFLAGS
416#define ZONETABLE_SHIFT (NODES_SHIFT + ZONES_SHIFT) 418#define ZONEID_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT)
417#else 419#else
418#define ZONETABLE_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT) 420#define ZONEID_SHIFT (NODES_SHIFT + ZONES_SHIFT)
421#endif
422
423#if ZONES_WIDTH > 0
424#define ZONEID_PGSHIFT ZONES_PGSHIFT
425#else
426#define ZONEID_PGSHIFT NODES_PGOFF
419#endif 427#endif
420#define ZONETABLE_PGSHIFT ZONES_PGSHIFT
421 428
422#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED 429#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
423#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED 430#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
@@ -426,23 +433,25 @@ void split_page(struct page *page, unsigned int order);
426#define ZONES_MASK ((1UL << ZONES_WIDTH) - 1) 433#define ZONES_MASK ((1UL << ZONES_WIDTH) - 1)
427#define NODES_MASK ((1UL << NODES_WIDTH) - 1) 434#define NODES_MASK ((1UL << NODES_WIDTH) - 1)
428#define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1) 435#define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1)
429#define ZONETABLE_MASK ((1UL << ZONETABLE_SHIFT) - 1) 436#define ZONEID_MASK ((1UL << ZONEID_SHIFT) - 1)
430 437
431static inline enum zone_type page_zonenum(struct page *page) 438static inline enum zone_type page_zonenum(struct page *page)
432{ 439{
433 return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK; 440 return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
434} 441}
435 442
436struct zone; 443/*
437extern struct zone *zone_table[]; 444 * The identification function is only used by the buddy allocator for
438 445 * determining if two pages could be buddies. We are not really
446 * identifying a zone since we could be using a the section number
447 * id if we have not node id available in page flags.
448 * We guarantee only that it will return the same value for two
449 * combinable pages in a zone.
450 */
439static inline int page_zone_id(struct page *page) 451static inline int page_zone_id(struct page *page)
440{ 452{
441 return (page->flags >> ZONETABLE_PGSHIFT) & ZONETABLE_MASK; 453 BUILD_BUG_ON(ZONEID_PGSHIFT == 0 && ZONEID_MASK);
442} 454 return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
443static inline struct zone *page_zone(struct page *page)
444{
445 return zone_table[page_zone_id(page)];
446} 455}
447 456
448static inline unsigned long zone_to_nid(struct zone *zone) 457static inline unsigned long zone_to_nid(struct zone *zone)
@@ -454,13 +463,20 @@ static inline unsigned long zone_to_nid(struct zone *zone)
454#endif 463#endif
455} 464}
456 465
466#ifdef NODE_NOT_IN_PAGE_FLAGS
467extern unsigned long page_to_nid(struct page *page);
468#else
457static inline unsigned long page_to_nid(struct page *page) 469static inline unsigned long page_to_nid(struct page *page)
458{ 470{
459 if (FLAGS_HAS_NODE) 471 return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
460 return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
461 else
462 return zone_to_nid(page_zone(page));
463} 472}
473#endif
474
475static inline struct zone *page_zone(struct page *page)
476{
477 return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
478}
479
464static inline unsigned long page_to_section(struct page *page) 480static inline unsigned long page_to_section(struct page *page)
465{ 481{
466 return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK; 482 return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
@@ -477,6 +493,7 @@ static inline void set_page_node(struct page *page, unsigned long node)
477 page->flags &= ~(NODES_MASK << NODES_PGSHIFT); 493 page->flags &= ~(NODES_MASK << NODES_PGSHIFT);
478 page->flags |= (node & NODES_MASK) << NODES_PGSHIFT; 494 page->flags |= (node & NODES_MASK) << NODES_PGSHIFT;
479} 495}
496
480static inline void set_page_section(struct page *page, unsigned long section) 497static inline void set_page_section(struct page *page, unsigned long section)
481{ 498{
482 page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT); 499 page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
@@ -947,8 +964,6 @@ extern void mem_init(void);
947extern void show_mem(void); 964extern void show_mem(void);
948extern void si_meminfo(struct sysinfo * val); 965extern void si_meminfo(struct sysinfo * val);
949extern void si_meminfo_node(struct sysinfo *val, int nid); 966extern void si_meminfo_node(struct sysinfo *val, int nid);
950extern void zonetable_add(struct zone *zone, int nid, enum zone_type zid,
951 unsigned long pfn, unsigned long size);
952 967
953#ifdef CONFIG_NUMA 968#ifdef CONFIG_NUMA
954extern void setup_per_cpu_pageset(void); 969extern void setup_per_cpu_pageset(void);