]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8188eu/os_dep/osdep_service.c
Merge tag 'mfd-for-linus-3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / drivers / staging / rtl8188eu / 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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20
21
22 #define _OSDEP_SERVICE_C_
23
24 #include <osdep_service.h>
25 #include <drv_types.h>
26 #include <recv_osdep.h>
27 #include <linux/vmalloc.h>
28 #include <rtw_ioctl_set.h>
29
30 /*
31 * Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE
32 * @return: one of RTW_STATUS_CODE
33 */
34 inline int RTW_STATUS_CODE(int error_code)
35 {
36         if (error_code >= 0)
37                 return _SUCCESS;
38         return _FAIL;
39 }
40
41 u32 rtw_atoi(u8 *s)
42 {
43         int num = 0, flag = 0;
44         int i;
45         for (i = 0; i <= strlen(s); i++) {
46                 if (s[i] >= '0' && s[i] <= '9')
47                         num = num * 10 + s[i] - '0';
48                 else if (s[0] == '-' && i == 0)
49                         flag = 1;
50                 else
51                         break;
52         }
53         if (flag == 1)
54                 num = num * -1;
55         return num;
56 }
57
58 u8 *_rtw_malloc(u32 sz)
59 {
60         u8      *pbuf = NULL;
61
62         pbuf = kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
63         return pbuf;
64 }
65
66 u8 *_rtw_zmalloc(u32 sz)
67 {
68         u8      *pbuf = _rtw_malloc(sz);
69
70         if (pbuf != NULL)
71                 memset(pbuf, 0, sz);
72         return pbuf;
73 }
74
75 void *rtw_malloc2d(int h, int w, int size)
76 {
77         int j;
78
79         void **a = (void **)rtw_zmalloc(h*sizeof(void *) + h*w*size);
80         if (a == NULL) {
81                 pr_info("%s: alloc memory fail!\n", __func__);
82                 return NULL;
83         }
84
85         for (j = 0; j < h; j++)
86                 a[j] = ((char *)(a+h)) + j*w*size;
87
88         return a;
89 }
90
91 void rtw_mfree2d(void *pbuf, int h, int w, int size)
92 {
93         kfree(pbuf);
94 }
95
96 void _rtw_memset(void *pbuf, int c, u32 sz)
97 {
98         memset(pbuf, c, sz);
99 }
100
101 void _rtw_init_listhead(struct list_head *list)
102 {
103         INIT_LIST_HEAD(list);
104 }
105
106 /*
107 For the following list_xxx operations,
108 caller must guarantee the atomic context.
109 Otherwise, there will be racing condition.
110 */
111 u32     rtw_is_list_empty(struct list_head *phead)
112 {
113         if (list_empty(phead))
114                 return true;
115         else
116                 return false;
117 }
118
119 void rtw_list_insert_head(struct list_head *plist, struct list_head *phead)
120 {
121         list_add(plist, phead);
122 }
123
124 void rtw_list_insert_tail(struct list_head *plist, struct list_head *phead)
125 {
126         list_add_tail(plist, phead);
127 }
128
129 /*
130 Caller must check if the list is empty before calling rtw_list_delete
131 */
132
133 u32 _rtw_down_sema(struct semaphore *sema)
134 {
135         if (down_interruptible(sema))
136                 return _FAIL;
137         else
138                 return _SUCCESS;
139 }
140
141 void    _rtw_init_queue(struct __queue *pqueue)
142 {
143         _rtw_init_listhead(&(pqueue->queue));
144         spin_lock_init(&(pqueue->lock));
145 }
146
147 u32       _rtw_queue_empty(struct __queue *pqueue)
148 {
149         return rtw_is_list_empty(&(pqueue->queue));
150 }
151
152 u32 rtw_end_of_queue_search(struct list_head *head, struct list_head *plist)
153 {
154         if (head == plist)
155                 return true;
156         else
157                 return false;
158 }
159
160 inline u32 rtw_systime_to_ms(u32 systime)
161 {
162         return systime * 1000 / HZ;
163 }
164
165 inline u32 rtw_ms_to_systime(u32 ms)
166 {
167         return ms * HZ / 1000;
168 }
169
170 /*  the input parameter start must be in jiffies */
171 inline s32 rtw_get_passing_time_ms(u32 start)
172 {
173         return rtw_systime_to_ms(jiffies-start);
174 }
175
176 inline s32 rtw_get_time_interval_ms(u32 start, u32 end)
177 {
178         return rtw_systime_to_ms(end-start);
179 }
180
181 void rtw_sleep_schedulable(int ms)
182 {
183         u32 delta;
184
185         delta = (ms * HZ)/1000;/* ms) */
186         if (delta == 0)
187                 delta = 1;/*  1 ms */
188         set_current_state(TASK_INTERRUPTIBLE);
189         if (schedule_timeout(delta) != 0)
190                 return;
191 }
192
193 #define RTW_SUSPEND_LOCK_NAME "rtw_wifi"
194
195 struct net_device *rtw_alloc_etherdev_with_old_priv(int sizeof_priv,
196                                                     void *old_priv)
197 {
198         struct net_device *pnetdev;
199         struct rtw_netdev_priv_indicator *pnpi;
200
201         pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
202         if (!pnetdev)
203                 goto RETURN;
204
205         pnpi = netdev_priv(pnetdev);
206         pnpi->priv = old_priv;
207         pnpi->sizeof_priv = sizeof_priv;
208
209 RETURN:
210         return pnetdev;
211 }
212
213 struct net_device *rtw_alloc_etherdev(int sizeof_priv)
214 {
215         struct net_device *pnetdev;
216         struct rtw_netdev_priv_indicator *pnpi;
217
218         pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
219         if (!pnetdev)
220                 goto RETURN;
221
222         pnpi = netdev_priv(pnetdev);
223
224         pnpi->priv = vzalloc(sizeof_priv);
225         if (!pnpi->priv) {
226                 free_netdev(pnetdev);
227                 pnetdev = NULL;
228                 goto RETURN;
229         }
230
231         pnpi->sizeof_priv = sizeof_priv;
232 RETURN:
233         return pnetdev;
234 }
235
236 void rtw_free_netdev(struct net_device *netdev)
237 {
238         struct rtw_netdev_priv_indicator *pnpi;
239
240         if (!netdev)
241                 goto RETURN;
242
243         pnpi = netdev_priv(netdev);
244
245         if (!pnpi->priv)
246                 goto RETURN;
247
248         vfree(pnpi->priv);
249         free_netdev(netdev);
250
251 RETURN:
252         return;
253 }
254
255 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
256 {
257         struct net_device *pnetdev;
258         struct net_device *cur_pnetdev;
259         struct rereg_nd_name_data *rereg_priv;
260         int ret;
261
262         if (!padapter)
263                 goto error;
264
265         cur_pnetdev = padapter->pnetdev;
266         rereg_priv = &padapter->rereg_nd_name_priv;
267
268         /* free the old_pnetdev */
269         if (rereg_priv->old_pnetdev) {
270                 free_netdev(rereg_priv->old_pnetdev);
271                 rereg_priv->old_pnetdev = NULL;
272         }
273
274         if (!rtnl_is_locked())
275                 unregister_netdev(cur_pnetdev);
276         else
277                 unregister_netdevice(cur_pnetdev);
278
279         rtw_proc_remove_one(cur_pnetdev);
280
281         rereg_priv->old_pnetdev = cur_pnetdev;
282
283         pnetdev = rtw_init_netdev(padapter);
284         if (!pnetdev)  {
285                 ret = -1;
286                 goto error;
287         }
288
289         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(adapter_to_dvobj(padapter)));
290
291         rtw_init_netdev_name(pnetdev, ifname);
292
293         memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
294
295         if (!rtnl_is_locked())
296                 ret = register_netdev(pnetdev);
297         else
298                 ret = register_netdevice(pnetdev);
299         if (ret != 0) {
300                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
301                          ("register_netdev() failed\n"));
302                 goto error;
303         }
304         rtw_proc_init_one(pnetdev);
305         return 0;
306 error:
307         return -1;
308 }
309
310 u64 rtw_modular64(u64 x, u64 y)
311 {
312         return do_div(x, y);
313 }
314
315 u64 rtw_division64(u64 x, u64 y)
316 {
317         do_div(x, y);
318         return x;
319 }
320
321 void rtw_buf_free(u8 **buf, u32 *buf_len)
322 {
323         *buf_len = 0;
324         kfree(*buf);
325         *buf = NULL;
326 }
327
328 void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
329 {
330         u32 ori_len = 0, dup_len = 0;
331         u8 *ori = NULL;
332         u8 *dup = NULL;
333
334         if (!buf || !buf_len)
335                 return;
336
337         if (!src || !src_len)
338                 goto keep_ori;
339
340         /* duplicate src */
341         dup = rtw_malloc(src_len);
342         if (dup) {
343                 dup_len = src_len;
344                 memcpy(dup, src, dup_len);
345         }
346
347 keep_ori:
348         ori = *buf;
349         ori_len = *buf_len;
350
351         /* replace buf with dup */
352         *buf_len = 0;
353         *buf = dup;
354         *buf_len = dup_len;
355
356         /* free ori */
357         kfree(ori);
358 }
359
360
361 /**
362  * rtw_cbuf_full - test if cbuf is full
363  * @cbuf: pointer of struct rtw_cbuf
364  *
365  * Returns: true if cbuf is full
366  */
367 inline bool rtw_cbuf_full(struct rtw_cbuf *cbuf)
368 {
369         return (cbuf->write == cbuf->read-1) ? true : false;
370 }
371
372 /**
373  * rtw_cbuf_empty - test if cbuf is empty
374  * @cbuf: pointer of struct rtw_cbuf
375  *
376  * Returns: true if cbuf is empty
377  */
378 inline bool rtw_cbuf_empty(struct rtw_cbuf *cbuf)
379 {
380         return (cbuf->write == cbuf->read) ? true : false;
381 }
382
383 /**
384  * rtw_cbuf_push - push a pointer into cbuf
385  * @cbuf: pointer of struct rtw_cbuf
386  * @buf: pointer to push in
387  *
388  * Lock free operation, be careful of the use scheme
389  * Returns: true push success
390  */
391 bool rtw_cbuf_push(struct rtw_cbuf *cbuf, void *buf)
392 {
393         if (rtw_cbuf_full(cbuf))
394                 return _FAIL;
395
396         if (0)
397                 DBG_88E("%s on %u\n", __func__, cbuf->write);
398         cbuf->bufs[cbuf->write] = buf;
399         cbuf->write = (cbuf->write+1)%cbuf->size;
400
401         return _SUCCESS;
402 }
403
404 /**
405  * rtw_cbuf_pop - pop a pointer from cbuf
406  * @cbuf: pointer of struct rtw_cbuf
407  *
408  * Lock free operation, be careful of the use scheme
409  * Returns: pointer popped out
410  */
411 void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
412 {
413         void *buf;
414         if (rtw_cbuf_empty(cbuf))
415                 return NULL;
416
417         if (0)
418                 DBG_88E("%s on %u\n", __func__, cbuf->read);
419         buf = cbuf->bufs[cbuf->read];
420         cbuf->read = (cbuf->read+1)%cbuf->size;
421
422         return buf;
423 }
424
425 /**
426  * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
427  * @size: size of pointer
428  *
429  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
430  */
431 struct rtw_cbuf *rtw_cbuf_alloc(u32 size)
432 {
433         struct rtw_cbuf *cbuf;
434
435         cbuf = (struct rtw_cbuf *)rtw_malloc(sizeof(*cbuf) +
436                sizeof(void *)*size);
437
438         if (cbuf) {
439                 cbuf->write = 0;
440                 cbuf->read = 0;
441                 cbuf->size = size;
442         }
443         return cbuf;
444 }