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 */
14 inline int RTW_STATUS_CODE(int error_code)
15 {
16 	if (error_code >= 0)
17 		return _SUCCESS;
18 	return _FAIL;
19 }
20 
21 void *_rtw_malloc(u32 sz)
22 {
23 	return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
24 }
25 
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 
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 
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 
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 
52 void _rtw_init_queue(struct __queue *pqueue)
53 {
54 	INIT_LIST_HEAD(&(pqueue->queue));
55 
56 	spin_lock_init(&(pqueue->lock));
57 }
58 
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 
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 
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 
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 
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 
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  */
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  */
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  */
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  */
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  */
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