diff options
| -rw-r--r-- | arch/mips/mm/ioremap.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c index 1986e09fb457..1601d90b087b 100644 --- a/arch/mips/mm/ioremap.c +++ b/arch/mips/mm/ioremap.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/export.h> | 9 | #include <linux/export.h> |
| 10 | #include <asm/addrspace.h> | 10 | #include <asm/addrspace.h> |
| 11 | #include <asm/byteorder.h> | 11 | #include <asm/byteorder.h> |
| 12 | #include <linux/ioport.h> | ||
| 12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 14 | #include <linux/vmalloc.h> | 15 | #include <linux/vmalloc.h> |
| @@ -98,6 +99,20 @@ static int remap_area_pages(unsigned long address, phys_addr_t phys_addr, | |||
| 98 | return error; | 99 | return error; |
| 99 | } | 100 | } |
| 100 | 101 | ||
| 102 | static int __ioremap_check_ram(unsigned long start_pfn, unsigned long nr_pages, | ||
| 103 | void *arg) | ||
| 104 | { | ||
| 105 | unsigned long i; | ||
| 106 | |||
| 107 | for (i = 0; i < nr_pages; i++) { | ||
| 108 | if (pfn_valid(start_pfn + i) && | ||
| 109 | !PageReserved(pfn_to_page(start_pfn + i))) | ||
| 110 | return 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 101 | /* | 116 | /* |
| 102 | * Generic mapping function (not visible outside): | 117 | * Generic mapping function (not visible outside): |
| 103 | */ | 118 | */ |
| @@ -116,8 +131,8 @@ static int remap_area_pages(unsigned long address, phys_addr_t phys_addr, | |||
| 116 | 131 | ||
| 117 | void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long flags) | 132 | void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long flags) |
| 118 | { | 133 | { |
| 134 | unsigned long offset, pfn, last_pfn; | ||
| 119 | struct vm_struct * area; | 135 | struct vm_struct * area; |
| 120 | unsigned long offset; | ||
| 121 | phys_addr_t last_addr; | 136 | phys_addr_t last_addr; |
| 122 | void * addr; | 137 | void * addr; |
| 123 | 138 | ||
| @@ -137,18 +152,16 @@ void __iomem * __ioremap(phys_addr_t phys_addr, phys_addr_t size, unsigned long | |||
| 137 | return (void __iomem *) CKSEG1ADDR(phys_addr); | 152 | return (void __iomem *) CKSEG1ADDR(phys_addr); |
| 138 | 153 | ||
| 139 | /* | 154 | /* |
| 140 | * Don't allow anybody to remap normal RAM that we're using.. | 155 | * Don't allow anybody to remap RAM that may be allocated by the page |
| 156 | * allocator, since that could lead to races & data clobbering. | ||
| 141 | */ | 157 | */ |
| 142 | if (phys_addr < virt_to_phys(high_memory)) { | 158 | pfn = PFN_DOWN(phys_addr); |
| 143 | char *t_addr, *t_end; | 159 | last_pfn = PFN_DOWN(last_addr); |
| 144 | struct page *page; | 160 | if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, |
| 145 | 161 | __ioremap_check_ram) == 1) { | |
| 146 | t_addr = __va(phys_addr); | 162 | WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", |
| 147 | t_end = t_addr + (size - 1); | 163 | &phys_addr, &last_addr); |
| 148 | 164 | return NULL; | |
| 149 | for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) | ||
| 150 | if(!PageReserved(page)) | ||
| 151 | return NULL; | ||
| 152 | } | 165 | } |
| 153 | 166 | ||
| 154 | /* | 167 | /* |
