cffrml.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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 <linux/netdevice.h>
  14. #include <net/caif/caif_layer.h>
  15. #include <net/caif/cfpkt.h>
  16. #include <net/caif/cffrml.h>
  17. #define container_obj(layr) container_of(layr, struct cffrml, layer)
  18. struct cffrml {
  19. struct cflayer layer;
  20. bool dofcs; /* !< FCS active */
  21. int __percpu *pcpu_refcnt;
  22. };
  23. static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
  24. static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
  25. static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  26. int phyid);
  27. static u32 cffrml_rcv_error;
  28. static u32 cffrml_rcv_checsum_error;
  29. struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
  30. {
  31. struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
  32. if (!this) {
  33. pr_warn("Out of memory\n");
  34. return NULL;
  35. }
  36. this->pcpu_refcnt = alloc_percpu(int);
  37. if (this->pcpu_refcnt == NULL) {
  38. kfree(this);
  39. return NULL;
  40. }
  41. caif_assert(offsetof(struct cffrml, layer) == 0);
  42. memset(this, 0, sizeof(struct cflayer));
  43. this->layer.receive = cffrml_receive;
  44. this->layer.transmit = cffrml_transmit;
  45. this->layer.ctrlcmd = cffrml_ctrlcmd;
  46. snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid);
  47. this->dofcs = use_fcs;
  48. this->layer.id = phyid;
  49. return (struct cflayer *) this;
  50. }
  51. void cffrml_free(struct cflayer *layer)
  52. {
  53. struct cffrml *this = container_obj(layer);
  54. free_percpu(this->pcpu_refcnt);
  55. kfree(layer);
  56. }
  57. void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
  58. {
  59. this->up = up;
  60. }
  61. void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn)
  62. {
  63. this->dn = dn;
  64. }
  65. static u16 cffrml_checksum(u16 chks, void *buf, u16 len)
  66. {
  67. /* FIXME: FCS should be moved to glue in order to use OS-Specific
  68. * solutions
  69. */
  70. return crc_ccitt(chks, buf, len);
  71. }
  72. static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
  73. {
  74. u16 tmp;
  75. u16 len;
  76. u16 hdrchks;
  77. u16 pktchks;
  78. struct cffrml *this;
  79. this = container_obj(layr);
  80. cfpkt_extr_head(pkt, &tmp, 2);
  81. len = le16_to_cpu(tmp);
  82. /* Subtract for FCS on length if FCS is not used. */
  83. if (!this->dofcs)
  84. len -= 2;
  85. if (cfpkt_setlen(pkt, len) < 0) {
  86. ++cffrml_rcv_error;
  87. pr_err("Framing length error (%d)\n", len);
  88. cfpkt_destroy(pkt);
  89. return -EPROTO;
  90. }
  91. /*
  92. * Don't do extract if FCS is false, rather do setlen - then we don't
  93. * get a cache-miss.
  94. */
  95. if (this->dofcs) {
  96. cfpkt_extr_trail(pkt, &tmp, 2);
  97. hdrchks = le16_to_cpu(tmp);
  98. pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
  99. if (pktchks != hdrchks) {
  100. cfpkt_add_trail(pkt, &tmp, 2);
  101. ++cffrml_rcv_error;
  102. ++cffrml_rcv_checsum_error;
  103. pr_info("Frame checksum error (0x%x != 0x%x)\n",
  104. hdrchks, pktchks);
  105. return -EILSEQ;
  106. }
  107. }
  108. if (cfpkt_erroneous(pkt)) {
  109. ++cffrml_rcv_error;
  110. pr_err("Packet is erroneous!\n");
  111. cfpkt_destroy(pkt);
  112. return -EPROTO;
  113. }
  114. if (layr->up == NULL) {
  115. pr_err("Layr up is missing!\n");
  116. cfpkt_destroy(pkt);
  117. return -EINVAL;
  118. }
  119. return layr->up->receive(layr->up, pkt);
  120. }
  121. static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
  122. {
  123. int tmp;
  124. u16 chks;
  125. u16 len;
  126. struct cffrml *this = container_obj(layr);
  127. if (this->dofcs) {
  128. chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
  129. tmp = cpu_to_le16(chks);
  130. cfpkt_add_trail(pkt, &tmp, 2);
  131. } else {
  132. cfpkt_pad_trail(pkt, 2);
  133. }
  134. len = cfpkt_getlen(pkt);
  135. tmp = cpu_to_le16(len);
  136. cfpkt_add_head(pkt, &tmp, 2);
  137. cfpkt_info(pkt)->hdr_len += 2;
  138. if (cfpkt_erroneous(pkt)) {
  139. pr_err("Packet is erroneous!\n");
  140. cfpkt_destroy(pkt);
  141. return -EPROTO;
  142. }
  143. if (layr->dn == NULL) {
  144. cfpkt_destroy(pkt);
  145. return -ENODEV;
  146. }
  147. return layr->dn->transmit(layr->dn, pkt);
  148. }
  149. static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  150. int phyid)
  151. {
  152. if (layr->up && layr->up->ctrlcmd)
  153. layr->up->ctrlcmd(layr->up, ctrl, layr->id);
  154. }
  155. void cffrml_put(struct cflayer *layr)
  156. {
  157. struct cffrml *this = container_obj(layr);
  158. if (layr != NULL && this->pcpu_refcnt != NULL)
  159. irqsafe_cpu_dec(*this->pcpu_refcnt);
  160. }
  161. void cffrml_hold(struct cflayer *layr)
  162. {
  163. struct cffrml *this = container_obj(layr);
  164. if (layr != NULL && this->pcpu_refcnt != NULL)
  165. irqsafe_cpu_inc(*this->pcpu_refcnt);
  166. }
  167. int cffrml_refcnt_read(struct cflayer *layr)
  168. {
  169. int i, refcnt = 0;
  170. struct cffrml *this = container_obj(layr);
  171. for_each_possible_cpu(i)
  172. refcnt += *per_cpu_ptr(this->pcpu_refcnt, i);
  173. return refcnt;
  174. }