at v5.13-rc7 74 lines 1.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Re-map IO memory to kernel address space so that we can access it. 4 * This is needed for high PCI addresses that aren't mapped in the 5 * 640k-1MB IO memory area on PC's 6 * 7 * (C) Copyright 1995 1996 Linus Torvalds 8 */ 9#include <linux/vmalloc.h> 10#include <linux/mm.h> 11#include <linux/sched.h> 12#include <linux/io.h> 13#include <linux/export.h> 14#include <asm/cacheflush.h> 15 16#include "pgalloc-track.h" 17 18#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP 19static unsigned int __ro_after_init iomap_max_page_shift = BITS_PER_LONG - 1; 20 21static int __init set_nohugeiomap(char *str) 22{ 23 iomap_max_page_shift = PAGE_SHIFT; 24 return 0; 25} 26early_param("nohugeiomap", set_nohugeiomap); 27#else /* CONFIG_HAVE_ARCH_HUGE_VMAP */ 28static const unsigned int iomap_max_page_shift = PAGE_SHIFT; 29#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ 30 31int ioremap_page_range(unsigned long addr, 32 unsigned long end, phys_addr_t phys_addr, pgprot_t prot) 33{ 34 return vmap_range(addr, end, phys_addr, prot, iomap_max_page_shift); 35} 36 37#ifdef CONFIG_GENERIC_IOREMAP 38void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot) 39{ 40 unsigned long offset, vaddr; 41 phys_addr_t last_addr; 42 struct vm_struct *area; 43 44 /* Disallow wrap-around or zero size */ 45 last_addr = addr + size - 1; 46 if (!size || last_addr < addr) 47 return NULL; 48 49 /* Page-align mappings */ 50 offset = addr & (~PAGE_MASK); 51 addr -= offset; 52 size = PAGE_ALIGN(size + offset); 53 54 area = get_vm_area_caller(size, VM_IOREMAP, 55 __builtin_return_address(0)); 56 if (!area) 57 return NULL; 58 vaddr = (unsigned long)area->addr; 59 60 if (ioremap_page_range(vaddr, vaddr + size, addr, __pgprot(prot))) { 61 free_vm_area(area); 62 return NULL; 63 } 64 65 return (void __iomem *)(vaddr + offset); 66} 67EXPORT_SYMBOL(ioremap_prot); 68 69void iounmap(volatile void __iomem *addr) 70{ 71 vunmap((void *)((unsigned long)addr & PAGE_MASK)); 72} 73EXPORT_SYMBOL(iounmap); 74#endif /* CONFIG_GENERIC_IOREMAP */