mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 16:40:52 +07:00
ARM: add generic ioremap optimization by reusing static mappings
Now that we have all the static mappings from iotable_init() located in the vmalloc area, it is trivial to optimize ioremap by reusing those static mappings when the requested physical area fits in one of them, and so in a generic way for all platforms. Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> Tested-by: Stephen Warren <swarren@nvidia.com> Tested-by: Kevin Hilman <khilman@ti.com> Tested-by: Jamie Iles <jamie@jamieiles.com>
This commit is contained in:
parent
6ee723a657
commit
576d2f2525
@ -36,12 +36,6 @@
|
||||
#include <asm/mach/map.h>
|
||||
#include "mm.h"
|
||||
|
||||
/*
|
||||
* Used by ioremap() and iounmap() code to mark (super)section-mapped
|
||||
* I/O regions in vm_struct->flags field.
|
||||
*/
|
||||
#define VM_ARM_SECTION_MAPPING 0x80000000
|
||||
|
||||
int ioremap_page(unsigned long virt, unsigned long phys,
|
||||
const struct mem_type *mtype)
|
||||
{
|
||||
@ -201,12 +195,6 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
||||
if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Don't allow RAM to be mapped - this causes problems with ARMv6+
|
||||
*/
|
||||
if (WARN_ON(pfn_valid(pfn)))
|
||||
return NULL;
|
||||
|
||||
type = get_mem_type(mtype);
|
||||
if (!type)
|
||||
return NULL;
|
||||
@ -216,6 +204,34 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
||||
*/
|
||||
size = PAGE_ALIGN(offset + size);
|
||||
|
||||
/*
|
||||
* Try to reuse one of the static mapping whenever possible.
|
||||
*/
|
||||
read_lock(&vmlist_lock);
|
||||
for (area = vmlist; area; area = area->next) {
|
||||
if (!size || (sizeof(phys_addr_t) == 4 && pfn >= 0x100000))
|
||||
break;
|
||||
if (!(area->flags & VM_ARM_STATIC_MAPPING))
|
||||
continue;
|
||||
if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))
|
||||
continue;
|
||||
if (__phys_to_pfn(area->phys_addr) > pfn ||
|
||||
__pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)
|
||||
continue;
|
||||
/* we can drop the lock here as we know *area is static */
|
||||
read_unlock(&vmlist_lock);
|
||||
addr = (unsigned long)area->addr;
|
||||
addr += __pfn_to_phys(pfn) - area->phys_addr;
|
||||
return (void __iomem *) (offset + addr);
|
||||
}
|
||||
read_unlock(&vmlist_lock);
|
||||
|
||||
/*
|
||||
* Don't allow RAM to be mapped - this causes problems with ARMv6+
|
||||
*/
|
||||
if (WARN_ON(pfn_valid(pfn)))
|
||||
return NULL;
|
||||
|
||||
area = get_vm_area_caller(size, VM_IOREMAP, caller);
|
||||
if (!area)
|
||||
return NULL;
|
||||
@ -313,26 +329,34 @@ __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
|
||||
void __iounmap(volatile void __iomem *io_addr)
|
||||
{
|
||||
void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
|
||||
#ifndef CONFIG_SMP
|
||||
struct vm_struct *vm;
|
||||
|
||||
/*
|
||||
* If this is a section based mapping we need to handle it
|
||||
* specially as the VM subsystem does not know how to handle
|
||||
* such a beast.
|
||||
*/
|
||||
read_lock(&vmlist_lock);
|
||||
for (vm = vmlist; vm; vm = vm->next) {
|
||||
if ((vm->flags & VM_IOREMAP) && (vm->addr == addr)) {
|
||||
if (vm->flags & VM_ARM_SECTION_MAPPING) {
|
||||
unmap_area_sections((unsigned long)vm->addr,
|
||||
vm->size);
|
||||
}
|
||||
if (vm->addr > addr)
|
||||
break;
|
||||
if (!(vm->flags & VM_IOREMAP))
|
||||
continue;
|
||||
/* If this is a static mapping we must leave it alone */
|
||||
if ((vm->flags & VM_ARM_STATIC_MAPPING) &&
|
||||
(vm->addr <= addr) && (vm->addr + vm->size > addr)) {
|
||||
read_unlock(&vmlist_lock);
|
||||
return;
|
||||
}
|
||||
#ifndef CONFIG_SMP
|
||||
/*
|
||||
* If this is a section based mapping we need to handle it
|
||||
* specially as the VM subsystem does not know how to handle
|
||||
* such a beast.
|
||||
*/
|
||||
if ((vm->addr == addr) &&
|
||||
(vm->flags & VM_ARM_SECTION_MAPPING)) {
|
||||
unmap_area_sections((unsigned long)vm->addr, vm->size);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
read_unlock(&vmlist_lock);
|
||||
#endif
|
||||
|
||||
vunmap(addr);
|
||||
}
|
||||
|
@ -21,6 +21,20 @@ const struct mem_type *get_mem_type(unsigned int type);
|
||||
|
||||
extern void __flush_dcache_page(struct address_space *mapping, struct page *page);
|
||||
|
||||
/*
|
||||
* ARM specific vm_struct->flags bits.
|
||||
*/
|
||||
|
||||
/* (super)section-mapped I/O regions used by ioremap()/iounmap() */
|
||||
#define VM_ARM_SECTION_MAPPING 0x80000000
|
||||
|
||||
/* permanent static mappings from iotable_init() */
|
||||
#define VM_ARM_STATIC_MAPPING 0x40000000
|
||||
|
||||
/* mapping type (attributes) for permanent static mappings */
|
||||
#define VM_ARM_MTYPE(mt) ((mt) << 20)
|
||||
#define VM_ARM_MTYPE_MASK (0x1f << 20)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ZONE_DMA
|
||||
|
@ -749,7 +749,8 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
|
||||
vm->addr = (void *)(md->virtual & PAGE_MASK);
|
||||
vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
|
||||
vm->phys_addr = __pfn_to_phys(md->pfn);
|
||||
vm->flags = VM_IOREMAP;
|
||||
vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
|
||||
vm->flags |= VM_ARM_MTYPE(md->type);
|
||||
vm->caller = iotable_init;
|
||||
vm_area_add_early(vm++);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user