2006-10-01 10:29:12 +04:00
/*
* Re - map IO memory to kernel address space so that we can access it .
* This is needed for high PCI addresses that aren ' t mapped in the
* 640 k - 1 MB IO memory area on PC ' s
*
* ( C ) Copyright 1995 1996 Linus Torvalds
*/
# include <linux/vmalloc.h>
# include <linux/mm.h>
Detach sched.h from mm.h
First thing mm.h does is including sched.h solely for can_do_mlock() inline
function which has "current" dereference inside. By dealing with can_do_mlock()
mm.h can be detached from sched.h which is good. See below, why.
This patch
a) removes unconditional inclusion of sched.h from mm.h
b) makes can_do_mlock() normal function in mm/mlock.c
c) exports can_do_mlock() to not break compilation
d) adds sched.h inclusions back to files that were getting it indirectly.
e) adds less bloated headers to some files (asm/signal.h, jiffies.h) that were
getting them indirectly
Net result is:
a) mm.h users would get less code to open, read, preprocess, parse, ... if
they don't need sched.h
b) sched.h stops being dependency for significant number of files:
on x86_64 allmodconfig touching sched.h results in recompile of 4083 files,
after patch it's only 3744 (-8.3%).
Cross-compile tested on
all arm defconfigs, all mips defconfigs, all powerpc defconfigs,
alpha alpha-up
arm
i386 i386-up i386-defconfig i386-allnoconfig
ia64 ia64-up
m68k
mips
parisc parisc-up
powerpc powerpc-up
s390 s390-up
sparc sparc-up
sparc64 sparc64-up
um-x86_64
x86_64 x86_64-up x86_64-defconfig x86_64-allnoconfig
as well as my two usual configs.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-21 01:22:52 +04:00
# include <linux/sched.h>
2007-10-17 10:26:42 +04:00
# include <linux/io.h>
2011-11-17 06:29:17 +04:00
# include <linux/export.h>
2006-10-01 10:29:12 +04:00
# include <asm/cacheflush.h>
# include <asm/pgtable.h>
2015-04-15 01:47:20 +03:00
# ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
2017-03-09 17:24:07 +03:00
static int __read_mostly ioremap_p4d_capable ;
2015-04-15 01:47:32 +03:00
static int __read_mostly ioremap_pud_capable ;
static int __read_mostly ioremap_pmd_capable ;
static int __read_mostly ioremap_huge_disabled ;
2015-04-15 01:47:20 +03:00
static int __init set_nohugeiomap ( char * str )
{
ioremap_huge_disabled = 1 ;
return 0 ;
}
early_param ( " nohugeiomap " , set_nohugeiomap ) ;
void __init ioremap_huge_init ( void )
{
if ( ! ioremap_huge_disabled ) {
if ( arch_ioremap_pud_supported ( ) )
ioremap_pud_capable = 1 ;
if ( arch_ioremap_pmd_supported ( ) )
ioremap_pmd_capable = 1 ;
}
}
2017-03-09 17:24:07 +03:00
static inline int ioremap_p4d_enabled ( void )
{
return ioremap_p4d_capable ;
}
2015-04-15 01:47:20 +03:00
static inline int ioremap_pud_enabled ( void )
{
return ioremap_pud_capable ;
}
static inline int ioremap_pmd_enabled ( void )
{
return ioremap_pmd_capable ;
}
# else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
2017-03-09 17:24:07 +03:00
static inline int ioremap_p4d_enabled ( void ) { return 0 ; }
2015-04-15 01:47:20 +03:00
static inline int ioremap_pud_enabled ( void ) { return 0 ; }
static inline int ioremap_pmd_enabled ( void ) { return 0 ; }
# endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
2006-10-01 10:29:12 +04:00
static int ioremap_pte_range ( pmd_t * pmd , unsigned long addr ,
2010-06-18 07:22:40 +04:00
unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
2006-10-01 10:29:12 +04:00
{
pte_t * pte ;
2010-06-18 07:22:40 +04:00
u64 pfn ;
2006-10-01 10:29:12 +04:00
pfn = phys_addr > > PAGE_SHIFT ;
pte = pte_alloc_kernel ( pmd , addr ) ;
if ( ! pte )
return - ENOMEM ;
do {
BUG_ON ( ! pte_none ( * pte ) ) ;
set_pte_at ( & init_mm , addr , pte , pfn_pte ( pfn , prot ) ) ;
pfn + + ;
} while ( pte + + , addr + = PAGE_SIZE , addr ! = end ) ;
return 0 ;
}
static inline int ioremap_pmd_range ( pud_t * pud , unsigned long addr ,
2010-06-18 07:22:40 +04:00
unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
2006-10-01 10:29:12 +04:00
{
pmd_t * pmd ;
unsigned long next ;
phys_addr - = addr ;
pmd = pmd_alloc ( & init_mm , pud , addr ) ;
if ( ! pmd )
return - ENOMEM ;
do {
next = pmd_addr_end ( addr , end ) ;
2015-04-15 01:47:23 +03:00
if ( ioremap_pmd_enabled ( ) & &
( ( next - addr ) = = PMD_SIZE ) & &
IS_ALIGNED ( phys_addr + addr , PMD_SIZE ) ) {
if ( pmd_set_huge ( pmd , phys_addr + addr , prot ) )
continue ;
}
2006-10-01 10:29:12 +04:00
if ( ioremap_pte_range ( pmd , addr , next , phys_addr + addr , prot ) )
return - ENOMEM ;
} while ( pmd + + , addr = next , addr ! = end ) ;
return 0 ;
}
2017-03-09 17:24:07 +03:00
static inline int ioremap_pud_range ( p4d_t * p4d , unsigned long addr ,
2010-06-18 07:22:40 +04:00
unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
2006-10-01 10:29:12 +04:00
{
pud_t * pud ;
unsigned long next ;
phys_addr - = addr ;
2017-03-09 17:24:07 +03:00
pud = pud_alloc ( & init_mm , p4d , addr ) ;
2006-10-01 10:29:12 +04:00
if ( ! pud )
return - ENOMEM ;
do {
next = pud_addr_end ( addr , end ) ;
2015-04-15 01:47:23 +03:00
if ( ioremap_pud_enabled ( ) & &
( ( next - addr ) = = PUD_SIZE ) & &
IS_ALIGNED ( phys_addr + addr , PUD_SIZE ) ) {
if ( pud_set_huge ( pud , phys_addr + addr , prot ) )
continue ;
}
2006-10-01 10:29:12 +04:00
if ( ioremap_pmd_range ( pud , addr , next , phys_addr + addr , prot ) )
return - ENOMEM ;
} while ( pud + + , addr = next , addr ! = end ) ;
return 0 ;
}
2017-03-09 17:24:07 +03:00
static inline int ioremap_p4d_range ( pgd_t * pgd , unsigned long addr ,
unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
{
p4d_t * p4d ;
unsigned long next ;
phys_addr - = addr ;
p4d = p4d_alloc ( & init_mm , pgd , addr ) ;
if ( ! p4d )
return - ENOMEM ;
do {
next = p4d_addr_end ( addr , end ) ;
if ( ioremap_p4d_enabled ( ) & &
( ( next - addr ) = = P4D_SIZE ) & &
IS_ALIGNED ( phys_addr + addr , P4D_SIZE ) ) {
if ( p4d_set_huge ( p4d , phys_addr + addr , prot ) )
continue ;
}
if ( ioremap_pud_range ( p4d , addr , next , phys_addr + addr , prot ) )
return - ENOMEM ;
} while ( p4d + + , addr = next , addr ! = end ) ;
return 0 ;
}
2006-10-01 10:29:12 +04:00
int ioremap_page_range ( unsigned long addr ,
2010-06-18 07:22:40 +04:00
unsigned long end , phys_addr_t phys_addr , pgprot_t prot )
2006-10-01 10:29:12 +04:00
{
pgd_t * pgd ;
unsigned long start ;
unsigned long next ;
int err ;
BUG_ON ( addr > = end ) ;
start = addr ;
phys_addr - = addr ;
pgd = pgd_offset_k ( addr ) ;
do {
next = pgd_addr_end ( addr , end ) ;
2017-03-09 17:24:07 +03:00
err = ioremap_p4d_range ( pgd , addr , next , phys_addr + addr , prot ) ;
2006-10-01 10:29:12 +04:00
if ( err )
break ;
} while ( pgd + + , addr = next , addr ! = end ) ;
2006-10-01 10:29:14 +04:00
flush_cache_vmap ( start , end ) ;
2006-10-01 10:29:12 +04:00
return err ;
}