diff options
-rw-r--r-- | include/linux/mmzone.h | 5 | ||||
-rw-r--r-- | mm/sparse.c | 22 |
2 files changed, 25 insertions, 2 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index e82fc1a52cd0..d6120fa69116 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -509,6 +509,10 @@ struct mem_section { | |||
509 | * pages. However, it is stored with some other magic. | 509 | * pages. However, it is stored with some other magic. |
510 | * (see sparse.c::sparse_init_one_section()) | 510 | * (see sparse.c::sparse_init_one_section()) |
511 | * | 511 | * |
512 | * Additionally during early boot we encode node id of | ||
513 | * the location of the section here to guide allocation. | ||
514 | * (see sparse.c::memory_present()) | ||
515 | * | ||
512 | * Making it a UL at least makes someone do a cast | 516 | * Making it a UL at least makes someone do a cast |
513 | * before using it wrong. | 517 | * before using it wrong. |
514 | */ | 518 | */ |
@@ -548,6 +552,7 @@ extern int __section_nr(struct mem_section* ms); | |||
548 | #define SECTION_HAS_MEM_MAP (1UL<<1) | 552 | #define SECTION_HAS_MEM_MAP (1UL<<1) |
549 | #define SECTION_MAP_LAST_BIT (1UL<<2) | 553 | #define SECTION_MAP_LAST_BIT (1UL<<2) |
550 | #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) | 554 | #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) |
555 | #define SECTION_NID_SHIFT 2 | ||
551 | 556 | ||
552 | static inline struct page *__section_mem_map_addr(struct mem_section *section) | 557 | static inline struct page *__section_mem_map_addr(struct mem_section *section) |
553 | { | 558 | { |
diff --git a/mm/sparse.c b/mm/sparse.c index 100040c0dfb6..e0a3fe48aa37 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -99,6 +99,22 @@ int __section_nr(struct mem_section* ms) | |||
99 | return (root_nr * SECTIONS_PER_ROOT) + (ms - root); | 99 | return (root_nr * SECTIONS_PER_ROOT) + (ms - root); |
100 | } | 100 | } |
101 | 101 | ||
102 | /* | ||
103 | * During early boot, before section_mem_map is used for an actual | ||
104 | * mem_map, we use section_mem_map to store the section's NUMA | ||
105 | * node. This keeps us from having to use another data structure. The | ||
106 | * node information is cleared just before we store the real mem_map. | ||
107 | */ | ||
108 | static inline unsigned long sparse_encode_early_nid(int nid) | ||
109 | { | ||
110 | return (nid << SECTION_NID_SHIFT); | ||
111 | } | ||
112 | |||
113 | static inline int sparse_early_nid(struct mem_section *section) | ||
114 | { | ||
115 | return (section->section_mem_map >> SECTION_NID_SHIFT); | ||
116 | } | ||
117 | |||
102 | /* Record a memory area against a node. */ | 118 | /* Record a memory area against a node. */ |
103 | void memory_present(int nid, unsigned long start, unsigned long end) | 119 | void memory_present(int nid, unsigned long start, unsigned long end) |
104 | { | 120 | { |
@@ -113,7 +129,8 @@ void memory_present(int nid, unsigned long start, unsigned long end) | |||
113 | 129 | ||
114 | ms = __nr_to_section(section); | 130 | ms = __nr_to_section(section); |
115 | if (!ms->section_mem_map) | 131 | if (!ms->section_mem_map) |
116 | ms->section_mem_map = SECTION_MARKED_PRESENT; | 132 | ms->section_mem_map = sparse_encode_early_nid(nid) | |
133 | SECTION_MARKED_PRESENT; | ||
117 | } | 134 | } |
118 | } | 135 | } |
119 | 136 | ||
@@ -164,6 +181,7 @@ static int sparse_init_one_section(struct mem_section *ms, | |||
164 | if (!valid_section(ms)) | 181 | if (!valid_section(ms)) |
165 | return -EINVAL; | 182 | return -EINVAL; |
166 | 183 | ||
184 | ms->section_mem_map &= ~SECTION_MAP_MASK; | ||
167 | ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum); | 185 | ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum); |
168 | 186 | ||
169 | return 1; | 187 | return 1; |
@@ -172,8 +190,8 @@ static int sparse_init_one_section(struct mem_section *ms, | |||
172 | static struct page *sparse_early_mem_map_alloc(unsigned long pnum) | 190 | static struct page *sparse_early_mem_map_alloc(unsigned long pnum) |
173 | { | 191 | { |
174 | struct page *map; | 192 | struct page *map; |
175 | int nid = early_pfn_to_nid(section_nr_to_pfn(pnum)); | ||
176 | struct mem_section *ms = __nr_to_section(pnum); | 193 | struct mem_section *ms = __nr_to_section(pnum); |
194 | int nid = sparse_early_nid(ms); | ||
177 | 195 | ||
178 | map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION); | 196 | map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION); |
179 | if (map) | 197 | if (map) |