8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / hal / hal_hci / hal_usb.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 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 #define _HAL_USB_C_
21
22 #include <drv_types.h>
23 #include <hal_data.h>
24
25 int     usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
26 {
27         struct recv_priv        *precvpriv = &padapter->recvpriv;
28         int     i, res = _SUCCESS;
29         struct recv_buf *precvbuf;
30
31 #ifdef CONFIG_RECV_THREAD_MODE
32         _rtw_init_sema(&precvpriv->recv_sema, 0);//will be removed
33         _rtw_init_sema(&precvpriv->terminate_recvthread_sema, 0);//will be removed
34 #endif /* CONFIG_RECV_THREAD_MODE */
35
36 #ifdef PLATFORM_LINUX
37         tasklet_init(&precvpriv->recv_tasklet,
38                 (void(*)(unsigned long))usb_recv_tasklet,
39                 (unsigned long)padapter);
40 #endif /* PLATFORM_LINUX */
41
42 #ifdef PLATFORM_FREEBSD 
43         #ifdef CONFIG_RX_INDICATE_QUEUE
44         TASK_INIT(&precvpriv->rx_indicate_tasklet, 0, rtw_rx_indicate_tasklet, padapter);
45         #endif /* CONFIG_RX_INDICATE_QUEUE */
46 #endif /* PLATFORM_FREEBSD */
47
48 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
49 #ifdef PLATFORM_LINUX
50         precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
51         if(precvpriv->int_in_urb == NULL){
52                 res = _FAIL;
53                 DBG_8192C("alloc_urb for interrupt in endpoint fail !!!!\n");
54                 goto exit;
55         }
56 #endif /* PLATFORM_LINUX */
57         precvpriv->int_in_buf = rtw_zmalloc(ini_in_buf_sz);
58         if(precvpriv->int_in_buf == NULL){
59                 res = _FAIL;
60                 DBG_8192C("alloc_mem for interrupt in endpoint fail !!!!\n");
61                 goto exit;
62         }
63 #endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
64
65         /* init recv_buf */
66         _rtw_init_queue(&precvpriv->free_recv_buf_queue);
67         _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
68         #ifndef CONFIG_USE_USB_BUFFER_ALLOC_RX
69         /* this is used only when RX_IOBUF is sk_buff */
70         skb_queue_head_init(&precvpriv->free_recv_skb_queue);
71         #endif
72
73         DBG_871X("NR_RECVBUFF: %d\n", NR_RECVBUFF);
74         DBG_871X("MAX_RECVBUF_SZ: %d\n", MAX_RECVBUF_SZ);
75         precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF *sizeof(struct recv_buf) + 4);
76         if(precvpriv->pallocated_recv_buf==NULL){
77                 res= _FAIL;
78                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("alloc recv_buf fail!\n"));
79                 goto exit;
80         }
81
82         precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
83
84         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
85
86         for(i=0; i < NR_RECVBUFF ; i++)
87         {
88                 _rtw_init_listhead(&precvbuf->list);
89
90                 _rtw_spinlock_init(&precvbuf->recvbuf_lock);
91
92                 precvbuf->alloc_sz = MAX_RECVBUF_SZ;
93
94                 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
95                 if(res==_FAIL)
96                         break;
97
98                 precvbuf->ref_cnt = 0;
99                 precvbuf->adapter =padapter;
100
101                 //rtw_list_insert_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue));
102
103                 precvbuf++;
104         }
105
106         precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
107
108 #if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
109
110         skb_queue_head_init(&precvpriv->rx_skb_queue);
111
112 #ifdef CONFIG_RX_INDICATE_QUEUE
113         memset(&precvpriv->rx_indicate_queue, 0, sizeof(struct ifqueue));
114         mtx_init(&precvpriv->rx_indicate_queue.ifq_mtx, "rx_indicate_queue", NULL, MTX_DEF);
115 #endif /* CONFIG_RX_INDICATE_QUEUE */
116
117 #ifdef CONFIG_PREALLOC_RECV_SKB
118         {
119                 int i;
120                 SIZE_PTR tmpaddr=0;
121                 SIZE_PTR alignment=0;
122                 struct sk_buff *pskb=NULL;
123
124                 DBG_871X("NR_PREALLOC_RECV_SKB: %d\n", NR_PREALLOC_RECV_SKB);
125                 for(i=0; i<NR_PREALLOC_RECV_SKB; i++)
126                 {
127 #ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
128                         pskb = rtw_alloc_skb_premem();
129 #else
130                         pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
131 #endif //CONFIG_PREALLOC_RX_SKB_BUFFER
132
133                         if(pskb)
134                         {
135                                 #ifdef PLATFORM_FREEBSD
136                                 pskb->dev = padapter->pifp;
137                                 #else
138                                 pskb->dev = padapter->pnetdev;
139                                 #endif //PLATFORM_FREEBSD
140
141 #ifndef CONFIG_PREALLOC_RX_SKB_BUFFER
142                                 tmpaddr = (SIZE_PTR)pskb->data;
143                                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
144                                 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
145 #endif
146                                 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
147                         }
148                 }
149         }
150 #endif /* CONFIG_PREALLOC_RECV_SKB */
151
152 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) */
153
154 exit:
155
156         return res;
157 }
158
159 void usb_free_recv_priv (_adapter *padapter, u16 ini_in_buf_sz)
160 {
161         int i;
162         struct recv_buf *precvbuf;
163         struct recv_priv        *precvpriv = &padapter->recvpriv;
164
165         precvbuf = (struct recv_buf *)precvpriv->precv_buf;
166
167         for(i=0; i < NR_RECVBUFF ; i++)
168         {
169                 rtw_os_recvbuf_resource_free(padapter, precvbuf);
170                 precvbuf++;
171         }
172
173         if(precvpriv->pallocated_recv_buf)
174                 rtw_mfree(precvpriv->pallocated_recv_buf, NR_RECVBUFF *sizeof(struct recv_buf) + 4);
175
176 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
177 #ifdef PLATFORM_LINUX
178         if(precvpriv->int_in_urb)
179         {
180                 usb_free_urb(precvpriv->int_in_urb);
181         }
182 #endif
183         if(precvpriv->int_in_buf)
184                 rtw_mfree(precvpriv->int_in_buf, ini_in_buf_sz);
185 #endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
186
187 #ifdef PLATFORM_LINUX
188
189         if (skb_queue_len(&precvpriv->rx_skb_queue)) {
190                 DBG_8192C(KERN_WARNING "rx_skb_queue not empty\n");
191         }
192
193         rtw_skb_queue_purge(&precvpriv->rx_skb_queue);
194
195         if (skb_queue_len(&precvpriv->free_recv_skb_queue)) {
196                 DBG_8192C(KERN_WARNING "free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
197         }
198
199 #if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX)
200         #if defined(CONFIG_PREALLOC_RECV_SKB) && defined(CONFIG_PREALLOC_RX_SKB_BUFFER)
201         {
202                 struct sk_buff *skb;
203
204                 while ((skb = skb_dequeue(&precvpriv->free_recv_skb_queue)) != NULL)
205                 {
206                         if (rtw_free_skb_premem(skb) != 0)
207                                 rtw_skb_free(skb);
208                 }
209         }
210         #else
211         rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
212         #endif /* defined(CONFIG_PREALLOC_RX_SKB_BUFFER) && defined(CONFIG_PREALLOC_RECV_SKB) */
213 #endif /* !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX) */
214
215 #endif /* PLATFORM_LINUX */
216
217 #ifdef PLATFORM_FREEBSD
218         struct sk_buff  *pskb;
219         while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue)))
220         {
221                 rtw_skb_free(pskb);
222         }
223
224         #if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX)
225         rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
226         #endif
227
228 #ifdef CONFIG_RX_INDICATE_QUEUE
229         struct mbuf *m;
230         for (;;) {
231                 IF_DEQUEUE(&precvpriv->rx_indicate_queue, m);
232                 if (m == NULL)
233                         break;
234                 m_freem(m);
235         }
236         mtx_destroy(&precvpriv->rx_indicate_queue.ifq_mtx);
237 #endif /* CONFIG_RX_INDICATE_QUEUE */
238
239 #endif /* PLATFORM_FREEBSD */
240 }
241
242 #ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
243 int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len)
244 {
245         u8 request;
246         u8 requesttype;
247         u16 wvalue;
248         u16 index;
249         int ret;
250
251         requesttype = VENDOR_WRITE;//write_out
252         request = REALTEK_USB_VENQT_CMD_REQ;
253         index = REALTEK_USB_VENQT_CMD_IDX;//n/a
254
255         wvalue = (u16)(addr&0x0000ffff);
256
257         ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype);
258
259         return ret;
260 }
261
262 int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
263 {
264         u8 data;
265         int ret;
266         struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)pintfhdl->pintf_dev;
267         struct usb_device *udev=pdvobjpriv->pusbdev;
268
269         _func_enter_;
270         data = val;
271         ret = usb_write_async(udev, addr, &data, 1);
272         _func_exit_;
273
274         return ret;
275 }
276
277 int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
278 {
279         u16 data;
280         int ret;
281         struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)pintfhdl->pintf_dev;
282         struct usb_device *udev=pdvobjpriv->pusbdev;
283
284         _func_enter_;
285         data = val;
286         ret = usb_write_async(udev, addr, &data, 2);
287         _func_exit_;
288
289         return ret;
290 }
291
292 int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
293 {
294         u32 data;
295         int ret;
296         struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)pintfhdl->pintf_dev;
297         struct usb_device *udev=pdvobjpriv->pusbdev;
298
299         _func_enter_;
300         data = val;
301         ret = usb_write_async(udev, addr, &data, 4);
302         _func_exit_;
303         
304         return ret;
305 }
306 #endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
307
308 u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
309 {
310         u8 request;
311         u8 requesttype;
312         u16 wvalue;
313         u16 index;
314         u16 len;
315         u8 data=0;
316         
317         _func_enter_;
318
319         request = 0x05;
320         requesttype = 0x01;//read_in
321         index = 0;//n/a
322
323         wvalue = (u16)(addr&0x0000ffff);
324         len = 1;        
325         usbctrl_vendorreq(pintfhdl, request, wvalue, index,
326                                         &data, len, requesttype);
327
328         _func_exit_;
329
330         return data;    
331 }
332
333 u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
334 {       
335         u8 request;
336         u8 requesttype;
337         u16 wvalue;
338         u16 index;
339         u16 len;
340         u16 data=0;
341         
342         _func_enter_;
343
344         request = 0x05;
345         requesttype = 0x01;//read_in
346         index = 0;//n/a
347
348         wvalue = (u16)(addr&0x0000ffff);
349         len = 2;        
350         usbctrl_vendorreq(pintfhdl, request, wvalue, index,
351                                         &data, len, requesttype);
352
353         _func_exit_;
354
355         return data;
356         
357 }
358
359 u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
360 {
361         u8 request;
362         u8 requesttype;
363         u16 wvalue;
364         u16 index;
365         u16 len;
366         u32 data=0;
367         
368         _func_enter_;
369
370         request = 0x05;
371         requesttype = 0x01;//read_in
372         index = 0;//n/a
373
374         wvalue = (u16)(addr&0x0000ffff);
375         len = 4;
376         usbctrl_vendorreq(pintfhdl, request, wvalue, index,
377                                                 &data, len, requesttype);
378         
379         _func_exit_;
380
381         return data;
382 }
383
384 int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
385 {
386         u8 request;
387         u8 requesttype;
388         u16 wvalue;
389         u16 index;
390         u16 len;
391         u8 data;
392         int ret;
393         
394         _func_enter_;
395
396         request = 0x05;
397         requesttype = 0x00;//write_out
398         index = 0;//n/a
399
400         wvalue = (u16)(addr&0x0000ffff);
401         len = 1;
402         
403         data = val;
404         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
405                                                 &data, len, requesttype);
406         
407         _func_exit_;
408         
409         return ret;
410 }
411
412 int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
413 {       
414         u8 request;
415         u8 requesttype;
416         u16 wvalue;
417         u16 index;
418         u16 len;
419         u16 data;
420         int ret;
421         
422         _func_enter_;
423
424         request = 0x05;
425         requesttype = 0x00;//write_out
426         index = 0;//n/a
427
428         wvalue = (u16)(addr&0x0000ffff);
429         len = 2;
430         
431         data = val;
432         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
433                                                 &data, len, requesttype);
434         
435         _func_exit_;
436         
437         return ret;
438         
439 }
440
441 int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
442 {
443         u8 request;
444         u8 requesttype;
445         u16 wvalue;
446         u16 index;
447         u16 len;
448         u32 data;
449         int ret;
450         
451         _func_enter_;
452
453         request = 0x05;
454         requesttype = 0x00;//write_out
455         index = 0;//n/a
456
457         wvalue = (u16)(addr&0x0000ffff);
458         len = 4;
459         data =val;
460         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
461                                                 &data, len, requesttype);
462
463         _func_exit_;
464         
465         return ret;
466         
467 }
468
469 int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
470 {
471         u8 request;
472         u8 requesttype;
473         u16 wvalue;
474         u16 index;
475         u16 len;
476         u8 buf[VENDOR_CMD_MAX_DATA_LEN]={0};
477         int ret;
478         
479         _func_enter_;
480
481         request = 0x05;
482         requesttype = 0x00;//write_out
483         index = 0;//n/a
484
485         wvalue = (u16)(addr&0x0000ffff);
486         len = length;
487          _rtw_memcpy(buf, pdata, len );
488         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
489                                                 buf, len, requesttype);
490         
491         _func_exit_;
492         
493         return ret;
494         
495 }