2008-06-25 19:22:42 +04:00
/*
* T10 Data Integrity Field CRC16 calculation
*
* Copyright ( c ) 2007 Oracle Corporation . All rights reserved .
* Written by Martin K . Petersen < martin . petersen @ oracle . com >
*
* This source code is licensed under the GNU General Public License ,
* Version 2. See the file COPYING for more details .
*/
# include <linux/types.h>
# include <linux/module.h>
# include <linux/crc-t10dif.h>
2013-09-07 06:56:26 +04:00
# include <linux/err.h>
# include <linux/init.h>
# include <crypto/hash.h>
2013-09-12 09:31:34 +04:00
# include <linux/static_key.h>
2008-06-25 19:22:42 +04:00
2013-09-07 06:56:26 +04:00
static struct crypto_shash * crct10dif_tfm ;
2013-09-12 09:31:34 +04:00
static struct static_key crct10dif_fallback __read_mostly ;
2008-06-25 19:22:42 +04:00
2015-05-01 09:23:50 +03:00
__u16 crc_t10dif_update ( __u16 crc , const unsigned char * buffer , size_t len )
2008-06-25 19:22:42 +04:00
{
2013-09-07 06:56:26 +04:00
struct {
struct shash_desc shash ;
char ctx [ 2 ] ;
} desc ;
int err ;
2013-09-12 09:31:34 +04:00
if ( static_key_false ( & crct10dif_fallback ) )
2015-05-01 09:23:50 +03:00
return crc_t10dif_generic ( crc , buffer , len ) ;
2013-09-12 09:31:34 +04:00
2013-09-07 06:56:26 +04:00
desc . shash . tfm = crct10dif_tfm ;
desc . shash . flags = 0 ;
2015-05-01 09:23:50 +03:00
* ( __u16 * ) desc . ctx = crc ;
2008-06-25 19:22:42 +04:00
2013-09-07 06:56:26 +04:00
err = crypto_shash_update ( & desc . shash , buffer , len ) ;
BUG_ON ( err ) ;
2008-06-25 19:22:42 +04:00
2013-09-07 06:56:26 +04:00
return * ( __u16 * ) desc . ctx ;
2008-06-25 19:22:42 +04:00
}
2015-05-01 09:23:50 +03:00
EXPORT_SYMBOL ( crc_t10dif_update ) ;
__u16 crc_t10dif ( const unsigned char * buffer , size_t len )
{
return crc_t10dif_update ( 0 , buffer , len ) ;
}
2008-06-25 19:22:42 +04:00
EXPORT_SYMBOL ( crc_t10dif ) ;
2013-09-07 06:56:26 +04:00
static int __init crc_t10dif_mod_init ( void )
{
crct10dif_tfm = crypto_alloc_shash ( " crct10dif " , 0 , 0 ) ;
2013-09-12 09:31:34 +04:00
if ( IS_ERR ( crct10dif_tfm ) ) {
static_key_slow_inc ( & crct10dif_fallback ) ;
crct10dif_tfm = NULL ;
}
return 0 ;
2013-09-07 06:56:26 +04:00
}
static void __exit crc_t10dif_mod_fini ( void )
{
crypto_free_shash ( crct10dif_tfm ) ;
}
module_init ( crc_t10dif_mod_init ) ;
module_exit ( crc_t10dif_mod_fini ) ;
2008-06-25 19:22:42 +04:00
MODULE_DESCRIPTION ( " T10 DIF CRC calculation " ) ;
MODULE_LICENSE ( " GPL " ) ;
2013-09-07 06:56:26 +04:00
MODULE_SOFTDEP ( " pre: crct10dif " ) ;