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