1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright(c) 2007 Intel Corporation. All rights reserved. 4 * 5 * Maintained at www.Open-FCoE.org 6 */ 7 8 /* 9 * Frame allocation. 10 */ 11 #include <linux/module.h> 12 #include <linux/kernel.h> 13 #include <linux/skbuff.h> 14 #include <linux/crc32.h> 15 #include <linux/gfp.h> 16 17 #include <scsi/fc_frame.h> 18 19 /* 20 * Check the CRC in a frame. 21 */ 22 u32 fc_frame_crc_check(struct fc_frame *fp) 23 { 24 u32 crc; 25 u32 error; 26 const u8 *bp; 27 unsigned int len; 28 29 WARN_ON(!fc_frame_is_linear(fp)); 30 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 31 len = (fr_len(fp) + 3) & ~3; /* round up length to include fill */ 32 bp = (const u8 *) fr_hdr(fp); 33 crc = ~crc32(~0, bp, len); 34 error = crc ^ fr_crc(fp); 35 return error; 36 } 37 EXPORT_SYMBOL(fc_frame_crc_check); 38 39 /* 40 * Allocate a frame intended to be sent. 41 * Get an sk_buff for the frame and set the length. 42 */ 43 struct fc_frame *_fc_frame_alloc(size_t len) 44 { 45 struct fc_frame *fp; 46 struct sk_buff *skb; 47 48 WARN_ON((len % sizeof(u32)) != 0); 49 len += sizeof(struct fc_frame_header); 50 skb = alloc_skb_fclone(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM + 51 NET_SKB_PAD, GFP_ATOMIC); 52 if (!skb) 53 return NULL; 54 skb_reserve(skb, NET_SKB_PAD + FC_FRAME_HEADROOM); 55 fp = (struct fc_frame *) skb; 56 fc_frame_init(fp); 57 skb_put(skb, len); 58 return fp; 59 } 60 EXPORT_SYMBOL(_fc_frame_alloc); 61 62 struct fc_frame *fc_frame_alloc_fill(struct fc_lport *lp, size_t payload_len) 63 { 64 struct fc_frame *fp; 65 size_t fill; 66 67 fill = payload_len % 4; 68 if (fill != 0) 69 fill = 4 - fill; 70 fp = _fc_frame_alloc(payload_len + fill); 71 if (fp) { 72 memset((char *) fr_hdr(fp) + payload_len, 0, fill); 73 /* trim is OK, we just allocated it so there are no fragments */ 74 skb_trim(fp_skb(fp), 75 payload_len + sizeof(struct fc_frame_header)); 76 } 77 return fp; 78 } 79 EXPORT_SYMBOL(fc_frame_alloc_fill); 80