OSDN Git Service

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