2005-04-17 02:20:36 +04:00
/*
* Cryptographic API .
*
* Cipher operations .
*
* Copyright ( c ) 2002 James Morris < jmorris @ intercode . com . au >
* 2002 Adam J . Richter < adam @ yggdrasil . com >
* 2004 Jean - Luc Cooke < jlcooke @ certainkey . com >
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation ; either version 2 of the License , or ( at your option )
* any later version .
*
*/
# include <linux/kernel.h>
# include <linux/mm.h>
2006-08-12 15:56:17 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/pagemap.h>
# include <linux/highmem.h>
2006-08-12 15:56:17 +04:00
# include <linux/scatterlist.h>
2005-04-17 02:20:36 +04:00
# include "internal.h"
# include "scatterwalk.h"
enum km_type crypto_km_types [ ] = {
KM_USER0 ,
KM_USER1 ,
KM_SOFTIRQ0 ,
KM_SOFTIRQ1 ,
} ;
2006-08-12 15:56:17 +04:00
EXPORT_SYMBOL_GPL ( crypto_km_types ) ;
2005-04-17 02:20:36 +04:00
2006-08-12 15:56:17 +04:00
static inline void memcpy_dir ( void * buf , void * sgdata , size_t nbytes , int out )
2005-04-17 02:20:36 +04:00
{
2006-08-12 15:56:17 +04:00
void * src = out ? buf : sgdata ;
void * dst = out ? sgdata : buf ;
memcpy ( dst , src , nbytes ) ;
2005-04-17 02:20:36 +04:00
}
void scatterwalk_start ( struct scatter_walk * walk , struct scatterlist * sg )
{
walk - > sg = sg ;
BUG_ON ( ! sg - > length ) ;
walk - > offset = sg - > offset ;
}
2006-08-12 15:56:17 +04:00
EXPORT_SYMBOL_GPL ( scatterwalk_start ) ;
2005-04-17 02:20:36 +04:00
2006-08-12 15:56:17 +04:00
void * scatterwalk_map ( struct scatter_walk * walk , int out )
2005-04-17 02:20:36 +04:00
{
2006-08-12 15:56:17 +04:00
return crypto_kmap ( scatterwalk_page ( walk ) , out ) +
offset_in_page ( walk - > offset ) ;
2005-04-17 02:20:36 +04:00
}
2006-08-12 15:56:17 +04:00
EXPORT_SYMBOL_GPL ( scatterwalk_map ) ;
2005-04-17 02:20:36 +04:00
static void scatterwalk_pagedone ( struct scatter_walk * walk , int out ,
unsigned int more )
{
2007-03-31 06:58:20 +04:00
if ( out ) {
struct page * page ;
page = walk - > sg - > page + ( ( walk - > offset - 1 ) > > PAGE_SHIFT ) ;
flush_dcache_page ( page ) ;
}
2005-04-17 02:20:36 +04:00
if ( more ) {
2006-08-12 15:56:17 +04:00
walk - > offset + = PAGE_SIZE - 1 ;
walk - > offset & = PAGE_MASK ;
if ( walk - > offset > = walk - > sg - > offset + walk - > sg - > length )
2005-04-17 02:20:36 +04:00
scatterwalk_start ( walk , sg_next ( walk - > sg ) ) ;
}
}
void scatterwalk_done ( struct scatter_walk * walk , int out , int more )
{
2006-08-12 15:56:17 +04:00
if ( ! offset_in_page ( walk - > offset ) | | ! more )
2005-04-17 02:20:36 +04:00
scatterwalk_pagedone ( walk , out , more ) ;
}
2006-08-12 15:56:17 +04:00
EXPORT_SYMBOL_GPL ( scatterwalk_done ) ;
2005-04-17 02:20:36 +04:00
2006-08-12 15:56:17 +04:00
void scatterwalk_copychunks ( void * buf , struct scatter_walk * walk ,
size_t nbytes , int out )
2005-04-17 02:20:36 +04:00
{
2006-08-12 15:56:17 +04:00
for ( ; ; ) {
unsigned int len_this_page = scatterwalk_pagelen ( walk ) ;
u8 * vaddr ;
if ( len_this_page > nbytes )
len_this_page = nbytes ;
vaddr = scatterwalk_map ( walk , out ) ;
memcpy_dir ( buf , vaddr , len_this_page , out ) ;
scatterwalk_unmap ( vaddr , out ) ;
2007-03-31 06:16:20 +04:00
scatterwalk_advance ( walk , len_this_page ) ;
2007-03-21 00:50:12 +03:00
2006-08-12 15:56:17 +04:00
if ( nbytes = = len_this_page )
break ;
buf + = len_this_page ;
nbytes - = len_this_page ;
2005-04-17 02:20:36 +04:00
scatterwalk_pagedone ( walk , out , 1 ) ;
2005-07-07 00:51:31 +04:00
}
2005-04-17 02:20:36 +04:00
}
2006-08-12 15:56:17 +04:00
EXPORT_SYMBOL_GPL ( scatterwalk_copychunks ) ;