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 #include <rtw_debug.h>
9
10 /*
11 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
12 * @return: one of RTW_STATUS_CODE
13 */
RTW_STATUS_CODE(int error_code)14 inline int RTW_STATUS_CODE(int error_code)
15 {
16 if (error_code >= 0)
17 return _SUCCESS;
18 return _FAIL;
19 }
20
_rtw_malloc(u32 sz)21 void *_rtw_malloc(u32 sz)
22 {
23 return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
24 }
25
_rtw_zmalloc(u32 sz)26 void *_rtw_zmalloc(u32 sz)
27 {
28 void *pbuf = _rtw_malloc(sz);
29
30 if (pbuf)
31 memset(pbuf, 0, sz);
32
33 return pbuf;
34 }
35
_rtw_skb_alloc(u32 sz)36 inline struct sk_buff *_rtw_skb_alloc(u32 sz)
37 {
38 return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
39 }
40
_rtw_skb_copy(const struct sk_buff * skb)41 inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)
42 {
43 return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
44 }
45
_rtw_netif_rx(struct net_device * ndev,struct sk_buff * skb)46 inline int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb)
47 {
48 skb->dev = ndev;
49 return netif_rx(skb);
50 }
51
_rtw_init_queue(struct __queue * pqueue)52 void _rtw_init_queue(struct __queue *pqueue)
53 {
54 INIT_LIST_HEAD(&(pqueue->queue));
55
56 spin_lock_init(&(pqueue->lock));
57 }
58
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)59 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
60 {
61 struct net_device *pnetdev;
62 struct rtw_netdev_priv_indicator *pnpi;
63
64 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
65 if (!pnetdev)
66 goto RETURN;
67
68 pnpi = netdev_priv(pnetdev);
69 pnpi->priv = old_priv;
70 pnpi->sizeof_priv = sizeof_priv;
71
72 RETURN:
73 return pnetdev;
74 }
75
rtw_alloc_etherdev(int sizeof_priv)76 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
77 {
78 struct net_device *pnetdev;
79 struct rtw_netdev_priv_indicator *pnpi;
80
81 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
82 if (!pnetdev)
83 goto RETURN;
84
85 pnpi = netdev_priv(pnetdev);
86
87 pnpi->priv = vzalloc(sizeof_priv);
88 if (!pnpi->priv) {
89 free_netdev(pnetdev);
90 pnetdev = NULL;
91 goto RETURN;
92 }
93
94 pnpi->sizeof_priv = sizeof_priv;
95 RETURN:
96 return pnetdev;
97 }
98
rtw_free_netdev(struct net_device * netdev)99 void rtw_free_netdev(struct net_device *netdev)
100 {
101 struct rtw_netdev_priv_indicator *pnpi;
102
103 if (!netdev)
104 goto RETURN;
105
106 pnpi = netdev_priv(netdev);
107
108 if (!pnpi->priv)
109 goto RETURN;
110
111 vfree(pnpi->priv);
112 free_netdev(netdev);
113
114 RETURN:
115 return;
116 }
117
rtw_change_ifname(struct adapter * padapter,const char * ifname)118 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
119 {
120 struct net_device *pnetdev;
121 struct net_device *cur_pnetdev;
122 struct rereg_nd_name_data *rereg_priv;
123 int ret;
124
125 if (!padapter)
126 goto error;
127
128 cur_pnetdev = padapter->pnetdev;
129 rereg_priv = &padapter->rereg_nd_name_priv;
130
131 /* free the old_pnetdev */
132 if (rereg_priv->old_pnetdev) {
133 free_netdev(rereg_priv->old_pnetdev);
134 rereg_priv->old_pnetdev = NULL;
135 }
136
137 if (!rtnl_is_locked())
138 unregister_netdev(cur_pnetdev);
139 else
140 unregister_netdevice(cur_pnetdev);
141
142 rereg_priv->old_pnetdev = cur_pnetdev;
143
144 pnetdev = rtw_init_netdev(padapter);
145 if (!pnetdev)
146 goto error;
147
148 SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
149
150 rtw_init_netdev_name(pnetdev, ifname);
151
152 memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
153
154 if (!rtnl_is_locked())
155 ret = register_netdev(pnetdev);
156 else
157 ret = register_netdevice(pnetdev);
158
159 if (ret != 0)
160 goto error;
161
162 return 0;
163
164 error:
165 return -1;
166 }
167
rtw_buf_free(u8 ** buf,u32 * buf_len)168 void rtw_buf_free(u8 **buf, u32 *buf_len)
169 {
170 if (!buf || !buf_len)
171 return;
172
173 if (*buf) {
174 *buf_len = 0;
175 kfree(*buf);
176 *buf = NULL;
177 }
178 }
179
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)180 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
181 {
182 u32 ori_len = 0, dup_len = 0;
183 u8 *ori = NULL;
184 u8 *dup = NULL;
185
186 if (!buf || !buf_len)
187 return;
188
189 if (!src || !src_len)
190 goto keep_ori;
191
192 /* duplicate src */
193 dup = rtw_malloc(src_len);
194 if (dup) {
195 dup_len = src_len;
196 memcpy(dup, src, dup_len);
197 }
198
199 keep_ori:
200 ori = *buf;
201 ori_len = *buf_len;
202
203 /* replace buf with dup */
204 *buf_len = 0;
205 *buf = dup;
206 *buf_len = dup_len;
207
208 /* free ori */
209 if (ori && ori_len > 0)
210 kfree(ori);
211 }
212
213
214 /**
215 * rtw_cbuf_full - test if cbuf is full
216 * @cbuf: pointer of struct rtw_cbuf
217 *
218 * Returns: true if cbuf is full
219 */
rtw_cbuf_full(struct rtw_cbuf * cbuf)220 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
221 {
222 return (cbuf->write == cbuf->read - 1) ? true : false;
223 }
224
225 /**
226 * rtw_cbuf_empty - test if cbuf is empty
227 * @cbuf: pointer of struct rtw_cbuf
228 *
229 * Returns: true if cbuf is empty
230 */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)231 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
232 {
233 return (cbuf->write == cbuf->read) ? true : false;
234 }
235
236 /**
237 * rtw_cbuf_push - push a pointer into cbuf
238 * @cbuf: pointer of struct rtw_cbuf
239 * @buf: pointer to push in
240 *
241 * Lock free operation, be careful of the use scheme
242 * Returns: true push success
243 */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)244 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
245 {
246 if (rtw_cbuf_full(cbuf))
247 return _FAIL;
248
249 cbuf->bufs[cbuf->write] = buf;
250 cbuf->write = (cbuf->write + 1) % cbuf->size;
251
252 return _SUCCESS;
253 }
254
255 /**
256 * rtw_cbuf_pop - pop a pointer from cbuf
257 * @cbuf: pointer of struct rtw_cbuf
258 *
259 * Lock free operation, be careful of the use scheme
260 * Returns: pointer popped out
261 */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)262 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
263 {
264 void *buf;
265 if (rtw_cbuf_empty(cbuf))
266 return NULL;
267
268 buf = cbuf->bufs[cbuf->read];
269 cbuf->read = (cbuf->read + 1) % cbuf->size;
270
271 return buf;
272 }
273
274 /**
275 * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
276 * @size: size of pointer
277 *
278 * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
279 */
rtw_cbuf_alloc(u32 size)280 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
281 {
282 struct rtw_cbuf *cbuf;
283
284 cbuf = rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);
285
286 if (cbuf) {
287 cbuf->write = cbuf->read = 0;
288 cbuf->size = size;
289 }
290
291 return cbuf;
292 }
293