Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 80512
b: refs/heads/master
c: e9332ca
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner authored and Ingo Molnar committed Jan 30, 2008
1 parent aa8bd81 commit 60a7fb5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 42 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 74ff2857f099951020a47420872f5c1460f32c27
refs/heads/master: e9332cacd74b25548a517b8dd4fff0216f7907db
90 changes: 49 additions & 41 deletions trunk/arch/x86/mm/ioremap_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* (C) Copyright 1995 1996 Linus Torvalds
*/

#include <linux/bootmem.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
Expand All @@ -18,6 +19,42 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>

/*
* Fix up the linear direct mapping of the kernel to avoid cache attribute
* conflicts.
*/
static int ioremap_change_attr(unsigned long phys_addr, unsigned long size,
pgprot_t prot)
{
unsigned long npages, vaddr, last_addr = phys_addr + size - 1;
int err, level;

/* No change for pages after the last mapping */
if (last_addr >= (max_pfn_mapped << PAGE_SHIFT))
return 0;

npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
vaddr = (unsigned long) __va(phys_addr);

/*
* If there is no identity map for this address,
* change_page_attr_addr is unnecessary
*/
if (!lookup_address(vaddr, &level))
return 0;

/*
* Must use an address here and not struct page because the
* phys addr can be a in hole between nodes and not have a
* memmap entry.
*/
err = change_page_attr_addr(vaddr, npages, prot);
if (!err)
global_flush_tlb();

return err;
}

/*
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
Expand All @@ -33,7 +70,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
void __iomem *addr;
struct vm_struct *area;
unsigned long offset, last_addr;
pgprot_t prot;
pgprot_t pgprot;

/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
Expand Down Expand Up @@ -62,7 +99,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
return NULL;
}

prot = MAKE_GLOBAL(__PAGE_KERNEL | flags);
pgprot = MAKE_GLOBAL(__PAGE_KERNEL | flags);

/*
* Mappings have to be page-aligned
Expand All @@ -79,11 +116,17 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
return NULL;
area->phys_addr = phys_addr;
addr = (void __iomem *) area->addr;
if (ioremap_page_range((unsigned long) addr,
(unsigned long) addr + size, phys_addr, prot)) {
if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
phys_addr, pgprot)) {
vunmap((void __force *) addr);
return NULL;
}

if (ioremap_change_attr(phys_addr, size, pgprot) < 0) {
vunmap(addr);
return NULL;
}

return (void __iomem *) (offset + (char __iomem *)addr);
}
EXPORT_SYMBOL(__ioremap);
Expand Down Expand Up @@ -111,37 +154,7 @@ EXPORT_SYMBOL(__ioremap);
*/
void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
{
unsigned long last_addr;
void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD | _PAGE_PWT);

if (!p)
return p;

/* Guaranteed to be > phys_addr, as per __ioremap() */
last_addr = phys_addr + size - 1;

if (last_addr < virt_to_phys(high_memory) - 1) {
struct page *ppage = virt_to_page(__va(phys_addr));
unsigned long npages;

phys_addr &= PAGE_MASK;

/* This might overflow and become zero.. */
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) {
iounmap(p);
p = NULL;
}
global_flush_tlb();
}

return p;
return __ioremap(phys_addr, size, _PAGE_PCD | _PAGE_PWT);
}
EXPORT_SYMBOL(ioremap_nocache);

Expand Down Expand Up @@ -189,12 +202,7 @@ void iounmap(volatile void __iomem *addr)
}

/* Reset the direct mapping. Can block */
if (p->phys_addr < virt_to_phys(high_memory) - 1) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
get_vm_area_size(p) >> PAGE_SHIFT,
PAGE_KERNEL);
global_flush_tlb();
}
ioremap_change_attr(p->phys_addr, p->size, PAGE_KERNEL);

/* Finally remove it */
o = remove_vm_area((void *)addr);
Expand Down

0 comments on commit 60a7fb5

Please sign in to comment.