xref: /OK3568_Linux_fs/kernel/net/caif/cfpkt_skbuff.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) ST-Ericsson AB 2010
4*4882a593Smuzhiyun  * Author:	Sjur Brendeland
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/string.h>
10*4882a593Smuzhiyun #include <linux/skbuff.h>
11*4882a593Smuzhiyun #include <linux/export.h>
12*4882a593Smuzhiyun #include <net/caif/cfpkt.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define PKT_PREFIX  48
15*4882a593Smuzhiyun #define PKT_POSTFIX 2
16*4882a593Smuzhiyun #define PKT_LEN_WHEN_EXTENDING 128
17*4882a593Smuzhiyun #define PKT_ERROR(pkt, errmsg)		   \
18*4882a593Smuzhiyun do {					   \
19*4882a593Smuzhiyun 	cfpkt_priv(pkt)->erronous = true;  \
20*4882a593Smuzhiyun 	skb_reset_tail_pointer(&pkt->skb); \
21*4882a593Smuzhiyun 	pr_warn(errmsg);		   \
22*4882a593Smuzhiyun } while (0)
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun struct cfpktq {
25*4882a593Smuzhiyun 	struct sk_buff_head head;
26*4882a593Smuzhiyun 	atomic_t count;
27*4882a593Smuzhiyun 	/* Lock protects count updates */
28*4882a593Smuzhiyun 	spinlock_t lock;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun  * net/caif/ is generic and does not
33*4882a593Smuzhiyun  * understand SKB, so we do this typecast
34*4882a593Smuzhiyun  */
35*4882a593Smuzhiyun struct cfpkt {
36*4882a593Smuzhiyun 	struct sk_buff skb;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* Private data inside SKB */
40*4882a593Smuzhiyun struct cfpkt_priv_data {
41*4882a593Smuzhiyun 	struct dev_info dev_info;
42*4882a593Smuzhiyun 	bool erronous;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
cfpkt_priv(struct cfpkt * pkt)45*4882a593Smuzhiyun static inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	return (struct cfpkt_priv_data *) pkt->skb.cb;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun 
is_erronous(struct cfpkt * pkt)50*4882a593Smuzhiyun static inline bool is_erronous(struct cfpkt *pkt)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	return cfpkt_priv(pkt)->erronous;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
pkt_to_skb(struct cfpkt * pkt)55*4882a593Smuzhiyun static inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	return &pkt->skb;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
skb_to_pkt(struct sk_buff * skb)60*4882a593Smuzhiyun static inline struct cfpkt *skb_to_pkt(struct sk_buff *skb)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	return (struct cfpkt *) skb;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
cfpkt_fromnative(enum caif_direction dir,void * nativepkt)65*4882a593Smuzhiyun struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	struct cfpkt *pkt = skb_to_pkt(nativepkt);
68*4882a593Smuzhiyun 	cfpkt_priv(pkt)->erronous = false;
69*4882a593Smuzhiyun 	return pkt;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun EXPORT_SYMBOL(cfpkt_fromnative);
72*4882a593Smuzhiyun 
cfpkt_tonative(struct cfpkt * pkt)73*4882a593Smuzhiyun void *cfpkt_tonative(struct cfpkt *pkt)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	return (void *) pkt;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun EXPORT_SYMBOL(cfpkt_tonative);
78*4882a593Smuzhiyun 
cfpkt_create_pfx(u16 len,u16 pfx)79*4882a593Smuzhiyun static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	struct sk_buff *skb;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	skb = alloc_skb(len + pfx, GFP_ATOMIC);
84*4882a593Smuzhiyun 	if (unlikely(skb == NULL))
85*4882a593Smuzhiyun 		return NULL;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	skb_reserve(skb, pfx);
88*4882a593Smuzhiyun 	return skb_to_pkt(skb);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
cfpkt_create(u16 len)91*4882a593Smuzhiyun inline struct cfpkt *cfpkt_create(u16 len)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
cfpkt_destroy(struct cfpkt * pkt)96*4882a593Smuzhiyun void cfpkt_destroy(struct cfpkt *pkt)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
99*4882a593Smuzhiyun 	kfree_skb(skb);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
cfpkt_more(struct cfpkt * pkt)102*4882a593Smuzhiyun inline bool cfpkt_more(struct cfpkt *pkt)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
105*4882a593Smuzhiyun 	return skb->len > 0;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
cfpkt_peek_head(struct cfpkt * pkt,void * data,u16 len)108*4882a593Smuzhiyun int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
111*4882a593Smuzhiyun 	if (skb_headlen(skb) >= len) {
112*4882a593Smuzhiyun 		memcpy(data, skb->data, len);
113*4882a593Smuzhiyun 		return 0;
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 	return !cfpkt_extr_head(pkt, data, len) &&
116*4882a593Smuzhiyun 	    !cfpkt_add_head(pkt, data, len);
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
cfpkt_extr_head(struct cfpkt * pkt,void * data,u16 len)119*4882a593Smuzhiyun int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
122*4882a593Smuzhiyun 	u8 *from;
123*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
124*4882a593Smuzhiyun 		return -EPROTO;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	if (unlikely(len > skb->len)) {
127*4882a593Smuzhiyun 		PKT_ERROR(pkt, "read beyond end of packet\n");
128*4882a593Smuzhiyun 		return -EPROTO;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	if (unlikely(len > skb_headlen(skb))) {
132*4882a593Smuzhiyun 		if (unlikely(skb_linearize(skb) != 0)) {
133*4882a593Smuzhiyun 			PKT_ERROR(pkt, "linearize failed\n");
134*4882a593Smuzhiyun 			return -EPROTO;
135*4882a593Smuzhiyun 		}
136*4882a593Smuzhiyun 	}
137*4882a593Smuzhiyun 	from = skb_pull(skb, len);
138*4882a593Smuzhiyun 	from -= len;
139*4882a593Smuzhiyun 	if (data)
140*4882a593Smuzhiyun 		memcpy(data, from, len);
141*4882a593Smuzhiyun 	return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun EXPORT_SYMBOL(cfpkt_extr_head);
144*4882a593Smuzhiyun 
cfpkt_extr_trail(struct cfpkt * pkt,void * dta,u16 len)145*4882a593Smuzhiyun int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
148*4882a593Smuzhiyun 	u8 *data = dta;
149*4882a593Smuzhiyun 	u8 *from;
150*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
151*4882a593Smuzhiyun 		return -EPROTO;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (unlikely(skb_linearize(skb) != 0)) {
154*4882a593Smuzhiyun 		PKT_ERROR(pkt, "linearize failed\n");
155*4882a593Smuzhiyun 		return -EPROTO;
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun 	if (unlikely(skb->data + len > skb_tail_pointer(skb))) {
158*4882a593Smuzhiyun 		PKT_ERROR(pkt, "read beyond end of packet\n");
159*4882a593Smuzhiyun 		return -EPROTO;
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 	from = skb_tail_pointer(skb) - len;
162*4882a593Smuzhiyun 	skb_trim(skb, skb->len - len);
163*4882a593Smuzhiyun 	memcpy(data, from, len);
164*4882a593Smuzhiyun 	return 0;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
cfpkt_pad_trail(struct cfpkt * pkt,u16 len)167*4882a593Smuzhiyun int cfpkt_pad_trail(struct cfpkt *pkt, u16 len)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	return cfpkt_add_body(pkt, NULL, len);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
cfpkt_add_body(struct cfpkt * pkt,const void * data,u16 len)172*4882a593Smuzhiyun int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
175*4882a593Smuzhiyun 	struct sk_buff *lastskb;
176*4882a593Smuzhiyun 	u8 *to;
177*4882a593Smuzhiyun 	u16 addlen = 0;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
181*4882a593Smuzhiyun 		return -EPROTO;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	lastskb = skb;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* Check whether we need to add space at the tail */
186*4882a593Smuzhiyun 	if (unlikely(skb_tailroom(skb) < len)) {
187*4882a593Smuzhiyun 		if (likely(len < PKT_LEN_WHEN_EXTENDING))
188*4882a593Smuzhiyun 			addlen = PKT_LEN_WHEN_EXTENDING;
189*4882a593Smuzhiyun 		else
190*4882a593Smuzhiyun 			addlen = len;
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/* Check whether we need to change the SKB before writing to the tail */
194*4882a593Smuzhiyun 	if (unlikely((addlen > 0) || skb_cloned(skb) || skb_shared(skb))) {
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 		/* Make sure data is writable */
197*4882a593Smuzhiyun 		if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) {
198*4882a593Smuzhiyun 			PKT_ERROR(pkt, "cow failed\n");
199*4882a593Smuzhiyun 			return -EPROTO;
200*4882a593Smuzhiyun 		}
201*4882a593Smuzhiyun 	}
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	/* All set to put the last SKB and optionally write data there. */
204*4882a593Smuzhiyun 	to = pskb_put(skb, lastskb, len);
205*4882a593Smuzhiyun 	if (likely(data))
206*4882a593Smuzhiyun 		memcpy(to, data, len);
207*4882a593Smuzhiyun 	return 0;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
cfpkt_addbdy(struct cfpkt * pkt,u8 data)210*4882a593Smuzhiyun inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	return cfpkt_add_body(pkt, &data, 1);
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
cfpkt_add_head(struct cfpkt * pkt,const void * data2,u16 len)215*4882a593Smuzhiyun int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
218*4882a593Smuzhiyun 	struct sk_buff *lastskb;
219*4882a593Smuzhiyun 	u8 *to;
220*4882a593Smuzhiyun 	const u8 *data = data2;
221*4882a593Smuzhiyun 	int ret;
222*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
223*4882a593Smuzhiyun 		return -EPROTO;
224*4882a593Smuzhiyun 	if (unlikely(skb_headroom(skb) < len)) {
225*4882a593Smuzhiyun 		PKT_ERROR(pkt, "no headroom\n");
226*4882a593Smuzhiyun 		return -EPROTO;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	/* Make sure data is writable */
230*4882a593Smuzhiyun 	ret = skb_cow_data(skb, 0, &lastskb);
231*4882a593Smuzhiyun 	if (unlikely(ret < 0)) {
232*4882a593Smuzhiyun 		PKT_ERROR(pkt, "cow failed\n");
233*4882a593Smuzhiyun 		return ret;
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	to = skb_push(skb, len);
237*4882a593Smuzhiyun 	memcpy(to, data, len);
238*4882a593Smuzhiyun 	return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun EXPORT_SYMBOL(cfpkt_add_head);
241*4882a593Smuzhiyun 
cfpkt_add_trail(struct cfpkt * pkt,const void * data,u16 len)242*4882a593Smuzhiyun inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	return cfpkt_add_body(pkt, data, len);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
cfpkt_getlen(struct cfpkt * pkt)247*4882a593Smuzhiyun inline u16 cfpkt_getlen(struct cfpkt *pkt)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
250*4882a593Smuzhiyun 	return skb->len;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
cfpkt_iterate(struct cfpkt * pkt,u16 (* iter_func)(u16,void *,u16),u16 data)253*4882a593Smuzhiyun int cfpkt_iterate(struct cfpkt *pkt,
254*4882a593Smuzhiyun 		  u16 (*iter_func)(u16, void *, u16),
255*4882a593Smuzhiyun 		  u16 data)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	/*
258*4882a593Smuzhiyun 	 * Don't care about the performance hit of linearizing,
259*4882a593Smuzhiyun 	 * Checksum should not be used on high-speed interfaces anyway.
260*4882a593Smuzhiyun 	 */
261*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
262*4882a593Smuzhiyun 		return -EPROTO;
263*4882a593Smuzhiyun 	if (unlikely(skb_linearize(&pkt->skb) != 0)) {
264*4882a593Smuzhiyun 		PKT_ERROR(pkt, "linearize failed\n");
265*4882a593Smuzhiyun 		return -EPROTO;
266*4882a593Smuzhiyun 	}
267*4882a593Smuzhiyun 	return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt));
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
cfpkt_setlen(struct cfpkt * pkt,u16 len)270*4882a593Smuzhiyun int cfpkt_setlen(struct cfpkt *pkt, u16 len)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
276*4882a593Smuzhiyun 		return -EPROTO;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (likely(len <= skb->len)) {
279*4882a593Smuzhiyun 		if (unlikely(skb->data_len))
280*4882a593Smuzhiyun 			___pskb_trim(skb, len);
281*4882a593Smuzhiyun 		else
282*4882a593Smuzhiyun 			skb_trim(skb, len);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 		return cfpkt_getlen(pkt);
285*4882a593Smuzhiyun 	}
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	/* Need to expand SKB */
288*4882a593Smuzhiyun 	if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len)))
289*4882a593Smuzhiyun 		PKT_ERROR(pkt, "skb_pad_trail failed\n");
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	return cfpkt_getlen(pkt);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
cfpkt_append(struct cfpkt * dstpkt,struct cfpkt * addpkt,u16 expectlen)294*4882a593Smuzhiyun struct cfpkt *cfpkt_append(struct cfpkt *dstpkt,
295*4882a593Smuzhiyun 			   struct cfpkt *addpkt,
296*4882a593Smuzhiyun 			   u16 expectlen)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun 	struct sk_buff *dst = pkt_to_skb(dstpkt);
299*4882a593Smuzhiyun 	struct sk_buff *add = pkt_to_skb(addpkt);
300*4882a593Smuzhiyun 	u16 addlen = skb_headlen(add);
301*4882a593Smuzhiyun 	u16 neededtailspace;
302*4882a593Smuzhiyun 	struct sk_buff *tmp;
303*4882a593Smuzhiyun 	u16 dstlen;
304*4882a593Smuzhiyun 	u16 createlen;
305*4882a593Smuzhiyun 	if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) {
306*4882a593Smuzhiyun 		return dstpkt;
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 	if (expectlen > addlen)
309*4882a593Smuzhiyun 		neededtailspace = expectlen;
310*4882a593Smuzhiyun 	else
311*4882a593Smuzhiyun 		neededtailspace = addlen;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	if (dst->tail + neededtailspace > dst->end) {
314*4882a593Smuzhiyun 		/* Create a dumplicate of 'dst' with more tail space */
315*4882a593Smuzhiyun 		struct cfpkt *tmppkt;
316*4882a593Smuzhiyun 		dstlen = skb_headlen(dst);
317*4882a593Smuzhiyun 		createlen = dstlen + neededtailspace;
318*4882a593Smuzhiyun 		tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX);
319*4882a593Smuzhiyun 		if (tmppkt == NULL)
320*4882a593Smuzhiyun 			return NULL;
321*4882a593Smuzhiyun 		tmp = pkt_to_skb(tmppkt);
322*4882a593Smuzhiyun 		skb_put_data(tmp, dst->data, dstlen);
323*4882a593Smuzhiyun 		cfpkt_destroy(dstpkt);
324*4882a593Smuzhiyun 		dst = tmp;
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 	skb_put_data(dst, add->data, skb_headlen(add));
327*4882a593Smuzhiyun 	cfpkt_destroy(addpkt);
328*4882a593Smuzhiyun 	return skb_to_pkt(dst);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
cfpkt_split(struct cfpkt * pkt,u16 pos)331*4882a593Smuzhiyun struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	struct sk_buff *skb2;
334*4882a593Smuzhiyun 	struct sk_buff *skb = pkt_to_skb(pkt);
335*4882a593Smuzhiyun 	struct cfpkt *tmppkt;
336*4882a593Smuzhiyun 	u8 *split = skb->data + pos;
337*4882a593Smuzhiyun 	u16 len2nd = skb_tail_pointer(skb) - split;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	if (unlikely(is_erronous(pkt)))
340*4882a593Smuzhiyun 		return NULL;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	if (skb->data + pos > skb_tail_pointer(skb)) {
343*4882a593Smuzhiyun 		PKT_ERROR(pkt, "trying to split beyond end of packet\n");
344*4882a593Smuzhiyun 		return NULL;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	/* Create a new packet for the second part of the data */
348*4882a593Smuzhiyun 	tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
349*4882a593Smuzhiyun 				  PKT_PREFIX);
350*4882a593Smuzhiyun 	if (tmppkt == NULL)
351*4882a593Smuzhiyun 		return NULL;
352*4882a593Smuzhiyun 	skb2 = pkt_to_skb(tmppkt);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	if (skb2 == NULL)
356*4882a593Smuzhiyun 		return NULL;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	skb_put_data(skb2, split, len2nd);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	/* Reduce the length of the original packet */
361*4882a593Smuzhiyun 	skb_trim(skb, pos);
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	skb2->priority = skb->priority;
364*4882a593Smuzhiyun 	return skb_to_pkt(skb2);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
cfpkt_erroneous(struct cfpkt * pkt)367*4882a593Smuzhiyun bool cfpkt_erroneous(struct cfpkt *pkt)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	return cfpkt_priv(pkt)->erronous;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
cfpkt_info(struct cfpkt * pkt)372*4882a593Smuzhiyun struct caif_payload_info *cfpkt_info(struct cfpkt *pkt)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun 	return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun EXPORT_SYMBOL(cfpkt_info);
377*4882a593Smuzhiyun 
cfpkt_set_prio(struct cfpkt * pkt,int prio)378*4882a593Smuzhiyun void cfpkt_set_prio(struct cfpkt *pkt, int prio)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun 	pkt_to_skb(pkt)->priority = prio;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun EXPORT_SYMBOL(cfpkt_set_prio);
383