2009-08-15 04:19:19 +04:00
/*
* arch / sh / mm / kmap . c
*
* Copyright ( C ) 1999 , 2000 , 2002 Niibe Yutaka
* Copyright ( C ) 2002 - 2009 Paul Mundt
*
* Released under the terms of the GNU GPL v2 .0 .
*/
# include <linux/mm.h>
# include <linux/init.h>
# include <linux/mutex.h>
# include <linux/fs.h>
# include <linux/highmem.h>
# include <linux/module.h>
# include <asm/mmu_context.h>
# include <asm/cacheflush.h>
# define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel ( pmd_offset ( pud_offset ( pgd_offset_k ( vaddr ) , ( vaddr ) ) , ( vaddr ) ) , ( vaddr ) )
static pte_t * kmap_coherent_pte ;
void __init kmap_coherent_init ( void )
{
unsigned long vaddr ;
/* cache the first coherent kmap pte */
vaddr = __fix_to_virt ( FIX_CMAP_BEGIN ) ;
kmap_coherent_pte = kmap_get_fixmap_pte ( vaddr ) ;
}
void * kmap_coherent ( struct page * page , unsigned long addr )
{
enum fixed_addresses idx ;
2009-09-03 12:21:10 +04:00
unsigned long vaddr ;
2009-08-15 04:19:19 +04:00
2010-12-01 09:39:51 +03:00
BUG_ON ( ! test_bit ( PG_dcache_clean , & page - > flags ) ) ;
2009-08-15 04:19:19 +04:00
2016-02-29 11:19:24 +03:00
preempt_disable ( ) ;
2009-09-03 12:21:10 +04:00
pagefault_disable ( ) ;
2009-08-15 04:19:19 +04:00
2009-09-03 12:21:10 +04:00
idx = FIX_CMAP_END -
2009-09-09 12:14:19 +04:00
( ( ( addr > > PAGE_SHIFT ) & ( FIX_N_COLOURS - 1 ) ) +
( FIX_N_COLOURS * smp_processor_id ( ) ) ) ;
2009-09-03 12:21:10 +04:00
vaddr = __fix_to_virt ( idx ) ;
2009-08-15 04:19:19 +04:00
2009-09-03 12:21:10 +04:00
BUG_ON ( ! pte_none ( * ( kmap_coherent_pte - idx ) ) ) ;
set_pte ( kmap_coherent_pte - idx , mk_pte ( page , PAGE_KERNEL ) ) ;
2009-08-15 04:19:19 +04:00
return ( void * ) vaddr ;
}
2009-09-03 12:21:10 +04:00
void kunmap_coherent ( void * kvaddr )
2009-08-15 04:19:19 +04:00
{
2009-09-03 12:21:10 +04:00
if ( kvaddr > = ( void * ) FIXADDR_START ) {
unsigned long vaddr = ( unsigned long ) kvaddr & PAGE_MASK ;
enum fixed_addresses idx = __virt_to_fix ( vaddr ) ;
2009-09-08 11:21:00 +04:00
/* XXX.. Kill this later, here for sanity at the moment.. */
__flush_purge_region ( ( void * ) vaddr , PAGE_SIZE ) ;
2009-09-03 12:21:10 +04:00
pte_clear ( & init_mm , vaddr , kmap_coherent_pte - idx ) ;
local_flush_tlb_one ( get_asid ( ) , vaddr ) ;
}
pagefault_enable ( ) ;
2016-02-29 11:19:24 +03:00
preempt_enable ( ) ;
2009-08-15 04:19:19 +04:00
}