Commit 4154cebf authored by Randy Dunlap's avatar Randy Dunlap Committed by Linus Torvalds

[PATCH] Fix crash-on-boot in init_l440gx SMP

ioremap_nocache() doesn't need to check for physical address
wraps because __ioremap() has already done that;
fix calculation of npages to handle non-aligned phys_addr;
parent b4a427fe
...@@ -190,23 +190,34 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag ...@@ -190,23 +190,34 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
void *ioremap_nocache (unsigned long phys_addr, unsigned long size) void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
{ {
unsigned long last_addr;
void *p = __ioremap(phys_addr, size, _PAGE_PCD); void *p = __ioremap(phys_addr, size, _PAGE_PCD);
if (!p) if (!p)
return p; return p;
if (phys_addr + size < virt_to_phys(high_memory)) { /* Guaranteed to be > phys_addr, as per __ioremap() */
last_addr = phys_addr + size - 1;
if (last_addr < virt_to_phys(high_memory)) {
struct page *ppage = virt_to_page(__va(phys_addr)); struct page *ppage = virt_to_page(__va(phys_addr));
unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long npages;
phys_addr &= PAGE_MASK;
BUG_ON(phys_addr+size > (unsigned long)high_memory); /* This might overflow and become zero.. */
BUG_ON(phys_addr + size < phys_addr); last_addr = PAGE_ALIGN(last_addr);
/* .. but that's ok, because modulo-2**n arithmetic will make
* the page-aligned "last - first" come out right.
*/
npages = (last_addr - phys_addr) >> PAGE_SHIFT;
if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) { if (change_page_attr(ppage, npages, PAGE_KERNEL_NOCACHE) < 0) {
iounmap(p); iounmap(p);
p = NULL; p = NULL;
} }
global_flush_tlb(); global_flush_tlb();
} }
return p; return p;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment