0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
0010
0011 #include <linux/stddef.h>
0012 #include <linux/spinlock.h>
0013 #include <linux/slab.h>
0014 #include <linux/crc-ccitt.h>
0015 #include <linux/netdevice.h>
0016 #include <net/caif/caif_layer.h>
0017 #include <net/caif/cfpkt.h>
0018 #include <net/caif/cffrml.h>
0019
0020 #define container_obj(layr) container_of(layr, struct cffrml, layer)
0021
0022 struct cffrml {
0023 struct cflayer layer;
0024 bool dofcs;
0025 int __percpu *pcpu_refcnt;
0026 };
0027
0028 static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
0029 static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt);
0030 static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
0031 int phyid);
0032
0033 static u32 cffrml_rcv_error;
0034 static u32 cffrml_rcv_checsum_error;
0035 struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
0036 {
0037 struct cffrml *this = kzalloc(sizeof(struct cffrml), GFP_ATOMIC);
0038 if (!this)
0039 return NULL;
0040 this->pcpu_refcnt = alloc_percpu(int);
0041 if (this->pcpu_refcnt == NULL) {
0042 kfree(this);
0043 return NULL;
0044 }
0045
0046 caif_assert(offsetof(struct cffrml, layer) == 0);
0047
0048 this->layer.receive = cffrml_receive;
0049 this->layer.transmit = cffrml_transmit;
0050 this->layer.ctrlcmd = cffrml_ctrlcmd;
0051 snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid);
0052 this->dofcs = use_fcs;
0053 this->layer.id = phyid;
0054 return (struct cflayer *) this;
0055 }
0056
0057 void cffrml_free(struct cflayer *layer)
0058 {
0059 struct cffrml *this = container_obj(layer);
0060 free_percpu(this->pcpu_refcnt);
0061 kfree(layer);
0062 }
0063
0064 void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
0065 {
0066 this->up = up;
0067 }
0068
0069 void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn)
0070 {
0071 this->dn = dn;
0072 }
0073
0074 static u16 cffrml_checksum(u16 chks, void *buf, u16 len)
0075 {
0076
0077
0078
0079 return crc_ccitt(chks, buf, len);
0080 }
0081
0082 static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
0083 {
0084 u16 tmp;
0085 u16 len;
0086 u16 hdrchks;
0087 int pktchks;
0088 struct cffrml *this;
0089 this = container_obj(layr);
0090
0091 cfpkt_extr_head(pkt, &tmp, 2);
0092 len = le16_to_cpu(tmp);
0093
0094
0095 if (!this->dofcs)
0096 len -= 2;
0097
0098 if (cfpkt_setlen(pkt, len) < 0) {
0099 ++cffrml_rcv_error;
0100 pr_err("Framing length error (%d)\n", len);
0101 cfpkt_destroy(pkt);
0102 return -EPROTO;
0103 }
0104
0105
0106
0107
0108 if (this->dofcs) {
0109 cfpkt_extr_trail(pkt, &tmp, 2);
0110 hdrchks = le16_to_cpu(tmp);
0111 pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
0112 if (pktchks != hdrchks) {
0113 cfpkt_add_trail(pkt, &tmp, 2);
0114 ++cffrml_rcv_error;
0115 ++cffrml_rcv_checsum_error;
0116 pr_info("Frame checksum error (0x%x != 0x%x)\n",
0117 hdrchks, pktchks);
0118 return -EILSEQ;
0119 }
0120 }
0121 if (cfpkt_erroneous(pkt)) {
0122 ++cffrml_rcv_error;
0123 pr_err("Packet is erroneous!\n");
0124 cfpkt_destroy(pkt);
0125 return -EPROTO;
0126 }
0127
0128 if (layr->up == NULL) {
0129 pr_err("Layr up is missing!\n");
0130 cfpkt_destroy(pkt);
0131 return -EINVAL;
0132 }
0133
0134 return layr->up->receive(layr->up, pkt);
0135 }
0136
0137 static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
0138 {
0139 u16 chks;
0140 u16 len;
0141 __le16 data;
0142
0143 struct cffrml *this = container_obj(layr);
0144 if (this->dofcs) {
0145 chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
0146 data = cpu_to_le16(chks);
0147 cfpkt_add_trail(pkt, &data, 2);
0148 } else {
0149 cfpkt_pad_trail(pkt, 2);
0150 }
0151 len = cfpkt_getlen(pkt);
0152 data = cpu_to_le16(len);
0153 cfpkt_add_head(pkt, &data, 2);
0154 cfpkt_info(pkt)->hdr_len += 2;
0155 if (cfpkt_erroneous(pkt)) {
0156 pr_err("Packet is erroneous!\n");
0157 cfpkt_destroy(pkt);
0158 return -EPROTO;
0159 }
0160
0161 if (layr->dn == NULL) {
0162 cfpkt_destroy(pkt);
0163 return -ENODEV;
0164
0165 }
0166 return layr->dn->transmit(layr->dn, pkt);
0167 }
0168
0169 static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
0170 int phyid)
0171 {
0172 if (layr->up && layr->up->ctrlcmd)
0173 layr->up->ctrlcmd(layr->up, ctrl, layr->id);
0174 }
0175
0176 void cffrml_put(struct cflayer *layr)
0177 {
0178 struct cffrml *this = container_obj(layr);
0179 if (layr != NULL && this->pcpu_refcnt != NULL)
0180 this_cpu_dec(*this->pcpu_refcnt);
0181 }
0182
0183 void cffrml_hold(struct cflayer *layr)
0184 {
0185 struct cffrml *this = container_obj(layr);
0186 if (layr != NULL && this->pcpu_refcnt != NULL)
0187 this_cpu_inc(*this->pcpu_refcnt);
0188 }
0189
0190 int cffrml_refcnt_read(struct cflayer *layr)
0191 {
0192 int i, refcnt = 0;
0193 struct cffrml *this = container_obj(layr);
0194 for_each_possible_cpu(i)
0195 refcnt += *per_cpu_ptr(this->pcpu_refcnt, i);
0196 return refcnt;
0197 }