diff options
Diffstat (limited to 'arch/x86/mm/ioremap.c')
-rw-r--r-- | arch/x86/mm/ioremap.c | 77 |
1 files changed, 57 insertions, 20 deletions
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 8876220d906b..e4c43ec71b29 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c | |||
@@ -616,16 +616,22 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx) | |||
616 | __early_set_fixmap(idx, 0, __pgprot(0)); | 616 | __early_set_fixmap(idx, 0, __pgprot(0)); |
617 | } | 617 | } |
618 | 618 | ||
619 | 619 | static void *prev_map[FIX_BTMAPS_SLOTS] __initdata; | |
620 | static int __initdata early_ioremap_nested; | 620 | static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; |
621 | |||
622 | static int __init check_early_ioremap_leak(void) | 621 | static int __init check_early_ioremap_leak(void) |
623 | { | 622 | { |
624 | if (!early_ioremap_nested) | 623 | int count = 0; |
624 | int i; | ||
625 | |||
626 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) | ||
627 | if (prev_map[i]) | ||
628 | count++; | ||
629 | |||
630 | if (!count) | ||
625 | return 0; | 631 | return 0; |
626 | WARN(1, KERN_WARNING | 632 | WARN(1, KERN_WARNING |
627 | "Debug warning: early ioremap leak of %d areas detected.\n", | 633 | "Debug warning: early ioremap leak of %d areas detected.\n", |
628 | early_ioremap_nested); | 634 | count); |
629 | printk(KERN_WARNING | 635 | printk(KERN_WARNING |
630 | "please boot with early_ioremap_debug and report the dmesg.\n"); | 636 | "please boot with early_ioremap_debug and report the dmesg.\n"); |
631 | 637 | ||
@@ -636,15 +642,30 @@ late_initcall(check_early_ioremap_leak); | |||
636 | static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) | 642 | static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) |
637 | { | 643 | { |
638 | unsigned long offset, last_addr; | 644 | unsigned long offset, last_addr; |
639 | unsigned int nrpages, nesting; | 645 | unsigned int nrpages; |
640 | enum fixed_addresses idx0, idx; | 646 | enum fixed_addresses idx0, idx; |
647 | int i, slot; | ||
641 | 648 | ||
642 | WARN_ON(system_state != SYSTEM_BOOTING); | 649 | WARN_ON(system_state != SYSTEM_BOOTING); |
643 | 650 | ||
644 | nesting = early_ioremap_nested; | 651 | slot = -1; |
652 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { | ||
653 | if (!prev_map[i]) { | ||
654 | slot = i; | ||
655 | break; | ||
656 | } | ||
657 | } | ||
658 | |||
659 | if (slot < 0) { | ||
660 | printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n", | ||
661 | phys_addr, size); | ||
662 | WARN_ON(1); | ||
663 | return NULL; | ||
664 | } | ||
665 | |||
645 | if (early_ioremap_debug) { | 666 | if (early_ioremap_debug) { |
646 | printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ", | 667 | printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ", |
647 | phys_addr, size, nesting); | 668 | phys_addr, size, slot); |
648 | dump_stack(); | 669 | dump_stack(); |
649 | } | 670 | } |
650 | 671 | ||
@@ -655,11 +676,7 @@ static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, | |||
655 | return NULL; | 676 | return NULL; |
656 | } | 677 | } |
657 | 678 | ||
658 | if (nesting >= FIX_BTMAPS_NESTING) { | 679 | prev_size[slot] = size; |
659 | WARN_ON(1); | ||
660 | return NULL; | ||
661 | } | ||
662 | early_ioremap_nested++; | ||
663 | /* | 680 | /* |
664 | * Mappings have to be page-aligned | 681 | * Mappings have to be page-aligned |
665 | */ | 682 | */ |
@@ -679,7 +696,7 @@ static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, | |||
679 | /* | 696 | /* |
680 | * Ok, go for it.. | 697 | * Ok, go for it.. |
681 | */ | 698 | */ |
682 | idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting; | 699 | idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; |
683 | idx = idx0; | 700 | idx = idx0; |
684 | while (nrpages > 0) { | 701 | while (nrpages > 0) { |
685 | early_set_fixmap(idx, phys_addr, prot); | 702 | early_set_fixmap(idx, phys_addr, prot); |
@@ -690,7 +707,8 @@ static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, | |||
690 | if (early_ioremap_debug) | 707 | if (early_ioremap_debug) |
691 | printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0)); | 708 | printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0)); |
692 | 709 | ||
693 | return (void *) (offset + fix_to_virt(idx0)); | 710 | prev_map[slot] = (void *) (offset + fix_to_virt(idx0)); |
711 | return prev_map[slot]; | ||
694 | } | 712 | } |
695 | 713 | ||
696 | /* Remap an IO device */ | 714 | /* Remap an IO device */ |
@@ -711,15 +729,33 @@ void __init early_iounmap(void *addr, unsigned long size) | |||
711 | unsigned long offset; | 729 | unsigned long offset; |
712 | unsigned int nrpages; | 730 | unsigned int nrpages; |
713 | enum fixed_addresses idx; | 731 | enum fixed_addresses idx; |
714 | int nesting; | 732 | int i, slot; |
733 | |||
734 | slot = -1; | ||
735 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { | ||
736 | if (prev_map[i] == addr) { | ||
737 | slot = i; | ||
738 | break; | ||
739 | } | ||
740 | } | ||
715 | 741 | ||
716 | nesting = --early_ioremap_nested; | 742 | if (slot < 0) { |
717 | if (WARN_ON(nesting < 0)) | 743 | printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n", |
744 | addr, size); | ||
745 | WARN_ON(1); | ||
746 | return; | ||
747 | } | ||
748 | |||
749 | if (prev_size[slot] != size) { | ||
750 | printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n", | ||
751 | addr, size, slot, prev_size[slot]); | ||
752 | WARN_ON(1); | ||
718 | return; | 753 | return; |
754 | } | ||
719 | 755 | ||
720 | if (early_ioremap_debug) { | 756 | if (early_ioremap_debug) { |
721 | printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr, | 757 | printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr, |
722 | size, nesting); | 758 | size, slot); |
723 | dump_stack(); | 759 | dump_stack(); |
724 | } | 760 | } |
725 | 761 | ||
@@ -731,12 +767,13 @@ void __init early_iounmap(void *addr, unsigned long size) | |||
731 | offset = virt_addr & ~PAGE_MASK; | 767 | offset = virt_addr & ~PAGE_MASK; |
732 | nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT; | 768 | nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT; |
733 | 769 | ||
734 | idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting; | 770 | idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; |
735 | while (nrpages > 0) { | 771 | while (nrpages > 0) { |
736 | early_clear_fixmap(idx); | 772 | early_clear_fixmap(idx); |
737 | --idx; | 773 | --idx; |
738 | --nrpages; | 774 | --nrpages; |
739 | } | 775 | } |
776 | prev_map[slot] = 0; | ||
740 | } | 777 | } |
741 | 778 | ||
742 | void __this_fixmap_does_not_exist(void) | 779 | void __this_fixmap_does_not_exist(void) |