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
9 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
11 #include <linux/stddef.h>
12 #include <linux/spinlock.h>
13 #include <linux/slab.h>
14 #include <linux/crc-ccitt.h>
15 #include <net/caif/caif_layer.h>
16 #include <net/caif/cfpkt.h>
17 #include <net/caif/cffrml.h>
19 #define container_obj(layr) container_of(layr, struct cffrml, layer)
23 bool dofcs
; /* !< FCS active */
26 static int cffrml_receive(struct cflayer
*layr
, struct cfpkt
*pkt
);
27 static int cffrml_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
);
28 static void cffrml_ctrlcmd(struct cflayer
*layr
, enum caif_ctrlcmd ctrl
,
31 static u32 cffrml_rcv_error
;
32 static u32 cffrml_rcv_checsum_error
;
33 struct cflayer
*cffrml_create(u16 phyid
, bool use_fcs
)
35 struct cffrml
*this = kmalloc(sizeof(struct cffrml
), GFP_ATOMIC
);
37 pr_warn("Out of memory\n");
40 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;
52 void cffrml_set_uplayer(struct cflayer
*this, struct cflayer
*up
)
57 void cffrml_set_dnlayer(struct cflayer
*this, struct cflayer
*dn
)
62 static u16
cffrml_checksum(u16 chks
, void *buf
, u16 len
)
64 /* FIXME: FCS should be moved to glue in order to use OS-Specific
67 return crc_ccitt(chks
, buf
, len
);
70 static int cffrml_receive(struct cflayer
*layr
, struct cfpkt
*pkt
)
77 this = container_obj(layr
);
79 cfpkt_extr_head(pkt
, &tmp
, 2);
80 len
= le16_to_cpu(tmp
);
82 /* Subtract for FCS on length if FCS is not used. */
86 if (cfpkt_setlen(pkt
, len
) < 0) {
88 pr_err("Framing length error (%d)\n", len
);
93 * Don't do extract if FCS is false, rather do setlen - then we don't
97 cfpkt_extr_trail(pkt
, &tmp
, 2);
98 hdrchks
= le16_to_cpu(tmp
);
99 pktchks
= cfpkt_iterate(pkt
, cffrml_checksum
, 0xffff);
100 if (pktchks
!= hdrchks
) {
101 cfpkt_add_trail(pkt
, &tmp
, 2);
103 ++cffrml_rcv_checsum_error
;
104 pr_info("Frame checksum error (0x%x != 0x%x)\n",
109 if (cfpkt_erroneous(pkt
)) {
111 pr_err("Packet is erroneous!\n");
115 return layr
->up
->receive(layr
->up
, pkt
);
118 static int cffrml_transmit(struct cflayer
*layr
, struct cfpkt
*pkt
)
124 struct cffrml
*this = container_obj(layr
);
126 chks
= cfpkt_iterate(pkt
, cffrml_checksum
, 0xffff);
127 tmp
= cpu_to_le16(chks
);
128 cfpkt_add_trail(pkt
, &tmp
, 2);
130 cfpkt_pad_trail(pkt
, 2);
132 len
= cfpkt_getlen(pkt
);
133 tmp
= cpu_to_le16(len
);
134 cfpkt_add_head(pkt
, &tmp
, 2);
135 cfpkt_info(pkt
)->hdr_len
+= 2;
136 if (cfpkt_erroneous(pkt
)) {
137 pr_err("Packet is erroneous!\n");
140 ret
= layr
->dn
->transmit(layr
->dn
, pkt
);
142 /* Remove header on faulty packet. */
143 cfpkt_extr_head(pkt
, &tmp
, 2);
148 static void cffrml_ctrlcmd(struct cflayer
*layr
, enum caif_ctrlcmd ctrl
,
151 if (layr
->up
->ctrlcmd
)
152 layr
->up
->ctrlcmd(layr
->up
, ctrl
, layr
->id
);