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