| 1 | |
| 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;
|
| 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 |
|
| 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);
|