2008-12-10 02:10:17 +03:00
/*
* Copyright ( c ) 2007 Intel Corporation . All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Maintained at www . Open - FCoE . org
*/
/*
* Frame allocation .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/skbuff.h>
# include <linux/crc32.h>
# include <scsi/fc_frame.h>
/*
* Check the CRC in a frame .
*/
u32 fc_frame_crc_check ( struct fc_frame * fp )
{
u32 crc ;
u32 error ;
const u8 * bp ;
unsigned int len ;
WARN_ON ( ! fc_frame_is_linear ( fp ) ) ;
fr_flags ( fp ) & = ~ FCPHF_CRC_UNCHECKED ;
len = ( fr_len ( fp ) + 3 ) & ~ 3 ; /* round up length to include fill */
bp = ( const u8 * ) fr_hdr ( fp ) ;
crc = ~ crc32 ( ~ 0 , bp , len ) ;
error = crc ^ fr_crc ( fp ) ;
return error ;
}
EXPORT_SYMBOL ( fc_frame_crc_check ) ;
/*
* Allocate a frame intended to be sent via fcoe_xmit .
* Get an sk_buff for the frame and set the length .
*/
2009-11-03 22:47:55 +03:00
struct fc_frame * _fc_frame_alloc ( size_t len )
2008-12-10 02:10:17 +03:00
{
struct fc_frame * fp ;
struct sk_buff * skb ;
WARN_ON ( ( len % sizeof ( u32 ) ) ! = 0 ) ;
len + = sizeof ( struct fc_frame_header ) ;
skb = dev_alloc_skb ( len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM ) ;
if ( ! skb )
return NULL ;
fp = ( struct fc_frame * ) skb ;
fc_frame_init ( fp ) ;
skb_reserve ( skb , FC_FRAME_HEADROOM ) ;
skb_put ( skb , len ) ;
return fp ;
}
2009-11-03 22:47:55 +03:00
EXPORT_SYMBOL ( _fc_frame_alloc ) ;
2008-12-10 02:10:17 +03:00
struct fc_frame * fc_frame_alloc_fill ( struct fc_lport * lp , size_t payload_len )
{
struct fc_frame * fp ;
size_t fill ;
fill = payload_len % 4 ;
if ( fill ! = 0 )
fill = 4 - fill ;
2009-11-03 22:47:55 +03:00
fp = _fc_frame_alloc ( payload_len + fill ) ;
2008-12-10 02:10:17 +03:00
if ( fp ) {
memset ( ( char * ) fr_hdr ( fp ) + payload_len , 0 , fill ) ;
/* trim is OK, we just allocated it so there are no fragments */
skb_trim ( fp_skb ( fp ) ,
payload_len + sizeof ( struct fc_frame_header ) ) ;
}
return fp ;
}
2009-11-03 22:47:18 +03:00
EXPORT_SYMBOL ( fc_frame_alloc_fill ) ;