1 /******************************************************************************
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_RECV_C_
31 #include <linux/slab.h>
32 #include <linux/kmemleak.h>
34 #include "osdep_service.h"
35 #include "drv_types.h"
36 #include "recv_osdep.h"
37 #include "mlme_osdep.h"
44 static const u8 SNAP_ETH_TYPE_IPX
[2] = {0x81, 0x37};
46 /* Datagram Delivery Protocol */
47 static const u8 SNAP_ETH_TYPE_APPLETALK_AARP
[2] = {0x80, 0xf3};
49 /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
50 static const u8 bridge_tunnel_header
[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
52 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
53 static const u8 rfc1042_header
[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
55 void _r8712_init_sta_recv_priv(struct sta_recv_priv
*psta_recvpriv
)
57 memset((u8
*)psta_recvpriv
, 0, sizeof(struct sta_recv_priv
));
58 spin_lock_init(&psta_recvpriv
->lock
);
59 _init_queue(&psta_recvpriv
->defrag_q
);
62 sint
_r8712_init_recv_priv(struct recv_priv
*precvpriv
,
63 struct _adapter
*padapter
)
66 union recv_frame
*precvframe
;
68 memset((unsigned char *)precvpriv
, 0, sizeof(struct recv_priv
));
69 spin_lock_init(&precvpriv
->lock
);
70 _init_queue(&precvpriv
->free_recv_queue
);
71 _init_queue(&precvpriv
->recv_pending_queue
);
72 precvpriv
->adapter
= padapter
;
73 precvpriv
->free_recvframe_cnt
= NR_RECVFRAME
;
74 precvpriv
->pallocated_frame_buf
= _malloc(NR_RECVFRAME
*
75 sizeof(union recv_frame
) +
77 if (precvpriv
->pallocated_frame_buf
== NULL
)
79 kmemleak_not_leak(precvpriv
->pallocated_frame_buf
);
80 memset(precvpriv
->pallocated_frame_buf
, 0, NR_RECVFRAME
*
81 sizeof(union recv_frame
) + RXFRAME_ALIGN_SZ
);
82 precvpriv
->precv_frame_buf
= precvpriv
->pallocated_frame_buf
+
84 ((addr_t
)(precvpriv
->pallocated_frame_buf
) &
85 (RXFRAME_ALIGN_SZ
-1));
86 precvframe
= (union recv_frame
*)precvpriv
->precv_frame_buf
;
87 for (i
= 0; i
< NR_RECVFRAME
; i
++) {
88 _init_listhead(&(precvframe
->u
.list
));
89 list_insert_tail(&(precvframe
->u
.list
),
90 &(precvpriv
->free_recv_queue
.queue
));
91 r8712_os_recv_resource_alloc(padapter
, precvframe
);
92 precvframe
->u
.hdr
.adapter
= padapter
;
95 precvpriv
->rx_pending_cnt
= 1;
96 sema_init(&precvpriv
->allrxreturnevt
, 0);
97 return r8712_init_recv_priv(precvpriv
, padapter
);
100 void _r8712_free_recv_priv(struct recv_priv
*precvpriv
)
102 kfree(precvpriv
->pallocated_frame_buf
);
103 r8712_free_recv_priv(precvpriv
);
106 union recv_frame
*r8712_alloc_recvframe(struct __queue
*pfree_recv_queue
)
109 union recv_frame
*precvframe
;
110 struct list_head
*plist
, *phead
;
111 struct _adapter
*padapter
;
112 struct recv_priv
*precvpriv
;
114 spin_lock_irqsave(&pfree_recv_queue
->lock
, irqL
);
115 if (_queue_empty(pfree_recv_queue
) == true)
118 phead
= get_list_head(pfree_recv_queue
);
119 plist
= get_next(phead
);
120 precvframe
= LIST_CONTAINOR(plist
, union recv_frame
, u
);
121 list_delete(&precvframe
->u
.hdr
.list
);
122 padapter
= precvframe
->u
.hdr
.adapter
;
123 if (padapter
!= NULL
) {
124 precvpriv
= &padapter
->recvpriv
;
125 if (pfree_recv_queue
== &precvpriv
->free_recv_queue
)
126 precvpriv
->free_recvframe_cnt
--;
129 spin_unlock_irqrestore(&pfree_recv_queue
->lock
, irqL
);
134 caller : defrag; recvframe_chk_defrag in recv_thread (passive)
135 pframequeue: defrag_queue : will be accessed in recv_thread (passive)
137 using spin_lock to protect
141 void r8712_free_recvframe_queue(struct __queue
*pframequeue
,
142 struct __queue
*pfree_recv_queue
)
144 union recv_frame
*precvframe
;
145 struct list_head
*plist
, *phead
;
147 spin_lock(&pframequeue
->lock
);
148 phead
= get_list_head(pframequeue
);
149 plist
= get_next(phead
);
150 while (end_of_queue_search(phead
, plist
) == false) {
151 precvframe
= LIST_CONTAINOR(plist
, union recv_frame
, u
);
152 plist
= get_next(plist
);
153 r8712_free_recvframe(precvframe
, pfree_recv_queue
);
155 spin_unlock(&pframequeue
->lock
);
158 sint
r8712_recvframe_chkmic(struct _adapter
*adapter
,
159 union recv_frame
*precvframe
)
161 sint i
, res
= _SUCCESS
;
165 u8
*pframe
, *payload
, *pframemic
;
166 u8
*mickey
, idx
, *iv
;
167 struct sta_info
*stainfo
;
168 struct rx_pkt_attrib
*prxattrib
= &precvframe
->u
.hdr
.attrib
;
169 struct security_priv
*psecuritypriv
= &adapter
->securitypriv
;
171 stainfo
= r8712_get_stainfo(&adapter
->stapriv
, &prxattrib
->ta
[0]);
172 if (prxattrib
->encrypt
== _TKIP_
) {
173 /* calculate mic code */
174 if (stainfo
!= NULL
) {
175 if (IS_MCAST(prxattrib
->ra
)) {
176 iv
= precvframe
->u
.hdr
.rx_data
+
179 mickey
= &psecuritypriv
->XGrprxmickey
[(((idx
>>
180 6) & 0x3)) - 1].skey
[0];
181 if (psecuritypriv
->binstallGrpkey
== false)
184 mickey
= &stainfo
->tkiprxmickey
.skey
[0];
185 /*icv_len included the mic code*/
186 datalen
= precvframe
->u
.hdr
.len
- prxattrib
->hdrlen
-
187 prxattrib
->iv_len
- prxattrib
->icv_len
- 8;
188 pframe
= precvframe
->u
.hdr
.rx_data
;
189 payload
= pframe
+ prxattrib
->hdrlen
+
191 seccalctkipmic(mickey
, pframe
, payload
, datalen
,
193 (unsigned char)prxattrib
->priority
);
194 pframemic
= payload
+ datalen
;
196 for (i
= 0; i
< 8; i
++) {
197 if (miccode
[i
] != *(pframemic
+ i
))
200 if (bmic_err
== true) {
201 if (prxattrib
->bdecrypted
== true)
202 r8712_handle_tkip_mic_err(adapter
,
203 (u8
)IS_MCAST(prxattrib
->ra
));
207 if ((psecuritypriv
->bcheck_grpkey
==
208 false) && (IS_MCAST(prxattrib
->ra
) ==
210 psecuritypriv
->bcheck_grpkey
= true;
212 recvframe_pull_tail(precvframe
, 8);
218 /* decrypt and set the ivlen,icvlen of the recv_frame */
219 union recv_frame
*r8712_decryptor(struct _adapter
*padapter
,
220 union recv_frame
*precv_frame
)
222 struct rx_pkt_attrib
*prxattrib
= &precv_frame
->u
.hdr
.attrib
;
223 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
224 union recv_frame
*return_packet
= precv_frame
;
226 if ((prxattrib
->encrypt
> 0) && ((prxattrib
->bdecrypted
== 0) ||
227 (psecuritypriv
->sw_decrypt
== true))) {
228 psecuritypriv
->hw_decrypted
= false;
229 switch (prxattrib
->encrypt
) {
232 r8712_wep_decrypt(padapter
, (u8
*)precv_frame
);
235 r8712_tkip_decrypt(padapter
, (u8
*)precv_frame
);
238 r8712_aes_decrypt(padapter
, (u8
*)precv_frame
);
243 } else if (prxattrib
->bdecrypted
== 1)
244 psecuritypriv
->hw_decrypted
= true;
245 return return_packet
;
247 /*###set the security information in the recv_frame */
248 union recv_frame
*r8712_portctrl(struct _adapter
*adapter
,
249 union recv_frame
*precv_frame
)
253 struct recv_frame_hdr
*pfhdr
;
254 struct sta_info
*psta
;
255 struct sta_priv
*pstapriv
;
256 union recv_frame
*prtnframe
;
259 pstapriv
= &adapter
->stapriv
;
260 ptr
= get_recvframe_data(precv_frame
);
261 pfhdr
= &precv_frame
->u
.hdr
;
262 psta_addr
= pfhdr
->attrib
.ta
;
263 psta
= r8712_get_stainfo(pstapriv
, psta_addr
);
264 auth_alg
= adapter
->securitypriv
.AuthAlgrthm
;
266 if ((psta
!= NULL
) && (psta
->ieee8021x_blocked
)) {
268 * only accept EAPOL frame */
269 prtnframe
= precv_frame
;
271 ptr
= ptr
+ pfhdr
->attrib
.hdrlen
+
272 pfhdr
->attrib
.iv_len
+ LLC_HEADER_SIZE
;
273 memcpy(ðer_type
, ptr
, 2);
274 ether_type
= ntohs((unsigned short)ether_type
);
275 if (ether_type
== 0x888e)
276 prtnframe
= precv_frame
;
279 r8712_free_recvframe(precv_frame
,
280 &adapter
->recvpriv
.free_recv_queue
);
285 * check decryption status, and decrypt the
287 prtnframe
= precv_frame
;
288 /* check is the EAPOL frame or not (Rekey) */
289 if (ether_type
== 0x888e) {
291 prtnframe
= precv_frame
;
295 prtnframe
= precv_frame
;
299 static sint
recv_decache(union recv_frame
*precv_frame
, u8 bretry
,
300 struct stainfo_rxcache
*prxcache
)
302 sint tid
= precv_frame
->u
.hdr
.attrib
.priority
;
303 u16 seq_ctrl
= ((precv_frame
->u
.hdr
.attrib
.seq_num
&0xffff) << 4) |
304 (precv_frame
->u
.hdr
.attrib
.frag_num
& 0xf);
308 if (seq_ctrl
== prxcache
->tid_rxseq
[tid
])
310 prxcache
->tid_rxseq
[tid
] = seq_ctrl
;
314 static sint
sta2sta_data_frame(struct _adapter
*adapter
,
315 union recv_frame
*precv_frame
,
316 struct sta_info
**psta
)
318 u8
*ptr
= precv_frame
->u
.hdr
.rx_data
;
320 struct rx_pkt_attrib
*pattrib
= &precv_frame
->u
.hdr
.attrib
;
321 struct sta_priv
*pstapriv
= &adapter
->stapriv
;
322 struct mlme_priv
*pmlmepriv
= &adapter
->mlmepriv
;
323 u8
*mybssid
= get_bssid(pmlmepriv
);
324 u8
*myhwaddr
= myid(&adapter
->eeprompriv
);
326 sint bmcast
= IS_MCAST(pattrib
->dst
);
328 if ((check_fwstate(pmlmepriv
, WIFI_ADHOC_STATE
) == true) ||
329 (check_fwstate(pmlmepriv
, WIFI_ADHOC_MASTER_STATE
) == true)) {
330 /* filter packets that SA is myself or multicast or broadcast */
331 if (!memcmp(myhwaddr
, pattrib
->src
, ETH_ALEN
))
333 if ((memcmp(myhwaddr
, pattrib
->dst
, ETH_ALEN
)) && (!bmcast
))
335 if (!memcmp(pattrib
->bssid
, "\x0\x0\x0\x0\x0\x0", ETH_ALEN
) ||
336 !memcmp(mybssid
, "\x0\x0\x0\x0\x0\x0", ETH_ALEN
) ||
337 (memcmp(pattrib
->bssid
, mybssid
, ETH_ALEN
)))
339 sta_addr
= pattrib
->src
;
340 } else if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
) == true) {
341 /* For Station mode, sa and bssid should always be BSSID,
342 * and DA is my mac-address */
343 if (memcmp(pattrib
->bssid
, pattrib
->src
, ETH_ALEN
))
345 sta_addr
= pattrib
->bssid
;
346 } else if (check_fwstate(pmlmepriv
, WIFI_AP_STATE
) == true) {
348 /* For AP mode, if DA == MCAST, then BSSID should
350 if (!IS_MCAST(pattrib
->bssid
))
352 } else { /* not mc-frame */
353 /* For AP mode, if DA is non-MCAST, then it must be
354 * BSSID, and bssid == BSSID */
355 if (memcmp(pattrib
->bssid
, pattrib
->dst
, ETH_ALEN
))
357 sta_addr
= pattrib
->src
;
359 } else if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true) {
360 memcpy(pattrib
->dst
, GetAddr1Ptr(ptr
), ETH_ALEN
);
361 memcpy(pattrib
->src
, GetAddr2Ptr(ptr
), ETH_ALEN
);
362 memcpy(pattrib
->bssid
, GetAddr3Ptr(ptr
), ETH_ALEN
);
363 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
364 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
369 *psta
= r8712_get_bcmc_stainfo(adapter
);
371 *psta
= r8712_get_stainfo(pstapriv
, sta_addr
); /* get ap_info */
373 if (check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true)
374 adapter
->mppriv
.rx_pktloss
++;
380 static sint
ap2sta_data_frame(struct _adapter
*adapter
,
381 union recv_frame
*precv_frame
,
382 struct sta_info
**psta
)
384 u8
*ptr
= precv_frame
->u
.hdr
.rx_data
;
385 struct rx_pkt_attrib
*pattrib
= &precv_frame
->u
.hdr
.attrib
;
386 struct sta_priv
*pstapriv
= &adapter
->stapriv
;
387 struct mlme_priv
*pmlmepriv
= &adapter
->mlmepriv
;
388 u8
*mybssid
= get_bssid(pmlmepriv
);
389 u8
*myhwaddr
= myid(&adapter
->eeprompriv
);
390 sint bmcast
= IS_MCAST(pattrib
->dst
);
392 if ((check_fwstate(pmlmepriv
, WIFI_STATION_STATE
) == true)
393 && (check_fwstate(pmlmepriv
, _FW_LINKED
) == true)) {
394 /* if NULL-frame, drop packet */
395 if ((GetFrameSubType(ptr
)) == WIFI_DATA_NULL
)
397 /* drop QoS-SubType Data, including QoS NULL,
398 * excluding QoS-Data */
399 if ((GetFrameSubType(ptr
) & WIFI_QOS_DATA_TYPE
) ==
400 WIFI_QOS_DATA_TYPE
) {
401 if (GetFrameSubType(ptr
) & (BIT(4) | BIT(5) | BIT(6)))
405 /* filter packets that SA is myself or multicast or broadcast */
406 if (!memcmp(myhwaddr
, pattrib
->src
, ETH_ALEN
))
409 /* da should be for me */
410 if ((memcmp(myhwaddr
, pattrib
->dst
, ETH_ALEN
)) && (!bmcast
))
413 if (!memcmp(pattrib
->bssid
, "\x0\x0\x0\x0\x0\x0", ETH_ALEN
) ||
414 !memcmp(mybssid
, "\x0\x0\x0\x0\x0\x0", ETH_ALEN
) ||
415 (memcmp(pattrib
->bssid
, mybssid
, ETH_ALEN
)))
418 *psta
= r8712_get_bcmc_stainfo(adapter
);
420 *psta
= r8712_get_stainfo(pstapriv
, pattrib
->bssid
);
423 } else if ((check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true) &&
424 (check_fwstate(pmlmepriv
, _FW_LINKED
) == true)) {
425 memcpy(pattrib
->dst
, GetAddr1Ptr(ptr
), ETH_ALEN
);
426 memcpy(pattrib
->src
, GetAddr2Ptr(ptr
), ETH_ALEN
);
427 memcpy(pattrib
->bssid
, GetAddr3Ptr(ptr
), ETH_ALEN
);
428 memcpy(pattrib
->ra
, pattrib
->dst
, ETH_ALEN
);
429 memcpy(pattrib
->ta
, pattrib
->src
, ETH_ALEN
);
430 memcpy(pattrib
->bssid
, mybssid
, ETH_ALEN
);
431 *psta
= r8712_get_stainfo(pstapriv
, pattrib
->bssid
);
439 static sint
sta2ap_data_frame(struct _adapter
*adapter
,
440 union recv_frame
*precv_frame
,
441 struct sta_info
**psta
)
443 struct rx_pkt_attrib
*pattrib
= &precv_frame
->u
.hdr
.attrib
;
444 struct sta_priv
*pstapriv
= &adapter
->stapriv
;
445 struct mlme_priv
*pmlmepriv
= &adapter
->mlmepriv
;
446 unsigned char *mybssid
= get_bssid(pmlmepriv
);
448 if (check_fwstate(pmlmepriv
, WIFI_AP_STATE
) == true) {
449 /* For AP mode, if DA is non-MCAST, then it must be BSSID,
451 * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR */
452 if (memcmp(pattrib
->bssid
, mybssid
, ETH_ALEN
))
454 *psta
= r8712_get_stainfo(pstapriv
, pattrib
->src
);
461 static sint
validate_recv_ctrl_frame(struct _adapter
*adapter
,
462 union recv_frame
*precv_frame
)
467 static sint
validate_recv_mgnt_frame(struct _adapter
*adapter
,
468 union recv_frame
*precv_frame
)
474 static sint
validate_recv_data_frame(struct _adapter
*adapter
,
475 union recv_frame
*precv_frame
)
479 u8
*psa
, *pda
, *pbssid
;
480 struct sta_info
*psta
= NULL
;
481 u8
*ptr
= precv_frame
->u
.hdr
.rx_data
;
482 struct rx_pkt_attrib
*pattrib
= &precv_frame
->u
.hdr
.attrib
;
483 struct security_priv
*psecuritypriv
= &adapter
->securitypriv
;
485 bretry
= GetRetry(ptr
);
488 pbssid
= get_hdr_bssid(ptr
);
491 memcpy(pattrib
->dst
, pda
, ETH_ALEN
);
492 memcpy(pattrib
->src
, psa
, ETH_ALEN
);
493 memcpy(pattrib
->bssid
, pbssid
, ETH_ALEN
);
494 switch (pattrib
->to_fr_ds
) {
496 memcpy(pattrib
->ra
, pda
, ETH_ALEN
);
497 memcpy(pattrib
->ta
, psa
, ETH_ALEN
);
498 res
= sta2sta_data_frame(adapter
, precv_frame
, &psta
);
501 memcpy(pattrib
->ra
, pda
, ETH_ALEN
);
502 memcpy(pattrib
->ta
, pbssid
, ETH_ALEN
);
503 res
= ap2sta_data_frame(adapter
, precv_frame
, &psta
);
506 memcpy(pattrib
->ra
, pbssid
, ETH_ALEN
);
507 memcpy(pattrib
->ta
, psa
, ETH_ALEN
);
508 res
= sta2ap_data_frame(adapter
, precv_frame
, &psta
);
511 memcpy(pattrib
->ra
, GetAddr1Ptr(ptr
), ETH_ALEN
);
512 memcpy(pattrib
->ta
, GetAddr2Ptr(ptr
), ETH_ALEN
);
522 precv_frame
->u
.hdr
.psta
= psta
;
524 /* parsing QC field */
525 if (pattrib
->qos
== 1) {
526 pattrib
->priority
= GetPriority((ptr
+ 24));
527 pattrib
->ack_policy
= GetAckpolicy((ptr
+ 24));
528 pattrib
->amsdu
= GetAMsdu((ptr
+ 24));
529 pattrib
->hdrlen
= pattrib
->to_fr_ds
== 3 ? 32 : 26;
531 pattrib
->priority
= 0;
532 pattrib
->hdrlen
= (pattrib
->to_fr_ds
== 3) ? 30 : 24;
535 if (pattrib
->order
)/*HT-CTRL 11n*/
536 pattrib
->hdrlen
+= 4;
537 precv_frame
->u
.hdr
.preorder_ctrl
=
538 &psta
->recvreorder_ctrl
[pattrib
->priority
];
540 /* decache, drop duplicate recv packets */
541 if (recv_decache(precv_frame
, bretry
, &psta
->sta_recvpriv
.rxcache
) ==
545 if (pattrib
->privacy
) {
546 GET_ENCRY_ALGO(psecuritypriv
, psta
, pattrib
->encrypt
,
547 IS_MCAST(pattrib
->ra
));
548 SET_ICE_IV_LEN(pattrib
->iv_len
, pattrib
->icv_len
,
551 pattrib
->encrypt
= 0;
552 pattrib
->iv_len
= pattrib
->icv_len
= 0;
557 sint
r8712_validate_recv_frame(struct _adapter
*adapter
,
558 union recv_frame
*precv_frame
)
560 /*shall check frame subtype, to / from ds, da, bssid */
561 /*then call check if rx seq/frag. duplicated.*/
565 sint retval
= _SUCCESS
;
566 struct rx_pkt_attrib
*pattrib
= &precv_frame
->u
.hdr
.attrib
;
568 u8
*ptr
= precv_frame
->u
.hdr
.rx_data
;
569 u8 ver
= (unsigned char)(*ptr
) & 0x3;
574 type
= GetFrameType(ptr
);
575 subtype
= GetFrameSubType(ptr
); /*bit(7)~bit(2)*/
576 pattrib
->to_fr_ds
= get_tofr_ds(ptr
);
577 pattrib
->frag_num
= GetFragNum(ptr
);
578 pattrib
->seq_num
= GetSequence(ptr
);
579 pattrib
->pw_save
= GetPwrMgt(ptr
);
580 pattrib
->mfrag
= GetMFrag(ptr
);
581 pattrib
->mdata
= GetMData(ptr
);
582 pattrib
->privacy
= GetPrivacy(ptr
);
583 pattrib
->order
= GetOrder(ptr
);
585 case WIFI_MGT_TYPE
: /*mgnt*/
586 retval
= validate_recv_mgnt_frame(adapter
, precv_frame
);
588 case WIFI_CTRL_TYPE
:/*ctrl*/
589 retval
= validate_recv_ctrl_frame(adapter
, precv_frame
);
591 case WIFI_DATA_TYPE
: /*data*/
592 pattrib
->qos
= (subtype
& BIT(7)) ? 1 : 0;
593 retval
= validate_recv_data_frame(adapter
, precv_frame
);
601 sint
r8712_wlanhdr_to_ethhdr(union recv_frame
*precvframe
)
603 /*remove the wlanhdr and add the eth_hdr*/
608 struct ieee80211_snap_hdr
*psnap
;
611 struct _adapter
*adapter
= precvframe
->u
.hdr
.adapter
;
612 struct mlme_priv
*pmlmepriv
= &adapter
->mlmepriv
;
614 u8
*ptr
= get_recvframe_data(precvframe
); /*point to frame_ctrl field*/
615 struct rx_pkt_attrib
*pattrib
= &precvframe
->u
.hdr
.attrib
;
617 if (pattrib
->encrypt
)
618 recvframe_pull_tail(precvframe
, pattrib
->icv_len
);
619 psnap
= (struct ieee80211_snap_hdr
*)(ptr
+ pattrib
->hdrlen
+
621 psnap_type
= ptr
+ pattrib
->hdrlen
+ pattrib
->iv_len
+ SNAP_SIZE
;
622 /* convert hdr + possible LLC headers into Ethernet header */
623 if ((!memcmp(psnap
, (void *)rfc1042_header
, SNAP_SIZE
) &&
624 (memcmp(psnap_type
, (void *)SNAP_ETH_TYPE_IPX
, 2)) &&
625 (memcmp(psnap_type
, (void *)SNAP_ETH_TYPE_APPLETALK_AARP
, 2))) ||
626 !memcmp(psnap
, (void *)bridge_tunnel_header
, SNAP_SIZE
)) {
627 /* remove RFC1042 or Bridge-Tunnel encapsulation and
628 * replace EtherType */
631 /* Leave Ethernet header part of hdr and full payload */
634 rmv_len
= pattrib
->hdrlen
+ pattrib
->iv_len
+
635 (bsnaphdr
? SNAP_SIZE
: 0);
636 len
= precvframe
->u
.hdr
.len
- rmv_len
;
637 if ((check_fwstate(pmlmepriv
, WIFI_MP_STATE
) == true)) {
642 /* append rx status for mp test packets */
643 ptr
= recvframe_pull(precvframe
, (rmv_len
-
644 sizeof(struct ethhdr
) + 2) - 24);
645 memcpy(ptr
, get_rxmem(precvframe
), 24);
648 ptr
= recvframe_pull(precvframe
, (rmv_len
-
649 sizeof(struct ethhdr
) + (bsnaphdr
? 2 : 0)));
651 memcpy(ptr
, pattrib
->dst
, ETH_ALEN
);
652 memcpy(ptr
+ETH_ALEN
, pattrib
->src
, ETH_ALEN
);
655 memcpy(ptr
+ 12, &len
, 2);
660 s32
r8712_recv_entry(union recv_frame
*precvframe
)
662 struct _adapter
*padapter
;
663 struct recv_priv
*precvpriv
;
664 struct mlme_priv
*pmlmepriv
;
665 struct recv_stat
*prxstat
;
666 struct dvobj_priv
*pdev
;
667 u8
*phead
, *pdata
, *ptail
, *pend
;
669 struct __queue
*pfree_recv_queue
, *ppending_recv_queue
;
671 struct intf_hdl
*pintfhdl
;
673 padapter
= precvframe
->u
.hdr
.adapter
;
674 pintfhdl
= &padapter
->pio_queue
->intf
;
675 pmlmepriv
= &padapter
->mlmepriv
;
676 precvpriv
= &(padapter
->recvpriv
);
677 pdev
= &padapter
->dvobjpriv
;
678 pfree_recv_queue
= &(precvpriv
->free_recv_queue
);
679 ppending_recv_queue
= &(precvpriv
->recv_pending_queue
);
680 phead
= precvframe
->u
.hdr
.rx_head
;
681 pdata
= precvframe
->u
.hdr
.rx_data
;
682 ptail
= precvframe
->u
.hdr
.rx_tail
;
683 pend
= precvframe
->u
.hdr
.rx_end
;
684 prxstat
= (struct recv_stat
*)phead
;
686 padapter
->ledpriv
.LedControlHandler(padapter
, LED_CTL_RX
);
688 ret
= recv_func(padapter
, precvframe
);
690 goto _recv_entry_drop
;
691 precvpriv
->rx_pkts
++;
692 precvpriv
->rx_bytes
+= (uint
)(precvframe
->u
.hdr
.rx_tail
-
693 precvframe
->u
.hdr
.rx_data
);
696 precvpriv
->rx_drop
++;
697 padapter
->mppriv
.rx_pktloss
= precvpriv
->rx_drop
;