net: mirror skb frag ref/unref helpers
[linux-2.6-block.git] / include / linux / skbuff_ref.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  *      Skb ref helpers.
4  *
5  */
6
7 #ifndef _LINUX_SKBUFF_REF_H
8 #define _LINUX_SKBUFF_REF_H
9
10 #include <linux/skbuff.h>
11 #include <net/page_pool/helpers.h>
12
13 #ifdef CONFIG_PAGE_POOL
14 static inline bool is_pp_page(struct page *page)
15 {
16         return (page->pp_magic & ~0x3UL) == PP_SIGNATURE;
17 }
18
19 static inline bool napi_pp_get_page(struct page *page)
20 {
21         page = compound_head(page);
22
23         if (!is_pp_page(page))
24                 return false;
25
26         page_pool_ref_page(page);
27         return true;
28 }
29 #endif
30
31 static inline void skb_page_ref(struct page *page, bool recycle)
32 {
33 #ifdef CONFIG_PAGE_POOL
34         if (recycle && napi_pp_get_page(page))
35                 return;
36 #endif
37         get_page(page);
38 }
39
40 /**
41  * __skb_frag_ref - take an addition reference on a paged fragment.
42  * @frag: the paged fragment
43  * @recycle: skb->pp_recycle param of the parent skb. False if no parent skb.
44  *
45  * Takes an additional reference on the paged fragment @frag. Obtains the
46  * correct reference count depending on whether skb->pp_recycle is set and
47  * whether the frag is a page pool frag.
48  */
49 static inline void __skb_frag_ref(skb_frag_t *frag, bool recycle)
50 {
51         skb_page_ref(skb_frag_page(frag), recycle);
52 }
53
54 /**
55  * skb_frag_ref - take an addition reference on a paged fragment of an skb.
56  * @skb: the buffer
57  * @f: the fragment offset.
58  *
59  * Takes an additional reference on the @f'th paged fragment of @skb.
60  */
61 static inline void skb_frag_ref(struct sk_buff *skb, int f)
62 {
63         __skb_frag_ref(&skb_shinfo(skb)->frags[f], skb->pp_recycle);
64 }
65
66 bool napi_pp_put_page(struct page *page);
67
68 static inline void
69 skb_page_unref(struct page *page, bool recycle)
70 {
71 #ifdef CONFIG_PAGE_POOL
72         if (recycle && napi_pp_put_page(page))
73                 return;
74 #endif
75         put_page(page);
76 }
77
78 /**
79  * __skb_frag_unref - release a reference on a paged fragment.
80  * @frag: the paged fragment
81  * @recycle: recycle the page if allocated via page_pool
82  *
83  * Releases a reference on the paged fragment @frag
84  * or recycles the page via the page_pool API.
85  */
86 static inline void __skb_frag_unref(skb_frag_t *frag, bool recycle)
87 {
88         skb_page_unref(skb_frag_page(frag), recycle);
89 }
90
91 /**
92  * skb_frag_unref - release a reference on a paged fragment of an skb.
93  * @skb: the buffer
94  * @f: the fragment offset
95  *
96  * Releases a reference on the @f'th paged fragment of @skb.
97  */
98 static inline void skb_frag_unref(struct sk_buff *skb, int f)
99 {
100         struct skb_shared_info *shinfo = skb_shinfo(skb);
101
102         if (!skb_zcopy_managed(skb))
103                 __skb_frag_unref(&shinfo->frags[f], skb->pp_recycle);
104 }
105
106 #endif  /* _LINUX_SKBUFF_REF_H */