Blame view
net/caif/cffrml.c
4.47 KB
b482cd205 net-caif: add CAI... |
1 2 3 4 |
/* * CAIF Framing Layer. * * Copyright (C) ST-Ericsson AB 2010 |
26ee65e68 caif: Remove my b... |
5 |
* Author: Sjur Brendeland |
b482cd205 net-caif: add CAI... |
6 7 |
* License terms: GNU General Public License (GPL) version 2 */ |
b31fa5bad net/caif: Use pr_fmt |
8 |
#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ |
b482cd205 net-caif: add CAI... |
9 10 11 12 |
#include <linux/stddef.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/crc-ccitt.h> |
cb3cb423a caif: Add ref-cou... |
13 |
#include <linux/netdevice.h> |
b482cd205 net-caif: add CAI... |
14 15 16 17 18 19 20 21 22 |
#include <net/caif/caif_layer.h> #include <net/caif/cfpkt.h> #include <net/caif/cffrml.h> #define container_obj(layr) container_of(layr, struct cffrml, layer) struct cffrml { struct cflayer layer; bool dofcs; /* !< FCS active */ |
cb3cb423a caif: Add ref-cou... |
23 |
int __percpu *pcpu_refcnt; |
b482cd205 net-caif: add CAI... |
24 25 26 27 28 |
}; static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt); static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, |
3bffc475f CAIF: fix indenta... |
29 |
int phyid); |
b482cd205 net-caif: add CAI... |
30 31 32 33 34 |
static u32 cffrml_rcv_error; static u32 cffrml_rcv_checsum_error; struct cflayer *cffrml_create(u16 phyid, bool use_fcs) { |
7ac2ed0ce caif: Remove OOM ... |
35 36 |
struct cffrml *this = kzalloc(sizeof(struct cffrml), GFP_ATOMIC); if (!this) |
b482cd205 net-caif: add CAI... |
37 |
return NULL; |
cb3cb423a caif: Add ref-cou... |
38 39 40 41 42 |
this->pcpu_refcnt = alloc_percpu(int); if (this->pcpu_refcnt == NULL) { kfree(this); return NULL; } |
b482cd205 net-caif: add CAI... |
43 |
caif_assert(offsetof(struct cffrml, layer) == 0); |
b482cd205 net-caif: add CAI... |
44 45 46 47 48 49 50 51 |
this->layer.receive = cffrml_receive; this->layer.transmit = cffrml_transmit; this->layer.ctrlcmd = cffrml_ctrlcmd; snprintf(this->layer.name, CAIF_LAYER_NAME_SZ, "frm%d", phyid); this->dofcs = use_fcs; this->layer.id = phyid; return (struct cflayer *) this; } |
cb3cb423a caif: Add ref-cou... |
52 53 54 55 56 57 |
void cffrml_free(struct cflayer *layer) { struct cffrml *this = container_obj(layer); free_percpu(this->pcpu_refcnt); kfree(layer); } |
b482cd205 net-caif: add CAI... |
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) { this->up = up; } void cffrml_set_dnlayer(struct cflayer *this, struct cflayer *dn) { this->dn = dn; } static u16 cffrml_checksum(u16 chks, void *buf, u16 len) { /* FIXME: FCS should be moved to glue in order to use OS-Specific * solutions */ return crc_ccitt(chks, buf, len); } static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) { u16 tmp; u16 len; u16 hdrchks; |
278f7b4ff caif: fix a signe... |
81 |
int pktchks; |
b482cd205 net-caif: add CAI... |
82 83 84 85 86 87 88 89 90 91 92 93 |
struct cffrml *this; this = container_obj(layr); cfpkt_extr_head(pkt, &tmp, 2); len = le16_to_cpu(tmp); /* Subtract for FCS on length if FCS is not used. */ if (!this->dofcs) len -= 2; if (cfpkt_setlen(pkt, len) < 0) { ++cffrml_rcv_error; |
b31fa5bad net/caif: Use pr_fmt |
94 95 |
pr_err("Framing length error (%d) ", len); |
b482cd205 net-caif: add CAI... |
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
cfpkt_destroy(pkt); return -EPROTO; } /* * Don't do extract if FCS is false, rather do setlen - then we don't * get a cache-miss. */ if (this->dofcs) { cfpkt_extr_trail(pkt, &tmp, 2); hdrchks = le16_to_cpu(tmp); pktchks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); if (pktchks != hdrchks) { cfpkt_add_trail(pkt, &tmp, 2); ++cffrml_rcv_error; ++cffrml_rcv_checsum_error; |
b31fa5bad net/caif: Use pr_fmt |
111 112 113 |
pr_info("Frame checksum error (0x%x != 0x%x) ", hdrchks, pktchks); |
b482cd205 net-caif: add CAI... |
114 115 116 117 118 |
return -EILSEQ; } } if (cfpkt_erroneous(pkt)) { ++cffrml_rcv_error; |
b31fa5bad net/caif: Use pr_fmt |
119 120 |
pr_err("Packet is erroneous! "); |
b482cd205 net-caif: add CAI... |
121 122 123 |
cfpkt_destroy(pkt); return -EPROTO; } |
c85c2951d caif: Handle dev_... |
124 125 126 127 128 129 130 |
if (layr->up == NULL) { pr_err("Layr up is missing! "); cfpkt_destroy(pkt); return -EINVAL; } |
b482cd205 net-caif: add CAI... |
131 132 133 134 135 |
return layr->up->receive(layr->up, pkt); } static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) { |
b482cd205 net-caif: add CAI... |
136 137 |
u16 chks; u16 len; |
f23aa6254 caif: fix endian ... |
138 |
__le16 data; |
b482cd205 net-caif: add CAI... |
139 140 141 |
struct cffrml *this = container_obj(layr); if (this->dofcs) { chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); |
f23aa6254 caif: fix endian ... |
142 143 |
data = cpu_to_le16(chks); cfpkt_add_trail(pkt, &data, 2); |
b482cd205 net-caif: add CAI... |
144 145 146 147 |
} else { cfpkt_pad_trail(pkt, 2); } len = cfpkt_getlen(pkt); |
f23aa6254 caif: fix endian ... |
148 149 |
data = cpu_to_le16(len); cfpkt_add_head(pkt, &data, 2); |
b482cd205 net-caif: add CAI... |
150 151 |
cfpkt_info(pkt)->hdr_len += 2; if (cfpkt_erroneous(pkt)) { |
b31fa5bad net/caif: Use pr_fmt |
152 153 |
pr_err("Packet is erroneous! "); |
c85c2951d caif: Handle dev_... |
154 |
cfpkt_destroy(pkt); |
b482cd205 net-caif: add CAI... |
155 156 |
return -EPROTO; } |
c85c2951d caif: Handle dev_... |
157 158 159 160 161 162 |
if (layr->dn == NULL) { cfpkt_destroy(pkt); return -ENODEV; } |
4dd820c08 caif: Don't resen... |
163 |
return layr->dn->transmit(layr->dn, pkt); |
b482cd205 net-caif: add CAI... |
164 165 166 |
} static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, |
3bffc475f CAIF: fix indenta... |
167 |
int phyid) |
b482cd205 net-caif: add CAI... |
168 |
{ |
c85c2951d caif: Handle dev_... |
169 |
if (layr->up && layr->up->ctrlcmd) |
b482cd205 net-caif: add CAI... |
170 171 |
layr->up->ctrlcmd(layr->up, ctrl, layr->id); } |
0b1e9738d caif: Use rcu_rea... |
172 173 174 |
void cffrml_put(struct cflayer *layr) { |
cb3cb423a caif: Add ref-cou... |
175 176 |
struct cffrml *this = container_obj(layr); if (layr != NULL && this->pcpu_refcnt != NULL) |
933393f58 percpu: Remove ir... |
177 |
this_cpu_dec(*this->pcpu_refcnt); |
0b1e9738d caif: Use rcu_rea... |
178 179 180 181 |
} void cffrml_hold(struct cflayer *layr) { |
cb3cb423a caif: Add ref-cou... |
182 183 |
struct cffrml *this = container_obj(layr); if (layr != NULL && this->pcpu_refcnt != NULL) |
933393f58 percpu: Remove ir... |
184 |
this_cpu_inc(*this->pcpu_refcnt); |
cb3cb423a caif: Add ref-cou... |
185 186 187 188 189 190 191 192 193 |
} int cffrml_refcnt_read(struct cflayer *layr) { int i, refcnt = 0; struct cffrml *this = container_obj(layr); for_each_possible_cpu(i) refcnt += *per_cpu_ptr(this->pcpu_refcnt, i); return refcnt; |
0b1e9738d caif: Use rcu_rea... |
194 |
} |