aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif/cffrml.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/caif/cffrml.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'net/caif/cffrml.c')
-rw-r--r--net/caif/cffrml.c74
1 files changed, 61 insertions, 13 deletions
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index e86a4ca3b217..04204b202718 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -6,10 +6,13 @@
6 * License terms: GNU General Public License (GPL) version 2 6 * License terms: GNU General Public License (GPL) version 2
7 */ 7 */
8 8
9#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
10
9#include <linux/stddef.h> 11#include <linux/stddef.h>
10#include <linux/spinlock.h> 12#include <linux/spinlock.h>
11#include <linux/slab.h> 13#include <linux/slab.h>
12#include <linux/crc-ccitt.h> 14#include <linux/crc-ccitt.h>
15#include <linux/netdevice.h>
13#include <net/caif/caif_layer.h> 16#include <net/caif/caif_layer.h>
14#include <net/caif/cfpkt.h> 17#include <net/caif/cfpkt.h>
15#include <net/caif/cffrml.h> 18#include <net/caif/cffrml.h>
@@ -19,6 +22,7 @@
19struct cffrml { 22struct cffrml {
20 struct cflayer layer; 23 struct cflayer layer;
21 bool dofcs; /* !< FCS active */ 24 bool dofcs; /* !< FCS active */
25 int __percpu *pcpu_refcnt;
22}; 26};
23 27
24static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); 28static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
@@ -32,9 +36,15 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
32{ 36{
33 struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC); 37 struct cffrml *this = kmalloc(sizeof(struct cffrml), GFP_ATOMIC);
34 if (!this) { 38 if (!this) {
35 pr_warning("CAIF: %s(): Out of memory\n", __func__); 39 pr_warn("Out of memory\n");
40 return NULL;
41 }
42 this->pcpu_refcnt = alloc_percpu(int);
43 if (this->pcpu_refcnt == NULL) {
44 kfree(this);
36 return NULL; 45 return NULL;
37 } 46 }
47
38 caif_assert(offsetof(struct cffrml, layer) == 0); 48 caif_assert(offsetof(struct cffrml, layer) == 0);
39 49
40 memset(this, 0, sizeof(struct cflayer)); 50 memset(this, 0, sizeof(struct cflayer));
@@ -47,6 +57,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
47 return (struct cflayer *) this; 57 return (struct cflayer *) this;
48} 58}
49 59
60void cffrml_free(struct cflayer *layer)
61{
62 struct cffrml *this = container_obj(layer);
63 free_percpu(this->pcpu_refcnt);
64 kfree(layer);
65}
66
50void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) 67void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
51{ 68{
52 this->up = up; 69 this->up = up;
@@ -83,7 +100,7 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
83 100
84 if (cfpkt_setlen(pkt, len) < 0) { 101 if (cfpkt_setlen(pkt, len) < 0) {
85 ++cffrml_rcv_error; 102 ++cffrml_rcv_error;
86 pr_err("CAIF: %s():Framing length error (%d)\n", __func__, len); 103 pr_err("Framing length error (%d)\n", len);
87 cfpkt_destroy(pkt); 104 cfpkt_destroy(pkt);
88 return -EPROTO; 105 return -EPROTO;
89 } 106 }
@@ -99,17 +116,24 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
99 cfpkt_add_trail(pkt, &tmp, 2); 116 cfpkt_add_trail(pkt, &tmp, 2);
100 ++cffrml_rcv_error; 117 ++cffrml_rcv_error;
101 ++cffrml_rcv_checsum_error; 118 ++cffrml_rcv_checsum_error;
102 pr_info("CAIF: %s(): Frame checksum error " 119 pr_info("Frame checksum error (0x%x != 0x%x)\n",
103 "(0x%x != 0x%x)\n", __func__, hdrchks, pktchks); 120 hdrchks, pktchks);
104 return -EILSEQ; 121 return -EILSEQ;
105 } 122 }
106 } 123 }
107 if (cfpkt_erroneous(pkt)) { 124 if (cfpkt_erroneous(pkt)) {
108 ++cffrml_rcv_error; 125 ++cffrml_rcv_error;
109 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); 126 pr_err("Packet is erroneous!\n");
110 cfpkt_destroy(pkt); 127 cfpkt_destroy(pkt);
111 return -EPROTO; 128 return -EPROTO;
112 } 129 }
130
131 if (layr->up == NULL) {
132 pr_err("Layr up is missing!\n");
133 cfpkt_destroy(pkt);
134 return -EINVAL;
135 }
136
113 return layr->up->receive(layr->up, pkt); 137 return layr->up->receive(layr->up, pkt);
114} 138}
115 139
@@ -118,7 +142,6 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
118 int tmp; 142 int tmp;
119 u16 chks; 143 u16 chks;
120 u16 len; 144 u16 len;
121 int ret;
122 struct cffrml *this = container_obj(layr); 145 struct cffrml *this = container_obj(layr);
123 if (this->dofcs) { 146 if (this->dofcs) {
124 chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); 147 chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
@@ -132,20 +155,45 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
132 cfpkt_add_head(pkt, &tmp, 2); 155 cfpkt_add_head(pkt, &tmp, 2);
133 cfpkt_info(pkt)->hdr_len += 2; 156 cfpkt_info(pkt)->hdr_len += 2;
134 if (cfpkt_erroneous(pkt)) { 157 if (cfpkt_erroneous(pkt)) {
135 pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); 158 pr_err("Packet is erroneous!\n");
159 cfpkt_destroy(pkt);
136 return -EPROTO; 160 return -EPROTO;
137 } 161 }
138 ret = layr->dn->transmit(layr->dn, pkt); 162
139 if (ret < 0) { 163 if (layr->dn == NULL) {
140 /* Remove header on faulty packet. */ 164 cfpkt_destroy(pkt);
141 cfpkt_extr_head(pkt, &tmp, 2); 165 return -ENODEV;
166
142 } 167 }
143 return ret; 168 return layr->dn->transmit(layr->dn, pkt);
144} 169}
145 170
146static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, 171static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
147 int phyid) 172 int phyid)
148{ 173{
149 if (layr->up->ctrlcmd) 174 if (layr->up && layr->up->ctrlcmd)
150 layr->up->ctrlcmd(layr->up, ctrl, layr->id); 175 layr->up->ctrlcmd(layr->up, ctrl, layr->id);
151} 176}
177
178void cffrml_put(struct cflayer *layr)
179{
180 struct cffrml *this = container_obj(layr);
181 if (layr != NULL && this->pcpu_refcnt != NULL)
182 irqsafe_cpu_dec(*this->pcpu_refcnt);
183}
184
185void cffrml_hold(struct cflayer *layr)
186{
187 struct cffrml *this = container_obj(layr);
188 if (layr != NULL && this->pcpu_refcnt != NULL)
189 irqsafe_cpu_inc(*this->pcpu_refcnt);
190}
191
192int cffrml_refcnt_read(struct cflayer *layr)
193{
194 int i, refcnt = 0;
195 struct cffrml *this = container_obj(layr);
196 for_each_possible_cpu(i)
197 refcnt += *per_cpu_ptr(this->pcpu_refcnt, i);
198 return refcnt;
199}