aboutsummaryrefslogtreecommitdiffstats
path: root/net/caif/cffrml.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/caif/cffrml.c')
-rw-r--r--net/caif/cffrml.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index a445043931ae..04204b202718 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -12,6 +12,7 @@
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/crc-ccitt.h> 14#include <linux/crc-ccitt.h>
15#include <linux/netdevice.h>
15#include <net/caif/caif_layer.h> 16#include <net/caif/caif_layer.h>
16#include <net/caif/cfpkt.h> 17#include <net/caif/cfpkt.h>
17#include <net/caif/cffrml.h> 18#include <net/caif/cffrml.h>
@@ -21,6 +22,7 @@
21struct cffrml { 22struct cffrml {
22 struct cflayer layer; 23 struct cflayer layer;
23 bool dofcs; /* !< FCS active */ 24 bool dofcs; /* !< FCS active */
25 int __percpu *pcpu_refcnt;
24}; 26};
25 27
26static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); 28static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt);
@@ -37,6 +39,12 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
37 pr_warn("Out of memory\n"); 39 pr_warn("Out of memory\n");
38 return NULL; 40 return NULL;
39 } 41 }
42 this->pcpu_refcnt = alloc_percpu(int);
43 if (this->pcpu_refcnt == NULL) {
44 kfree(this);
45 return NULL;
46 }
47
40 caif_assert(offsetof(struct cffrml, layer) == 0); 48 caif_assert(offsetof(struct cffrml, layer) == 0);
41 49
42 memset(this, 0, sizeof(struct cflayer)); 50 memset(this, 0, sizeof(struct cflayer));
@@ -49,6 +57,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs)
49 return (struct cflayer *) this; 57 return (struct cflayer *) this;
50} 58}
51 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
52void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) 67void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up)
53{ 68{
54 this->up = up; 69 this->up = up;
@@ -112,6 +127,13 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
112 cfpkt_destroy(pkt); 127 cfpkt_destroy(pkt);
113 return -EPROTO; 128 return -EPROTO;
114 } 129 }
130
131 if (layr->up == NULL) {
132 pr_err("Layr up is missing!\n");
133 cfpkt_destroy(pkt);
134 return -EINVAL;
135 }
136
115 return layr->up->receive(layr->up, pkt); 137 return layr->up->receive(layr->up, pkt);
116} 138}
117 139
@@ -120,7 +142,6 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
120 int tmp; 142 int tmp;
121 u16 chks; 143 u16 chks;
122 u16 len; 144 u16 len;
123 int ret;
124 struct cffrml *this = container_obj(layr); 145 struct cffrml *this = container_obj(layr);
125 if (this->dofcs) { 146 if (this->dofcs) {
126 chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); 147 chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
@@ -135,19 +156,44 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
135 cfpkt_info(pkt)->hdr_len += 2; 156 cfpkt_info(pkt)->hdr_len += 2;
136 if (cfpkt_erroneous(pkt)) { 157 if (cfpkt_erroneous(pkt)) {
137 pr_err("Packet is erroneous!\n"); 158 pr_err("Packet is erroneous!\n");
159 cfpkt_destroy(pkt);
138 return -EPROTO; 160 return -EPROTO;
139 } 161 }
140 ret = layr->dn->transmit(layr->dn, pkt); 162
141 if (ret < 0) { 163 if (layr->dn == NULL) {
142 /* Remove header on faulty packet. */ 164 cfpkt_destroy(pkt);
143 cfpkt_extr_head(pkt, &tmp, 2); 165 return -ENODEV;
166
144 } 167 }
145 return ret; 168 return layr->dn->transmit(layr->dn, pkt);
146} 169}
147 170
148static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, 171static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
149 int phyid) 172 int phyid)
150{ 173{
151 if (layr->up->ctrlcmd) 174 if (layr->up && layr->up->ctrlcmd)
152 layr->up->ctrlcmd(layr->up, ctrl, layr->id); 175 layr->up->ctrlcmd(layr->up, ctrl, layr->id);
153} 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}