diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/caif/cffrml.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 74 |
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 @@ | |||
19 | struct cffrml { | 22 | struct 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 | ||
24 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); | 28 | static 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 | ||
60 | void cffrml_free(struct cflayer *layer) | ||
61 | { | ||
62 | struct cffrml *this = container_obj(layer); | ||
63 | free_percpu(this->pcpu_refcnt); | ||
64 | kfree(layer); | ||
65 | } | ||
66 | |||
50 | void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) | 67 | void 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 | ||
146 | static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | 171 | static 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 | |||
178 | void 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 | |||
185 | void 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 | |||
192 | int 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 | } | ||