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