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 */
18 inline int RTW_STATUS_CODE(int error_code)
19 {
20 	if (error_code >= 0)
21 		return _SUCCESS;
22 	return _FAIL;
23 }
24 
25 void *_rtw_malloc(u32 sz)
26 {
27 	return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
28 }
29 
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 
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 
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 
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 
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 
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 */
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 */
96 static int closeFile(struct file *fp)
97 {
98 	filp_close(fp, NULL);
99 	return 0;
100 }
101 
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 =fp->f_op->read(fp, (char __force __user *)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 */
128 static int isFileReadable(char *path)
129 {
130 	struct file *fp;
131 	int ret = 0;
132 	mm_segment_t oldfs;
133 	char buf;
134 
135 	fp =filp_open(path, O_RDONLY, 0);
136 	if (IS_ERR(fp)) {
137 		ret = PTR_ERR(fp);
138 	}
139 	else {
140 		oldfs = get_fs(); set_fs(get_ds());
141 
142 		if (1!=readFile(fp, &buf, 1))
143 			ret = -EINVAL;
144 
145 		set_fs(oldfs);
146 		filp_close(fp, NULL);
147 	}
148 	return ret;
149 }
150 
151 /*
152 * Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
153 * @param path the path of the file to open and read
154 * @param buf the starting address of the buffer to store file content
155 * @param sz how many bytes to read at most
156 * @return the byte we've read, or Linux specific error code
157 */
158 static int retriveFromFile(char *path, u8 *buf, u32 sz)
159 {
160 	int ret =-1;
161 	mm_segment_t oldfs;
162 	struct file *fp;
163 
164 	if (path && buf) {
165 		if (0 == (ret =openFile(&fp, path, O_RDONLY, 0))) {
166 			DBG_871X("%s openFile path:%s fp =%p\n", __func__, path , fp);
167 
168 			oldfs = get_fs(); set_fs(get_ds());
169 			ret =readFile(fp, buf, sz);
170 			set_fs(oldfs);
171 			closeFile(fp);
172 
173 			DBG_871X("%s readFile, ret:%d\n", __func__, ret);
174 
175 		} else {
176 			DBG_871X("%s openFile path:%s Fail, ret:%d\n", __func__, path, ret);
177 		}
178 	} else {
179 		DBG_871X("%s NULL pointer\n", __func__);
180 		ret =  -EINVAL;
181 	}
182 	return ret;
183 }
184 
185 /*
186 * Test if the specifi @param path is a file and readable
187 * @param path the path of the file to test
188 * @return true or false
189 */
190 int rtw_is_file_readable(char *path)
191 {
192 	if (isFileReadable(path) == 0)
193 		return true;
194 	else
195 		return false;
196 }
197 
198 /*
199 * Open the file with @param path and retrive the file content into memory starting from @param buf for @param sz at most
200 * @param path the path of the file to open and read
201 * @param buf the starting address of the buffer to store file content
202 * @param sz how many bytes to read at most
203 * @return the byte we've read
204 */
205 int rtw_retrive_from_file(char *path, u8 *buf, u32 sz)
206 {
207 	int ret =retriveFromFile(path, buf, sz);
208 	return ret>= 0?ret:0;
209 }
210 
211 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv, void *old_priv)
212 {
213 	struct net_device *pnetdev;
214 	struct rtw_netdev_priv_indicator *pnpi;
215 
216 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
217 	if (!pnetdev)
218 		goto RETURN;
219 
220 	pnpi = netdev_priv(pnetdev);
221 	pnpi->priv =old_priv;
222 	pnpi->sizeof_priv =sizeof_priv;
223 
224 RETURN:
225 	return pnetdev;
226 }
227 
228 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
229 {
230 	struct net_device *pnetdev;
231 	struct rtw_netdev_priv_indicator *pnpi;
232 
233 	pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
234 	if (!pnetdev)
235 		goto RETURN;
236 
237 	pnpi = netdev_priv(pnetdev);
238 
239 	pnpi->priv = vzalloc(sizeof_priv);
240 	if (!pnpi->priv) {
241 		free_netdev(pnetdev);
242 		pnetdev = NULL;
243 		goto RETURN;
244 	}
245 
246 	pnpi->sizeof_priv =sizeof_priv;
247 RETURN:
248 	return pnetdev;
249 }
250 
251 void rtw_free_netdev(struct net_device * netdev)
252 {
253 	struct rtw_netdev_priv_indicator *pnpi;
254 
255 	if (!netdev)
256 		goto RETURN;
257 
258 	pnpi = netdev_priv(netdev);
259 
260 	if (!pnpi->priv)
261 		goto RETURN;
262 
263 	vfree(pnpi->priv);
264 	free_netdev(netdev);
265 
266 RETURN:
267 	return;
268 }
269 
270 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
271 {
272 	struct net_device *pnetdev;
273 	struct net_device *cur_pnetdev;
274 	struct rereg_nd_name_data *rereg_priv;
275 	int ret;
276 
277 	if (!padapter)
278 		goto error;
279 
280 	cur_pnetdev = padapter->pnetdev;
281 	rereg_priv = &padapter->rereg_nd_name_priv;
282 
283 	/* free the old_pnetdev */
284 	if (rereg_priv->old_pnetdev) {
285 		free_netdev(rereg_priv->old_pnetdev);
286 		rereg_priv->old_pnetdev = NULL;
287 	}
288 
289 	if (!rtnl_is_locked())
290 		unregister_netdev(cur_pnetdev);
291 	else
292 		unregister_netdevice(cur_pnetdev);
293 
294 	rereg_priv->old_pnetdev =cur_pnetdev;
295 
296 	pnetdev = rtw_init_netdev(padapter);
297 	if (!pnetdev)  {
298 		ret = -1;
299 		goto error;
300 	}
301 
302 	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
303 
304 	rtw_init_netdev_name(pnetdev, ifname);
305 
306 	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
307 
308 	if (!rtnl_is_locked())
309 		ret = register_netdev(pnetdev);
310 	else
311 		ret = register_netdevice(pnetdev);
312 
313 	if (ret != 0) {
314 		RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n"));
315 		goto error;
316 	}
317 
318 	return 0;
319 
320 error:
321 
322 	return -1;
323 
324 }
325 
326 u64 rtw_modular64(u64 x, u64 y)
327 {
328 	return do_div(x, y);
329 }
330 
331 void rtw_buf_free(u8 **buf, u32 *buf_len)
332 {
333 	u32 ori_len;
334 
335 	if (!buf || !buf_len)
336 		return;
337 
338 	ori_len = *buf_len;
339 
340 	if (*buf) {
341 		*buf_len = 0;
342 		kfree(*buf);
343 		*buf = NULL;
344 	}
345 }
346 
347 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
348 {
349 	u32 ori_len = 0, dup_len = 0;
350 	u8 *ori = NULL;
351 	u8 *dup = NULL;
352 
353 	if (!buf || !buf_len)
354 		return;
355 
356 	if (!src || !src_len)
357 		goto keep_ori;
358 
359 	/* duplicate src */
360 	dup = rtw_malloc(src_len);
361 	if (dup) {
362 		dup_len = src_len;
363 		memcpy(dup, src, dup_len);
364 	}
365 
366 keep_ori:
367 	ori = *buf;
368 	ori_len = *buf_len;
369 
370 	/* replace buf with dup */
371 	*buf_len = 0;
372 	*buf = dup;
373 	*buf_len = dup_len;
374 
375 	/* free ori */
376 	if (ori && ori_len > 0)
377 		kfree(ori);
378 }
379 
380 
381 /**
382  * rtw_cbuf_full - test if cbuf is full
383  * @cbuf: pointer of struct rtw_cbuf
384  *
385  * Returns: true if cbuf is full
386  */
387 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
388 {
389 	return (cbuf->write == cbuf->read-1)? true : false;
390 }
391 
392 /**
393  * rtw_cbuf_empty - test if cbuf is empty
394  * @cbuf: pointer of struct rtw_cbuf
395  *
396  * Returns: true if cbuf is empty
397  */
398 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
399 {
400 	return (cbuf->write == cbuf->read)? true : false;
401 }
402 
403 /**
404  * rtw_cbuf_push - push a pointer into cbuf
405  * @cbuf: pointer of struct rtw_cbuf
406  * @buf: pointer to push in
407  *
408  * Lock free operation, be careful of the use scheme
409  * Returns: true push success
410  */
411 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
412 {
413 	if (rtw_cbuf_full(cbuf))
414 		return _FAIL;
415 
416 	DBG_871X("%s on %u\n", __func__, cbuf->write);
417 	cbuf->bufs[cbuf->write] = buf;
418 	cbuf->write = (cbuf->write+1)%cbuf->size;
419 
420 	return _SUCCESS;
421 }
422 
423 /**
424  * rtw_cbuf_pop - pop a pointer from cbuf
425  * @cbuf: pointer of struct rtw_cbuf
426  *
427  * Lock free operation, be careful of the use scheme
428  * Returns: pointer popped out
429  */
430 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
431 {
432 	void *buf;
433 	if (rtw_cbuf_empty(cbuf))
434 		return NULL;
435 
436         DBG_871X("%s on %u\n", __func__, cbuf->read);
437 	buf = cbuf->bufs[cbuf->read];
438 	cbuf->read = (cbuf->read+1)%cbuf->size;
439 
440 	return buf;
441 }
442 
443 /**
444  * rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization
445  * @size: size of pointer
446  *
447  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
448  */
449 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
450 {
451 	struct rtw_cbuf *cbuf;
452 
453 	cbuf = rtw_malloc(sizeof(*cbuf) + sizeof(void *) * size);
454 
455 	if (cbuf) {
456 		cbuf->write = cbuf->read = 0;
457 		cbuf->size = size;
458 	}
459 
460 	return cbuf;
461 }
462