c0e893db6792b8ce8bbb739da76f56ea87d68475
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / hal / rtl8723b / usb / rtl8723bu_recv.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 _RTL8723BU_RECV_C_
21
22 #include <rtl8723b_hal.h>
23
24 int     rtl8723bu_init_recv_priv(_adapter *padapter)
25 {
26         struct recv_priv        *precvpriv = &padapter->recvpriv;
27         int     i, res = _SUCCESS;
28         struct recv_buf *precvbuf;
29
30 #ifdef CONFIG_RECV_THREAD_MODE  
31         _rtw_init_sema(&precvpriv->recv_sema, 0);//will be removed
32         _rtw_init_sema(&precvpriv->terminate_recvthread_sema, 0);//will be removed
33 #endif
34
35 #ifdef PLATFORM_LINUX
36         tasklet_init(&precvpriv->recv_tasklet,
37              (void(*)(unsigned long))usb_recv_tasklet,
38              (unsigned long)padapter);
39 #endif
40
41 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
42 #ifdef PLATFORM_LINUX
43         precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
44         if(precvpriv->int_in_urb == NULL){
45                 DBG_8192C("alloc_urb for interrupt in endpoint fail !!!!\n");
46         }
47 #endif
48         precvpriv->int_in_buf = rtw_zmalloc(USB_INTR_CONTENT_LENGTH);
49         if(precvpriv->int_in_buf == NULL){
50                 DBG_8192C("alloc_mem for interrupt in endpoint fail !!!!\n");
51         }
52 #endif
53
54         //init recv_buf
55         _rtw_init_queue(&precvpriv->free_recv_buf_queue);
56
57         _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
58
59         precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF *sizeof(struct recv_buf) + 4);
60         if(precvpriv->pallocated_recv_buf==NULL){
61                 res= _FAIL;
62                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("alloc recv_buf fail!\n"));
63                 goto exit;
64         }
65         _rtw_memset(precvpriv->pallocated_recv_buf, 0, NR_RECVBUFF *sizeof(struct recv_buf) + 4);
66
67         precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
68         //precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
69         //                                              ((uint) (precvpriv->pallocated_recv_buf) &(4-1));
70
71
72         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
73
74         for(i=0; i < NR_RECVBUFF ; i++)
75         {
76                 _rtw_init_listhead(&precvbuf->list);
77
78                 _rtw_spinlock_init(&precvbuf->recvbuf_lock);
79
80                 precvbuf->alloc_sz = MAX_RECVBUF_SZ;
81
82                 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
83                 if(res==_FAIL)
84                         break;
85
86                 precvbuf->ref_cnt = 0;
87                 precvbuf->adapter =padapter;
88
89
90                 //rtw_list_insert_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue));
91
92                 precvbuf++;
93
94         }
95
96         precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
97
98 #ifdef PLATFORM_LINUX
99
100         skb_queue_head_init(&precvpriv->rx_skb_queue);
101
102 #ifdef CONFIG_PREALLOC_RECV_SKB
103         {
104                 int i;
105                 SIZE_PTR tmpaddr=0;
106                 SIZE_PTR alignment=0;
107                 struct sk_buff *pskb=NULL;
108
109                 skb_queue_head_init(&precvpriv->free_recv_skb_queue);
110
111                 for(i=0; i<NR_PREALLOC_RECV_SKB; i++)
112                 {
113
114 #ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
115                         pskb = rtw_alloc_skb_premem();
116 #else
117                         pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
118 #endif
119
120                         if(pskb)
121                         {
122                                 pskb->dev = padapter->pnetdev;
123
124 #ifndef CONFIG_PREALLOC_RX_SKB_BUFFER
125                                 tmpaddr = (SIZE_PTR)pskb->data;
126                                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
127                                 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
128 #endif //!
129
130                                 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
131                         }
132
133                         pskb=NULL;
134
135                 }
136         }
137 #endif
138
139 #endif
140
141 exit:
142
143         return res;
144
145 }
146
147 void rtl8723bu_free_recv_priv (_adapter *padapter)
148 {
149         int     i;
150         struct recv_buf *precvbuf;
151         struct recv_priv        *precvpriv = &padapter->recvpriv;
152
153         precvbuf = (struct recv_buf *)precvpriv->precv_buf;
154
155         for(i=0; i < NR_RECVBUFF ; i++)
156         {
157                 rtw_os_recvbuf_resource_free(padapter, precvbuf);
158                 precvbuf++;
159         }
160
161         if(precvpriv->pallocated_recv_buf)
162                 rtw_mfree(precvpriv->pallocated_recv_buf, NR_RECVBUFF *sizeof(struct recv_buf) + 4);
163
164 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
165 #ifdef PLATFORM_LINUX
166         if(precvpriv->int_in_urb)
167         {
168                 usb_free_urb(precvpriv->int_in_urb);
169         }
170 #endif
171         if(precvpriv->int_in_buf)
172                 rtw_mfree(precvpriv->int_in_buf, USB_INTR_CONTENT_LENGTH);
173 #endif
174
175 #ifdef PLATFORM_LINUX
176
177         if (skb_queue_len(&precvpriv->rx_skb_queue)) {
178                 DBG_8192C(KERN_WARNING "rx_skb_queue not empty\n");
179         }
180
181         rtw_skb_queue_purge(&precvpriv->rx_skb_queue);
182
183 #ifdef CONFIG_PREALLOC_RECV_SKB
184
185         if (skb_queue_len(&precvpriv->free_recv_skb_queue)) {
186                 DBG_8192C(KERN_WARNING "free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
187         }
188
189 #ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
190         {
191                 int i=0;
192                 struct sk_buff *skb;
193
194                 while ((skb = skb_dequeue(&precvpriv->free_recv_skb_queue)) != NULL)
195                 {
196                         if(i<NR_PREALLOC_RECV_SKB)
197                                 rtw_free_skb_premem(skb);
198                         else                            
199                                 _rtw_skb_free(skb);
200
201                         i++;
202                 }       
203         }       
204 #else 
205         rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
206 #endif //CONFIG_PREALLOC_RX_SKB_BUFFER
207
208 #endif
209
210 #endif
211 }
212