diff options
Diffstat (limited to 'mm/sparse.c')
-rw-r--r-- | mm/sparse.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/mm/sparse.c b/mm/sparse.c index eb188eb6b82d..2ea8b3dbd0df 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -381,6 +381,7 @@ static void __init sparse_early_usemaps_alloc_node(void *data, | |||
381 | unsigned long pnum; | 381 | unsigned long pnum; |
382 | unsigned long **usemap_map = (unsigned long **)data; | 382 | unsigned long **usemap_map = (unsigned long **)data; |
383 | int size = usemap_size(); | 383 | int size = usemap_size(); |
384 | int nr_consumed_maps = 0; | ||
384 | 385 | ||
385 | usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid), | 386 | usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid), |
386 | size * usemap_count); | 387 | size * usemap_count); |
@@ -392,9 +393,10 @@ static void __init sparse_early_usemaps_alloc_node(void *data, | |||
392 | for (pnum = pnum_begin; pnum < pnum_end; pnum++) { | 393 | for (pnum = pnum_begin; pnum < pnum_end; pnum++) { |
393 | if (!present_section_nr(pnum)) | 394 | if (!present_section_nr(pnum)) |
394 | continue; | 395 | continue; |
395 | usemap_map[pnum] = usemap; | 396 | usemap_map[nr_consumed_maps] = usemap; |
396 | usemap += size; | 397 | usemap += size; |
397 | check_usemap_section_nr(nodeid, usemap_map[pnum]); | 398 | check_usemap_section_nr(nodeid, usemap_map[nr_consumed_maps]); |
399 | nr_consumed_maps++; | ||
398 | } | 400 | } |
399 | } | 401 | } |
400 | 402 | ||
@@ -419,29 +421,34 @@ void __init sparse_mem_maps_populate_node(struct page **map_map, | |||
419 | void *map; | 421 | void *map; |
420 | unsigned long pnum; | 422 | unsigned long pnum; |
421 | unsigned long size = sizeof(struct page) * PAGES_PER_SECTION; | 423 | unsigned long size = sizeof(struct page) * PAGES_PER_SECTION; |
424 | int nr_consumed_maps; | ||
422 | 425 | ||
423 | size = PAGE_ALIGN(size); | 426 | size = PAGE_ALIGN(size); |
424 | map = memblock_virt_alloc_try_nid_raw(size * map_count, | 427 | map = memblock_virt_alloc_try_nid_raw(size * map_count, |
425 | PAGE_SIZE, __pa(MAX_DMA_ADDRESS), | 428 | PAGE_SIZE, __pa(MAX_DMA_ADDRESS), |
426 | BOOTMEM_ALLOC_ACCESSIBLE, nodeid); | 429 | BOOTMEM_ALLOC_ACCESSIBLE, nodeid); |
427 | if (map) { | 430 | if (map) { |
431 | nr_consumed_maps = 0; | ||
428 | for (pnum = pnum_begin; pnum < pnum_end; pnum++) { | 432 | for (pnum = pnum_begin; pnum < pnum_end; pnum++) { |
429 | if (!present_section_nr(pnum)) | 433 | if (!present_section_nr(pnum)) |
430 | continue; | 434 | continue; |
431 | map_map[pnum] = map; | 435 | map_map[nr_consumed_maps] = map; |
432 | map += size; | 436 | map += size; |
437 | nr_consumed_maps++; | ||
433 | } | 438 | } |
434 | return; | 439 | return; |
435 | } | 440 | } |
436 | 441 | ||
437 | /* fallback */ | 442 | /* fallback */ |
443 | nr_consumed_maps = 0; | ||
438 | for (pnum = pnum_begin; pnum < pnum_end; pnum++) { | 444 | for (pnum = pnum_begin; pnum < pnum_end; pnum++) { |
439 | struct mem_section *ms; | 445 | struct mem_section *ms; |
440 | 446 | ||
441 | if (!present_section_nr(pnum)) | 447 | if (!present_section_nr(pnum)) |
442 | continue; | 448 | continue; |
443 | map_map[pnum] = sparse_mem_map_populate(pnum, nodeid, NULL); | 449 | map_map[nr_consumed_maps] = |
444 | if (map_map[pnum]) | 450 | sparse_mem_map_populate(pnum, nodeid, NULL); |
451 | if (map_map[nr_consumed_maps++]) | ||
445 | continue; | 452 | continue; |
446 | ms = __nr_to_section(pnum); | 453 | ms = __nr_to_section(pnum); |
447 | pr_err("%s: sparsemem memory map backing failed some memory will not be available\n", | 454 | pr_err("%s: sparsemem memory map backing failed some memory will not be available\n", |
@@ -521,6 +528,7 @@ static void __init alloc_usemap_and_memmap(void (*alloc_func) | |||
521 | /* new start, update count etc*/ | 528 | /* new start, update count etc*/ |
522 | nodeid_begin = nodeid; | 529 | nodeid_begin = nodeid; |
523 | pnum_begin = pnum; | 530 | pnum_begin = pnum; |
531 | data += map_count * data_unit_size; | ||
524 | map_count = 1; | 532 | map_count = 1; |
525 | } | 533 | } |
526 | /* ok, last chunk */ | 534 | /* ok, last chunk */ |
@@ -539,6 +547,7 @@ void __init sparse_init(void) | |||
539 | unsigned long *usemap; | 547 | unsigned long *usemap; |
540 | unsigned long **usemap_map; | 548 | unsigned long **usemap_map; |
541 | int size; | 549 | int size; |
550 | int nr_consumed_maps = 0; | ||
542 | #ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER | 551 | #ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER |
543 | int size2; | 552 | int size2; |
544 | struct page **map_map; | 553 | struct page **map_map; |
@@ -561,7 +570,7 @@ void __init sparse_init(void) | |||
561 | * powerpc need to call sparse_init_one_section right after each | 570 | * powerpc need to call sparse_init_one_section right after each |
562 | * sparse_early_mem_map_alloc, so allocate usemap_map at first. | 571 | * sparse_early_mem_map_alloc, so allocate usemap_map at first. |
563 | */ | 572 | */ |
564 | size = sizeof(unsigned long *) * NR_MEM_SECTIONS; | 573 | size = sizeof(unsigned long *) * nr_present_sections; |
565 | usemap_map = memblock_virt_alloc(size, 0); | 574 | usemap_map = memblock_virt_alloc(size, 0); |
566 | if (!usemap_map) | 575 | if (!usemap_map) |
567 | panic("can not allocate usemap_map\n"); | 576 | panic("can not allocate usemap_map\n"); |
@@ -570,7 +579,7 @@ void __init sparse_init(void) | |||
570 | sizeof(usemap_map[0])); | 579 | sizeof(usemap_map[0])); |
571 | 580 | ||
572 | #ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER | 581 | #ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER |
573 | size2 = sizeof(struct page *) * NR_MEM_SECTIONS; | 582 | size2 = sizeof(struct page *) * nr_present_sections; |
574 | map_map = memblock_virt_alloc(size2, 0); | 583 | map_map = memblock_virt_alloc(size2, 0); |
575 | if (!map_map) | 584 | if (!map_map) |
576 | panic("can not allocate map_map\n"); | 585 | panic("can not allocate map_map\n"); |
@@ -579,27 +588,46 @@ void __init sparse_init(void) | |||
579 | sizeof(map_map[0])); | 588 | sizeof(map_map[0])); |
580 | #endif | 589 | #endif |
581 | 590 | ||
591 | /* | ||
592 | * The number of present sections stored in nr_present_sections | ||
593 | * are kept the same since mem sections are marked as present in | ||
594 | * memory_present(). In this for loop, we need check which sections | ||
595 | * failed to allocate memmap or usemap, then clear its | ||
596 | * ->section_mem_map accordingly. During this process, we need | ||
597 | * increase 'nr_consumed_maps' whether its allocation of memmap | ||
598 | * or usemap failed or not, so that after we handle the i-th | ||
599 | * memory section, can get memmap and usemap of (i+1)-th section | ||
600 | * correctly. | ||
601 | */ | ||
582 | for_each_present_section_nr(0, pnum) { | 602 | for_each_present_section_nr(0, pnum) { |
583 | struct mem_section *ms; | 603 | struct mem_section *ms; |
604 | |||
605 | if (nr_consumed_maps >= nr_present_sections) { | ||
606 | pr_err("nr_consumed_maps goes beyond nr_present_sections\n"); | ||
607 | break; | ||
608 | } | ||
584 | ms = __nr_to_section(pnum); | 609 | ms = __nr_to_section(pnum); |
585 | usemap = usemap_map[pnum]; | 610 | usemap = usemap_map[nr_consumed_maps]; |
586 | if (!usemap) { | 611 | if (!usemap) { |
587 | ms->section_mem_map = 0; | 612 | ms->section_mem_map = 0; |
613 | nr_consumed_maps++; | ||
588 | continue; | 614 | continue; |
589 | } | 615 | } |
590 | 616 | ||
591 | #ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER | 617 | #ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER |
592 | map = map_map[pnum]; | 618 | map = map_map[nr_consumed_maps]; |
593 | #else | 619 | #else |
594 | map = sparse_early_mem_map_alloc(pnum); | 620 | map = sparse_early_mem_map_alloc(pnum); |
595 | #endif | 621 | #endif |
596 | if (!map) { | 622 | if (!map) { |
597 | ms->section_mem_map = 0; | 623 | ms->section_mem_map = 0; |
624 | nr_consumed_maps++; | ||
598 | continue; | 625 | continue; |
599 | } | 626 | } |
600 | 627 | ||
601 | sparse_init_one_section(__nr_to_section(pnum), pnum, map, | 628 | sparse_init_one_section(__nr_to_section(pnum), pnum, map, |
602 | usemap); | 629 | usemap); |
630 | nr_consumed_maps++; | ||
603 | } | 631 | } |
604 | 632 | ||
605 | vmemmap_populate_print_last(); | 633 | vmemmap_populate_print_last(); |