fc_frame.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright(c) 2007 Intel Corporation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU General Public License,
  6. * version 2, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along with
  14. * this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * Maintained at www.Open-FCoE.org
  18. */
  19. /*
  20. * Frame allocation.
  21. */
  22. #include <linux/module.h>
  23. #include <linux/kernel.h>
  24. #include <linux/skbuff.h>
  25. #include <linux/crc32.h>
  26. #include <linux/gfp.h>
  27. #include <scsi/fc_frame.h>
  28. /*
  29. * Check the CRC in a frame.
  30. */
  31. u32 fc_frame_crc_check(struct fc_frame *fp)
  32. {
  33. u32 crc;
  34. u32 error;
  35. const u8 *bp;
  36. unsigned int len;
  37. WARN_ON(!fc_frame_is_linear(fp));
  38. fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
  39. len = (fr_len(fp) + 3) & ~3; /* round up length to include fill */
  40. bp = (const u8 *) fr_hdr(fp);
  41. crc = ~crc32(~0, bp, len);
  42. error = crc ^ fr_crc(fp);
  43. return error;
  44. }
  45. EXPORT_SYMBOL(fc_frame_crc_check);
  46. /*
  47. * Allocate a frame intended to be sent.
  48. * Get an sk_buff for the frame and set the length.
  49. */
  50. struct fc_frame *_fc_frame_alloc(size_t len)
  51. {
  52. struct fc_frame *fp;
  53. struct sk_buff *skb;
  54. WARN_ON((len % sizeof(u32)) != 0);
  55. len += sizeof(struct fc_frame_header);
  56. skb = alloc_skb_fclone(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM +
  57. NET_SKB_PAD, GFP_ATOMIC);
  58. if (!skb)
  59. return NULL;
  60. skb_reserve(skb, NET_SKB_PAD + FC_FRAME_HEADROOM);
  61. fp = (struct fc_frame *) skb;
  62. fc_frame_init(fp);
  63. skb_put(skb, len);
  64. return fp;
  65. }
  66. EXPORT_SYMBOL(_fc_frame_alloc);
  67. struct fc_frame *fc_frame_alloc_fill(struct fc_lport *lp, size_t payload_len)
  68. {
  69. struct fc_frame *fp;
  70. size_t fill;
  71. fill = payload_len % 4;
  72. if (fill != 0)
  73. fill = 4 - fill;
  74. fp = _fc_frame_alloc(payload_len + fill);
  75. if (fp) {
  76. memset((char *) fr_hdr(fp) + payload_len, 0, fill);
  77. /* trim is OK, we just allocated it so there are no fragments */
  78. skb_trim(fp_skb(fp),
  79. payload_len + sizeof(struct fc_frame_header));
  80. }
  81. return fp;
  82. }
  83. EXPORT_SYMBOL(fc_frame_alloc_fill);