OSDN Git Service

Remove memcpy wrapper
[android-x86/external-modules-rtl8723au.git] / os_dep / recv_linux.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 _RECV_OSDEP_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25
26 #include <wifi.h>
27 #include <recv_osdep.h>
28
29 #include <osdep_intf.h>
30 #include <ethernet.h>
31
32 #ifdef CONFIG_USB_HCI
33 #include <usb_ops.h>
34 #endif
35
36 //init os related resource in struct recv_priv
37 int rtw_os_recv_resource_init(struct recv_priv *precvpriv, _adapter *padapter)
38 {
39         int     res=_SUCCESS;
40
41         return res;
42 }
43
44 //alloc os related resource in union recv_frame
45 int rtw_os_recv_resource_alloc(_adapter *padapter, union recv_frame *precvframe)
46 {
47         int     res=_SUCCESS;
48
49         precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL;
50
51         return res;
52
53 }
54
55 //free os related resource in union recv_frame
56 void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
57 {
58
59 }
60
61
62 //alloc os related resource in struct recv_buf
63 int rtw_os_recvbuf_resource_alloc(_adapter *padapter, struct recv_buf *precvbuf)
64 {
65         int res=_SUCCESS;
66
67 #ifdef CONFIG_USB_HCI
68         struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(padapter);
69         struct usb_device       *pusbd = pdvobjpriv->pusbdev;
70
71         precvbuf->irp_pending = _FALSE;
72         precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
73         if(precvbuf->purb == NULL){
74                 res = _FAIL;
75         }
76
77         precvbuf->pskb = NULL;
78
79         precvbuf->reuse = _FALSE;
80
81         precvbuf->pallocated_buf  = precvbuf->pbuf = NULL;
82
83         precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pend = NULL;
84
85         precvbuf->transfer_len = 0;
86
87         precvbuf->len = 0;
88
89         #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
90         precvbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)precvbuf->alloc_sz, &precvbuf->dma_transfer_addr);
91         precvbuf->pbuf = precvbuf->pallocated_buf;
92         if(precvbuf->pallocated_buf == NULL)
93                 return _FAIL;
94         #endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
95
96 #endif //CONFIG_USB_HCI
97
98         return res;
99 }
100
101 //free os related resource in struct recv_buf
102 int rtw_os_recvbuf_resource_free(_adapter *padapter, struct recv_buf *precvbuf)
103 {
104         int ret = _SUCCESS;
105
106 #ifdef CONFIG_USB_HCI
107
108 #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
109
110         struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(padapter);
111         struct usb_device       *pusbd = pdvobjpriv->pusbdev;
112
113         rtw_usb_buffer_free(pusbd, (size_t)precvbuf->alloc_sz, precvbuf->pallocated_buf, precvbuf->dma_transfer_addr);
114         precvbuf->pallocated_buf =  NULL;
115         precvbuf->dma_transfer_addr = 0;
116
117 #endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
118
119         if(precvbuf->purb)
120         {
121                 //usb_kill_urb(precvbuf->purb);
122                 usb_free_urb(precvbuf->purb);
123         }
124
125 #endif //CONFIG_USB_HCI
126
127
128         if(precvbuf->pskb)
129                 dev_kfree_skb_any(precvbuf->pskb);
130
131
132         return ret;
133
134 }
135
136 void rtw_handle_tkip_mic_err(_adapter *padapter,u8 bgroup)
137 {
138 #ifdef CONFIG_IOCTL_CFG80211
139         enum nl80211_key_type key_type;
140 #endif
141         union iwreq_data wrqu;
142         struct iw_michaelmicfailure    ev;
143         struct mlme_priv*              pmlmepriv  = &padapter->mlmepriv;
144         struct security_priv    *psecuritypriv = &padapter->securitypriv;
145         u32 cur_time = 0;
146
147         if( psecuritypriv->last_mic_err_time == 0 )
148         {
149                 psecuritypriv->last_mic_err_time = rtw_get_current_time();
150         }
151         else
152         {
153                 cur_time = rtw_get_current_time();
154
155                 if( cur_time - psecuritypriv->last_mic_err_time < 60*HZ )
156                 {
157                         psecuritypriv->btkip_countermeasure = _TRUE;
158                         psecuritypriv->last_mic_err_time = 0;
159                         psecuritypriv->btkip_countermeasure_time = cur_time;
160                 }
161                 else
162                 {
163                         psecuritypriv->last_mic_err_time = rtw_get_current_time();
164                 }
165         }
166
167 #ifdef CONFIG_IOCTL_CFG80211
168         if ( bgroup )
169         {
170                 key_type |= NL80211_KEYTYPE_GROUP;
171         }
172         else
173         {
174                 key_type |= NL80211_KEYTYPE_PAIRWISE;
175         }
176
177         cfg80211_michael_mic_failure(padapter->pnetdev, (u8 *)&pmlmepriv->assoc_bssid[ 0 ], key_type, -1,
178                 NULL, GFP_ATOMIC);
179 #endif
180
181         _rtw_memset( &ev, 0x00, sizeof( ev ) );
182         if ( bgroup )
183         {
184             ev.flags |= IW_MICFAILURE_GROUP;
185         }
186         else
187         {
188             ev.flags |= IW_MICFAILURE_PAIRWISE;
189         }
190
191         ev.src_addr.sa_family = ARPHRD_ETHER;
192         memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
193
194         _rtw_memset( &wrqu, 0x00, sizeof( wrqu ) );
195         wrqu.data.length = sizeof( ev );
196
197 #ifndef CONFIG_IOCTL_CFG80211
198         wireless_send_event( padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, (char*) &ev );
199 #endif
200 }
201
202 void rtw_hostapd_mlme_rx(_adapter *padapter, union recv_frame *precv_frame)
203 {
204 #ifdef CONFIG_HOSTAPD_MLME
205         _pkt *skb;
206         struct hostapd_priv *phostapdpriv  = padapter->phostapdpriv;
207         struct net_device *pmgnt_netdev = phostapdpriv->pmgnt_netdev;
208
209         RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("+rtw_hostapd_mlme_rx\n"));
210
211         skb = precv_frame->u.hdr.pkt;
212
213         if (skb == NULL)
214                 return;
215
216         skb->data = precv_frame->u.hdr.rx_data;
217         skb->tail = precv_frame->u.hdr.rx_tail;
218         skb->len = precv_frame->u.hdr.len;
219
220         //pskb_copy = skb_copy(skb, GFP_ATOMIC);
221 //      if(skb == NULL) goto _exit;
222
223         skb->dev = pmgnt_netdev;
224         skb->ip_summed = CHECKSUM_NONE;
225         skb->pkt_type = PACKET_OTHERHOST;
226         //skb->protocol = __constant_htons(0x0019); /*ETH_P_80211_RAW*/
227         skb->protocol = __constant_htons(0x0003); /*ETH_P_80211_RAW*/
228
229         //DBG_8723A("(1)data=0x%x, head=0x%x, tail=0x%x, mac_header=0x%x, len=%d\n", skb->data, skb->head, skb->tail, skb->mac_header, skb->len);
230
231         //skb->mac.raw = skb->data;
232         skb_reset_mac_header(skb);
233
234        //skb_pull(skb, 24);
235        _rtw_memset(skb->cb, 0, sizeof(skb->cb));
236
237         netif_rx(skb);
238
239         precv_frame->u.hdr.pkt = NULL; // set pointer to NULL before rtw_free_recvframe() if call netif_rx()
240 #endif
241 }
242
243 int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame)
244 {
245         struct recv_priv *precvpriv;
246         _queue  *pfree_recv_queue;
247         _pkt *skb;
248         struct mlme_priv*pmlmepriv = &padapter->mlmepriv;
249 #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
250         struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
251 #endif
252
253 #ifdef CONFIG_BR_EXT
254         void *br_port = NULL;
255 #endif
256
257 _func_enter_;
258
259         precvpriv = &(padapter->recvpriv);
260         pfree_recv_queue = &(precvpriv->free_recv_queue);
261
262 #ifdef CONFIG_DRVEXT_MODULE
263         if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS)
264         {
265                 goto _recv_indicatepkt_drop;
266         }
267 #endif
268
269 #ifdef CONFIG_WAPI_SUPPORT
270         if (rtw_wapi_check_for_drop(padapter,precv_frame))
271         {
272                 WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__);
273                 goto _recv_indicatepkt_drop;
274         }
275 #endif
276
277         skb = precv_frame->u.hdr.pkt;
278         if(skb == NULL)
279         {
280                 RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n"));
281                 goto _recv_indicatepkt_drop;
282         }
283
284         RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n"));
285         RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head=%p  precv_frame->hdr.rx_data=%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data));
286         RT_TRACE(_module_recv_osdep_c_,_drv_info_,("precv_frame->hdr.rx_tail=%p precv_frame->u.hdr.rx_end=%p precv_frame->hdr.len=%d \n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len));
287
288         skb->data = precv_frame->u.hdr.rx_data;
289
290         skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
291
292         skb->len = precv_frame->u.hdr.len;
293
294         RT_TRACE(_module_recv_osdep_c_, _drv_info_,
295                  ("\n skb->head=%p skb->data=%p skb->tail=%p skb->end=%p skb->len=%d\n",
296                  skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len));
297
298         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
299         {
300                 _pkt *pskb2=NULL;
301                 struct sta_info *psta = NULL;
302                 struct sta_priv *pstapriv = &padapter->stapriv;
303                 struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
304                 int bmcast = IS_MCAST(pattrib->dst);
305
306                 //DBG_8723A("bmcast=%d\n", bmcast);
307
308                 if(_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)==_FALSE)
309                 {
310                         //DBG_8723A("not ap psta=%p, addr=%pM\n", psta, pattrib->dst);
311
312                         if(bmcast)
313                         {
314                                 psta = rtw_get_bcmc_stainfo(padapter);
315                                 pskb2 = skb_clone(skb, GFP_ATOMIC);
316                         } else {
317                                 psta = rtw_get_stainfo(pstapriv, pattrib->dst);
318                         }
319
320                         if(psta)
321                         {
322                                 struct net_device *pnetdev= (struct net_device*)padapter->pnetdev;
323
324                                 //DBG_8723A("directly forwarding to the rtw_xmit_entry\n");
325
326                                 //skb->ip_summed = CHECKSUM_NONE;
327                                 skb->dev = pnetdev;
328 #if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
329                                 skb_set_queue_mapping(skb, rtw_recv_select_queue(skb));
330 #endif //LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35)
331
332                                 rtw_xmit_entry(skb, pnetdev);
333
334                                 if(bmcast)
335                                         skb = pskb2;
336                                 else
337                                         goto _recv_indicatepkt_end;
338                         }
339
340
341                 }
342                 else// to APself
343                 {
344                         //DBG_8723A("to APSelf\n");
345                 }
346         }
347
348
349 #ifdef CONFIG_BR_EXT
350
351 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
352         br_port = padapter->pnetdev->br_port;
353 #else   // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
354         rcu_read_lock();
355         br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
356         rcu_read_unlock();
357 #endif  // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
358
359         if( br_port     && (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) )
360         {
361                 int nat25_handle_frame(_adapter *priv, struct sk_buff *skb);
362                 if (nat25_handle_frame(padapter, skb) == -1) {
363                         //priv->ext_stats.rx_data_drops++;
364                         //DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n");
365                         //return FAIL;
366 #if 1
367                         // bypass this frame to upper layer!!
368 #else
369                         goto _recv_indicatepkt_drop;
370 #endif
371                 }
372         }
373
374 #endif  // CONFIG_BR_EXT
375
376
377 #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
378         if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) {
379                 skb->ip_summed = CHECKSUM_UNNECESSARY;
380                 //DBG_8723A("CHECKSUM_UNNECESSARY \n");
381         } else {
382                 skb->ip_summed = CHECKSUM_NONE;
383                 //DBG_8723A("CHECKSUM_NONE(%d, %d) \n", pattrib->tcpchk_valid, pattrib->tcp_chkrpt);
384         }
385 #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
386
387         skb->ip_summed = CHECKSUM_NONE;
388
389 #endif
390
391         skb->dev = padapter->pnetdev;
392         skb->protocol = eth_type_trans(skb, padapter->pnetdev);
393
394         netif_rx(skb);
395
396 _recv_indicatepkt_end:
397
398         precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe()
399
400         rtw_free_recvframe(precv_frame, pfree_recv_queue);
401
402         RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after netif_rx!!!!\n"));
403
404 _func_exit_;
405
406         return _SUCCESS;
407
408 _recv_indicatepkt_drop:
409
410          rtw_free_recvframe(precv_frame, pfree_recv_queue);
411
412 _func_exit_;
413          return _FAIL;
414 }
415
416 void rtw_os_read_port(_adapter *padapter, struct recv_buf *precvbuf)
417 {
418         struct recv_priv *precvpriv = &padapter->recvpriv;
419
420 #ifdef CONFIG_USB_HCI
421
422         precvbuf->ref_cnt--;
423
424         //free skb in recv_buf
425         dev_kfree_skb_any(precvbuf->pskb);
426
427         precvbuf->pskb = NULL;
428         precvbuf->reuse = _FALSE;
429
430         if(precvbuf->irp_pending == _FALSE)
431         {
432                 rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
433         }
434
435
436 #endif
437 #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
438                 precvbuf->pskb = NULL;
439 #endif
440
441 }
442 void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext);
443 void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext)
444 {
445         struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)FunctionContext;
446         rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
447 }
448
449 void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
450 {
451         _adapter *padapter = preorder_ctrl->padapter;
452
453         _init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, _rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
454
455 }