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 =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 */
isFileReadable(char * path)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 */
retriveFromFile(char * path,u8 * buf,u32 sz)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 */
rtw_is_file_readable(char * path)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 */
rtw_retrive_from_file(char * path,u8 * buf,u32 sz)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
rtw_alloc_etherdev_with_old_priv(int sizeof_priv,void * old_priv)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
rtw_alloc_etherdev(int sizeof_priv)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
rtw_free_netdev(struct net_device * netdev)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
rtw_change_ifname(struct adapter * padapter,const char * ifname)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
rtw_modular64(u64 x,u64 y)326 u64 rtw_modular64(u64 x, u64 y)
327 {
328 return do_div(x, y);
329 }
330
rtw_buf_free(u8 ** buf,u32 * buf_len)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
rtw_buf_update(u8 ** buf,u32 * buf_len,u8 * src,u32 src_len)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 */
rtw_cbuf_full(struct rtw_cbuf * cbuf)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 */
rtw_cbuf_empty(struct rtw_cbuf * cbuf)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 */
rtw_cbuf_push(struct rtw_cbuf * cbuf,void * buf)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 */
rtw_cbuf_pop(struct rtw_cbuf * cbuf)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 */
rtw_cbuf_alloc(u32 size)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