blob: 2579a404a766521e7d8f4e28c5150532fc13bcb9 [file] [log] [blame]
Larry Fingera2c60d42013-08-21 22:33:58 -05001/******************************************************************************
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*/
34inline int RTW_STATUS_CODE(int error_code)
35{
36 if (error_code >= 0)
37 return _SUCCESS;
38 return _FAIL;
39}
40
41u32 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;
Teodora Baluta1f9d82d2013-11-08 00:13:46 +020055 return num;
Larry Fingera2c60d42013-08-21 22:33:58 -050056}
57
Larry Fingera2c60d42013-08-21 22:33:58 -050058u8 *_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
66u8 *_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
75void *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
91void rtw_mfree2d(void *pbuf, int h, int w, int size)
92{
93 kfree(pbuf);
94}
95
Larry Fingera2c60d42013-08-21 22:33:58 -050096void _rtw_memset(void *pbuf, int c, u32 sz)
97{
98 memset(pbuf, c, sz);
99}
100
101void _rtw_init_listhead(struct list_head *list)
102{
103 INIT_LIST_HEAD(list);
104}
105
106/*
107For the following list_xxx operations,
108caller must guarantee the atomic context.
109Otherwise, there will be racing condition.
110*/
111u32 rtw_is_list_empty(struct list_head *phead)
112{
113 if (list_empty(phead))
114 return true;
115 else
116 return false;
117}
118
119void rtw_list_insert_head(struct list_head *plist, struct list_head *phead)
120{
121 list_add(plist, phead);
122}
123
124void rtw_list_insert_tail(struct list_head *plist, struct list_head *phead)
125{
126 list_add_tail(plist, phead);
127}
128
129/*
130Caller must check if the list is empty before calling rtw_list_delete
131*/
132
Larry Fingera2c60d42013-08-21 22:33:58 -0500133u32 _rtw_down_sema(struct semaphore *sema)
134{
135 if (down_interruptible(sema))
136 return _FAIL;
137 else
138 return _SUCCESS;
139}
140
Larry Fingera2c60d42013-08-21 22:33:58 -0500141void _rtw_init_queue(struct __queue *pqueue)
142{
143 _rtw_init_listhead(&(pqueue->queue));
Larry Fingerf214e522013-12-19 22:38:38 -0600144 spin_lock_init(&(pqueue->lock));
Larry Fingera2c60d42013-08-21 22:33:58 -0500145}
146
147u32 _rtw_queue_empty(struct __queue *pqueue)
148{
149 return rtw_is_list_empty(&(pqueue->queue));
150}
151
152u32 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
Larry Fingera2c60d42013-08-21 22:33:58 -0500160inline u32 rtw_systime_to_ms(u32 systime)
161{
162 return systime * 1000 / HZ;
163}
164
165inline u32 rtw_ms_to_systime(u32 ms)
166{
167 return ms * HZ / 1000;
168}
169
Larry Fingerc01fb492013-12-19 22:38:40 -0600170/* the input parameter start must be in jiffies */
Larry Fingera2c60d42013-08-21 22:33:58 -0500171inline s32 rtw_get_passing_time_ms(u32 start)
172{
173 return rtw_systime_to_ms(jiffies-start);
174}
175
176inline s32 rtw_get_time_interval_ms(u32 start, u32 end)
177{
178 return rtw_systime_to_ms(end-start);
179}
180
181void 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
Larry Fingera2c60d42013-08-21 22:33:58 -0500193#define RTW_SUSPEND_LOCK_NAME "rtw_wifi"
194
Larry Fingera2c60d42013-08-21 22:33:58 -0500195struct 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
209RETURN:
210 return pnetdev;
211}
212
213struct 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
Larry Finger2397c6e2014-02-06 20:45:42 -0600224 pnpi->priv = vzalloc(sizeof_priv);
Larry Fingera2c60d42013-08-21 22:33:58 -0500225 if (!pnpi->priv) {
226 free_netdev(pnetdev);
227 pnetdev = NULL;
228 goto RETURN;
229 }
230
231 pnpi->sizeof_priv = sizeof_priv;
232RETURN:
233 return pnetdev;
234}
235
236void 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
Larry Finger03bd6ae2014-02-06 20:45:43 -0600248 vfree(pnpi->priv);
Larry Fingera2c60d42013-08-21 22:33:58 -0500249 free_netdev(netdev);
250
251RETURN:
252 return;
253}
254
255int rtw_change_ifname(struct adapter *padapter, const char *ifname)
256{
257 struct net_device *pnetdev;
Larry Fingerefbff732013-09-04 15:56:00 -0500258 struct net_device *cur_pnetdev;
Larry Fingera2c60d42013-08-21 22:33:58 -0500259 struct rereg_nd_name_data *rereg_priv;
260 int ret;
261
262 if (!padapter)
263 goto error;
264
Larry Fingerefbff732013-09-04 15:56:00 -0500265 cur_pnetdev = padapter->pnetdev;
Larry Fingera2c60d42013-08-21 22:33:58 -0500266 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;
306error:
307 return -1;
308}
309
310u64 rtw_modular64(u64 x, u64 y)
311{
312 return do_div(x, y);
313}
314
315u64 rtw_division64(u64 x, u64 y)
316{
317 do_div(x, y);
318 return x;
319}
320
321void rtw_buf_free(u8 **buf, u32 *buf_len)
322{
323 *buf_len = 0;
324 kfree(*buf);
325 *buf = NULL;
326}
327
328void 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
347keep_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 */
367inline 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 */
378inline 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 */
391bool 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 */
411void *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/**
Masanari Iida7efc02c2013-09-27 00:11:46 +0900426 * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
Larry Fingera2c60d42013-08-21 22:33:58 -0500427 * @size: size of pointer
428 *
429 * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
430 */
431struct 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}