blob: 9ce6d22b9589d80df96889a2b56de9be4062128e [file] [log] [blame]
Larry Finger5e93f352014-03-28 21:37:38 -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 ******************************************************************************/
15#define _RTW_RECV_C_
16#include <osdep_service.h>
17#include <drv_types.h>
18#include <recv_osdep.h>
19#include <mlme_osdep.h>
20#include <linux/ip.h>
21#include <linux/if_ether.h>
Larry Finger5e93f352014-03-28 21:37:38 -050022#include <usb_ops.h>
23#include <linux/ieee80211.h>
24#include <wifi.h>
Jes Sorensenb3d139a2014-05-16 10:04:17 +020025#include <rtl8723a_recv.h>
Jes Sorensen638443d2014-05-16 10:04:18 +020026#include <rtl8723a_xmit.h>
Larry Finger5e93f352014-03-28 21:37:38 -050027
28void rtw_signal_stat_timer_hdl23a(unsigned long data);
29
30void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv)
31{
32
33
34
35 spin_lock_init(&psta_recvpriv->lock);
36
37 /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */
38 /* _rtw_init_queue23a(&psta_recvpriv->blk_strms[i]); */
39
40 _rtw_init_queue23a(&psta_recvpriv->defrag_q);
41
42
43}
44
45int _rtw_init_recv_priv23a(struct recv_priv *precvpriv,
46 struct rtw_adapter *padapter)
47{
48 struct recv_frame *precvframe;
49 int i;
50 int res = _SUCCESS;
51
Larry Finger5e93f352014-03-28 21:37:38 -050052 spin_lock_init(&precvpriv->lock);
53
54 _rtw_init_queue23a(&precvpriv->free_recv_queue);
55 _rtw_init_queue23a(&precvpriv->recv_pending_queue);
56 _rtw_init_queue23a(&precvpriv->uc_swdec_pending_queue);
57
58 precvpriv->adapter = padapter;
59
Larry Finger5e93f352014-03-28 21:37:38 -050060 for (i = 0; i < NR_RECVFRAME ; i++) {
Sachin Kamat7b20f7b2014-05-28 17:36:25 +053061 precvframe = kzalloc(sizeof(struct recv_frame), GFP_KERNEL);
Jes Sorensenfd6d1c12014-05-09 15:03:55 +020062 if (!precvframe)
63 break;
Larry Finger5e93f352014-03-28 21:37:38 -050064 INIT_LIST_HEAD(&precvframe->list);
65
66 list_add_tail(&precvframe->list,
67 &precvpriv->free_recv_queue.queue);
68
Larry Finger5e93f352014-03-28 21:37:38 -050069 precvframe->adapter = padapter;
70 precvframe++;
71 }
72
Jes Sorensenfd6d1c12014-05-09 15:03:55 +020073 precvpriv->free_recvframe_cnt = i;
Larry Finger5e93f352014-03-28 21:37:38 -050074 precvpriv->rx_pending_cnt = 1;
75
Jes Sorensenb3d139a2014-05-16 10:04:17 +020076 res = rtl8723au_init_recv_priv(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -050077
78 setup_timer(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl23a,
79 (unsigned long)padapter);
80
81 precvpriv->signal_stat_sampling_interval = 1000; /* ms */
82
83 rtw_set_signal_stat_timer(precvpriv);
84
Larry Finger5e93f352014-03-28 21:37:38 -050085 return res;
86}
87
88void _rtw_free_recv_priv23a (struct recv_priv *precvpriv)
89{
90 struct rtw_adapter *padapter = precvpriv->adapter;
Jes Sorensenfd6d1c12014-05-09 15:03:55 +020091 struct recv_frame *precvframe;
92 struct list_head *plist, *ptmp;
Larry Finger5e93f352014-03-28 21:37:38 -050093
94 rtw_free_uc_swdec_pending_queue23a(padapter);
95
Jes Sorensenfd6d1c12014-05-09 15:03:55 +020096 list_for_each_safe(plist, ptmp, &precvpriv->free_recv_queue.queue) {
97 precvframe = container_of(plist, struct recv_frame, list);
98 list_del_init(&precvframe->list);
99 kfree(precvframe);
Larry Finger5e93f352014-03-28 21:37:38 -0500100 }
101
Jes Sorensenb3d139a2014-05-16 10:04:17 +0200102 rtl8723au_free_recv_priv(padapter);
Larry Finger5e93f352014-03-28 21:37:38 -0500103}
104
105struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue)
106{
107 struct recv_frame *pframe;
108 struct list_head *plist, *phead;
109 struct rtw_adapter *padapter;
110 struct recv_priv *precvpriv;
111
112 spin_lock_bh(&pfree_recv_queue->lock);
113
Jes Sorensen794ff052014-05-09 15:03:59 +0200114 if (list_empty(&pfree_recv_queue->queue))
Larry Finger5e93f352014-03-28 21:37:38 -0500115 pframe = NULL;
116 else {
117 phead = get_list_head(pfree_recv_queue);
118
119 plist = phead->next;
120
121 pframe = container_of(plist, struct recv_frame, list);
122
123 list_del_init(&pframe->list);
124 padapter = pframe->adapter;
125 if (padapter) {
126 precvpriv = &padapter->recvpriv;
127 if (pfree_recv_queue == &precvpriv->free_recv_queue)
128 precvpriv->free_recvframe_cnt--;
129 }
130 }
131
132 spin_unlock_bh(&pfree_recv_queue->lock);
133
134 return pframe;
135}
136
Jes Sorensenc5779a02014-05-09 15:03:58 +0200137int rtw_free_recvframe23a(struct recv_frame *precvframe)
Larry Finger5e93f352014-03-28 21:37:38 -0500138{
139 struct rtw_adapter *padapter = precvframe->adapter;
140 struct recv_priv *precvpriv = &padapter->recvpriv;
Jes Sorensenc5779a02014-05-09 15:03:58 +0200141 struct rtw_queue *pfree_recv_queue;
Larry Finger5e93f352014-03-28 21:37:38 -0500142
143 if (precvframe->pkt) {
144 dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */
145 precvframe->pkt = NULL;
146 }
147
Jes Sorensenc5779a02014-05-09 15:03:58 +0200148 pfree_recv_queue = &precvpriv->free_recv_queue;
Larry Finger5e93f352014-03-28 21:37:38 -0500149 spin_lock_bh(&pfree_recv_queue->lock);
150
151 list_del_init(&precvframe->list);
152
153 list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue));
154
155 if (padapter) {
156 if (pfree_recv_queue == &precvpriv->free_recv_queue)
157 precvpriv->free_recvframe_cnt++;
158 }
159
160 spin_unlock_bh(&pfree_recv_queue->lock);
161
162
163
164 return _SUCCESS;
165}
166
167int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue)
168{
169 struct rtw_adapter *padapter = precvframe->adapter;
170 struct recv_priv *precvpriv = &padapter->recvpriv;
171
172 spin_lock_bh(&queue->lock);
173
174 list_del_init(&precvframe->list);
175
176 list_add_tail(&precvframe->list, get_list_head(queue));
177
178 if (padapter) {
179 if (queue == &precvpriv->free_recv_queue)
180 precvpriv->free_recvframe_cnt++;
181 }
182
183 spin_unlock_bh(&queue->lock);
184
185 return _SUCCESS;
186}
187
188/*
189caller : defrag ; recvframe_chk_defrag23a in recv_thread (passive)
190pframequeue: defrag_queue : will be accessed in recv_thread (passive)
191
192using spinlock to protect
193
194*/
195
Jes Sorensenc5779a02014-05-09 15:03:58 +0200196static void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue)
Larry Finger5e93f352014-03-28 21:37:38 -0500197{
198 struct recv_frame *hdr;
199 struct list_head *plist, *phead, *ptmp;
200
Larry Finger5e93f352014-03-28 21:37:38 -0500201 spin_lock(&pframequeue->lock);
202
203 phead = get_list_head(pframequeue);
204 plist = phead->next;
205
206 list_for_each_safe(plist, ptmp, phead) {
207 hdr = container_of(plist, struct recv_frame, list);
Jes Sorensenc5779a02014-05-09 15:03:58 +0200208 rtw_free_recvframe23a(hdr);
Larry Finger5e93f352014-03-28 21:37:38 -0500209 }
210
211 spin_unlock(&pframequeue->lock);
Larry Finger5e93f352014-03-28 21:37:38 -0500212}
213
214u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter)
215{
216 u32 cnt = 0;
217 struct recv_frame *pending_frame;
Yeliz Taneroglu831fa5f2014-10-09 01:22:18 +0300218
Larry Finger5e93f352014-03-28 21:37:38 -0500219 while ((pending_frame = rtw_alloc_recvframe23a(&adapter->recvpriv.uc_swdec_pending_queue))) {
Jes Sorensenc5779a02014-05-09 15:03:58 +0200220 rtw_free_recvframe23a(pending_frame);
Larry Finger5e93f352014-03-28 21:37:38 -0500221 DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__);
222 cnt++;
223 }
224
225 return cnt;
226}
227
228int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct rtw_queue *queue)
229{
230 spin_lock_bh(&queue->lock);
231
232 list_del_init(&precvbuf->list);
233 list_add(&precvbuf->list, get_list_head(queue));
234
235 spin_unlock_bh(&queue->lock);
236
237 return _SUCCESS;
238}
239
240int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue *queue)
241{
242 unsigned long irqL;
Yeliz Taneroglu831fa5f2014-10-09 01:22:18 +0300243
Larry Finger5e93f352014-03-28 21:37:38 -0500244 spin_lock_irqsave(&queue->lock, irqL);
245
246 list_del_init(&precvbuf->list);
247
248 list_add_tail(&precvbuf->list, get_list_head(queue));
249 spin_unlock_irqrestore(&queue->lock, irqL);
250 return _SUCCESS;
251}
252
253struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue)
254{
255 unsigned long irqL;
256 struct recv_buf *precvbuf;
257 struct list_head *plist, *phead;
258
259 spin_lock_irqsave(&queue->lock, irqL);
260
Jes Sorensen794ff052014-05-09 15:03:59 +0200261 if (list_empty(&queue->queue)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500262 precvbuf = NULL;
263 } else {
264 phead = get_list_head(queue);
265
266 plist = phead->next;
267
268 precvbuf = container_of(plist, struct recv_buf, list);
269
270 list_del_init(&precvbuf->list);
271 }
272
273 spin_unlock_irqrestore(&queue->lock, irqL);
274
275 return precvbuf;
276}
277
278int recvframe_chkmic(struct rtw_adapter *adapter,
279 struct recv_frame *precvframe);
280int recvframe_chkmic(struct rtw_adapter *adapter,
281 struct recv_frame *precvframe) {
282
283 int i, res = _SUCCESS;
284 u32 datalen;
285 u8 miccode[8];
286 u8 bmic_err = false, brpt_micerror = true;
Greg Donald99dc94f2014-09-04 15:49:30 -0500287 u8 *pframe, *payload, *pframemic;
Larry Finger5e93f352014-03-28 21:37:38 -0500288 u8 *mickey;
289 /* u8 *iv, rxdata_key_idx = 0; */
290 struct sta_info *stainfo;
291 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
292 struct security_priv *psecuritypriv = &adapter->securitypriv;
293
294 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
295 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
296
297
298 stainfo = rtw_get_stainfo23a(&adapter->stapriv, &prxattrib->ta[0]);
299
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200300 if (prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) {
Larry Finger5e93f352014-03-28 21:37:38 -0500301 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200302 ("\n recvframe_chkmic:prxattrib->encrypt == WLAN_CIPHER_SUITE_TKIP\n"));
Larry Finger5e93f352014-03-28 21:37:38 -0500303 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
Joe Perchesea072782015-03-24 11:10:09 -0700304 ("\n recvframe_chkmic:da = %pM\n", prxattrib->ra));
Larry Finger5e93f352014-03-28 21:37:38 -0500305
306 /* calculate mic code */
307 if (stainfo != NULL) {
308 if (is_multicast_ether_addr(prxattrib->ra)) {
309 mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
310
311 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
312 ("\n recvframe_chkmic: bcmc key\n"));
313
Jes Sorensen9216c512014-05-21 09:37:29 +0200314 if (!psecuritypriv->binstallGrpkey) {
Larry Finger5e93f352014-03-28 21:37:38 -0500315 res = _FAIL;
316 RT_TRACE(_module_rtl871x_recv_c_,
317 _drv_err_,
318 ("\n recvframe_chkmic:didn't "
319 "install group key!!!!!!\n"));
320 DBG_8723A("\n recvframe_chkmic:didn't "
321 "install group key!!!!!!\n");
322 goto exit;
323 }
324 } else {
325 mickey = &stainfo->dot11tkiprxmickey.skey[0];
326 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
327 ("\n recvframe_chkmic: unicast "
328 "key\n"));
329 }
330
331 /* icv_len included the mic code */
332 datalen = precvframe->pkt->len-prxattrib->
333 hdrlen-prxattrib->iv_len-prxattrib->icv_len - 8;
334 pframe = precvframe->pkt->data;
335 payload = pframe + prxattrib->hdrlen +
336 prxattrib->iv_len;
337
338 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
339 ("\n prxattrib->iv_len =%d prxattrib->icv_len ="
340 "%d\n", prxattrib->iv_len,
341 prxattrib->icv_len));
342
343 /* care the length of the data */
344 rtw_seccalctkipmic23a(mickey, pframe, payload,
345 datalen, &miccode[0],
346 (unsigned char)prxattrib->priority);
347
348 pframemic = payload + datalen;
349
350 bmic_err = false;
351
352 for (i = 0; i < 8; i++) {
353 if (miccode[i] != *(pframemic + i)) {
354 RT_TRACE(_module_rtl871x_recv_c_,
355 _drv_err_,
356 ("recvframe_chkmic:miccode"
357 "[%d](%02x) != *(pframemic+"
358 "%d)(%02x) ", i, miccode[i],
359 i, *(pframemic + i)));
360 bmic_err = true;
361 }
362 }
363
364 if (bmic_err == true) {
365 int i;
Yeliz Taneroglu831fa5f2014-10-09 01:22:18 +0300366
Larry Finger5e93f352014-03-28 21:37:38 -0500367 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
368 ("\n *(pframemic-8)-*(pframemic-1) ="
369 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
370 "0x%02x:0x%02x:0x%02x\n",
371 *(pframemic - 8), *(pframemic - 7),
372 *(pframemic - 6), *(pframemic - 5),
373 *(pframemic - 4), *(pframemic - 3),
374 *(pframemic - 2), *(pframemic - 1)));
375 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
376 ("\n *(pframemic-16)-*(pframemic-9) ="
377 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
378 "0x%02x:0x%02x:0x%02x\n",
379 *(pframemic - 16), *(pframemic - 15),
380 *(pframemic - 14), *(pframemic - 13),
381 *(pframemic - 12), *(pframemic - 11),
382 *(pframemic - 10), *(pframemic - 9)));
383
384 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
385 ("\n ====== demp packet (len =%d) ======"
386 "\n", precvframe->pkt->len));
387 for (i = 0; i < precvframe->pkt->len; i = i + 8) {
388 RT_TRACE(_module_rtl871x_recv_c_,
389 _drv_err_, ("0x%02x:0x%02x:0x"
390 "%02x:0x%02x:0x%0"
391 "2x:0x%02x:0x%02x"
392 ":0x%02x",
393 *(precvframe->pkt->data+i),*(precvframe->pkt->data+i+1),
394 *(precvframe->pkt->data+i+2),*(precvframe->pkt->data+i+3),
395 *(precvframe->pkt->data+i+4),*(precvframe->pkt->data+i+5),
396 *(precvframe->pkt->data+i+6),*(precvframe->pkt->data+i+7)));
397 }
398 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
399 ("\n ====== demp packet end [len =%d]"
400 "======\n", precvframe->pkt->len));
401 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
402 ("\n hrdlen =%d,\n",
403 prxattrib->hdrlen));
404
405 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
Joe Perchesea072782015-03-24 11:10:09 -0700406 ("ra = %pM psecuritypriv->binstallGrpkey =%d ",
407 prxattrib->ra,
Larry Finger5e93f352014-03-28 21:37:38 -0500408 psecuritypriv->binstallGrpkey));
409
410 /* double check key_index for some timing
411 issue, cannot compare with
412 psecuritypriv->dot118021XGrpKeyid also
413 cause timing issue */
414 if ((is_multicast_ether_addr(prxattrib->ra)) &&
415 (prxattrib->key_index !=
416 pmlmeinfo->key_index))
417 brpt_micerror = false;
418
419 if ((prxattrib->bdecrypted == true) &&
420 (brpt_micerror == true)) {
421 rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra));
422 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
423 DBG_8723A(" mic error :prxattrib->"
424 "bdecrypted =%d\n",
425 prxattrib->bdecrypted);
426 } else {
427 RT_TRACE(_module_rtl871x_recv_c_,
428 _drv_err_,
429 (" mic error :prxattrib->"
430 "bdecrypted =%d ",
431 prxattrib->bdecrypted));
432 DBG_8723A(" mic error :prxattrib->"
433 "bdecrypted =%d\n",
434 prxattrib->bdecrypted);
435 }
436
437 res = _FAIL;
438 } else {
439 /* mic checked ok */
Jes Sorensen9216c512014-05-21 09:37:29 +0200440 if (!psecuritypriv->bcheck_grpkey &&
441 is_multicast_ether_addr(prxattrib->ra)) {
442 psecuritypriv->bcheck_grpkey = 1;
Larry Finger5e93f352014-03-28 21:37:38 -0500443 RT_TRACE(_module_rtl871x_recv_c_,
444 _drv_err_,
445 ("psecuritypriv->bcheck_grp"
446 "key = true"));
447 }
448 }
449 } else {
450 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
451 ("recvframe_chkmic: rtw_get_stainfo23a =="
452 "NULL!!!\n"));
453 }
454
455 skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
456 }
457
458exit:
459
460
461
462 return res;
463}
464
465/* decrypt and set the ivlen, icvlen of the recv_frame */
466struct recv_frame *decryptor(struct rtw_adapter *padapter,
467 struct recv_frame *precv_frame);
468struct recv_frame *decryptor(struct rtw_adapter *padapter,
469 struct recv_frame *precv_frame)
470{
471 struct rx_pkt_attrib *prxattrib = &precv_frame->attrib;
472 struct security_priv *psecuritypriv = &padapter->securitypriv;
473 struct recv_frame *return_packet = precv_frame;
Jes Sorensen69632482014-05-16 10:04:36 +0200474 int res = _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -0500475
476 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
477 ("prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n",
478 prxattrib->bdecrypted, prxattrib->encrypt));
479
480 if (prxattrib->encrypt > 0) {
481 u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen;
Yeliz Taneroglu831fa5f2014-10-09 01:22:18 +0300482
Larry Finger5e93f352014-03-28 21:37:38 -0500483 prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
484
485 if (prxattrib->key_index > WEP_KEYS) {
486 DBG_8723A("prxattrib->key_index(%d) > WEP_KEYS\n",
487 prxattrib->key_index);
488
489 switch (prxattrib->encrypt) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200490 case WLAN_CIPHER_SUITE_WEP40:
491 case WLAN_CIPHER_SUITE_WEP104:
Larry Finger5e93f352014-03-28 21:37:38 -0500492 prxattrib->key_index =
493 psecuritypriv->dot11PrivacyKeyIndex;
494 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200495 case WLAN_CIPHER_SUITE_TKIP:
496 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -0500497 default:
498 prxattrib->key_index =
499 psecuritypriv->dot118021XGrpKeyid;
500 break;
501 }
502 }
503 }
504
505 if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0))) {
Jes Sorensen9216c512014-05-21 09:37:29 +0200506 psecuritypriv->hw_decrypted = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500507 switch (prxattrib->encrypt) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200508 case WLAN_CIPHER_SUITE_WEP40:
509 case WLAN_CIPHER_SUITE_WEP104:
Larry Finger5e93f352014-03-28 21:37:38 -0500510 rtw_wep_decrypt23a(padapter, precv_frame);
511 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200512 case WLAN_CIPHER_SUITE_TKIP:
Larry Finger5e93f352014-03-28 21:37:38 -0500513 res = rtw_tkip_decrypt23a(padapter, precv_frame);
514 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200515 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -0500516 res = rtw_aes_decrypt23a(padapter, precv_frame);
517 break;
518 default:
519 break;
520 }
521 } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
522 (psecuritypriv->busetkipkey == 1 ||
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200523 prxattrib->encrypt != WLAN_CIPHER_SUITE_TKIP)) {
Jes Sorensen9216c512014-05-21 09:37:29 +0200524 psecuritypriv->hw_decrypted = 1;
Larry Finger5e93f352014-03-28 21:37:38 -0500525 }
526
527 if (res == _FAIL) {
Jes Sorensenc5779a02014-05-09 15:03:58 +0200528 rtw_free_recvframe23a(return_packet);
Larry Finger5e93f352014-03-28 21:37:38 -0500529 return_packet = NULL;
530 }
531
532
533
534 return return_packet;
535}
536
537/* set the security information in the recv_frame */
538static struct recv_frame *portctrl(struct rtw_adapter *adapter,
539 struct recv_frame *precv_frame)
540{
Jes Sorensen7d0d2b12014-04-09 23:21:22 +0200541 u8 *psta_addr, *ptr;
Larry Finger5e93f352014-03-28 21:37:38 -0500542 uint auth_alg;
543 struct recv_frame *pfhdr;
544 struct sta_info *psta;
545 struct sta_priv *pstapriv ;
546 struct recv_frame *prtnframe;
Jes Sorensen514c4852014-04-09 23:21:21 +0200547 u16 ether_type;
Jes Sorensen7dd1e722014-04-09 23:21:20 +0200548 u16 eapol_type = ETH_P_PAE;/* for Funia BD's WPA issue */
Larry Finger5e93f352014-03-28 21:37:38 -0500549 struct rx_pkt_attrib *pattrib;
550
551 pstapriv = &adapter->stapriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500552
553 auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
554
Larry Finger5e93f352014-03-28 21:37:38 -0500555 pfhdr = precv_frame;
556 pattrib = &pfhdr->attrib;
557 psta_addr = pattrib->ta;
Jes Sorensen7d0d2b12014-04-09 23:21:22 +0200558 psta = rtw_get_stainfo23a(pstapriv, psta_addr);
Larry Finger5e93f352014-03-28 21:37:38 -0500559
560 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
561 ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm ="
562 "%d\n", adapter->securitypriv.dot11AuthAlgrthm));
563
Jes Sorensena0c5ff02014-11-10 18:11:41 -0500564 prtnframe = precv_frame;
565
Jes Sorensen514c4852014-04-09 23:21:21 +0200566 if (auth_alg == dot11AuthAlgrthm_8021X) {
567 /* get ether_type */
Jes Sorensen94b080b2014-04-09 23:21:23 +0200568 ptr = pfhdr->pkt->data + pfhdr->attrib.hdrlen;
569
570 ether_type = (ptr[6] << 8) | ptr[7];
Jes Sorensen514c4852014-04-09 23:21:21 +0200571
Jes Sorensena0c5ff02014-11-10 18:11:41 -0500572 if (psta && psta->ieee8021x_blocked) {
Larry Finger5e93f352014-03-28 21:37:38 -0500573 /* blocked */
574 /* only accept EAPOL frame */
575 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
576 ("########portctrl:psta->ieee8021x_blocked =="
577 "1\n"));
578
Jes Sorensena0c5ff02014-11-10 18:11:41 -0500579 if (ether_type != eapol_type) {
Larry Finger5e93f352014-03-28 21:37:38 -0500580 /* free this frame */
Jes Sorensenc5779a02014-05-09 15:03:58 +0200581 rtw_free_recvframe23a(precv_frame);
Larry Finger5e93f352014-03-28 21:37:38 -0500582 prtnframe = NULL;
583 }
Larry Finger5e93f352014-03-28 21:37:38 -0500584 }
Larry Finger5e93f352014-03-28 21:37:38 -0500585 }
586
Jes Sorensen514c4852014-04-09 23:21:21 +0200587 return prtnframe;
Larry Finger5e93f352014-03-28 21:37:38 -0500588}
589
590int recv_decache(struct recv_frame *precv_frame, u8 bretry,
591 struct stainfo_rxcache *prxcache);
592int recv_decache(struct recv_frame *precv_frame, u8 bretry,
593 struct stainfo_rxcache *prxcache)
594{
595 int tid = precv_frame->attrib.priority;
596
597 u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) |
598 (precv_frame->attrib.frag_num & 0xf);
599
600
601
602 if (tid > 15) {
603 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
604 ("recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n",
605 seq_ctrl, tid));
606
607 return _FAIL;
608 }
609
610 if (1) { /* if (bretry) */
611 if (seq_ctrl == prxcache->tid_rxseq[tid]) {
612 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
613 ("recv_decache, seq_ctrl = 0x%x, tid = 0x%x, "
614 "tid_rxseq = 0x%x\n",
615 seq_ctrl, tid, prxcache->tid_rxseq[tid]));
616
617 return _FAIL;
618 }
619 }
620
621 prxcache->tid_rxseq[tid] = seq_ctrl;
622
623
624
625 return _SUCCESS;
626}
627
628void process23a_pwrbit_data(struct rtw_adapter *padapter,
629 struct recv_frame *precv_frame);
630void process23a_pwrbit_data(struct rtw_adapter *padapter,
631 struct recv_frame *precv_frame)
632{
633#ifdef CONFIG_8723AU_AP_MODE
634 unsigned char pwrbit;
635 struct sk_buff *skb = precv_frame->pkt;
636 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
637 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
638 struct sta_priv *pstapriv = &padapter->stapriv;
639 struct sta_info *psta = NULL;
640
641 psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
642
643 if (psta) {
644 pwrbit = ieee80211_has_pm(hdr->frame_control);
645
646 if (pwrbit) {
647 if (!(psta->state & WIFI_SLEEP_STATE))
648 stop_sta_xmit23a(padapter, psta);
649 } else {
650 if (psta->state & WIFI_SLEEP_STATE)
651 wakeup_sta_to_xmit23a(padapter, psta);
652 }
653 }
654
655#endif
656}
657
658void process_wmmps_data(struct rtw_adapter *padapter,
659 struct recv_frame *precv_frame);
660void process_wmmps_data(struct rtw_adapter *padapter,
661 struct recv_frame *precv_frame)
662{
663#ifdef CONFIG_8723AU_AP_MODE
664 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
665 struct sta_priv *pstapriv = &padapter->stapriv;
666 struct sta_info *psta = NULL;
667
668 psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
669
670 if (!psta)
671 return;
672
673
674 if (!psta->qos_option)
675 return;
676
677 if (!(psta->qos_info & 0xf))
678 return;
679
680 if (psta->state & WIFI_SLEEP_STATE) {
681 u8 wmmps_ac = 0;
682
683 switch (pattrib->priority) {
684 case 1:
685 case 2:
686 wmmps_ac = psta->uapsd_bk & BIT(1);
687 break;
688 case 4:
689 case 5:
690 wmmps_ac = psta->uapsd_vi & BIT(1);
691 break;
692 case 6:
693 case 7:
694 wmmps_ac = psta->uapsd_vo & BIT(1);
695 break;
696 case 0:
697 case 3:
698 default:
699 wmmps_ac = psta->uapsd_be & BIT(1);
700 break;
701 }
702
703 if (wmmps_ac) {
704 if (psta->sleepq_ac_len > 0) {
705 /* process received triggered frame */
706 xmit_delivery_enabled_frames23a(padapter, psta);
707 } else {
708 /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
709 issue_qos_nulldata23a(padapter, psta->hwaddr,
710 (u16)pattrib->priority,
711 0, 0);
712 }
713 }
714 }
715
716#endif
717}
718
719static void count_rx_stats(struct rtw_adapter *padapter,
720 struct recv_frame *prframe, struct sta_info *sta)
721{
722 int sz;
723 struct sta_info *psta = NULL;
724 struct stainfo_stats *pstats = NULL;
725 struct rx_pkt_attrib *pattrib = & prframe->attrib;
726 struct recv_priv *precvpriv = &padapter->recvpriv;
727
728 sz = prframe->pkt->len;
729 precvpriv->rx_bytes += sz;
730
731 padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
732
733 if ((!is_broadcast_ether_addr(pattrib->dst)) &&
734 (!is_multicast_ether_addr(pattrib->dst)))
735 padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
736
737 if (sta)
738 psta = sta;
739 else
740 psta = prframe->psta;
741
742 if (psta) {
743 pstats = &psta->sta_stats;
744
745 pstats->rx_data_pkts++;
746 pstats->rx_bytes += sz;
747 }
748}
749
750static int sta2sta_data_frame(struct rtw_adapter *adapter,
751 struct recv_frame *precv_frame,
752 struct sta_info**psta)
753{
754 struct sk_buff *skb = precv_frame->pkt;
755 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
756 int ret = _SUCCESS;
757 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
758 struct sta_priv *pstapriv = &adapter->stapriv;
759 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
760 u8 *mybssid = get_bssid(pmlmepriv);
761 u8 *myhwaddr = myid(&adapter->eeprompriv);
762 u8 *sta_addr = NULL;
763 int bmcast = is_multicast_ether_addr(pattrib->dst);
764
765
766
Jes Sorensenf2f97032014-05-25 22:43:04 +0200767 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
768 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500769
770 /* filter packets that SA is myself or multicast or broadcast */
771 if (ether_addr_equal(myhwaddr, pattrib->src)) {
772 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
773 (" SA == myself\n"));
774 ret = _FAIL;
775 goto exit;
776 }
777
778 if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
779 ret = _FAIL;
780 goto exit;
781 }
782
783 if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") ||
784 ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
785 !ether_addr_equal(pattrib->bssid, mybssid)) {
786 ret = _FAIL;
787 goto exit;
788 }
789
790 sta_addr = pattrib->src;
Jes Sorensenf2f97032014-05-25 22:43:04 +0200791 } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500792 /* For Station mode, sa and bssid should always be BSSID,
793 and DA is my mac-address */
794 if (!ether_addr_equal(pattrib->bssid, pattrib->src)) {
795 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
796 ("bssid != TA under STATION_MODE; drop "
797 "pkt\n"));
798 ret = _FAIL;
799 goto exit;
800 }
801
802 sta_addr = pattrib->bssid;
803
Jes Sorensenf2f97032014-05-25 22:43:04 +0200804 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500805 if (bmcast) {
806 /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
807 if (!is_multicast_ether_addr(pattrib->bssid)) {
808 ret = _FAIL;
809 goto exit;
810 }
811 } else { /* not mc-frame */
812 /* For AP mode, if DA is non-MCAST, then it must
813 be BSSID, and bssid == BSSID */
814 if (!ether_addr_equal(pattrib->bssid, pattrib->dst)) {
815 ret = _FAIL;
816 goto exit;
817 }
818
819 sta_addr = pattrib->src;
820 }
Jes Sorensenf2f97032014-05-25 22:43:04 +0200821 } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500822 ether_addr_copy(pattrib->dst, hdr->addr1);
823 ether_addr_copy(pattrib->src, hdr->addr2);
824 ether_addr_copy(pattrib->bssid, hdr->addr3);
825 ether_addr_copy(pattrib->ra, pattrib->dst);
826 ether_addr_copy(pattrib->ta, pattrib->src);
827
828 sta_addr = mybssid;
829 } else {
830 ret = _FAIL;
831 }
832
833 if (bmcast)
834 *psta = rtw_get_bcmc_stainfo23a(adapter);
835 else
836 *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /* get ap_info */
837
838 if (*psta == NULL) {
839 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
840 ret = _FAIL;
841 goto exit;
842 }
843
844exit:
845
846 return ret;
847}
848
849int ap2sta_data_frame(struct rtw_adapter *adapter,
850 struct recv_frame *precv_frame,
851 struct sta_info **psta);
852int ap2sta_data_frame(struct rtw_adapter *adapter,
853 struct recv_frame *precv_frame,
854 struct sta_info **psta)
855{
856 struct sk_buff *skb = precv_frame->pkt;
857 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
858 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
859 int ret = _SUCCESS;
860 struct sta_priv *pstapriv = &adapter->stapriv;
861 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
862 u8 *mybssid = get_bssid(pmlmepriv);
863 u8 *myhwaddr = myid(&adapter->eeprompriv);
864 int bmcast = is_multicast_ether_addr(pattrib->dst);
865
866
867
Jes Sorensenf2f97032014-05-25 22:43:04 +0200868 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
869 (check_fwstate(pmlmepriv, _FW_LINKED) ||
870 check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
Larry Finger5e93f352014-03-28 21:37:38 -0500871
872 /* filter packets that SA is myself or multicast or broadcast */
873 if (ether_addr_equal(myhwaddr, pattrib->src)) {
874 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
875 (" SA == myself\n"));
876 ret = _FAIL;
877 goto exit;
878 }
879
880 /* da should be for me */
881 if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
882 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
Joe Perchesea072782015-03-24 11:10:09 -0700883 (" ap2sta_data_frame: compare DA fail; DA=%pM\n",
884 pattrib->dst));
Larry Finger5e93f352014-03-28 21:37:38 -0500885 ret = _FAIL;
886 goto exit;
887 }
888
889 /* check BSSID */
890 if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") ||
891 ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
892 !ether_addr_equal(pattrib->bssid, mybssid)) {
893 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
Joe Perchesea072782015-03-24 11:10:09 -0700894 (" ap2sta_data_frame: compare BSSID fail ; BSSID=%pM\n",
895 pattrib->bssid));
Larry Finger5e93f352014-03-28 21:37:38 -0500896 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
Joe Perchesea072782015-03-24 11:10:09 -0700897 ("mybssid=%pM\n", mybssid));
Larry Finger5e93f352014-03-28 21:37:38 -0500898
899 if (!bmcast) {
Joe Perchesea072782015-03-24 11:10:09 -0700900 DBG_8723A("issue_deauth23a to the nonassociated ap=%pM for the reason(7)\n",
901 pattrib->bssid);
Larry Finger5e93f352014-03-28 21:37:38 -0500902 issue_deauth23a(adapter, pattrib->bssid,
903 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
904 }
905
906 ret = _FAIL;
907 goto exit;
908 }
909
910 if (bmcast)
911 *psta = rtw_get_bcmc_stainfo23a(adapter);
912 else
913 /* get ap_info */
914 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
915
916 if (*psta == NULL) {
917 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
918 ("ap2sta: can't get psta under STATION_MODE ;"
919 " drop pkt\n"));
920 ret = _FAIL;
921 goto exit;
922 }
923
924 if (ieee80211_is_nullfunc(hdr->frame_control)) {
925 /* No data, will not indicate to upper layer,
926 temporily count it here */
927 count_rx_stats(adapter, precv_frame, *psta);
928 ret = RTW_RX_HANDLED;
929 goto exit;
930 }
931
Jes Sorensenf2f97032014-05-25 22:43:04 +0200932 } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
933 check_fwstate(pmlmepriv, _FW_LINKED)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500934 ether_addr_copy(pattrib->dst, hdr->addr1);
935 ether_addr_copy(pattrib->src, hdr->addr2);
936 ether_addr_copy(pattrib->bssid, hdr->addr3);
937 ether_addr_copy(pattrib->ra, pattrib->dst);
938 ether_addr_copy(pattrib->ta, pattrib->src);
939
940 /* */
941 ether_addr_copy(pattrib->bssid, mybssid);
942
943 /* get sta_info */
944 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
945 if (*psta == NULL) {
946 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
947 ("can't get psta under MP_MODE ; drop pkt\n"));
948 ret = _FAIL;
949 goto exit;
950 }
Jes Sorensenf2f97032014-05-25 22:43:04 +0200951 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500952 /* Special case */
953 ret = RTW_RX_HANDLED;
954 goto exit;
955 } else {
956 if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
957 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
958 if (*psta == NULL) {
Joe Perchesea072782015-03-24 11:10:09 -0700959 DBG_8723A("issue_deauth23a to the ap=%pM for the reason(7)\n",
960 pattrib->bssid);
Larry Finger5e93f352014-03-28 21:37:38 -0500961
962 issue_deauth23a(adapter, pattrib->bssid,
963 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
964 }
965 }
966
967 ret = _FAIL;
968 }
969
970exit:
971
972
973
974 return ret;
975}
976
977int sta2ap_data_frame(struct rtw_adapter *adapter,
978 struct recv_frame *precv_frame,
979 struct sta_info **psta);
980int sta2ap_data_frame(struct rtw_adapter *adapter,
981 struct recv_frame *precv_frame,
982 struct sta_info **psta)
983{
984 struct sk_buff *skb = precv_frame->pkt;
985 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
986 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
987 struct sta_priv *pstapriv = &adapter->stapriv;
988 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
989 unsigned char *mybssid = get_bssid(pmlmepriv);
990 int ret = _SUCCESS;
991
992
993
Jes Sorensenf2f97032014-05-25 22:43:04 +0200994 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500995 /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
996 if (!ether_addr_equal(pattrib->bssid, mybssid)) {
997 ret = _FAIL;
998 goto exit;
999 }
1000
1001 *psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
1002 if (*psta == NULL) {
1003 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1004 ("can't get psta under AP_MODE; drop pkt\n"));
Joe Perchesea072782015-03-24 11:10:09 -07001005 DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n",
1006 pattrib->src);
Larry Finger5e93f352014-03-28 21:37:38 -05001007
1008 issue_deauth23a(adapter, pattrib->src,
1009 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1010
1011 ret = RTW_RX_HANDLED;
1012 goto exit;
1013 }
1014
1015 process23a_pwrbit_data(adapter, precv_frame);
1016
1017 /* We only get here if it's a data frame, so no need to
1018 * confirm data frame type first */
1019 if (ieee80211_is_data_qos(hdr->frame_control))
1020 process_wmmps_data(adapter, precv_frame);
1021
1022 if (ieee80211_is_nullfunc(hdr->frame_control)) {
1023 /* No data, will not indicate to upper layer,
1024 temporily count it here */
1025 count_rx_stats(adapter, precv_frame, *psta);
1026 ret = RTW_RX_HANDLED;
1027 goto exit;
1028 }
1029 } else {
1030 u8 *myhwaddr = myid(&adapter->eeprompriv);
Yeliz Taneroglu831fa5f2014-10-09 01:22:18 +03001031
Larry Finger5e93f352014-03-28 21:37:38 -05001032 if (!ether_addr_equal(pattrib->ra, myhwaddr)) {
1033 ret = RTW_RX_HANDLED;
1034 goto exit;
1035 }
Joe Perchesea072782015-03-24 11:10:09 -07001036 DBG_8723A("issue_deauth23a to sta=%pM for the reason(7)\n",
1037 pattrib->src);
Larry Finger5e93f352014-03-28 21:37:38 -05001038 issue_deauth23a(adapter, pattrib->src,
1039 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1040 ret = RTW_RX_HANDLED;
1041 goto exit;
1042 }
1043
1044exit:
1045
1046
1047
1048 return ret;
1049}
1050
Jes Sorensen22220322014-05-09 15:03:29 +02001051static int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
1052 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001053{
1054#ifdef CONFIG_8723AU_AP_MODE
1055 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
1056 struct sta_priv *pstapriv = &padapter->stapriv;
1057 struct sk_buff *skb = precv_frame->pkt;
1058 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -05001059
1060 if (!ieee80211_is_ctl(hdr->frame_control))
1061 return _FAIL;
1062
1063 /* receive the frames that ra(a1) is my address */
1064 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv)))
1065 return _FAIL;
1066
1067 /* only handle ps-poll */
1068 if (ieee80211_is_pspoll(hdr->frame_control)) {
Jes Sorensenc51e8862014-05-09 15:03:34 +02001069 struct ieee80211_pspoll *psp = (struct ieee80211_pspoll *)hdr;
Larry Finger5e93f352014-03-28 21:37:38 -05001070 u16 aid;
1071 u8 wmmps_ac = 0;
1072 struct sta_info *psta = NULL;
1073
Jes Sorensenc51e8862014-05-09 15:03:34 +02001074 aid = le16_to_cpu(psp->aid) & 0x3fff;
Larry Finger5e93f352014-03-28 21:37:38 -05001075 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1076
Jes Sorensenc51e8862014-05-09 15:03:34 +02001077 if (!psta || psta->aid != aid)
Larry Finger5e93f352014-03-28 21:37:38 -05001078 return _FAIL;
1079
1080 /* for rx pkt statistics */
1081 psta->sta_stats.rx_ctrl_pkts++;
1082
1083 switch (pattrib->priority) {
1084 case 1:
1085 case 2:
1086 wmmps_ac = psta->uapsd_bk & BIT(0);
1087 break;
1088 case 4:
1089 case 5:
1090 wmmps_ac = psta->uapsd_vi & BIT(0);
1091 break;
1092 case 6:
1093 case 7:
1094 wmmps_ac = psta->uapsd_vo & BIT(0);
1095 break;
1096 case 0:
1097 case 3:
1098 default:
1099 wmmps_ac = psta->uapsd_be & BIT(0);
1100 break;
1101 }
1102
1103 if (wmmps_ac)
1104 return _FAIL;
1105
1106 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1107 DBG_8723A("%s alive check-rx ps-poll\n", __func__);
1108 psta->expire_to = pstapriv->expire_to;
1109 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1110 }
1111
1112 if ((psta->state & WIFI_SLEEP_STATE) &&
1113 (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid))) {
1114 struct list_head *xmitframe_plist, *xmitframe_phead;
1115 struct xmit_frame *pxmitframe;
1116 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1117
1118 spin_lock_bh(&pxmitpriv->lock);
1119
1120 xmitframe_phead = get_list_head(&psta->sleep_q);
1121 xmitframe_plist = xmitframe_phead->next;
1122
1123 if (!list_empty(xmitframe_phead)) {
1124 pxmitframe = container_of(xmitframe_plist,
1125 struct xmit_frame,
1126 list);
1127
1128 xmitframe_plist = xmitframe_plist->next;
1129
1130 list_del_init(&pxmitframe->list);
1131
1132 psta->sleepq_len--;
1133
1134 if (psta->sleepq_len>0)
1135 pxmitframe->attrib.mdata = 1;
Greg Donalda82b4b02014-09-08 20:50:23 -05001136 else
Larry Finger5e93f352014-03-28 21:37:38 -05001137 pxmitframe->attrib.mdata = 0;
1138
1139 pxmitframe->attrib.triggered = 1;
1140
1141 /* DBG_8723A("handling ps-poll, q_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
1142
Jes Sorensen638443d2014-05-16 10:04:18 +02001143 rtl8723au_hal_xmitframe_enqueue(padapter,
1144 pxmitframe);
Larry Finger5e93f352014-03-28 21:37:38 -05001145
1146 if (psta->sleepq_len == 0) {
1147 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
1148
1149 /* DBG_8723A("after handling ps-poll, tim =%x\n", pstapriv->tim_bitmap); */
1150
Masanari Iida808bcb42014-07-22 23:42:53 +09001151 /* update BCN for TIM IE */
Larry Finger5e93f352014-03-28 21:37:38 -05001152 /* update_BCNTIM(padapter); */
Jes Sorensendf220942014-04-15 19:43:32 +02001153 update_beacon23a(padapter, WLAN_EID_TIM,
1154 NULL, false);
Larry Finger5e93f352014-03-28 21:37:38 -05001155 }
1156
1157 /* spin_unlock_bh(&psta->sleep_q.lock); */
1158 spin_unlock_bh(&pxmitpriv->lock);
1159
1160 } else {
1161 /* spin_unlock_bh(&psta->sleep_q.lock); */
1162 spin_unlock_bh(&pxmitpriv->lock);
1163
1164 /* DBG_8723A("no buffered packets to xmit\n"); */
1165 if (pstapriv->tim_bitmap & CHKBIT(psta->aid)) {
1166 if (psta->sleepq_len == 0) {
1167 DBG_8723A("no buffered packets "
1168 "to xmit\n");
1169
1170 /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
1171 issue_nulldata23a(padapter,
1172 psta->hwaddr,
1173 0, 0, 0);
1174 } else {
1175 DBG_8723A("error!psta->sleepq"
1176 "_len =%d\n",
1177 psta->sleepq_len);
1178 psta->sleepq_len = 0;
1179 }
1180
1181 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
1182
Masanari Iida808bcb42014-07-22 23:42:53 +09001183 /* update BCN for TIM IE */
Larry Finger5e93f352014-03-28 21:37:38 -05001184 /* update_BCNTIM(padapter); */
Jes Sorensendf220942014-04-15 19:43:32 +02001185 update_beacon23a(padapter, WLAN_EID_TIM,
1186 NULL, false);
Larry Finger5e93f352014-03-28 21:37:38 -05001187 }
1188 }
1189 }
1190 }
1191
1192#endif
1193 return _FAIL;
1194}
1195
Greg Donald4e66cf02014-08-22 10:57:49 -05001196struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -05001197 struct recv_frame *precv_frame);
Jes Sorensen22220322014-05-09 15:03:29 +02001198static int validate_recv_mgnt_frame(struct rtw_adapter *padapter,
1199 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001200{
1201 struct sta_info *psta;
1202 struct sk_buff *skb;
1203 struct ieee80211_hdr *hdr;
1204 /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */
1205
1206 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1207 ("+validate_recv_mgnt_frame\n"));
1208
1209 precv_frame = recvframe_chk_defrag23a(padapter, precv_frame);
1210 if (precv_frame == NULL) {
1211 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
1212 ("%s: fragment packet\n", __func__));
1213 return _SUCCESS;
1214 }
1215
1216 skb = precv_frame->pkt;
1217 hdr = (struct ieee80211_hdr *) skb->data;
1218
1219 /* for rx pkt statistics */
1220 psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2);
1221 if (psta) {
1222 psta->sta_stats.rx_mgnt_pkts++;
1223
1224 if (ieee80211_is_beacon(hdr->frame_control))
1225 psta->sta_stats.rx_beacon_pkts++;
1226 else if (ieee80211_is_probe_req(hdr->frame_control))
1227 psta->sta_stats.rx_probereq_pkts++;
1228 else if (ieee80211_is_probe_resp(hdr->frame_control)) {
1229 if (ether_addr_equal(padapter->eeprompriv.mac_addr,
1230 hdr->addr1))
1231 psta->sta_stats.rx_probersp_pkts++;
1232 else if (is_broadcast_ether_addr(hdr->addr1) ||
1233 is_multicast_ether_addr(hdr->addr1))
1234 psta->sta_stats.rx_probersp_bm_pkts++;
1235 else
1236 psta->sta_stats.rx_probersp_uo_pkts++;
1237 }
1238 }
1239
1240 mgt_dispatcher23a(padapter, precv_frame);
1241
1242 return _SUCCESS;
1243}
1244
Jes Sorensen22220322014-05-09 15:03:29 +02001245static int validate_recv_data_frame(struct rtw_adapter *adapter,
1246 struct recv_frame *precv_frame)
Larry Finger5e93f352014-03-28 21:37:38 -05001247{
1248 u8 bretry;
Jes Sorensenaa66fbb2014-05-09 15:03:31 +02001249 u8 *psa, *pda;
Larry Finger5e93f352014-03-28 21:37:38 -05001250 struct sta_info *psta = NULL;
Larry Finger5e93f352014-03-28 21:37:38 -05001251 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1252 struct security_priv *psecuritypriv = &adapter->securitypriv;
1253 int ret = _SUCCESS;
1254 struct sk_buff *skb = precv_frame->pkt;
1255 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1256
1257
1258
1259 bretry = ieee80211_has_retry(hdr->frame_control);
1260 pda = ieee80211_get_DA(hdr);
1261 psa = ieee80211_get_SA(hdr);
Larry Finger5e93f352014-03-28 21:37:38 -05001262
1263 ether_addr_copy(pattrib->dst, pda);
1264 ether_addr_copy(pattrib->src, psa);
1265
Jes Sorensen5ca12b72014-05-09 15:03:30 +02001266 switch (hdr->frame_control &
1267 cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
1268 case cpu_to_le16(0):
Jes Sorensenaa66fbb2014-05-09 15:03:31 +02001269 ether_addr_copy(pattrib->bssid, hdr->addr3);
Larry Finger5e93f352014-03-28 21:37:38 -05001270 ether_addr_copy(pattrib->ra, pda);
1271 ether_addr_copy(pattrib->ta, psa);
1272 ret = sta2sta_data_frame(adapter, precv_frame, &psta);
1273 break;
1274
Jes Sorensen5ca12b72014-05-09 15:03:30 +02001275 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
Jes Sorensenaa66fbb2014-05-09 15:03:31 +02001276 ether_addr_copy(pattrib->bssid, hdr->addr2);
Larry Finger5e93f352014-03-28 21:37:38 -05001277 ether_addr_copy(pattrib->ra, pda);
Jes Sorensenaa66fbb2014-05-09 15:03:31 +02001278 ether_addr_copy(pattrib->ta, hdr->addr2);
Larry Finger5e93f352014-03-28 21:37:38 -05001279 ret = ap2sta_data_frame(adapter, precv_frame, &psta);
1280 break;
1281
Jes Sorensen5ca12b72014-05-09 15:03:30 +02001282 case cpu_to_le16(IEEE80211_FCTL_TODS):
Jes Sorensenaa66fbb2014-05-09 15:03:31 +02001283 ether_addr_copy(pattrib->bssid, hdr->addr1);
1284 ether_addr_copy(pattrib->ra, hdr->addr1);
Larry Finger5e93f352014-03-28 21:37:38 -05001285 ether_addr_copy(pattrib->ta, psa);
1286 ret = sta2ap_data_frame(adapter, precv_frame, &psta);
1287 break;
1288
Jes Sorensen5ca12b72014-05-09 15:03:30 +02001289 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
Jes Sorensenaa66fbb2014-05-09 15:03:31 +02001290 /*
1291 * There is no BSSID in this case, but the driver has been
1292 * using addr1 so far, so keep it for now.
1293 */
1294 ether_addr_copy(pattrib->bssid, hdr->addr1);
Larry Finger5e93f352014-03-28 21:37:38 -05001295 ether_addr_copy(pattrib->ra, hdr->addr1);
1296 ether_addr_copy(pattrib->ta, hdr->addr2);
1297 ret = _FAIL;
1298 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
1299 break;
Larry Finger5e93f352014-03-28 21:37:38 -05001300 }
1301
1302 if ((ret == _FAIL) || (ret == RTW_RX_HANDLED))
1303 goto exit;
1304
1305 if (!psta) {
1306 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1307 (" after to_fr_ds_chk; psta == NULL\n"));
1308 ret = _FAIL;
1309 goto exit;
1310 }
1311
1312 /* psta->rssi = prxcmd->rssi; */
1313 /* psta->signal_quality = prxcmd->sq; */
1314 precv_frame->psta = psta;
1315
1316 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
1317 if (ieee80211_has_a4(hdr->frame_control))
1318 pattrib->hdrlen += ETH_ALEN;
1319
1320 /* parsing QC field */
1321 if (pattrib->qos == 1) {
1322 __le16 *qptr = (__le16 *)ieee80211_get_qos_ctl(hdr);
1323 u16 qos_ctrl = le16_to_cpu(*qptr);
1324
1325 pattrib->priority = qos_ctrl & IEEE80211_QOS_CTL_TID_MASK;
1326 pattrib->ack_policy = (qos_ctrl >> 5) & 3;
1327 pattrib->amsdu =
1328 (qos_ctrl & IEEE80211_QOS_CTL_A_MSDU_PRESENT) >> 7;
1329 pattrib->hdrlen += IEEE80211_QOS_CTL_LEN;
1330
1331 if (pattrib->priority != 0 && pattrib->priority != 3) {
1332 adapter->recvpriv.bIsAnyNonBEPkts = true;
1333 }
1334 } else {
1335 pattrib->priority = 0;
1336 pattrib->ack_policy = 0;
1337 pattrib->amsdu = 0;
1338 }
1339
1340 if (pattrib->order) { /* HT-CTRL 11n */
1341 pattrib->hdrlen += 4;
1342 }
1343
1344 precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
1345
1346 /* decache, drop duplicate recv packets */
1347 if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
1348 _FAIL) {
1349 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1350 ("decache : drop pkt\n"));
1351 ret = _FAIL;
1352 goto exit;
1353 }
1354
1355 if (pattrib->privacy) {
1356 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1357 ("validate_recv_data_frame:pattrib->privacy =%x\n",
1358 pattrib->privacy));
1359 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1360 ("\n ^^^^^^^^^^^is_multicast_ether_addr"
1361 "(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n",
1362 pattrib->ra[0],
1363 is_multicast_ether_addr(pattrib->ra)));
1364
1365 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
1366 is_multicast_ether_addr(pattrib->ra));
1367
1368 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1369 ("\n pattrib->encrypt =%d\n", pattrib->encrypt));
1370
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07001371 switch (pattrib->encrypt) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001372 case WLAN_CIPHER_SUITE_WEP40:
1373 case WLAN_CIPHER_SUITE_WEP104:
Jes Sorensen06e17e32014-05-25 22:43:02 +02001374 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
1375 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -05001376 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001377 case WLAN_CIPHER_SUITE_TKIP:
Jes Sorensen06e17e32014-05-25 22:43:02 +02001378 pattrib->iv_len = IEEE80211_TKIP_IV_LEN;
1379 pattrib->icv_len = IEEE80211_TKIP_ICV_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -05001380 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001381 case WLAN_CIPHER_SUITE_CCMP:
Jes Sorensen06e17e32014-05-25 22:43:02 +02001382 pattrib->iv_len = IEEE80211_CCMP_HDR_LEN;
1383 pattrib->icv_len = IEEE80211_CCMP_MIC_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -05001384 break;
Larry Finger5e93f352014-03-28 21:37:38 -05001385 default:
1386 pattrib->iv_len = 0;
1387 pattrib->icv_len = 0;
1388 break;
1389 }
1390 } else {
1391 pattrib->encrypt = 0;
1392 pattrib->iv_len = 0;
1393 pattrib->icv_len = 0;
1394 }
1395
1396exit:
1397
1398
1399
1400 return ret;
1401}
1402
1403static void dump_rx_pkt(struct sk_buff *skb, u16 type, int level)
1404{
1405 int i;
1406 u8 *ptr;
1407
1408 if ((level == 1) ||
1409 ((level == 2) && (type == IEEE80211_FTYPE_MGMT)) ||
1410 ((level == 3) && (type == IEEE80211_FTYPE_DATA))) {
1411
1412 ptr = skb->data;
1413
1414 DBG_8723A("#############################\n");
1415
1416 for (i = 0; i < 64; i = i + 8)
1417 DBG_8723A("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n",
1418 *(ptr + i), *(ptr + i + 1), *(ptr + i + 2),
1419 *(ptr + i + 3), *(ptr + i + 4),
1420 *(ptr + i + 5), *(ptr + i + 6),
1421 *(ptr + i + 7));
1422 DBG_8723A("#############################\n");
1423 }
1424}
1425
1426static int validate_recv_frame(struct rtw_adapter *adapter,
1427 struct recv_frame *precv_frame)
1428{
1429 /* shall check frame subtype, to / from ds, da, bssid */
1430
1431 /* then call check if rx seq/frag. duplicated. */
1432 u8 type;
1433 u8 subtype;
1434 int retval = _SUCCESS;
1435 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1436 struct sk_buff *skb = precv_frame->pkt;
1437 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1438 u8 ver;
1439 u8 bDumpRxPkt;
1440 u16 seq_ctrl, fctl;
1441
1442 fctl = le16_to_cpu(hdr->frame_control);
1443 ver = fctl & IEEE80211_FCTL_VERS;
1444 type = fctl & IEEE80211_FCTL_FTYPE;
1445 subtype = fctl & IEEE80211_FCTL_STYPE;
1446
1447 /* add version chk */
1448 if (ver != 0) {
1449 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1450 ("validate_recv_data_frame fail! (ver!= 0)\n"));
1451 retval = _FAIL;
1452 goto exit;
1453 }
1454
Larry Finger5e93f352014-03-28 21:37:38 -05001455 seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
1456 pattrib->frag_num = seq_ctrl & IEEE80211_SCTL_FRAG;
1457 pattrib->seq_num = seq_ctrl >> 4;
1458
1459 pattrib->pw_save = ieee80211_has_pm(hdr->frame_control);
1460 pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control);
1461 pattrib->mdata = ieee80211_has_moredata(hdr->frame_control);
1462 pattrib->privacy = ieee80211_has_protected(hdr->frame_control);
1463 pattrib->order = ieee80211_has_order(hdr->frame_control);
1464
Jes Sorensen39f1a8e2014-05-16 10:04:20 +02001465 GetHalDefVar8192CUsb(adapter, HAL_DEF_DBG_DUMP_RXPKT, &bDumpRxPkt);
Larry Finger5e93f352014-03-28 21:37:38 -05001466
1467 if (unlikely(bDumpRxPkt == 1))
1468 dump_rx_pkt(skb, type, bDumpRxPkt);
1469
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07001470 switch (type) {
Larry Finger5e93f352014-03-28 21:37:38 -05001471 case IEEE80211_FTYPE_MGMT:
1472 retval = validate_recv_mgnt_frame(adapter, precv_frame);
1473 if (retval == _FAIL) {
1474 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1475 ("validate_recv_mgnt_frame fail\n"));
1476 }
1477 retval = _FAIL; /* only data frame return _SUCCESS */
1478 break;
1479 case IEEE80211_FTYPE_CTL:
1480 retval = validate_recv_ctrl_frame(adapter, precv_frame);
1481 if (retval == _FAIL) {
1482 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1483 ("validate_recv_ctrl_frame fail\n"));
1484 }
1485 retval = _FAIL; /* only data frame return _SUCCESS */
1486 break;
1487 case IEEE80211_FTYPE_DATA:
Larry Finger5e93f352014-03-28 21:37:38 -05001488 pattrib->qos = (subtype & IEEE80211_STYPE_QOS_DATA) ? 1 : 0;
1489 retval = validate_recv_data_frame(adapter, precv_frame);
1490 if (retval == _FAIL) {
1491 struct recv_priv *precvpriv = &adapter->recvpriv;
1492 /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail\n")); */
1493 precvpriv->rx_drop++;
1494 }
1495 break;
1496 default:
1497 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1498 ("validate_recv_data_frame fail! type = 0x%x\n", type));
1499 retval = _FAIL;
1500 break;
1501 }
1502
1503exit:
1504 return retval;
1505}
1506
1507/* remove the wlanhdr and add the eth_hdr */
1508
1509static int wlanhdr_to_ethhdr (struct recv_frame *precvframe)
1510{
1511 u16 eth_type, len, hdrlen;
1512 u8 bsnaphdr;
1513 u8 *psnap;
Larry Finger5e93f352014-03-28 21:37:38 -05001514 struct rtw_adapter *adapter = precvframe->adapter;
1515 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1516
1517 struct sk_buff *skb = precvframe->pkt;
1518 u8 *ptr;
1519 struct rx_pkt_attrib *pattrib = &precvframe->attrib;
1520
1521
1522
1523 ptr = skb->data;
1524 hdrlen = pattrib->hdrlen;
1525 psnap = ptr + hdrlen;
1526 eth_type = (psnap[6] << 8) | psnap[7];
1527 /* convert hdr + possible LLC headers into Ethernet header */
1528 /* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */
1529 if ((ether_addr_equal(psnap, rfc1042_header) &&
1530 eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
1531 ether_addr_equal(psnap, bridge_tunnel_header)) {
1532 /* remove RFC1042 or Bridge-Tunnel encapsulation
1533 and replace EtherType */
1534 bsnaphdr = true;
1535 hdrlen += SNAP_SIZE;
1536 } else {
1537 /* Leave Ethernet header part of hdr and full payload */
1538 bsnaphdr = false;
1539 eth_type = (psnap[0] << 8) | psnap[1];
1540 }
1541
1542 len = skb->len - hdrlen;
1543
1544 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1545 ("\n === pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n\n",
1546 pattrib->hdrlen, pattrib->iv_len));
1547
1548 pattrib->eth_type = eth_type;
Jes Sorensenf2f97032014-05-25 22:43:04 +02001549 if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001550 ptr += hdrlen;
1551 *ptr = 0x87;
1552 *(ptr + 1) = 0x12;
1553
1554 eth_type = 0x8712;
1555 /* append rx status for mp test packets */
1556
1557 ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + 2) - 24);
1558 memcpy(ptr, skb->head, 24);
1559 ptr += 24;
1560 } else {
1561 ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) +
1562 (bsnaphdr ? 2:0)));
1563 }
1564
1565 ether_addr_copy(ptr, pattrib->dst);
1566 ether_addr_copy(ptr + ETH_ALEN, pattrib->src);
1567
1568 if (!bsnaphdr) {
1569 len = htons(len);
1570 memcpy(ptr + 12, &len, 2);
1571 }
1572
1573
Roberta Dobrescu038b7032014-10-26 23:30:09 +02001574 return _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05001575}
1576
1577/* perform defrag */
1578struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
1579 struct rtw_queue *defrag_q);
1580struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
1581 struct rtw_queue *defrag_q)
1582{
1583 struct list_head *plist, *phead, *ptmp;
1584 u8 *data, wlanhdr_offset;
1585 u8 curfragnum;
1586 struct recv_frame *pnfhdr;
1587 struct recv_frame *prframe, *pnextrframe;
1588 struct rtw_queue *pfree_recv_queue;
1589 struct sk_buff *skb;
1590
1591
1592
1593 curfragnum = 0;
1594 pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
1595
1596 phead = get_list_head(defrag_q);
1597 plist = phead->next;
1598 prframe = container_of(plist, struct recv_frame, list);
1599 list_del_init(&prframe->list);
1600 skb = prframe->pkt;
1601
1602 if (curfragnum != prframe->attrib.frag_num) {
1603 /* the first fragment number must be 0 */
1604 /* free the whole queue */
Jes Sorensenc5779a02014-05-09 15:03:58 +02001605 rtw_free_recvframe23a(prframe);
1606 rtw_free_recvframe23a_queue(defrag_q);
Larry Finger5e93f352014-03-28 21:37:38 -05001607
1608 return NULL;
1609 }
1610
1611 curfragnum++;
1612
1613 phead = get_list_head(defrag_q);
1614
1615 data = prframe->pkt->data;
1616
1617 list_for_each_safe(plist, ptmp, phead) {
1618 pnfhdr = container_of(plist, struct recv_frame, list);
1619 pnextrframe = (struct recv_frame *)pnfhdr;
1620 /* check the fragment sequence (2nd ~n fragment frame) */
1621
1622 if (curfragnum != pnfhdr->attrib.frag_num) {
1623 /* the fragment number must be increasing
1624 (after decache) */
1625 /* release the defrag_q & prframe */
Jes Sorensenc5779a02014-05-09 15:03:58 +02001626 rtw_free_recvframe23a(prframe);
1627 rtw_free_recvframe23a_queue(defrag_q);
Larry Finger5e93f352014-03-28 21:37:38 -05001628 return NULL;
1629 }
1630
1631 curfragnum++;
1632
1633 /* copy the 2nd~n fragment frame's payload to the
1634 first fragment */
1635 /* get the 2nd~last fragment frame's payload */
1636
1637 wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
1638
1639 skb_pull(pnfhdr->pkt, wlanhdr_offset);
1640
1641 /* append to first fragment frame's tail
1642 (if privacy frame, pull the ICV) */
1643
1644 skb_trim(skb, skb->len - prframe->attrib.icv_len);
1645
1646 memcpy(skb_tail_pointer(skb), pnfhdr->pkt->data,
1647 pnfhdr->pkt->len);
1648
1649 skb_put(skb, pnfhdr->pkt->len);
1650
1651 prframe->attrib.icv_len = pnfhdr->attrib.icv_len;
Roberta Dobrescub9b42242014-10-26 23:30:06 +02001652 }
Larry Finger5e93f352014-03-28 21:37:38 -05001653
1654 /* free the defrag_q queue and return the prframe */
Jes Sorensenc5779a02014-05-09 15:03:58 +02001655 rtw_free_recvframe23a_queue(defrag_q);
Larry Finger5e93f352014-03-28 21:37:38 -05001656
1657 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1658 ("Performance defrag!!!!!\n"));
1659
1660
1661
1662 return prframe;
1663}
1664
1665/* check if need to defrag, if needed queue the frame to defrag_q */
Greg Donald4e66cf02014-08-22 10:57:49 -05001666struct recv_frame *recvframe_chk_defrag23a(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -05001667 struct recv_frame *precv_frame)
1668{
1669 u8 ismfrag;
1670 u8 fragnum;
1671 u8 *psta_addr;
1672 struct recv_frame *pfhdr;
1673 struct sta_info *psta;
1674 struct sta_priv *pstapriv;
1675 struct list_head *phead;
1676 struct recv_frame *prtnframe = NULL;
1677 struct rtw_queue *pfree_recv_queue, *pdefrag_q;
1678
1679
1680
1681 pstapriv = &padapter->stapriv;
1682
1683 pfhdr = precv_frame;
1684
1685 pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
1686
1687 /* need to define struct of wlan header frame ctrl */
1688 ismfrag = pfhdr->attrib.mfrag;
1689 fragnum = pfhdr->attrib.frag_num;
1690
1691 psta_addr = pfhdr->attrib.ta;
1692 psta = rtw_get_stainfo23a(pstapriv, psta_addr);
1693 if (!psta) {
1694 struct ieee80211_hdr *hdr =
1695 (struct ieee80211_hdr *) pfhdr->pkt->data;
1696 if (!ieee80211_is_data(hdr->frame_control)) {
1697 psta = rtw_get_bcmc_stainfo23a(padapter);
1698 pdefrag_q = &psta->sta_recvpriv.defrag_q;
1699 } else
1700 pdefrag_q = NULL;
1701 } else
1702 pdefrag_q = &psta->sta_recvpriv.defrag_q;
1703
1704 if ((ismfrag == 0) && (fragnum == 0)) {
1705 prtnframe = precv_frame;/* isn't a fragment frame */
1706 }
1707
1708 if (ismfrag == 1) {
1709 /* 0~(n-1) fragment frame */
1710 /* enqueue to defraf_g */
1711 if (pdefrag_q != NULL) {
1712 if (fragnum == 0) {
1713 /* the first fragment */
Jes Sorensen794ff052014-05-09 15:03:59 +02001714 if (!list_empty(&pdefrag_q->queue)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001715 /* free current defrag_q */
Jes Sorensenc5779a02014-05-09 15:03:58 +02001716 rtw_free_recvframe23a_queue(pdefrag_q);
Larry Finger5e93f352014-03-28 21:37:38 -05001717 }
1718 }
1719
1720 /* Then enqueue the 0~(n-1) fragment into the
1721 defrag_q */
1722
1723 /* spin_lock(&pdefrag_q->lock); */
1724 phead = get_list_head(pdefrag_q);
1725 list_add_tail(&pfhdr->list, phead);
1726 /* spin_unlock(&pdefrag_q->lock); */
1727
1728 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1729 ("Enqueuq: ismfrag = %d, fragnum = %d\n",
1730 ismfrag, fragnum));
1731
1732 prtnframe = NULL;
1733
1734 } else {
1735 /* can't find this ta's defrag_queue,
1736 so free this recv_frame */
Jes Sorensenc5779a02014-05-09 15:03:58 +02001737 rtw_free_recvframe23a(precv_frame);
Larry Finger5e93f352014-03-28 21:37:38 -05001738 prtnframe = NULL;
1739 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1740 ("Free because pdefrag_q == NULL: ismfrag = "
1741 "%d, fragnum = %d\n", ismfrag, fragnum));
1742 }
1743 }
1744
1745 if ((ismfrag == 0) && (fragnum != 0)) {
1746 /* the last fragment frame */
1747 /* enqueue the last fragment */
1748 if (pdefrag_q != NULL) {
1749 /* spin_lock(&pdefrag_q->lock); */
1750 phead = get_list_head(pdefrag_q);
1751 list_add_tail(&pfhdr->list, phead);
1752 /* spin_unlock(&pdefrag_q->lock); */
1753
1754 /* call recvframe_defrag to defrag */
1755 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1756 ("defrag: ismfrag = %d, fragnum = %d\n",
1757 ismfrag, fragnum));
1758 precv_frame = recvframe_defrag(padapter, pdefrag_q);
1759 prtnframe = precv_frame;
1760 } else {
1761 /* can't find this ta's defrag_queue,
1762 so free this recv_frame */
Jes Sorensenc5779a02014-05-09 15:03:58 +02001763 rtw_free_recvframe23a(precv_frame);
Larry Finger5e93f352014-03-28 21:37:38 -05001764 prtnframe = NULL;
1765 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1766 ("Free because pdefrag_q == NULL: ismfrag = "
1767 "%d, fragnum = %d\n", ismfrag, fragnum));
1768 }
1769
1770 }
1771
1772 if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) {
1773 /* after defrag we must check tkip mic code */
1774 if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
1775 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1776 ("recvframe_chkmic(padapter, prtnframe) =="
1777 "_FAIL\n"));
Jes Sorensenc5779a02014-05-09 15:03:58 +02001778 rtw_free_recvframe23a(prtnframe);
Larry Finger5e93f352014-03-28 21:37:38 -05001779 prtnframe = NULL;
1780 }
1781 }
1782
1783
1784
1785 return prtnframe;
1786}
1787
1788int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe);
1789int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
1790{
1791 struct rx_pkt_attrib *pattrib;
1792 struct sk_buff *skb, *sub_skb;
1793 struct sk_buff_head skb_list;
Larry Finger5e93f352014-03-28 21:37:38 -05001794
1795 pattrib = &prframe->attrib;
1796
1797 skb = prframe->pkt;
1798 skb_pull(skb, prframe->attrib.hdrlen);
1799 __skb_queue_head_init(&skb_list);
1800
1801 ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false);
1802
1803 while (!skb_queue_empty(&skb_list)) {
1804 sub_skb = __skb_dequeue(&skb_list);
1805
1806 sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
1807 sub_skb->dev = padapter->pnetdev;
1808
1809 sub_skb->ip_summed = CHECKSUM_NONE;
1810
1811 netif_rx(sub_skb);
1812 }
1813
1814 prframe->pkt = NULL;
Jes Sorensenc5779a02014-05-09 15:03:58 +02001815 rtw_free_recvframe23a(prframe);
Larry Finger5e93f352014-03-28 21:37:38 -05001816 return _SUCCESS;
1817}
1818
1819int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
1820int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
1821{
1822 u8 wsize = preorder_ctrl->wsize_b;
1823 u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF;
1824
1825 /* Rx Reorder initialize condition. */
1826 if (preorder_ctrl->indicate_seq == 0xFFFF)
1827 preorder_ctrl->indicate_seq = seq_num;
1828
1829 /* Drop out the packet which SeqNum is smaller than WinStart */
1830 if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
1831 return false;
1832
1833 /* */
1834 /* Sliding window manipulation. Conditions includes: */
1835 /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
1836 /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */
1837 /* */
1838 if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {
1839 preorder_ctrl->indicate_seq =
1840 (preorder_ctrl->indicate_seq + 1) & 0xFFF;
1841 } else if (SN_LESS(wend, seq_num)) {
1842 /* boundary situation, when seq_num cross 0xFFF */
1843 if (seq_num >= (wsize - 1))
1844 preorder_ctrl->indicate_seq = seq_num + 1 -wsize;
1845 else
1846 preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
1847 }
1848 return true;
1849}
1850
Larry Fingerc0b99be2014-04-26 18:55:17 +02001851static int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl,
Greg Donalda82b4b02014-09-08 20:50:23 -05001852 struct recv_frame *prframe)
Larry Finger5e93f352014-03-28 21:37:38 -05001853{
1854 struct rx_pkt_attrib *pattrib = &prframe->attrib;
1855 struct rtw_queue *ppending_recvframe_queue;
1856 struct list_head *phead, *plist, *ptmp;
1857 struct recv_frame *hdr;
1858 struct rx_pkt_attrib *pnextattrib;
1859
1860 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
1861 /* DbgPrint("+enqueue_reorder_recvframe23a()\n"); */
1862
1863 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1864 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1865
1866 phead = get_list_head(ppending_recvframe_queue);
1867
1868 list_for_each_safe(plist, ptmp, phead) {
1869 hdr = container_of(plist, struct recv_frame, list);
1870 pnextattrib = &hdr->attrib;
1871
1872 if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) {
1873 continue;
1874 } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) {
1875 /* Duplicate entry is found!! Do not insert current entry. */
1876 /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
1877
1878 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1879 return false;
1880 } else {
1881 break;
1882 }
1883
1884 /* DbgPrint("enqueue_reorder_recvframe23a():while\n"); */
1885 }
1886
1887 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1888 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1889
1890 list_del_init(&prframe->list);
1891
1892 list_add_tail(&prframe->list, plist);
1893
1894 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
1895 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1896
1897 /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
1898 return true;
1899}
1900
1901int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
1902 struct recv_reorder_ctrl *preorder_ctrl,
1903 int bforced);
1904int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
1905 struct recv_reorder_ctrl *preorder_ctrl,
1906 int bforced)
1907{
1908 /* u8 bcancelled; */
1909 struct list_head *phead, *plist;
1910 struct recv_frame *prframe;
1911 struct rx_pkt_attrib *pattrib;
1912 /* u8 index = 0; */
1913 int bPktInBuf = false;
1914 struct recv_priv *precvpriv;
1915 struct rtw_queue *ppending_recvframe_queue;
1916
1917 precvpriv = &padapter->recvpriv;
1918 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
1919 /* DbgPrint("+recv_indicatepkts_in_order\n"); */
1920
1921 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1922 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1923
1924 phead = get_list_head(ppending_recvframe_queue);
1925 plist = phead->next;
1926
1927 /* Handling some condition for forced indicate case. */
1928 if (bforced) {
1929 if (list_empty(phead)) {
1930 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1931 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
1932 return true;
1933 }
1934
1935 prframe = container_of(plist, struct recv_frame, list);
Greg Donalda82b4b02014-09-08 20:50:23 -05001936 pattrib = &prframe->attrib;
Larry Finger5e93f352014-03-28 21:37:38 -05001937 preorder_ctrl->indicate_seq = pattrib->seq_num;
1938 }
1939
1940 /* Prepare indication list and indication. */
1941 /* Check if there is any packet need indicate. */
1942 while (!list_empty(phead)) {
1943
1944 prframe = container_of(plist, struct recv_frame, list);
1945 pattrib = &prframe->attrib;
1946
1947 if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
1948 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
1949 ("recv_indicatepkts_in_order: indicate =%d "
1950 "seq =%d amsdu =%d\n",
1951 preorder_ctrl->indicate_seq,
1952 pattrib->seq_num, pattrib->amsdu));
1953
1954 plist = plist->next;
1955 list_del_init(&prframe->list);
1956
1957 if (SN_EQUAL(preorder_ctrl->indicate_seq,
1958 pattrib->seq_num)) {
1959 preorder_ctrl->indicate_seq =
1960 (preorder_ctrl->indicate_seq + 1)&0xFFF;
1961 }
1962
1963 if (!pattrib->amsdu) {
1964 if ((padapter->bDriverStopped == false) &&
1965 (padapter->bSurpriseRemoved == false)) {
1966 rtw_recv_indicatepkt23a(padapter, prframe);
1967 }
1968 } else {
1969 if (amsdu_to_msdu(padapter, prframe) !=
Jes Sorensenc5779a02014-05-09 15:03:58 +02001970 _SUCCESS)
1971 rtw_free_recvframe23a(prframe);
Larry Finger5e93f352014-03-28 21:37:38 -05001972 }
1973
1974 /* Update local variables. */
1975 bPktInBuf = false;
1976
1977 } else {
1978 bPktInBuf = true;
1979 break;
1980 }
1981
1982 /* DbgPrint("recv_indicatepkts_in_order():while\n"); */
1983 }
1984
1985 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
1986 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1987
1988 return bPktInBuf;
1989}
1990
1991int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
1992 struct recv_frame *prframe);
1993int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
1994 struct recv_frame *prframe)
1995{
1996 int retval = _SUCCESS;
1997 struct rx_pkt_attrib *pattrib;
1998 struct recv_reorder_ctrl *preorder_ctrl;
1999 struct rtw_queue *ppending_recvframe_queue;
2000
2001 pattrib = &prframe->attrib;
2002 preorder_ctrl = prframe->preorder_ctrl;
2003 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2004
2005 if (!pattrib->amsdu) {
2006 /* s1. */
2007 wlanhdr_to_ethhdr(prframe);
2008
Jes Sorensen7dd1e722014-04-09 23:21:20 +02002009 if ((pattrib->qos!= 1) || (pattrib->eth_type == ETH_P_ARP) ||
Larry Finger5e93f352014-03-28 21:37:38 -05002010 (pattrib->ack_policy != 0)) {
2011 if ((padapter->bDriverStopped == false) &&
2012 (padapter->bSurpriseRemoved == false)) {
2013 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2014 ("@@@@ recv_indicatepkt_reorder -"
2015 "recv_func recv_indicatepkt\n"));
2016
2017 rtw_recv_indicatepkt23a(padapter, prframe);
2018 return _SUCCESS;
2019 }
2020
2021 return _FAIL;
2022 }
2023
2024 if (preorder_ctrl->enable == false) {
2025 /* indicate this recv_frame */
2026 preorder_ctrl->indicate_seq = pattrib->seq_num;
2027 rtw_recv_indicatepkt23a(padapter, prframe);
2028
2029 preorder_ctrl->indicate_seq =
2030 (preorder_ctrl->indicate_seq + 1) % 4096;
2031 return _SUCCESS;
2032 }
2033 } else {
2034 /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
2035 if (preorder_ctrl->enable == false) {
2036 preorder_ctrl->indicate_seq = pattrib->seq_num;
2037 retval = amsdu_to_msdu(padapter, prframe);
2038
2039 preorder_ctrl->indicate_seq =
2040 (preorder_ctrl->indicate_seq + 1) % 4096;
2041 return retval;
2042 }
2043 }
2044
2045 spin_lock_bh(&ppending_recvframe_queue->lock);
2046
2047 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2048 ("recv_indicatepkt_reorder: indicate =%d seq =%d\n",
2049 preorder_ctrl->indicate_seq, pattrib->seq_num));
2050
2051 /* s2. check if winstart_b(indicate_seq) needs to been updated */
2052 if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
2053 goto _err_exit;
2054 }
2055
2056 /* s3. Insert all packet into Reorder Queue to maintain its ordering. */
2057 if (!enqueue_reorder_recvframe23a(preorder_ctrl, prframe)) {
2058 goto _err_exit;
2059 }
2060
2061 /* s4. */
2062 /* Indication process. */
2063 /* After Packet dropping and Sliding Window shifting as above,
2064 we can now just indicate the packets */
2065 /* with the SeqNum smaller than latest WinStart and buffer
2066 other packets. */
2067 /* */
2068 /* For Rx Reorder condition: */
2069 /* 1. All packets with SeqNum smaller than WinStart => Indicate */
2070 /* 2. All packets with SeqNum larger than or equal to WinStart =>
2071 Buffer it. */
2072 /* */
2073
2074 if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) {
2075 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
2076 jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
2077 spin_unlock_bh(&ppending_recvframe_queue->lock);
2078 } else {
2079 spin_unlock_bh(&ppending_recvframe_queue->lock);
2080 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
2081 }
2082 return _SUCCESS;
2083
2084_err_exit:
2085
Greg Donalda82b4b02014-09-08 20:50:23 -05002086 spin_unlock_bh(&ppending_recvframe_queue->lock);
Larry Finger5e93f352014-03-28 21:37:38 -05002087 return _FAIL;
2088}
2089
2090void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext)
2091{
2092 struct recv_reorder_ctrl *preorder_ctrl;
2093 struct rtw_adapter *padapter;
2094 struct rtw_queue *ppending_recvframe_queue;
2095
2096 preorder_ctrl = (struct recv_reorder_ctrl *)pcontext;
2097 padapter = preorder_ctrl->padapter;
2098 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2099
2100 if (padapter->bDriverStopped || padapter->bSurpriseRemoved) {
2101 return;
2102 }
2103
2104 /* DBG_8723A("+rtw_reordering_ctrl_timeout_handler23a() =>\n"); */
2105
2106 spin_lock_bh(&ppending_recvframe_queue->lock);
2107
2108 if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true) {
2109 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
2110 jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
2111 }
2112
2113 spin_unlock_bh(&ppending_recvframe_queue->lock);
2114}
2115
2116int process_recv_indicatepkts(struct rtw_adapter *padapter,
2117 struct recv_frame *prframe);
2118int process_recv_indicatepkts(struct rtw_adapter *padapter,
2119 struct recv_frame *prframe)
2120{
2121 int retval = _SUCCESS;
2122 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2123 /* struct rx_pkt_attrib *pattrib = &prframe->attrib; */
2124 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2125 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2126
2127 if (phtpriv->ht_option == true) { /* B/G/N Mode */
2128 /* prframe->preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
2129
2130 /* including perform A-MPDU Rx Ordering Buffer Control */
2131 if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
2132 if ((padapter->bDriverStopped == false) &&
2133 (padapter->bSurpriseRemoved == false)) {
2134 retval = _FAIL;
2135 return retval;
2136 }
2137 }
Tina Ruchandani5db8bee2014-10-23 20:17:20 -07002138 } else { /* B/G mode */
Larry Finger5e93f352014-03-28 21:37:38 -05002139 retval = wlanhdr_to_ethhdr(prframe);
2140 if (retval != _SUCCESS) {
2141 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2142 ("wlanhdr_to_ethhdr: drop pkt\n"));
2143 return retval;
2144 }
2145
2146 if ((padapter->bDriverStopped == false) &&
2147 (padapter->bSurpriseRemoved == false)) {
2148 /* indicate this recv_frame */
2149 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2150 ("@@@@ process_recv_indicatepkts- "
2151 "recv_func recv_indicatepkt\n"));
2152 rtw_recv_indicatepkt23a(padapter, prframe);
2153 } else {
2154 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2155 ("@@@@ process_recv_indicatepkts- "
2156 "recv_func free_indicatepkt\n"));
2157
2158 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2159 ("recv_func:bDriverStopped(%d) OR "
2160 "bSurpriseRemoved(%d)",
2161 padapter->bDriverStopped,
2162 padapter->bSurpriseRemoved));
2163 retval = _FAIL;
2164 return retval;
2165 }
2166
2167 }
2168
2169 return retval;
2170}
2171
2172static int recv_func_prehandle(struct rtw_adapter *padapter,
2173 struct recv_frame *rframe)
2174{
Larry Finger5e93f352014-03-28 21:37:38 -05002175 int ret = _SUCCESS;
2176
2177 /* check the frame crtl field and decache */
2178 ret = validate_recv_frame(padapter, rframe);
2179 if (ret != _SUCCESS) {
2180 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
2181 ("recv_func: validate_recv_frame fail! drop pkt\n"));
Jes Sorensenc5779a02014-05-09 15:03:58 +02002182 rtw_free_recvframe23a(rframe);
Larry Finger5e93f352014-03-28 21:37:38 -05002183 goto exit;
2184 }
2185
2186exit:
2187 return ret;
2188}
2189
2190static int recv_func_posthandle(struct rtw_adapter *padapter,
2191 struct recv_frame *prframe)
2192{
2193 int ret = _SUCCESS;
2194 struct recv_frame *orig_prframe = prframe;
2195 struct recv_priv *precvpriv = &padapter->recvpriv;
Larry Finger5e93f352014-03-28 21:37:38 -05002196
2197 /* DATA FRAME */
Larry Finger5e93f352014-03-28 21:37:38 -05002198 prframe = decryptor(padapter, prframe);
2199 if (prframe == NULL) {
2200 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2201 ("decryptor: drop pkt\n"));
2202 ret = _FAIL;
2203 goto _recv_data_drop;
2204 }
2205
2206 prframe = recvframe_chk_defrag23a(padapter, prframe);
2207 if (!prframe) {
2208 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2209 ("recvframe_chk_defrag23a: drop pkt\n"));
2210 goto _recv_data_drop;
2211 }
2212
2213 /*
2214 * Pull off crypto headers
2215 */
2216 if (prframe->attrib.iv_len > 0) {
2217 skb_pull(prframe->pkt, prframe->attrib.iv_len);
2218 }
2219
2220 if (prframe->attrib.icv_len > 0) {
2221 skb_trim(prframe->pkt,
2222 prframe->pkt->len - prframe->attrib.icv_len);
2223 }
2224
2225 prframe = portctrl(padapter, prframe);
2226 if (!prframe) {
2227 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2228 ("portctrl: drop pkt\n"));
2229 ret = _FAIL;
2230 goto _recv_data_drop;
2231 }
2232
2233 count_rx_stats(padapter, prframe, NULL);
2234
2235 ret = process_recv_indicatepkts(padapter, prframe);
2236 if (ret != _SUCCESS) {
2237 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2238 ("recv_func: process_recv_indicatepkts fail!\n"));
Jes Sorensenc5779a02014-05-09 15:03:58 +02002239 rtw_free_recvframe23a(orig_prframe);/* free this recv_frame */
Larry Finger5e93f352014-03-28 21:37:38 -05002240 goto _recv_data_drop;
2241 }
2242 return ret;
2243
2244_recv_data_drop:
2245 precvpriv->rx_drop++;
2246 return ret;
2247}
2248
2249int rtw_recv_entry23a(struct recv_frame *rframe)
2250{
2251 int ret, r;
2252 struct rtw_adapter *padapter = rframe->adapter;
2253 struct rx_pkt_attrib *prxattrib = &rframe->attrib;
2254 struct recv_priv *recvpriv = &padapter->recvpriv;
2255 struct security_priv *psecuritypriv = &padapter->securitypriv;
2256 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
2257
2258 /* check if need to handle uc_swdec_pending_queue*/
2259 if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2260 psecuritypriv->busetkipkey) {
2261 struct recv_frame *pending_frame;
2262
2263 while ((pending_frame = rtw_alloc_recvframe23a(&padapter->recvpriv.uc_swdec_pending_queue))) {
2264 r = recv_func_posthandle(padapter, pending_frame);
2265 if (r == _SUCCESS)
2266 DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__);
2267 }
2268 }
2269
2270 ret = recv_func_prehandle(padapter, rframe);
2271
2272 if (ret == _SUCCESS) {
2273 /* check if need to enqueue into uc_swdec_pending_queue*/
2274 if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2275 !is_multicast_ether_addr(prxattrib->ra) &&
2276 prxattrib->encrypt > 0 &&
2277 (prxattrib->bdecrypted == 0) &&
2278 !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) &&
2279 !psecuritypriv->busetkipkey) {
2280 rtw_enqueue_recvframe23a(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
2281 DBG_8723A("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
2282 goto exit;
2283 }
2284
2285 ret = recv_func_posthandle(padapter, rframe);
2286
2287 recvpriv->rx_pkts++;
2288 }
2289
2290exit:
2291 return ret;
2292}
2293
2294void rtw_signal_stat_timer_hdl23a(unsigned long data)
2295{
2296 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
2297 struct recv_priv *recvpriv = &adapter->recvpriv;
2298
2299 u32 tmp_s, tmp_q;
2300 u8 avg_signal_strength = 0;
2301 u8 avg_signal_qual = 0;
2302 u32 num_signal_strength = 0;
2303 u32 num_signal_qual = 0;
2304 u8 _alpha = 3; /* this value is based on converging_constant = 5000 */
2305 /* and sampling_interval = 1000 */
2306
Jes Sorensen707ce722014-11-30 16:04:52 -05002307 if (recvpriv->signal_strength_data.update_req == 0) {
2308 /* update_req is clear, means we got rx */
2309 avg_signal_strength = recvpriv->signal_strength_data.avg_val;
2310 num_signal_strength = recvpriv->signal_strength_data.total_num;
2311 /* after avg_vals are acquired, we can re-stat */
2312 /* the signal values */
2313 recvpriv->signal_strength_data.update_req = 1;
Larry Finger5e93f352014-03-28 21:37:38 -05002314 }
Jes Sorensen707ce722014-11-30 16:04:52 -05002315
2316 if (recvpriv->signal_qual_data.update_req == 0) {
2317 /* update_req is clear, means we got rx */
2318 avg_signal_qual = recvpriv->signal_qual_data.avg_val;
2319 num_signal_qual = recvpriv->signal_qual_data.total_num;
2320 /* after avg_vals are acquired, we can re-stat */
2321 /*the signal values */
2322 recvpriv->signal_qual_data.update_req = 1;
2323 }
2324
2325 /* update value of signal_strength, rssi, signal_qual */
2326 if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) {
Haneen Mohammedacc4b972015-03-13 20:45:25 +03002327 tmp_s = avg_signal_strength + (_alpha - 1) *
2328 recvpriv->signal_strength;
Jes Sorensen707ce722014-11-30 16:04:52 -05002329 if (tmp_s %_alpha)
2330 tmp_s = tmp_s / _alpha + 1;
2331 else
2332 tmp_s = tmp_s / _alpha;
2333 if (tmp_s > 100)
2334 tmp_s = 100;
2335
2336 tmp_q = avg_signal_qual + (_alpha - 1) * recvpriv->signal_qual;
2337 if (tmp_q %_alpha)
2338 tmp_q = tmp_q / _alpha + 1;
2339 else
2340 tmp_q = tmp_q / _alpha;
2341 if (tmp_q > 100)
2342 tmp_q = 100;
2343
2344 recvpriv->signal_strength = tmp_s;
Jes Sorensen707ce722014-11-30 16:04:52 -05002345 recvpriv->signal_qual = tmp_q;
2346
Jes Sorensenf7bf8c22014-11-30 16:04:53 -05002347 DBG_8723A("%s signal_strength:%3u, signal_qual:%3u, "
2348 "num_signal_strength:%u, num_signal_qual:%u\n",
Jes Sorensen707ce722014-11-30 16:04:52 -05002349 __func__, recvpriv->signal_strength,
Jes Sorensenf7bf8c22014-11-30 16:04:53 -05002350 recvpriv->signal_qual, num_signal_strength,
2351 num_signal_qual);
Jes Sorensen707ce722014-11-30 16:04:52 -05002352 }
2353
Larry Finger5e93f352014-03-28 21:37:38 -05002354 rtw_set_signal_stat_timer(recvpriv);
2355}