diff options
Diffstat (limited to 'net/caif/cfpkt_skbuff.c')
-rw-r--r-- | net/caif/cfpkt_skbuff.c | 243 |
1 files changed, 32 insertions, 211 deletions
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index c49a6695793a..75d4bfae1a78 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * License terms: GNU General Public License (GPL) version 2 | 4 | * License terms: GNU General Public License (GPL) version 2 |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ | ||
8 | |||
7 | #include <linux/string.h> | 9 | #include <linux/string.h> |
8 | #include <linux/skbuff.h> | 10 | #include <linux/skbuff.h> |
9 | #include <linux/hardirq.h> | 11 | #include <linux/hardirq.h> |
@@ -12,11 +14,12 @@ | |||
12 | #define PKT_PREFIX 48 | 14 | #define PKT_PREFIX 48 |
13 | #define PKT_POSTFIX 2 | 15 | #define PKT_POSTFIX 2 |
14 | #define PKT_LEN_WHEN_EXTENDING 128 | 16 | #define PKT_LEN_WHEN_EXTENDING 128 |
15 | #define PKT_ERROR(pkt, errmsg) do { \ | 17 | #define PKT_ERROR(pkt, errmsg) \ |
16 | cfpkt_priv(pkt)->erronous = true; \ | 18 | do { \ |
17 | skb_reset_tail_pointer(&pkt->skb); \ | 19 | cfpkt_priv(pkt)->erronous = true; \ |
18 | pr_warning("CAIF: " errmsg);\ | 20 | skb_reset_tail_pointer(&pkt->skb); \ |
19 | } while (0) | 21 | pr_warn(errmsg); \ |
22 | } while (0) | ||
20 | 23 | ||
21 | struct cfpktq { | 24 | struct cfpktq { |
22 | struct sk_buff_head head; | 25 | struct sk_buff_head head; |
@@ -39,22 +42,22 @@ struct cfpkt_priv_data { | |||
39 | bool erronous; | 42 | bool erronous; |
40 | }; | 43 | }; |
41 | 44 | ||
42 | inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) | 45 | static inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) |
43 | { | 46 | { |
44 | return (struct cfpkt_priv_data *) pkt->skb.cb; | 47 | return (struct cfpkt_priv_data *) pkt->skb.cb; |
45 | } | 48 | } |
46 | 49 | ||
47 | inline bool is_erronous(struct cfpkt *pkt) | 50 | static inline bool is_erronous(struct cfpkt *pkt) |
48 | { | 51 | { |
49 | return cfpkt_priv(pkt)->erronous; | 52 | return cfpkt_priv(pkt)->erronous; |
50 | } | 53 | } |
51 | 54 | ||
52 | inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) | 55 | static inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) |
53 | { | 56 | { |
54 | return &pkt->skb; | 57 | return &pkt->skb; |
55 | } | 58 | } |
56 | 59 | ||
57 | inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) | 60 | static inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) |
58 | { | 61 | { |
59 | return (struct cfpkt *) skb; | 62 | return (struct cfpkt *) skb; |
60 | } | 63 | } |
@@ -94,21 +97,20 @@ inline struct cfpkt *cfpkt_create(u16 len) | |||
94 | { | 97 | { |
95 | return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | 98 | return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); |
96 | } | 99 | } |
97 | EXPORT_SYMBOL(cfpkt_create); | ||
98 | 100 | ||
99 | void cfpkt_destroy(struct cfpkt *pkt) | 101 | void cfpkt_destroy(struct cfpkt *pkt) |
100 | { | 102 | { |
101 | struct sk_buff *skb = pkt_to_skb(pkt); | 103 | struct sk_buff *skb = pkt_to_skb(pkt); |
102 | kfree_skb(skb); | 104 | kfree_skb(skb); |
103 | } | 105 | } |
104 | EXPORT_SYMBOL(cfpkt_destroy); | 106 | |
105 | 107 | ||
106 | inline bool cfpkt_more(struct cfpkt *pkt) | 108 | inline bool cfpkt_more(struct cfpkt *pkt) |
107 | { | 109 | { |
108 | struct sk_buff *skb = pkt_to_skb(pkt); | 110 | struct sk_buff *skb = pkt_to_skb(pkt); |
109 | return skb->len > 0; | 111 | return skb->len > 0; |
110 | } | 112 | } |
111 | EXPORT_SYMBOL(cfpkt_more); | 113 | |
112 | 114 | ||
113 | int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) | 115 | int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) |
114 | { | 116 | { |
@@ -120,7 +122,6 @@ int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) | |||
120 | return !cfpkt_extr_head(pkt, data, len) && | 122 | return !cfpkt_extr_head(pkt, data, len) && |
121 | !cfpkt_add_head(pkt, data, len); | 123 | !cfpkt_add_head(pkt, data, len); |
122 | } | 124 | } |
123 | EXPORT_SYMBOL(cfpkt_peek_head); | ||
124 | 125 | ||
125 | int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) | 126 | int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) |
126 | { | 127 | { |
@@ -130,13 +131,13 @@ int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) | |||
130 | return -EPROTO; | 131 | return -EPROTO; |
131 | 132 | ||
132 | if (unlikely(len > skb->len)) { | 133 | if (unlikely(len > skb->len)) { |
133 | PKT_ERROR(pkt, "cfpkt_extr_head read beyond end of packet\n"); | 134 | PKT_ERROR(pkt, "read beyond end of packet\n"); |
134 | return -EPROTO; | 135 | return -EPROTO; |
135 | } | 136 | } |
136 | 137 | ||
137 | if (unlikely(len > skb_headlen(skb))) { | 138 | if (unlikely(len > skb_headlen(skb))) { |
138 | if (unlikely(skb_linearize(skb) != 0)) { | 139 | if (unlikely(skb_linearize(skb) != 0)) { |
139 | PKT_ERROR(pkt, "cfpkt_extr_head linearize failed\n"); | 140 | PKT_ERROR(pkt, "linearize failed\n"); |
140 | return -EPROTO; | 141 | return -EPROTO; |
141 | } | 142 | } |
142 | } | 143 | } |
@@ -145,7 +146,6 @@ int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) | |||
145 | memcpy(data, from, len); | 146 | memcpy(data, from, len); |
146 | return 0; | 147 | return 0; |
147 | } | 148 | } |
148 | EXPORT_SYMBOL(cfpkt_extr_head); | ||
149 | 149 | ||
150 | int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) | 150 | int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) |
151 | { | 151 | { |
@@ -156,11 +156,11 @@ int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) | |||
156 | return -EPROTO; | 156 | return -EPROTO; |
157 | 157 | ||
158 | if (unlikely(skb_linearize(skb) != 0)) { | 158 | if (unlikely(skb_linearize(skb) != 0)) { |
159 | PKT_ERROR(pkt, "cfpkt_extr_trail linearize failed\n"); | 159 | PKT_ERROR(pkt, "linearize failed\n"); |
160 | return -EPROTO; | 160 | return -EPROTO; |
161 | } | 161 | } |
162 | if (unlikely(skb->data + len > skb_tail_pointer(skb))) { | 162 | if (unlikely(skb->data + len > skb_tail_pointer(skb))) { |
163 | PKT_ERROR(pkt, "cfpkt_extr_trail read beyond end of packet\n"); | 163 | PKT_ERROR(pkt, "read beyond end of packet\n"); |
164 | return -EPROTO; | 164 | return -EPROTO; |
165 | } | 165 | } |
166 | from = skb_tail_pointer(skb) - len; | 166 | from = skb_tail_pointer(skb) - len; |
@@ -168,13 +168,13 @@ int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) | |||
168 | memcpy(data, from, len); | 168 | memcpy(data, from, len); |
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | EXPORT_SYMBOL(cfpkt_extr_trail); | 171 | |
172 | 172 | ||
173 | int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) | 173 | int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) |
174 | { | 174 | { |
175 | return cfpkt_add_body(pkt, NULL, len); | 175 | return cfpkt_add_body(pkt, NULL, len); |
176 | } | 176 | } |
177 | EXPORT_SYMBOL(cfpkt_pad_trail); | 177 | |
178 | 178 | ||
179 | int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | 179 | int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) |
180 | { | 180 | { |
@@ -202,7 +202,7 @@ int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | |||
202 | 202 | ||
203 | /* Make sure data is writable */ | 203 | /* Make sure data is writable */ |
204 | if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) { | 204 | if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) { |
205 | PKT_ERROR(pkt, "cfpkt_add_body: cow failed\n"); | 205 | PKT_ERROR(pkt, "cow failed\n"); |
206 | return -EPROTO; | 206 | return -EPROTO; |
207 | } | 207 | } |
208 | /* | 208 | /* |
@@ -211,8 +211,7 @@ int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | |||
211 | * lengths of the top SKB. | 211 | * lengths of the top SKB. |
212 | */ | 212 | */ |
213 | if (lastskb != skb) { | 213 | if (lastskb != skb) { |
214 | pr_warning("CAIF: %s(): Packet is non-linear\n", | 214 | pr_warn("Packet is non-linear\n"); |
215 | __func__); | ||
216 | skb->len += len; | 215 | skb->len += len; |
217 | skb->data_len += len; | 216 | skb->data_len += len; |
218 | } | 217 | } |
@@ -224,13 +223,11 @@ int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | |||
224 | memcpy(to, data, len); | 223 | memcpy(to, data, len); |
225 | return 0; | 224 | return 0; |
226 | } | 225 | } |
227 | EXPORT_SYMBOL(cfpkt_add_body); | ||
228 | 226 | ||
229 | inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) | 227 | inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) |
230 | { | 228 | { |
231 | return cfpkt_add_body(pkt, &data, 1); | 229 | return cfpkt_add_body(pkt, &data, 1); |
232 | } | 230 | } |
233 | EXPORT_SYMBOL(cfpkt_addbdy); | ||
234 | 231 | ||
235 | int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | 232 | int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) |
236 | { | 233 | { |
@@ -242,14 +239,14 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | |||
242 | if (unlikely(is_erronous(pkt))) | 239 | if (unlikely(is_erronous(pkt))) |
243 | return -EPROTO; | 240 | return -EPROTO; |
244 | if (unlikely(skb_headroom(skb) < len)) { | 241 | if (unlikely(skb_headroom(skb) < len)) { |
245 | PKT_ERROR(pkt, "cfpkt_add_head: no headroom\n"); | 242 | PKT_ERROR(pkt, "no headroom\n"); |
246 | return -EPROTO; | 243 | return -EPROTO; |
247 | } | 244 | } |
248 | 245 | ||
249 | /* Make sure data is writable */ | 246 | /* Make sure data is writable */ |
250 | ret = skb_cow_data(skb, 0, &lastskb); | 247 | ret = skb_cow_data(skb, 0, &lastskb); |
251 | if (unlikely(ret < 0)) { | 248 | if (unlikely(ret < 0)) { |
252 | PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n"); | 249 | PKT_ERROR(pkt, "cow failed\n"); |
253 | return ret; | 250 | return ret; |
254 | } | 251 | } |
255 | 252 | ||
@@ -257,20 +254,20 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | |||
257 | memcpy(to, data, len); | 254 | memcpy(to, data, len); |
258 | return 0; | 255 | return 0; |
259 | } | 256 | } |
260 | EXPORT_SYMBOL(cfpkt_add_head); | 257 | |
261 | 258 | ||
262 | inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) | 259 | inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) |
263 | { | 260 | { |
264 | return cfpkt_add_body(pkt, data, len); | 261 | return cfpkt_add_body(pkt, data, len); |
265 | } | 262 | } |
266 | EXPORT_SYMBOL(cfpkt_add_trail); | 263 | |
267 | 264 | ||
268 | inline u16 cfpkt_getlen(struct cfpkt *pkt) | 265 | inline u16 cfpkt_getlen(struct cfpkt *pkt) |
269 | { | 266 | { |
270 | struct sk_buff *skb = pkt_to_skb(pkt); | 267 | struct sk_buff *skb = pkt_to_skb(pkt); |
271 | return skb->len; | 268 | return skb->len; |
272 | } | 269 | } |
273 | EXPORT_SYMBOL(cfpkt_getlen); | 270 | |
274 | 271 | ||
275 | inline u16 cfpkt_iterate(struct cfpkt *pkt, | 272 | inline u16 cfpkt_iterate(struct cfpkt *pkt, |
276 | u16 (*iter_func)(u16, void *, u16), | 273 | u16 (*iter_func)(u16, void *, u16), |
@@ -283,12 +280,12 @@ inline u16 cfpkt_iterate(struct cfpkt *pkt, | |||
283 | if (unlikely(is_erronous(pkt))) | 280 | if (unlikely(is_erronous(pkt))) |
284 | return -EPROTO; | 281 | return -EPROTO; |
285 | if (unlikely(skb_linearize(&pkt->skb) != 0)) { | 282 | if (unlikely(skb_linearize(&pkt->skb) != 0)) { |
286 | PKT_ERROR(pkt, "cfpkt_iterate: linearize failed\n"); | 283 | PKT_ERROR(pkt, "linearize failed\n"); |
287 | return -EPROTO; | 284 | return -EPROTO; |
288 | } | 285 | } |
289 | return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); | 286 | return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); |
290 | } | 287 | } |
291 | EXPORT_SYMBOL(cfpkt_iterate); | 288 | |
292 | 289 | ||
293 | int cfpkt_setlen(struct cfpkt *pkt, u16 len) | 290 | int cfpkt_setlen(struct cfpkt *pkt, u16 len) |
294 | { | 291 | { |
@@ -309,22 +306,10 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len) | |||
309 | 306 | ||
310 | /* Need to expand SKB */ | 307 | /* Need to expand SKB */ |
311 | if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len))) | 308 | if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len))) |
312 | PKT_ERROR(pkt, "cfpkt_setlen: skb_pad_trail failed\n"); | 309 | PKT_ERROR(pkt, "skb_pad_trail failed\n"); |
313 | 310 | ||
314 | return cfpkt_getlen(pkt); | 311 | return cfpkt_getlen(pkt); |
315 | } | 312 | } |
316 | EXPORT_SYMBOL(cfpkt_setlen); | ||
317 | |||
318 | struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) | ||
319 | { | ||
320 | struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | ||
321 | if (!pkt) | ||
322 | return NULL; | ||
323 | if (unlikely(data != NULL)) | ||
324 | cfpkt_add_body(pkt, data, len); | ||
325 | return pkt; | ||
326 | } | ||
327 | EXPORT_SYMBOL(cfpkt_create_uplink); | ||
328 | 313 | ||
329 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | 314 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, |
330 | struct cfpkt *addpkt, | 315 | struct cfpkt *addpkt, |
@@ -366,7 +351,6 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | |||
366 | dst->len += addlen; | 351 | dst->len += addlen; |
367 | return skb_to_pkt(dst); | 352 | return skb_to_pkt(dst); |
368 | } | 353 | } |
369 | EXPORT_SYMBOL(cfpkt_append); | ||
370 | 354 | ||
371 | struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | 355 | struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) |
372 | { | 356 | { |
@@ -380,8 +364,7 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | |||
380 | return NULL; | 364 | return NULL; |
381 | 365 | ||
382 | if (skb->data + pos > skb_tail_pointer(skb)) { | 366 | if (skb->data + pos > skb_tail_pointer(skb)) { |
383 | PKT_ERROR(pkt, | 367 | PKT_ERROR(pkt, "trying to split beyond end of packet\n"); |
384 | "cfpkt_split: trying to split beyond end of packet"); | ||
385 | return NULL; | 368 | return NULL; |
386 | } | 369 | } |
387 | 370 | ||
@@ -405,175 +388,13 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | |||
405 | skb2->len += len2nd; | 388 | skb2->len += len2nd; |
406 | return skb_to_pkt(skb2); | 389 | return skb_to_pkt(skb2); |
407 | } | 390 | } |
408 | EXPORT_SYMBOL(cfpkt_split); | ||
409 | |||
410 | char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen) | ||
411 | { | ||
412 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
413 | char *p = buf; | ||
414 | int i; | ||
415 | |||
416 | /* | ||
417 | * Sanity check buffer length, it needs to be at least as large as | ||
418 | * the header info: ~=50+ bytes | ||
419 | */ | ||
420 | if (buflen < 50) | ||
421 | return NULL; | ||
422 | |||
423 | snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [", | ||
424 | is_erronous(pkt) ? "ERRONOUS-SKB" : | ||
425 | (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"), | ||
426 | skb, | ||
427 | (long) skb->len, | ||
428 | (long) (skb_tail_pointer(skb) - skb->data), | ||
429 | (long) skb->data_len, | ||
430 | (long) (skb->data - skb->head), | ||
431 | (long) (skb_tail_pointer(skb) - skb->head)); | ||
432 | p = buf + strlen(buf); | ||
433 | |||
434 | for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) { | ||
435 | if (p > buf + buflen - 10) { | ||
436 | sprintf(p, "..."); | ||
437 | p = buf + strlen(buf); | ||
438 | break; | ||
439 | } | ||
440 | sprintf(p, "%02x,", skb->data[i]); | ||
441 | p = buf + strlen(buf); | ||
442 | } | ||
443 | sprintf(p, "]\n"); | ||
444 | return buf; | ||
445 | } | ||
446 | EXPORT_SYMBOL(cfpkt_log_pkt); | ||
447 | 391 | ||
448 | int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen) | 392 | bool cfpkt_erroneous(struct cfpkt *pkt) |
449 | { | ||
450 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
451 | struct sk_buff *lastskb; | ||
452 | |||
453 | caif_assert(buf != NULL); | ||
454 | if (unlikely(is_erronous(pkt))) | ||
455 | return -EPROTO; | ||
456 | /* Make sure SKB is writable */ | ||
457 | if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { | ||
458 | PKT_ERROR(pkt, "cfpkt_raw_append: skb_cow_data failed\n"); | ||
459 | return -EPROTO; | ||
460 | } | ||
461 | |||
462 | if (unlikely(skb_linearize(skb) != 0)) { | ||
463 | PKT_ERROR(pkt, "cfpkt_raw_append: linearize failed\n"); | ||
464 | return -EPROTO; | ||
465 | } | ||
466 | |||
467 | if (unlikely(skb_tailroom(skb) < buflen)) { | ||
468 | PKT_ERROR(pkt, "cfpkt_raw_append: buffer too short - failed\n"); | ||
469 | return -EPROTO; | ||
470 | } | ||
471 | |||
472 | *buf = skb_put(skb, buflen); | ||
473 | return 1; | ||
474 | } | ||
475 | EXPORT_SYMBOL(cfpkt_raw_append); | ||
476 | |||
477 | int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen) | ||
478 | { | ||
479 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
480 | |||
481 | caif_assert(buf != NULL); | ||
482 | if (unlikely(is_erronous(pkt))) | ||
483 | return -EPROTO; | ||
484 | |||
485 | if (unlikely(buflen > skb->len)) { | ||
486 | PKT_ERROR(pkt, "cfpkt_raw_extract: buflen too large " | ||
487 | "- failed\n"); | ||
488 | return -EPROTO; | ||
489 | } | ||
490 | |||
491 | if (unlikely(buflen > skb_headlen(skb))) { | ||
492 | if (unlikely(skb_linearize(skb) != 0)) { | ||
493 | PKT_ERROR(pkt, "cfpkt_raw_extract: linearize failed\n"); | ||
494 | return -EPROTO; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | *buf = skb->data; | ||
499 | skb_pull(skb, buflen); | ||
500 | |||
501 | return 1; | ||
502 | } | ||
503 | EXPORT_SYMBOL(cfpkt_raw_extract); | ||
504 | |||
505 | inline bool cfpkt_erroneous(struct cfpkt *pkt) | ||
506 | { | 393 | { |
507 | return cfpkt_priv(pkt)->erronous; | 394 | return cfpkt_priv(pkt)->erronous; |
508 | } | 395 | } |
509 | EXPORT_SYMBOL(cfpkt_erroneous); | ||
510 | |||
511 | struct cfpktq *cfpktq_create(void) | ||
512 | { | ||
513 | struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC); | ||
514 | if (!q) | ||
515 | return NULL; | ||
516 | skb_queue_head_init(&q->head); | ||
517 | atomic_set(&q->count, 0); | ||
518 | spin_lock_init(&q->lock); | ||
519 | return q; | ||
520 | } | ||
521 | EXPORT_SYMBOL(cfpktq_create); | ||
522 | |||
523 | void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio) | ||
524 | { | ||
525 | atomic_inc(&pktq->count); | ||
526 | spin_lock(&pktq->lock); | ||
527 | skb_queue_tail(&pktq->head, pkt_to_skb(pkt)); | ||
528 | spin_unlock(&pktq->lock); | ||
529 | |||
530 | } | ||
531 | EXPORT_SYMBOL(cfpkt_queue); | ||
532 | |||
533 | struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq) | ||
534 | { | ||
535 | struct cfpkt *tmp; | ||
536 | spin_lock(&pktq->lock); | ||
537 | tmp = skb_to_pkt(skb_peek(&pktq->head)); | ||
538 | spin_unlock(&pktq->lock); | ||
539 | return tmp; | ||
540 | } | ||
541 | EXPORT_SYMBOL(cfpkt_qpeek); | ||
542 | |||
543 | struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq) | ||
544 | { | ||
545 | struct cfpkt *pkt; | ||
546 | spin_lock(&pktq->lock); | ||
547 | pkt = skb_to_pkt(skb_dequeue(&pktq->head)); | ||
548 | if (pkt) { | ||
549 | atomic_dec(&pktq->count); | ||
550 | caif_assert(atomic_read(&pktq->count) >= 0); | ||
551 | } | ||
552 | spin_unlock(&pktq->lock); | ||
553 | return pkt; | ||
554 | } | ||
555 | EXPORT_SYMBOL(cfpkt_dequeue); | ||
556 | |||
557 | int cfpkt_qcount(struct cfpktq *pktq) | ||
558 | { | ||
559 | return atomic_read(&pktq->count); | ||
560 | } | ||
561 | EXPORT_SYMBOL(cfpkt_qcount); | ||
562 | |||
563 | struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt) | ||
564 | { | ||
565 | struct cfpkt *clone; | ||
566 | clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC)); | ||
567 | /* Free original packet. */ | ||
568 | cfpkt_destroy(pkt); | ||
569 | if (!clone) | ||
570 | return NULL; | ||
571 | return clone; | ||
572 | } | ||
573 | EXPORT_SYMBOL(cfpkt_clone_release); | ||
574 | 396 | ||
575 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) | 397 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) |
576 | { | 398 | { |
577 | return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; | 399 | return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; |
578 | } | 400 | } |
579 | EXPORT_SYMBOL(cfpkt_info); | ||