cffrml.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * CAIF Framing Layer.
  3. *
  4. * Copyright (C) ST-Ericsson AB 2010
  5. * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
  6. * License terms: GNU General Public License (GPL) version 2
  7. */
  8. #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
  9. #include <linux/stddef.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/slab.h>
  12. #include <linux/crc-ccitt.h>
  13. #include <net/caif/caif_layer.h>
  14. #include <net/caif/cfpkt.h>
  15. #include <net/caif/cffrml.h>
  16. #define container_obj(layr) container_of(layr, struct cffrml, layer)
  17. struct cffrml {
  18. struct cflayer layer;
  19. bool dofcs; /* !< FCS active */
  20. };
  21. static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
  22. static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
  23. static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  24. int phyid);
  25. static u32 cffrml_rcv_error;
  26. static u32 cffrml_rcv_checsum_error;
  27. struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
  28. {
  29. struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
  30. if (!this) {
  31. pr_warn("Out of memory\n");
  32. return NULL;
  33. }
  34. caif_assert(offsetof(struct cffrml, layer) == 0);
  35. memset(this, 0, sizeof(struct cflayer));
  36. this->layer.receive = cffrml_receive;
  37. this->layer.transmit = cffrml_transmit;
  38. this->layer.ctrlcmd = cffrml_ctrlcmd;
  39. snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid);
  40. this->dofcs = use_fcs;
  41. this->layer.id = phyid;
  42. return (struct cflayer *) this;
  43. }
  44. void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
  45. {
  46. this->up = up;
  47. }
  48. void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn)
  49. {
  50. this->dn = dn;
  51. }
  52. static u16 cffrml_checksum(u16 chks, void *buf, u16 len)
  53. {
  54. /* FIXME: FCS should be moved to glue in order to use OS-Specific
  55. * solutions
  56. */
  57. return crc_ccitt(chks, buf, len);
  58. }
  59. static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
  60. {
  61. u16 tmp;
  62. u16 len;
  63. u16 hdrchks;
  64. u16 pktchks;
  65. struct cffrml *this;
  66. this = container_obj(layr);
  67. cfpkt_extr_head(pkt, &tmp, 2);
  68. len = le16_to_cpu(tmp);
  69. /* Subtract for FCS on length if FCS is not used. */
  70. if (!this->dofcs)
  71. len -= 2;
  72. if (cfpkt_setlen(pkt, len) < 0) {
  73. ++cffrml_rcv_error;
  74. pr_err("Framing length error (%d)\n", len);
  75. cfpkt_destroy(pkt);
  76. return -EPROTO;
  77. }
  78. /*
  79. * Don't do extract if FCS is false, rather do setlen - then we don't
  80. * get a cache-miss.
  81. */
  82. if (this->dofcs) {
  83. cfpkt_extr_trail(pkt, &tmp, 2);
  84. hdrchks = le16_to_cpu(tmp);
  85. pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
  86. if (pktchks != hdrchks) {
  87. cfpkt_add_trail(pkt, &tmp, 2);
  88. ++cffrml_rcv_error;
  89. ++cffrml_rcv_checsum_error;
  90. pr_info("Frame checksum error (0x%x != 0x%x)\n",
  91. hdrchks, pktchks);
  92. return -EILSEQ;
  93. }
  94. }
  95. if (cfpkt_erroneous(pkt)) {
  96. ++cffrml_rcv_error;
  97. pr_err("Packet is erroneous!\n");
  98. cfpkt_destroy(pkt);
  99. return -EPROTO;
  100. }
  101. return layr->up->receive(layr->up, pkt);
  102. }
  103. static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
  104. {
  105. int tmp;
  106. u16 chks;
  107. u16 len;
  108. int ret;
  109. struct cffrml *this = container_obj(layr);
  110. if (this->dofcs) {
  111. chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
  112. tmp = cpu_to_le16(chks);
  113. cfpkt_add_trail(pkt, &tmp, 2);
  114. } else {
  115. cfpkt_pad_trail(pkt, 2);
  116. }
  117. len = cfpkt_getlen(pkt);
  118. tmp = cpu_to_le16(len);
  119. cfpkt_add_head(pkt, &tmp, 2);
  120. cfpkt_info(pkt)->hdr_len += 2;
  121. if (cfpkt_erroneous(pkt)) {
  122. pr_err("Packet is erroneous!\n");
  123. return -EPROTO;
  124. }
  125. ret = layr->dn->transmit(layr->dn, pkt);
  126. if (ret < 0) {
  127. /* Remove header on faulty packet. */
  128. cfpkt_extr_head(pkt, &tmp, 2);
  129. }
  130. return ret;
  131. }
  132. static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  133. int phyid)
  134. {
  135. if (layr->up->ctrlcmd)
  136. layr->up->ctrlcmd(layr->up, ctrl, layr->id);
  137. }