diff options
Diffstat (limited to 'mm/memory_hotplug.c')
| -rw-r--r-- | mm/memory_hotplug.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 01c9fb97c619..c37319542b70 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -52,6 +52,9 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn) | |||
| 52 | int nr_pages = PAGES_PER_SECTION; | 52 | int nr_pages = PAGES_PER_SECTION; |
| 53 | int ret; | 53 | int ret; |
| 54 | 54 | ||
| 55 | if (pfn_valid(phys_start_pfn)) | ||
| 56 | return -EEXIST; | ||
| 57 | |||
| 55 | ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); | 58 | ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); |
| 56 | 59 | ||
| 57 | if (ret < 0) | 60 | if (ret < 0) |
| @@ -76,15 +79,22 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
| 76 | { | 79 | { |
| 77 | unsigned long i; | 80 | unsigned long i; |
| 78 | int err = 0; | 81 | int err = 0; |
| 82 | int start_sec, end_sec; | ||
| 83 | /* during initialize mem_map, align hot-added range to section */ | ||
| 84 | start_sec = pfn_to_section_nr(phys_start_pfn); | ||
| 85 | end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1); | ||
| 79 | 86 | ||
| 80 | for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) { | 87 | for (i = start_sec; i <= end_sec; i++) { |
| 81 | err = __add_section(zone, phys_start_pfn + i); | 88 | err = __add_section(zone, i << PFN_SECTION_SHIFT); |
| 82 | 89 | ||
| 83 | /* We want to keep adding the rest of the | 90 | /* |
| 84 | * sections if the first ones already exist | 91 | * EEXIST is finally dealed with by ioresource collision |
| 92 | * check. see add_memory() => register_memory_resource() | ||
| 93 | * Warning will be printed if there is collision. | ||
| 85 | */ | 94 | */ |
| 86 | if (err && (err != -EEXIST)) | 95 | if (err && (err != -EEXIST)) |
| 87 | break; | 96 | break; |
| 97 | err = 0; | ||
| 88 | } | 98 | } |
| 89 | 99 | ||
| 90 | return err; | 100 | return err; |
| @@ -156,7 +166,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) | |||
| 156 | res.flags = IORESOURCE_MEM; /* we just need system ram */ | 166 | res.flags = IORESOURCE_MEM; /* we just need system ram */ |
| 157 | section_end = res.end; | 167 | section_end = res.end; |
| 158 | 168 | ||
| 159 | while (find_next_system_ram(&res) >= 0) { | 169 | while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) { |
| 160 | start_pfn = (unsigned long)(res.start >> PAGE_SHIFT); | 170 | start_pfn = (unsigned long)(res.start >> PAGE_SHIFT); |
| 161 | nr_pages = (unsigned long) | 171 | nr_pages = (unsigned long) |
| 162 | ((res.end + 1 - res.start) >> PAGE_SHIFT); | 172 | ((res.end + 1 - res.start) >> PAGE_SHIFT); |
| @@ -213,10 +223,9 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat) | |||
| 213 | } | 223 | } |
| 214 | 224 | ||
| 215 | /* add this memory to iomem resource */ | 225 | /* add this memory to iomem resource */ |
| 216 | static void register_memory_resource(u64 start, u64 size) | 226 | static struct resource *register_memory_resource(u64 start, u64 size) |
| 217 | { | 227 | { |
| 218 | struct resource *res; | 228 | struct resource *res; |
| 219 | |||
| 220 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); | 229 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); |
| 221 | BUG_ON(!res); | 230 | BUG_ON(!res); |
| 222 | 231 | ||
| @@ -228,7 +237,18 @@ static void register_memory_resource(u64 start, u64 size) | |||
| 228 | printk("System RAM resource %llx - %llx cannot be added\n", | 237 | printk("System RAM resource %llx - %llx cannot be added\n", |
| 229 | (unsigned long long)res->start, (unsigned long long)res->end); | 238 | (unsigned long long)res->start, (unsigned long long)res->end); |
| 230 | kfree(res); | 239 | kfree(res); |
| 240 | res = NULL; | ||
| 231 | } | 241 | } |
| 242 | return res; | ||
| 243 | } | ||
| 244 | |||
| 245 | static void release_memory_resource(struct resource *res) | ||
| 246 | { | ||
| 247 | if (!res) | ||
| 248 | return; | ||
| 249 | release_resource(res); | ||
| 250 | kfree(res); | ||
| 251 | return; | ||
| 232 | } | 252 | } |
| 233 | 253 | ||
| 234 | 254 | ||
| @@ -237,8 +257,13 @@ int add_memory(int nid, u64 start, u64 size) | |||
| 237 | { | 257 | { |
| 238 | pg_data_t *pgdat = NULL; | 258 | pg_data_t *pgdat = NULL; |
| 239 | int new_pgdat = 0; | 259 | int new_pgdat = 0; |
| 260 | struct resource *res; | ||
| 240 | int ret; | 261 | int ret; |
| 241 | 262 | ||
| 263 | res = register_memory_resource(start, size); | ||
| 264 | if (!res) | ||
| 265 | return -EEXIST; | ||
| 266 | |||
| 242 | if (!node_online(nid)) { | 267 | if (!node_online(nid)) { |
| 243 | pgdat = hotadd_new_pgdat(nid, start); | 268 | pgdat = hotadd_new_pgdat(nid, start); |
| 244 | if (!pgdat) | 269 | if (!pgdat) |
| @@ -268,14 +293,13 @@ int add_memory(int nid, u64 start, u64 size) | |||
| 268 | BUG_ON(ret); | 293 | BUG_ON(ret); |
| 269 | } | 294 | } |
| 270 | 295 | ||
| 271 | /* register this memory as resource */ | ||
| 272 | register_memory_resource(start, size); | ||
| 273 | |||
| 274 | return ret; | 296 | return ret; |
| 275 | error: | 297 | error: |
| 276 | /* rollback pgdat allocation and others */ | 298 | /* rollback pgdat allocation and others */ |
| 277 | if (new_pgdat) | 299 | if (new_pgdat) |
| 278 | rollback_node_hotadd(nid, pgdat); | 300 | rollback_node_hotadd(nid, pgdat); |
| 301 | if (res) | ||
| 302 | release_memory_resource(res); | ||
| 279 | 303 | ||
| 280 | return ret; | 304 | return ret; |
| 281 | } | 305 | } |
