1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 
8 
9 #define _OSDEP_SERVICE_C_
10 
11 #include <drv_types.h>
12 #include <rtw_debug.h>
13 
14 /*
15 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
16 * @return: one of RTW_STATUS_CODE
17 */
RTW_STATUS_CODE(int error_code)18 inline int RTW_STATUS_CODE(int error_code)
19 {
20 	if (error_code >= 0)
21 		return _SUCCESS;
22 	return _FAIL;
23 }
24 
_rtw_malloc(u32 sz)25 void *_rtw_malloc(u32 sz)
26 {
27 	return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
28 }
29 
_rtw_zmalloc(u32 sz)30 void *_rtw_zmalloc(u32 sz)
31 {
32 	void *pbuf = _rtw_malloc(sz);
33 
34 	if (pbuf)
35 		memset(pbuf, 0, sz);
36 
37 	return pbuf;
38 }
39 
_rtw_skb_alloc(u32 sz)40 inline struct sk_buff *_rtw_skb_alloc(u32 sz)
41 {
42 	return __dev_alloc_skb(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
43 }
44 
_rtw_skb_copy(const struct sk_buff * skb)45 inline struct sk_buff *_rtw_skb_copy(const struct sk_buff *skb)
46 {
47 	return skb_copy(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
48 }
49 
_rtw_skb_clone(struct sk_buff * skb)50 inline struct sk_buff *_rtw_skb_clone(struct sk_buff *skb)
51 {
52 	return skb_clone(skb, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
53 }
54 
_rtw_netif_rx(_nic_hdl ndev,struct sk_buff * skb)55 inline int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb)
56 {
57 	skb->dev = ndev;
58 	return netif_rx(skb);
59 }
60 
_rtw_init_queue(struct __queue * pqueue)61 void _rtw_init_queue(struct __queue *pqueue)
62 {
63 	INIT_LIST_HEAD(&(pqueue->queue));
64 
65 	spin_lock_init(&(pqueue->lock));
66 }
67 
68 /*
69 * Open a file with the specific @param path, @param flag, @param mode
70 * @param fpp the pointer of struct file pointer to get struct file pointer while file opening is success
71 * @param path the path of the file to open
72 * @param flag file operation flags, please refer to linux document
73 * @param mode please refer to linux document
74 * @return Linux specific error code
75 */
openFile(struct file ** fpp,char * path,int flag,int mode)76 static int openFile(struct file **fpp, char *path, int flag, int mode)
77 {
78 	struct file *fp;
79 
80 	fp = filp_open(path, flag, mode);
81 	if (IS_ERR(fp)) {
82 		*fpp = NULL;
83 		return PTR_ERR(fp);
84 	}
85 	else {
86 		*fpp = fp;
87 		return 0;
88 	}
89 }
90 
91 /*
92 * Close the file with the specific @param fp
93 * @param fp the pointer of struct file to close
94 * @return always 0
95 */
closeFile(struct file * fp)96 static int closeFile(struct file *fp)
97 {
98 	filp_close(fp, NULL);
99 	return 0;
100 }
101 
readFile(struct file * fp,char * buf,int len)102 static int readFile(struct file *fp, char *buf, int len)
103 {
104 	int rlen = 0, sum = 0;
105 
106 	if (!fp->f_op || !fp->f_op->read)
107 		return -EPERM;
108 
109 	while (sum < len) {
110 		rlen = kernel_read(fp, buf + sum, len - sum, &fp->f_pos);
111 		if (rlen > 0)
112 			sum += rlen;
113 		else if (0 != rlen)
114 			return rlen;
115 		else
116 			break;
117 	}
118 
119 	return sum;
120 
121 }
122 
123 /*
124 * Test if the specifi @param path is a file and readable
125 * @param path the path of the file to test
126 * @return Linux specific error code
127 */
isFileReadable(char * path)128 static int isFileReadable(char *path)
129 {
130 	struct file *fp;
131 	int ret = 0;
132 	char buf;
133 
134 	fp = filp_open(path, O_RDONLY, 0);
135 	if (IS_ERR(fp))
136 		return PTR_ERR(fp);
137 
138 	if (readFile(fp, &buf, 1) != 1)
139 		ret = -EINVAL;
140 
141 	filp_close(fp, NULL);
142 	return ret;
143 }
144 
145 /*
146 * Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
147 * @param path the path of the file to open and read
148 * @param buf the starting address of the buffer to store file content
149 * @param sz how many bytes to read at most
150 * @return the byte we've read, or Linux specific error code
151 */
retriveFromFile(char * path,u8 * buf,u32 sz)152 static int retriveFromFile(char *path, u8 *buf, u32 sz)
153 {
154 	int ret = -1;
155 	struct file *fp;
156 
157 	if (path && buf) {
158 		ret = openFile(&fp, path, O_RDONLY, 0);
159 
160 		if (ret == 0) {
161 			DBG_871X("%s openFile path:%s fp =%p\n", __func__, path , fp);
162 
163 			ret = readFile(fp, buf, sz);
164 			closeFile(fp);
165 
166 			DBG_871X("%s readFile, ret:%d\n", __func__, ret);
167 
168 		} else {
169 			DBG_871X("%s openFile path:%s Fail, ret:%d\n", __func__, path, ret);
170 		}
171 	} else {
172 		DBG_871X("%s NULL pointer\n", __func__);
173 		ret =  -EINVAL;
174 	}
175 	return ret;
176 }
177 
178 /*
179 * Test if the specifi @param path is a file and readable
180 * @param path the path of the file to test
181 * @return true or false
182 */
rtw_is_file_readable(char * path)183 int rtw_is_file_readable(char *path)
184 {
185 	if (isFileReadable(path) == 0)
186 		return true;
187 	else
188 		return false;
189 }
190 
191 /*
192 * Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
193 * @param path the path of the file to open and read
194 * @param buf the starting address of the buffer to store file content
195 * @param sz how many bytes to read at most
196 * @return the byte we've read
197 */
rtw_retrive_from_file(char * path,u8 * buf,u32 sz)198 int rtw_retrive_from_file(char *path, u8 *buf, u32 sz)
199 {
200 	int ret = retriveFromFile(path, buf, sz);
201 	return ret >= 0 ? ret : 0;
202 }
203 
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)204 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
205 {
206 	struct net_device *pnetdev;
207 	struct rtw_netdev_priv_indicator *pnpi;
208 
209 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
210 	if (!pnetdev)
211 		goto RETURN;
212 
213 	pnpi = netdev_priv(pnetdev);
214 	pnpi->priv = old_priv;
215 	pnpi->sizeof_priv = sizeof_priv;
216 
217 RETURN:
218 	return pnetdev;
219 }
220 
rtw_alloc_etherdev(int sizeof_priv)221 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
222 {
223 	struct net_device *pnetdev;
224 	struct rtw_netdev_priv_indicator *pnpi;
225 
226 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
227 	if (!pnetdev)
228 		goto RETURN;
229 
230 	pnpi = netdev_priv(pnetdev);
231 
232 	pnpi->priv = vzalloc(sizeof_priv);
233 	if (!pnpi->priv) {
234 		free_netdev(pnetdev);
235 		pnetdev = NULL;
236 		goto RETURN;
237 	}
238 
239 	pnpi->sizeof_priv = sizeof_priv;
240 RETURN:
241 	return pnetdev;
242 }
243 
rtw_free_netdev(struct net_device * netdev)244 void rtw_free_netdev(struct net_device *netdev)
245 {
246 	struct rtw_netdev_priv_indicator *pnpi;
247 
248 	if (!netdev)
249 		goto RETURN;
250 
251 	pnpi = netdev_priv(netdev);
252 
253 	if (!pnpi->priv)
254 		goto RETURN;
255 
256 	vfree(pnpi->priv);
257 	free_netdev(netdev);
258 
259 RETURN:
260 	return;
261 }
262 
rtw_change_ifname(struct adapter * padapter,const char * ifname)263 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
264 {
265 	struct net_device *pnetdev;
266 	struct net_device *cur_pnetdev;
267 	struct rereg_nd_name_data *rereg_priv;
268 	int ret;
269 
270 	if (!padapter)
271 		goto error;
272 
273 	cur_pnetdev = padapter->pnetdev;
274 	rereg_priv = &padapter->rereg_nd_name_priv;
275 
276 	/* free the old_pnetdev */
277 	if (rereg_priv->old_pnetdev) {
278 		free_netdev(rereg_priv->old_pnetdev);
279 		rereg_priv->old_pnetdev = NULL;
280 	}
281 
282 	if (!rtnl_is_locked())
283 		unregister_netdev(cur_pnetdev);
284 	else
285 		unregister_netdevice(cur_pnetdev);
286 
287 	rereg_priv->old_pnetdev = cur_pnetdev;
288 
289 	pnetdev = rtw_init_netdev(padapter);
290 	if (!pnetdev)  {
291 		ret = -1;
292 		goto error;
293 	}
294 
295 	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
296 
297 	rtw_init_netdev_name(pnetdev, ifname);
298 
299 	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
300 
301 	if (!rtnl_is_locked())
302 		ret = register_netdev(pnetdev);
303 	else
304 		ret = register_netdevice(pnetdev);
305 
306 	if (ret != 0) {
307 		RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n"));
308 		goto error;
309 	}
310 
311 	return 0;
312 
313 error:
314 
315 	return -1;
316 
317 }
318 
rtw_buf_free(u8 ** buf,u32 * buf_len)319 void rtw_buf_free(u8 **buf, u32 *buf_len)
320 {
321 	if (!buf || !buf_len)
322 		return;
323 
324 	if (*buf) {
325 		*buf_len = 0;
326 		kfree(*buf);
327 		*buf = NULL;
328 	}
329 }
330 
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)331 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
332 {
333 	u32 ori_len = 0, dup_len = 0;
334 	u8 *ori = NULL;
335 	u8 *dup = NULL;
336 
337 	if (!buf || !buf_len)
338 		return;
339 
340 	if (!src || !src_len)
341 		goto keep_ori;
342 
343 	/* duplicate src */
344 	dup = rtw_malloc(src_len);
345 	if (dup) {
346 		dup_len = src_len;
347 		memcpy(dup, src, dup_len);
348 	}
349 
350 keep_ori:
351 	ori = *buf;
352 	ori_len = *buf_len;
353 
354 	/* replace buf with dup */
355 	*buf_len = 0;
356 	*buf = dup;
357 	*buf_len = dup_len;
358 
359 	/* free ori */
360 	if (ori && ori_len > 0)
361 		kfree(ori);
362 }
363 
364 
365 /**
366  * rtw_cbuf_full - test if cbuf is full
367  * @cbuf: pointer of struct rtw_cbuf
368  *
369  * Returns: true if cbuf is full
370  */
rtw_cbuf_full(struct rtw_cbuf * cbuf)371 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
372 {
373 	return (cbuf->write == cbuf->read - 1) ? true : false;
374 }
375 
376 /**
377  * rtw_cbuf_empty - test if cbuf is empty
378  * @cbuf: pointer of struct rtw_cbuf
379  *
380  * Returns: true if cbuf is empty
381  */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)382 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
383 {
384 	return (cbuf->write == cbuf->read) ? true : false;
385 }
386 
387 /**
388  * rtw_cbuf_push - push a pointer into cbuf
389  * @cbuf: pointer of struct rtw_cbuf
390  * @buf: pointer to push in
391  *
392  * Lock free operation, be careful of the use scheme
393  * Returns: true push success
394  */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)395 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
396 {
397 	if (rtw_cbuf_full(cbuf))
398 		return _FAIL;
399 
400 	DBG_871X("%s on %u\n", __func__, cbuf->write);
401 	cbuf->bufs[cbuf->write] = buf;
402 	cbuf->write = (cbuf->write + 1) % cbuf->size;
403 
404 	return _SUCCESS;
405 }
406 
407 /**
408  * rtw_cbuf_pop - pop a pointer from cbuf
409  * @cbuf: pointer of struct rtw_cbuf
410  *
411  * Lock free operation, be careful of the use scheme
412  * Returns: pointer popped out
413  */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)414 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
415 {
416 	void *buf;
417 	if (rtw_cbuf_empty(cbuf))
418 		return NULL;
419 
420         DBG_871X("%s on %u\n", __func__, cbuf->read);
421 	buf = cbuf->bufs[cbuf->read];
422 	cbuf->read = (cbuf->read + 1) % cbuf->size;
423 
424 	return buf;
425 }
426 
427 /**
428  * rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization
429  * @size: size of pointer
430  *
431  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
432  */
rtw_cbuf_alloc(u32 size)433 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
434 {
435 	struct rtw_cbuf *cbuf;
436 
437 	cbuf = rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);
438 
439 	if (cbuf) {
440 		cbuf->write = cbuf->read = 0;
441 		cbuf->size = size;
442 	}
443 
444 	return cbuf;
445 }
446