1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7 #include <drv_types.h>
8
9 /*
10 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
11 * @return: one of RTW_STATUS_CODE
12 */
RTW_STATUS_CODE(int error_code)13 inline int RTW_STATUS_CODE(int error_code)
14 {
15 if (error_code >= 0)
16 return _SUCCESS;
17 return _FAIL;
18 }
19
_rtw_malloc(u32 sz)20 void *_rtw_malloc(u32 sz)
21 {
22 return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
23 }
24
_rtw_zmalloc(u32 sz)25 void *_rtw_zmalloc(u32 sz)
26 {
27 void *pbuf = _rtw_malloc(sz);
28
29 if (pbuf)
30 memset(pbuf, 0, sz);
31
32 return pbuf;
33 }
34
_rtw_skb_alloc(u32 sz)35 inline struct sk_buff *_rtw_skb_alloc(u32 sz)
36 {
37 return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
38 }
39
_rtw_skb_copy(const struct sk_buff * skb)40 inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)
41 {
42 return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
43 }
44
_rtw_netif_rx(struct net_device * ndev,struct sk_buff * skb)45 inline int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb)
46 {
47 skb->dev = ndev;
48 return netif_rx(skb);
49 }
50
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)51 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
52 {
53 struct net_device *pnetdev;
54 struct rtw_netdev_priv_indicator *pnpi;
55
56 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
57 if (!pnetdev)
58 goto RETURN;
59
60 pnpi = netdev_priv(pnetdev);
61 pnpi->priv = old_priv;
62 pnpi->sizeof_priv = sizeof_priv;
63
64 RETURN:
65 return pnetdev;
66 }
67
rtw_alloc_etherdev(int sizeof_priv)68 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
69 {
70 struct net_device *pnetdev;
71 struct rtw_netdev_priv_indicator *pnpi;
72
73 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
74 if (!pnetdev)
75 goto RETURN;
76
77 pnpi = netdev_priv(pnetdev);
78
79 pnpi->priv = vzalloc(sizeof_priv);
80 if (!pnpi->priv) {
81 free_netdev(pnetdev);
82 pnetdev = NULL;
83 goto RETURN;
84 }
85
86 pnpi->sizeof_priv = sizeof_priv;
87 RETURN:
88 return pnetdev;
89 }
90
rtw_free_netdev(struct net_device * netdev)91 void rtw_free_netdev(struct net_device *netdev)
92 {
93 struct rtw_netdev_priv_indicator *pnpi;
94
95 if (!netdev)
96 goto RETURN;
97
98 pnpi = netdev_priv(netdev);
99
100 if (!pnpi->priv)
101 goto RETURN;
102
103 vfree(pnpi->priv);
104 free_netdev(netdev);
105
106 RETURN:
107 return;
108 }
109
rtw_buf_free(u8 ** buf,u32 * buf_len)110 void rtw_buf_free(u8 **buf, u32 *buf_len)
111 {
112 if (!buf || !buf_len)
113 return;
114
115 if (*buf) {
116 *buf_len = 0;
117 kfree(*buf);
118 *buf = NULL;
119 }
120 }
121
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)122 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
123 {
124 u32 ori_len = 0, dup_len = 0;
125 u8 *ori = NULL;
126 u8 *dup = NULL;
127
128 if (!buf || !buf_len)
129 return;
130
131 if (!src || !src_len)
132 goto keep_ori;
133
134 /* duplicate src */
135 dup = rtw_malloc(src_len);
136 if (dup) {
137 dup_len = src_len;
138 memcpy(dup, src, dup_len);
139 }
140
141 keep_ori:
142 ori = *buf;
143 ori_len = *buf_len;
144
145 /* replace buf with dup */
146 *buf_len = 0;
147 *buf = dup;
148 *buf_len = dup_len;
149
150 /* free ori */
151 if (ori && ori_len > 0)
152 kfree(ori);
153 }
154
155
156 /**
157 * rtw_cbuf_full - test if cbuf is full
158 * @cbuf: pointer of struct rtw_cbuf
159 *
160 * Returns: true if cbuf is full
161 */
rtw_cbuf_full(struct rtw_cbuf * cbuf)162 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
163 {
164 return (cbuf->write == cbuf->read - 1) ? true : false;
165 }
166
167 /**
168 * rtw_cbuf_empty - test if cbuf is empty
169 * @cbuf: pointer of struct rtw_cbuf
170 *
171 * Returns: true if cbuf is empty
172 */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)173 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
174 {
175 return (cbuf->write == cbuf->read) ? true : false;
176 }
177
178 /**
179 * rtw_cbuf_push - push a pointer into cbuf
180 * @cbuf: pointer of struct rtw_cbuf
181 * @buf: pointer to push in
182 *
183 * Lock free operation, be careful of the use scheme
184 * Returns: true push success
185 */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)186 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
187 {
188 if (rtw_cbuf_full(cbuf))
189 return _FAIL;
190
191 cbuf->bufs[cbuf->write] = buf;
192 cbuf->write = (cbuf->write + 1) % cbuf->size;
193
194 return _SUCCESS;
195 }
196
197 /**
198 * rtw_cbuf_pop - pop a pointer from cbuf
199 * @cbuf: pointer of struct rtw_cbuf
200 *
201 * Lock free operation, be careful of the use scheme
202 * Returns: pointer popped out
203 */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)204 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
205 {
206 void *buf;
207 if (rtw_cbuf_empty(cbuf))
208 return NULL;
209
210 buf = cbuf->bufs[cbuf->read];
211 cbuf->read = (cbuf->read + 1) % cbuf->size;
212
213 return buf;
214 }
215
216 /**
217 * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
218 * @size: size of pointer
219 *
220 * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
221 */
rtw_cbuf_alloc(u32 size)222 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
223 {
224 struct rtw_cbuf *cbuf;
225
226 cbuf = rtw_malloc(struct_size(cbuf, bufs, size));
227
228 if (cbuf) {
229 cbuf->write = cbuf->read = 0;
230 cbuf->size = size;
231 }
232
233 return cbuf;
234 }
235