GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / staging / rtl8723bs / os_dep / osdep_service.c
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 }