2013-05-08 21:45:39 +00:00
/******************************************************************************
*
* Copyright ( c ) 2007 - 2012 Realtek Corporation . All rights reserved .
2013-05-19 04:28:07 +00:00
*
2013-05-08 21:45:39 +00:00
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 , USA
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define _RTW_RECV_C_
2013-07-21 18:00:05 +00:00
2013-05-08 21:45:39 +00:00
# include <osdep_service.h>
# include <drv_types.h>
# include <recv_osdep.h>
# include <mlme_osdep.h>
# include <wifi.h>
2014-11-16 00:18:30 +00:00
# include <linux/vmalloc.h>
# define ETHERNET_HEADER_SIZE 14 /* Ethernet Header Length */
# define LLC_HEADER_SIZE 6 /* LLC Header Length */
2013-05-08 21:45:39 +00:00
2013-09-06 10:09:58 +00:00
static u8 SNAP_ETH_TYPE_IPX [ 2 ] = { 0x81 , 0x37 } ;
static u8 SNAP_ETH_TYPE_APPLETALK_AARP [ 2 ] = { 0x80 , 0xf3 } ;
/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
static u8 rtw_bridge_tunnel_header [ ] = {
2013-10-19 17:45:47 +00:00
0xaa , 0xaa , 0x03 , 0x00 , 0x00 , 0xf8
} ;
static u8 rtw_rfc1042_header [ ] = {
0xaa , 0xaa , 0x03 , 0x00 , 0x00 , 0x00
2013-09-06 10:09:58 +00:00
} ;
2013-05-08 21:45:39 +00:00
void rtw_signal_stat_timer_hdl ( RTW_TIMER_HDL_ARGS ) ;
void _rtw_init_sta_recv_priv ( struct sta_recv_priv * psta_recvpriv )
{
2014-11-28 17:08:37 +00:00
memset ( ( u8 * ) psta_recvpriv , 0 , sizeof ( struct sta_recv_priv ) ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
spin_lock_init ( & psta_recvpriv - > lock ) ;
2013-05-08 21:45:39 +00:00
_rtw_init_queue ( & psta_recvpriv - > defrag_q ) ;
}
2013-07-27 01:08:39 +00:00
int _rtw_init_recv_priv ( struct recv_priv * precvpriv , struct adapter * padapter )
2013-05-08 21:45:39 +00:00
{
2013-07-26 22:56:14 +00:00
int i ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
struct recv_frame * precvframe ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
int res = _SUCCESS ;
2013-05-08 21:45:39 +00:00
_rtw_init_queue ( & precvpriv - > free_recv_queue ) ;
_rtw_init_queue ( & precvpriv - > recv_pending_queue ) ;
_rtw_init_queue ( & precvpriv - > uc_swdec_pending_queue ) ;
precvpriv - > adapter = padapter ;
precvpriv - > free_recvframe_cnt = NR_RECVFRAME ;
2014-11-16 00:18:30 +00:00
precvpriv - > pallocated_frame_buf = vzalloc ( NR_RECVFRAME * sizeof ( struct recv_frame ) + RXFRAME_ALIGN_SZ ) ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
if ( precvpriv - > pallocated_frame_buf = = NULL ) {
res = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-07-24 17:19:14 +00:00
precvpriv - > precv_frame_buf = ( u8 * ) N_BYTE_ALIGMENT ( ( size_t ) ( precvpriv - > pallocated_frame_buf ) , RXFRAME_ALIGN_SZ ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
precvframe = ( struct recv_frame * ) precvpriv - > precv_frame_buf ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
for ( i = 0 ; i < NR_RECVFRAME ; i + + ) {
2014-11-16 00:18:30 +00:00
INIT_LIST_HEAD ( & ( precvframe - > list ) ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
list_add_tail ( & ( precvframe - > list ) ,
& ( precvpriv - > free_recv_queue . queue ) ) ;
2013-05-08 21:45:39 +00:00
res = rtw_os_recv_resource_alloc ( padapter , precvframe ) ;
2014-11-16 00:18:30 +00:00
precvframe - > len = 0 ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
precvframe - > adapter = padapter ;
2013-05-08 21:45:39 +00:00
precvframe + + ;
}
2013-08-01 02:43:28 +00:00
precvpriv - > rx_pending_cnt = 1 ;
2013-05-08 21:45:39 +00:00
res = rtw_hal_init_recv_priv ( padapter ) ;
_init_timer ( & precvpriv - > signal_stat_timer , padapter - > pnetdev , RTW_TIMER_HDL_NAME ( signal_stat ) , padapter ) ;
2013-07-09 22:38:46 +00:00
precvpriv - > signal_stat_sampling_interval = 1000 ; /* ms */
2013-05-08 21:45:39 +00:00
rtw_set_signal_stat_timer ( precvpriv ) ;
exit :
return res ;
}
2014-11-28 17:08:37 +00:00
void _rtw_free_recv_priv ( struct recv_priv * precvpriv )
2013-05-08 21:45:39 +00:00
{
2013-07-27 01:08:39 +00:00
struct adapter * padapter = precvpriv - > adapter ;
2013-05-08 21:45:39 +00:00
rtw_free_uc_swdec_pending_queue ( padapter ) ;
2013-05-09 04:04:25 +00:00
if ( precvpriv - > pallocated_frame_buf ) {
2014-11-16 00:18:30 +00:00
vfree ( precvpriv - > pallocated_frame_buf ) ;
2013-05-08 21:45:39 +00:00
}
rtw_hal_free_recv_priv ( padapter ) ;
}
2014-11-28 17:08:37 +00:00
struct recv_frame * _rtw_alloc_recvframe ( struct __queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct recv_frame * hdr ;
2013-07-25 14:49:25 +00:00
struct list_head * plist , * phead ;
2013-07-27 01:08:39 +00:00
struct adapter * padapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv ;
2014-11-16 00:18:30 +00:00
if ( list_empty ( & pfree_recv_queue - > queue ) ) {
hdr = NULL ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pfree_recv_queue ) ;
2014-11-16 00:18:30 +00:00
plist = phead - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
hdr = container_of ( plist , struct recv_frame , list ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
list_del_init ( & hdr - > list ) ;
padapter = hdr - > adapter ;
2013-08-01 02:43:28 +00:00
if ( padapter ! = NULL ) {
precvpriv = & padapter - > recvpriv ;
2013-05-09 04:04:25 +00:00
if ( pfree_recv_queue = = & precvpriv - > free_recv_queue )
2013-05-08 21:45:39 +00:00
precvpriv - > free_recvframe_cnt - - ;
}
}
2014-11-16 00:18:30 +00:00
return ( struct recv_frame * ) hdr ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
struct recv_frame * rtw_alloc_recvframe ( struct __queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct recv_frame * precvframe ;
2013-05-19 04:28:07 +00:00
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & pfree_recv_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
precvframe = _rtw_alloc_recvframe ( pfree_recv_queue ) ;
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & pfree_recv_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
return precvframe ;
}
2014-11-16 00:18:30 +00:00
void rtw_init_recvframe ( struct recv_frame * precvframe , struct recv_priv * precvpriv )
2013-05-08 21:45:39 +00:00
{
/* Perry: This can be removed */
2014-11-16 00:18:30 +00:00
INIT_LIST_HEAD ( & precvframe - > list ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
precvframe - > len = 0 ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
int rtw_free_recvframe ( struct recv_frame * precvframe ,
struct __queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2013-11-29 22:10:20 +00:00
struct adapter * padapter ;
struct recv_priv * precvpriv ;
2013-05-08 21:45:39 +00:00
2013-11-29 22:10:20 +00:00
if ( ! precvframe )
return _FAIL ;
2014-11-16 00:18:30 +00:00
padapter = precvframe - > adapter ;
2013-11-29 22:10:20 +00:00
precvpriv = & padapter - > recvpriv ;
2014-11-16 00:18:30 +00:00
if ( precvframe - > pkt ) {
dev_kfree_skb_any ( precvframe - > pkt ) ; /* free skb by driver */
precvframe - > pkt = NULL ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & pfree_recv_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
list_del_init ( & ( precvframe - > list ) ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
precvframe - > len = 0 ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
list_add_tail ( & ( precvframe - > list ) , get_list_head ( pfree_recv_queue ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( padapter ! = NULL ) {
2013-05-09 04:04:25 +00:00
if ( pfree_recv_queue = = & precvpriv - > free_recv_queue )
2013-05-08 21:45:39 +00:00
precvpriv - > free_recvframe_cnt + + ;
}
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & pfree_recv_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
}
2014-11-16 00:18:30 +00:00
int _rtw_enqueue_recvframe ( struct recv_frame * precvframe , struct __queue * queue )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct adapter * padapter = precvframe - > adapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2014-11-16 00:18:30 +00:00
list_del_init ( & ( precvframe - > list ) ) ;
list_add_tail ( & ( precvframe - > list ) , get_list_head ( queue ) ) ;
2013-05-08 21:45:39 +00:00
if ( padapter ! = NULL ) {
if ( queue = = & precvpriv - > free_recv_queue )
precvpriv - > free_recvframe_cnt + + ;
}
return _SUCCESS ;
}
2014-11-16 00:18:30 +00:00
int rtw_enqueue_recvframe ( struct recv_frame * precvframe , struct __queue * queue )
2013-05-08 21:45:39 +00:00
{
2013-07-26 22:56:14 +00:00
int ret ;
2013-05-19 04:28:07 +00:00
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & queue - > lock ) ;
2013-05-08 21:45:39 +00:00
ret = _rtw_enqueue_recvframe ( precvframe , queue ) ;
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & queue - > lock ) ;
2013-05-08 21:45:39 +00:00
return ret ;
}
/*
caller : defrag ; recvframe_chk_defrag in recv_thread ( passive )
pframequeue : defrag_queue : will be accessed in recv_thread ( passive )
using spinlock to protect
*/
2013-07-24 22:55:38 +00:00
void rtw_free_recvframe_queue ( struct __queue * pframequeue , struct __queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct recv_frame * hdr ;
2013-07-25 14:49:25 +00:00
struct list_head * plist , * phead ;
2013-05-08 21:45:39 +00:00
2013-06-03 19:52:18 +00:00
spin_lock ( & pframequeue - > lock ) ;
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pframequeue ) ;
2014-11-16 00:18:30 +00:00
plist = phead - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
while ( phead ! = plist ) {
hdr = container_of ( plist , struct recv_frame , list ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
plist = plist - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
rtw_free_recvframe ( ( struct recv_frame * ) hdr , pfree_recv_queue ) ;
2013-05-08 21:45:39 +00:00
}
2013-06-03 19:52:18 +00:00
spin_unlock ( & pframequeue - > lock ) ;
2013-05-08 21:45:39 +00:00
}
2013-07-27 01:08:39 +00:00
u32 rtw_free_uc_swdec_pending_queue ( struct adapter * adapter )
2013-05-08 21:45:39 +00:00
{
u32 cnt = 0 ;
2014-11-16 00:18:30 +00:00
struct recv_frame * pending_frame ;
2013-08-01 02:43:28 +00:00
while ( ( pending_frame = rtw_alloc_recvframe ( & adapter - > recvpriv . uc_swdec_pending_queue ) ) ) {
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( pending_frame , & adapter - > recvpriv . free_recv_queue ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s: dequeue uc_swdec_pending_queue \n " , __func__ ) ;
2013-05-08 21:45:39 +00:00
cnt + + ;
}
return cnt ;
}
2014-11-16 00:18:30 +00:00
static int recvframe_chkmic ( struct adapter * adapter ,
struct recv_frame * precvframe )
2013-08-01 02:43:28 +00:00
{
int i , res = _SUCCESS ;
2013-05-08 21:45:39 +00:00
u32 datalen ;
u8 miccode [ 8 ] ;
2013-08-01 02:43:28 +00:00
u8 bmic_err = false , brpt_micerror = true ;
u8 * pframe , * payload , * pframemic ;
2013-05-08 21:45:39 +00:00
u8 * mickey ;
struct sta_info * stainfo ;
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * prxattrib = & precvframe - > attrib ;
2013-08-01 02:43:28 +00:00
struct security_priv * psecuritypriv = & adapter - > securitypriv ;
2013-05-08 21:45:39 +00:00
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
2013-08-01 02:43:28 +00:00
stainfo = rtw_get_stainfo ( & adapter - > stapriv , & prxattrib - > ta [ 0 ] ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( prxattrib - > encrypt = = _TKIP_ ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n recvframe_chkmic:prxattrib->encrypt==_TKIP_ \n " ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n recvframe_chkmic:da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x \n " ,
prxattrib - > ra [ 0 ] , prxattrib - > ra [ 1 ] , prxattrib - > ra [ 2 ] , prxattrib - > ra [ 3 ] , prxattrib - > ra [ 4 ] , prxattrib - > ra [ 5 ] ) ) ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* calculate mic code */
2013-08-01 02:43:28 +00:00
if ( stainfo ! = NULL ) {
if ( IS_MCAST ( prxattrib - > ra ) ) {
if ( ! psecuritypriv ) {
res = _FAIL ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " \n recvframe_chkmic:didn't install group key!!!!!!!!!! \n " ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " \n recvframe_chkmic:didn't install group key!!!!!!!!!! \n " ) ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-11-16 00:18:30 +00:00
mickey = & psecuritypriv - > dot118021XGrprxmickey [ prxattrib - > key_index ] . skey [ 0 ] ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n recvframe_chkmic: bcmc key \n " ) ) ;
2013-08-01 02:43:28 +00:00
} else {
mickey = & stainfo - > dot11tkiprxmickey . skey [ 0 ] ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " \n recvframe_chkmic: unicast key \n " ) ) ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
/* icv_len included the mic code */
datalen = precvframe - > len - prxattrib - > hdrlen -
prxattrib - > iv_len - prxattrib - > icv_len - 8 ;
pframe = precvframe - > rx_data ;
2013-08-01 02:43:28 +00:00
payload = pframe + prxattrib - > hdrlen + prxattrib - > iv_len ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n prxattrib->iv_len=%d prxattrib->icv_len=%d \n " , prxattrib - > iv_len , prxattrib - > icv_len ) ) ;
rtw_seccalctkipmic ( mickey , pframe , payload , datalen , & miccode [ 0 ] ,
( unsigned char ) prxattrib - > priority ) ; /* care the length of the data */
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
pframemic = payload + datalen ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
bmic_err = false ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
for ( i = 0 ; i < 8 ; i + + ) {
if ( miccode [ i ] ! = * ( pframemic + i ) ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " recvframe_chkmic:miccode[%d](%02x)!=*(pframemic+%d)(%02x) " ,
i , miccode [ i ] , i , * ( pframemic + i ) ) ) ;
bmic_err = true ;
2013-05-08 21:45:39 +00:00
}
}
2013-08-01 02:43:28 +00:00
if ( bmic_err ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " \n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x \n " ,
* ( pframemic - 8 ) , * ( pframemic - 7 ) , * ( pframemic - 6 ) ,
* ( pframemic - 5 ) , * ( pframemic - 4 ) , * ( pframemic - 3 ) ,
* ( pframemic - 2 ) , * ( pframemic - 1 ) ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " \n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x \n " ,
* ( pframemic - 16 ) , * ( pframemic - 15 ) , * ( pframemic - 14 ) ,
* ( pframemic - 13 ) , * ( pframemic - 12 ) , * ( pframemic - 11 ) ,
* ( pframemic - 10 ) , * ( pframemic - 9 ) ) ) ;
2013-05-08 21:45:39 +00:00
{
uint i ;
2014-11-16 00:18:30 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " \n ======demp packet (len=%d)====== \n " ,
precvframe - > len ) ) ;
for ( i = 0 ; i < precvframe - > len ; i + = 8 ) {
RT_TRACE ( _module_rtl871x_recv_c_ ,
_drv_err_ ,
( " 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x " ,
* ( precvframe - > rx_data + i ) ,
* ( precvframe - > rx_data + i + 1 ) ,
* ( precvframe - > rx_data + i + 2 ) ,
* ( precvframe - > rx_data + i + 3 ) ,
* ( precvframe - > rx_data + i + 4 ) ,
* ( precvframe - > rx_data + i + 5 ) ,
* ( precvframe - > rx_data + i + 6 ) ,
* ( precvframe - > rx_data + i + 7 ) ) ) ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ ,
_drv_err_ ,
( " \n ====== demp packet end [len=%d]====== \n " ,
precvframe - > len ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ ,
_drv_err_ ,
( " \n hrdlen=%d, \n " ,
prxattrib - > hdrlen ) ) ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d " ,
prxattrib - > ra [ 0 ] , prxattrib - > ra [ 1 ] , prxattrib - > ra [ 2 ] ,
prxattrib - > ra [ 3 ] , prxattrib - > ra [ 4 ] , prxattrib - > ra [ 5 ] , psecuritypriv - > binstallGrpkey ) ) ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* double check key_index for some timing issue , */
/* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */
2013-08-01 02:43:28 +00:00
if ( ( IS_MCAST ( prxattrib - > ra ) = = true ) & & ( prxattrib - > key_index ! = pmlmeinfo - > key_index ) )
2013-05-26 03:02:10 +00:00
brpt_micerror = false ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
if ( ( prxattrib - > bdecrypted ) & & ( brpt_micerror ) ) {
rtw_handle_tkip_mic_err ( adapter , ( u8 ) IS_MCAST ( prxattrib - > ra ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " mic error :prxattrib->bdecrypted=%d " , prxattrib - > bdecrypted ) ) ;
DBG_88E ( " mic error :prxattrib->bdecrypted=%d \n " , prxattrib - > bdecrypted ) ;
} else {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " mic error :prxattrib->bdecrypted=%d " , prxattrib - > bdecrypted ) ) ;
DBG_88E ( " mic error :prxattrib->bdecrypted=%d \n " , prxattrib - > bdecrypted ) ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
res = _FAIL ;
} else {
2013-07-09 22:38:46 +00:00
/* mic checked ok */
2013-08-01 02:43:28 +00:00
if ( ( ! psecuritypriv - > bcheck_grpkey ) & & ( IS_MCAST ( prxattrib - > ra ) ) ) {
psecuritypriv - > bcheck_grpkey = true ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " psecuritypriv->bcheck_grpkey = true " ) ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-08-01 02:43:28 +00:00
} else {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recvframe_chkmic: rtw_get_stainfo==NULL!!! \n " ) ) ;
2013-05-08 21:45:39 +00:00
}
recvframe_pull_tail ( precvframe , 8 ) ;
}
exit :
return res ;
}
2013-08-01 02:43:28 +00:00
/* decrypt and set the ivlen, icvlen of the recv_frame */
2014-11-16 00:18:30 +00:00
static struct recv_frame * decryptor ( struct adapter * padapter ,
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * prxattrib = & precv_frame - > attrib ;
2013-08-01 02:43:28 +00:00
struct security_priv * psecuritypriv = & padapter - > securitypriv ;
2014-11-16 00:18:30 +00:00
struct recv_frame * return_packet = precv_frame ;
2013-08-01 02:43:28 +00:00
u32 res = _SUCCESS ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " prxstat->decrypted=%x prxattrib->encrypt=0x%03x \n " , prxattrib - > bdecrypted , prxattrib - > encrypt ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( prxattrib - > encrypt > 0 ) {
2014-11-16 00:18:30 +00:00
u8 * iv = precv_frame - > rx_data + prxattrib - > hdrlen ;
2013-08-01 02:43:28 +00:00
prxattrib - > key_index = ( ( ( iv [ 3 ] ) > > 6 ) & 0x3 ) ;
if ( prxattrib - > key_index > WEP_KEYS ) {
DBG_88E ( " prxattrib->key_index(%d)>WEP_KEYS \n " , prxattrib - > key_index ) ;
switch ( prxattrib - > encrypt ) {
case _WEP40_ :
case _WEP104_ :
prxattrib - > key_index = psecuritypriv - > dot11PrivacyKeyIndex ;
break ;
case _TKIP_ :
case _AES_ :
default :
prxattrib - > key_index = psecuritypriv - > dot118021XGrpKeyid ;
break ;
2013-05-19 04:28:07 +00:00
}
}
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
if ( ( prxattrib - > encrypt > 0 ) & & ( ( prxattrib - > bdecrypted = = 0 ) | | ( psecuritypriv - > sw_decrypt ) ) ) {
psecuritypriv - > hw_decrypted = false ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
switch ( prxattrib - > encrypt ) {
2013-05-08 21:45:39 +00:00
case _WEP40_ :
case _WEP104_ :
rtw_wep_decrypt ( padapter , ( u8 * ) precv_frame ) ;
break ;
case _TKIP_ :
res = rtw_tkip_decrypt ( padapter , ( u8 * ) precv_frame ) ;
break ;
case _AES_ :
2013-08-01 02:43:28 +00:00
res = rtw_aes_decrypt ( padapter , ( u8 * ) precv_frame ) ;
2013-05-08 21:45:39 +00:00
break ;
default :
2013-07-12 06:29:15 +00:00
break ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
} else if ( prxattrib - > bdecrypted = = 1 & & prxattrib - > encrypt > 0 & &
( psecuritypriv - > busetkipkey = = 1 | | prxattrib - > encrypt ! = _TKIP_ ) )
psecuritypriv - > hw_decrypted = true ;
2013-05-19 04:28:07 +00:00
2013-07-20 21:35:29 +00:00
if ( res = = _FAIL ) {
2013-08-01 02:43:28 +00:00
rtw_free_recvframe ( return_packet , & padapter - > recvpriv . free_recv_queue ) ;
2013-05-08 21:45:39 +00:00
return_packet = NULL ;
}
return return_packet ;
}
2013-07-20 21:35:29 +00:00
2013-07-09 22:38:46 +00:00
/* set the security information in the recv_frame */
2014-11-16 00:18:30 +00:00
static struct recv_frame * portctrl ( struct adapter * adapter ,
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
u8 * psta_addr , * ptr ;
2013-05-08 21:45:39 +00:00
uint auth_alg ;
2014-11-16 00:18:30 +00:00
struct recv_frame * pfhdr ;
2013-05-08 21:45:39 +00:00
struct sta_info * psta ;
2013-08-01 02:43:28 +00:00
struct sta_priv * pstapriv ;
2014-11-16 00:18:30 +00:00
struct recv_frame * prtnframe ;
u16 ether_type ;
2013-07-09 22:38:46 +00:00
u16 eapol_type = 0x888e ; /* for Funia BD's WPA issue */
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * pattrib ;
2013-06-20 15:13:14 +00:00
__be16 be_tmp ;
2013-05-08 21:45:39 +00:00
pstapriv = & adapter - > stapriv ;
auth_alg = adapter - > securitypriv . dot11AuthAlgrthm ;
2014-11-16 00:18:30 +00:00
ptr = precv_frame - > rx_data ;
pfhdr = precv_frame ;
2013-05-08 21:45:39 +00:00
pattrib = & pfhdr - > attrib ;
psta_addr = pattrib - > ta ;
2014-11-16 00:18:30 +00:00
psta = rtw_get_stainfo ( pstapriv , psta_addr ) ;
2013-05-08 21:45:39 +00:00
prtnframe = NULL ;
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d \n " , adapter - > securitypriv . dot11AuthAlgrthm ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( auth_alg = = 2 ) {
2014-11-16 00:18:30 +00:00
/* get ether_type */
ptr = ptr + pfhdr - > attrib . hdrlen + LLC_HEADER_SIZE ;
memcpy ( & be_tmp , ptr , 2 ) ;
ether_type = ntohs ( be_tmp ) ;
2013-08-01 02:43:28 +00:00
if ( ( psta ! = NULL ) & & ( psta - > ieee8021x_blocked ) ) {
2013-07-09 22:38:46 +00:00
/* blocked */
/* only accept EAPOL frame */
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ########portctrl:psta->ieee8021x_blocked==1 \n " ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( ether_type = = eapol_type ) {
prtnframe = precv_frame ;
} else {
2013-07-09 22:38:46 +00:00
/* free this frame */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precv_frame , & adapter - > recvpriv . free_recv_queue ) ;
2013-08-01 02:43:28 +00:00
prtnframe = NULL ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
} else {
2013-07-09 22:38:46 +00:00
/* allowed */
/* check decryption status, and decrypt the frame if needed */
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ########portctrl:psta->ieee8021x_blocked==0 \n " ) ) ;
2014-11-16 00:18:30 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " portctrl:precv_frame->hdr.attrib.privacy=%x \n " ,
precv_frame - > attrib . privacy ) ) ;
2013-05-08 21:45:39 +00:00
if ( pattrib - > bdecrypted = = 0 )
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " portctrl:prxstat->decrypted=%x \n " , pattrib - > bdecrypted ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
prtnframe = precv_frame ;
2013-07-09 22:38:46 +00:00
/* check is the EAPOL frame or not (Rekey) */
2013-08-01 02:43:28 +00:00
if ( ether_type = = eapol_type ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " ########portctrl:ether_type==0x888e \n " ) ) ;
2013-07-09 22:38:46 +00:00
/* check Rekey */
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
prtnframe = precv_frame ;
} else {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ########portctrl:ether_type=0x%04x \n " , ether_type ) ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-08-01 02:43:28 +00:00
} else {
prtnframe = precv_frame ;
2013-05-08 21:45:39 +00:00
}
return prtnframe ;
}
2014-11-16 00:18:30 +00:00
static int recv_decache ( struct recv_frame * precv_frame , u8 bretry ,
struct stainfo_rxcache * prxcache )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
int tid = precv_frame - > attrib . priority ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
u16 seq_ctrl = ( ( precv_frame - > attrib . seq_num & 0xffff ) < < 4 ) |
( precv_frame - > attrib . frag_num & 0xf ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( tid > 15 ) {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x \n " , seq_ctrl , tid ) ) ;
return _FAIL ;
}
2013-08-01 02:43:28 +00:00
if ( 1 ) { /* if (bretry) */
if ( seq_ctrl = = prxcache - > tid_rxseq [ tid ] ) {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " recv_decache, seq_ctrl=0x%x, tid=0x%x, tid_rxseq=0x%x \n " , seq_ctrl , tid , prxcache - > tid_rxseq [ tid ] ) ) ;
return _FAIL ;
}
}
prxcache - > tid_rxseq [ tid ] = seq_ctrl ;
return _SUCCESS ;
}
2014-11-16 00:18:30 +00:00
static void process_pwrbit_data ( struct adapter * padapter ,
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2013-10-19 17:45:47 +00:00
# ifdef CONFIG_88EU_AP_MODE
2013-05-08 21:45:39 +00:00
unsigned char pwrbit ;
2014-11-16 00:18:30 +00:00
u8 * ptr = precv_frame - > rx_data ;
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-05-08 21:45:39 +00:00
struct sta_priv * pstapriv = & padapter - > stapriv ;
2013-08-01 02:43:28 +00:00
struct sta_info * psta = NULL ;
2013-05-08 21:45:39 +00:00
psta = rtw_get_stainfo ( pstapriv , pattrib - > src ) ;
pwrbit = GetPwrMgt ( ptr ) ;
2013-08-01 02:43:28 +00:00
if ( psta ) {
if ( pwrbit ) {
2013-05-09 04:04:25 +00:00
if ( ! ( psta - > state & WIFI_SLEEP_STATE ) )
2013-05-08 21:45:39 +00:00
stop_sta_xmit ( padapter , psta ) ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-09 04:04:25 +00:00
if ( psta - > state & WIFI_SLEEP_STATE )
2013-05-08 21:45:39 +00:00
wakeup_sta_to_xmit ( padapter , psta ) ;
}
}
# endif
}
2014-11-16 00:18:30 +00:00
static void process_wmmps_data ( struct adapter * padapter ,
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2013-10-19 17:45:47 +00:00
# ifdef CONFIG_88EU_AP_MODE
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-05-08 21:45:39 +00:00
struct sta_priv * pstapriv = & padapter - > stapriv ;
2013-08-01 02:43:28 +00:00
struct sta_info * psta = NULL ;
2013-05-08 21:45:39 +00:00
psta = rtw_get_stainfo ( pstapriv , pattrib - > src ) ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
if ( ! psta )
return ;
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( ! psta - > qos_option )
2013-05-08 21:45:39 +00:00
return ;
2013-05-09 04:04:25 +00:00
if ( ! ( psta - > qos_info & 0xf ) )
2013-05-08 21:45:39 +00:00
return ;
2013-05-19 04:28:07 +00:00
2013-07-12 01:13:07 +00:00
if ( psta - > state & WIFI_SLEEP_STATE ) {
2013-08-01 02:43:28 +00:00
u8 wmmps_ac = 0 ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
switch ( pattrib - > priority ) {
case 1 :
case 2 :
wmmps_ac = psta - > uapsd_bk & BIT ( 1 ) ;
break ;
case 4 :
case 5 :
wmmps_ac = psta - > uapsd_vi & BIT ( 1 ) ;
break ;
case 6 :
case 7 :
wmmps_ac = psta - > uapsd_vo & BIT ( 1 ) ;
break ;
case 0 :
case 3 :
default :
wmmps_ac = psta - > uapsd_be & BIT ( 1 ) ;
break ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
if ( wmmps_ac ) {
if ( psta - > sleepq_ac_len > 0 ) {
2013-07-09 22:38:46 +00:00
/* process received triggered frame */
2013-05-08 21:45:39 +00:00
xmit_delivery_enabled_frames ( padapter , psta ) ;
2013-08-01 02:43:28 +00:00
} else {
/* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
2013-05-08 21:45:39 +00:00
issue_qos_nulldata ( padapter , psta - > hwaddr , ( u16 ) pattrib - > priority , 0 , 0 ) ;
}
}
}
2013-05-19 04:28:07 +00:00
# endif
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
static void count_rx_stats ( struct adapter * padapter ,
struct recv_frame * prframe ,
struct sta_info * sta )
2013-05-08 21:45:39 +00:00
{
int sz ;
struct sta_info * psta = NULL ;
struct stainfo_stats * pstats = NULL ;
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & prframe - > attrib ;
2013-08-01 02:43:28 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
sz = prframe - > len ;
2013-05-08 21:45:39 +00:00
precvpriv - > rx_bytes + = sz ;
padapter - > mlmepriv . LinkDetectInfo . NumRxOkInPeriod + + ;
2013-08-01 02:43:28 +00:00
if ( ( ! MacAddr_isBcst ( pattrib - > dst ) ) & & ( ! IS_MCAST ( pattrib - > dst ) ) )
2013-05-08 21:45:39 +00:00
padapter - > mlmepriv . LinkDetectInfo . NumRxUnicastOkInPeriod + + ;
2013-05-09 04:04:25 +00:00
if ( sta )
2013-05-08 21:45:39 +00:00
psta = sta ;
else
2014-11-16 00:18:30 +00:00
psta = prframe - > psta ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( psta ) {
2013-05-08 21:45:39 +00:00
pstats = & psta - > sta_stats ;
pstats - > rx_data_pkts + + ;
pstats - > rx_bytes + = sz ;
}
}
2013-07-26 22:56:14 +00:00
int sta2sta_data_frame (
2013-07-27 01:08:39 +00:00
struct adapter * adapter ,
2014-11-16 00:18:30 +00:00
struct recv_frame * precv_frame ,
2013-08-01 02:43:28 +00:00
struct sta_info * * psta
2013-05-08 21:45:39 +00:00
) ;
2013-08-01 02:43:28 +00:00
2014-11-16 00:18:30 +00:00
int sta2sta_data_frame ( struct adapter * adapter , struct recv_frame * precv_frame ,
struct sta_info * * psta )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
u8 * ptr = precv_frame - > rx_data ;
2013-07-26 22:56:14 +00:00
int ret = _SUCCESS ;
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-08-01 02:43:28 +00:00
struct sta_priv * pstapriv = & adapter - > stapriv ;
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
2013-05-08 21:45:39 +00:00
u8 * mybssid = get_bssid ( pmlmepriv ) ;
u8 * myhwaddr = myid ( & adapter - > eeprompriv ) ;
2013-08-01 02:43:28 +00:00
u8 * sta_addr = NULL ;
2013-07-26 22:56:14 +00:00
int bmcast = IS_MCAST ( pattrib - > dst ) ;
2013-05-08 21:45:39 +00:00
2013-05-26 03:02:10 +00:00
if ( ( check_fwstate ( pmlmepriv , WIFI_ADHOC_STATE ) = = true ) | |
2013-08-01 02:43:28 +00:00
( check_fwstate ( pmlmepriv , WIFI_ADHOC_MASTER_STATE ) = = true ) ) {
2013-07-09 22:38:46 +00:00
/* filter packets that SA is myself or multicast or broadcast */
2014-11-16 00:18:30 +00:00
if ( ! memcmp ( myhwaddr , pattrib - > src , ETH_ALEN ) ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " SA==myself \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-11-16 00:18:30 +00:00
if ( ( memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) ) & & ( ! bmcast ) ) {
2013-08-01 02:43:28 +00:00
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-11-16 00:18:30 +00:00
if ( ! memcmp ( pattrib - > bssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
! memcmp ( mybssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) ) {
2013-08-01 02:43:28 +00:00
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
sta_addr = pattrib - > src ;
2013-08-01 02:43:28 +00:00
} else if ( check_fwstate ( pmlmepriv , WIFI_STATION_STATE ) ) {
2013-07-12 01:13:07 +00:00
/* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */
2014-11-16 00:18:30 +00:00
if ( memcmp ( pattrib - > bssid , pattrib - > src , ETH_ALEN ) ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " bssid!=TA under STATION_MODE; drop pkt \n " ) ) ;
ret = _FAIL ;
2013-07-12 01:13:07 +00:00
goto exit ;
2013-05-08 21:45:39 +00:00
}
sta_addr = pattrib - > bssid ;
2013-08-01 02:43:28 +00:00
} else if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) ) {
if ( bmcast ) {
2013-07-09 22:38:46 +00:00
/* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
2013-08-01 02:43:28 +00:00
if ( ! IS_MCAST ( pattrib - > bssid ) ) {
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-08-01 02:43:28 +00:00
} else { /* not mc-frame */
2013-07-09 22:38:46 +00:00
/* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
2014-11-16 00:18:30 +00:00
if ( memcmp ( pattrib - > bssid , pattrib - > dst , ETH_ALEN ) ) {
2013-08-01 02:43:28 +00:00
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
sta_addr = pattrib - > src ;
}
2013-08-01 02:43:28 +00:00
} else if ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) ) {
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > dst , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > src , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > bssid , GetAddr3Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > ra , pattrib - > dst , ETH_ALEN ) ;
memcpy ( pattrib - > ta , pattrib - > src , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
sta_addr = mybssid ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
}
2013-05-09 04:04:25 +00:00
if ( bmcast )
2013-05-08 21:45:39 +00:00
* psta = rtw_get_bcmc_stainfo ( adapter ) ;
else
2013-07-09 22:38:46 +00:00
* psta = rtw_get_stainfo ( pstapriv , sta_addr ) ; /* get ap_info */
2013-05-08 21:45:39 +00:00
if ( * psta = = NULL ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " can't get psta under sta2sta_data_frame ; drop pkt \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
exit :
return ret ;
}
2014-11-28 17:08:37 +00:00
static int ap2sta_data_frame (
2013-07-27 01:08:39 +00:00
struct adapter * adapter ,
2014-11-16 00:18:30 +00:00
struct recv_frame * precv_frame ,
2013-08-01 02:43:28 +00:00
struct sta_info * * psta )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
u8 * ptr = precv_frame - > rx_data ;
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-07-26 22:56:14 +00:00
int ret = _SUCCESS ;
2013-08-01 02:43:28 +00:00
struct sta_priv * pstapriv = & adapter - > stapriv ;
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
2013-05-08 21:45:39 +00:00
u8 * mybssid = get_bssid ( pmlmepriv ) ;
u8 * myhwaddr = myid ( & adapter - > eeprompriv ) ;
2013-07-26 22:56:14 +00:00
int bmcast = IS_MCAST ( pattrib - > dst ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( ( check_fwstate ( pmlmepriv , WIFI_STATION_STATE ) = = true ) & &
( check_fwstate ( pmlmepriv , _FW_LINKED ) = = true | |
check_fwstate ( pmlmepriv , _FW_UNDER_LINKING ) ) ) {
2013-07-09 22:38:46 +00:00
/* filter packets that SA is myself or multicast or broadcast */
2014-11-16 00:18:30 +00:00
if ( ! memcmp ( myhwaddr , pattrib - > src , ETH_ALEN ) ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " SA==myself \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-07-09 22:38:46 +00:00
/* da should be for me */
2014-11-16 00:18:30 +00:00
if ( ( memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) ) & & ( ! bmcast ) ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " ap2sta_data_frame: compare DA fail; DA=%pM \n " , ( pattrib - > dst ) ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-07-09 22:38:46 +00:00
/* check BSSID */
2014-11-16 00:18:30 +00:00
if ( ! memcmp ( pattrib - > bssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
! memcmp ( mybssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
( memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) ) ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " ap2sta_data_frame: compare BSSID fail ; BSSID=%pM \n " , ( pattrib - > bssid ) ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " mybssid=%pM \n " , ( mybssid ) ) ) ;
if ( ! bmcast ) {
2013-05-30 20:51:53 +00:00
DBG_88E ( " issue_deauth to the nonassociated ap=%pM for the reason(7) \n " , ( pattrib - > bssid ) ) ;
2013-05-08 21:45:39 +00:00
issue_deauth ( adapter , pattrib - > bssid , WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA ) ;
}
2013-08-01 02:43:28 +00:00
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-05-09 04:04:25 +00:00
if ( bmcast )
2013-05-08 21:45:39 +00:00
* psta = rtw_get_bcmc_stainfo ( adapter ) ;
else
2013-07-09 22:38:46 +00:00
* psta = rtw_get_stainfo ( pstapriv , pattrib - > bssid ) ; /* get ap_info */
2013-05-08 21:45:39 +00:00
if ( * psta = = NULL ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " ap2sta: can't get psta under STATION_MODE ; drop pkt \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-07-09 22:38:46 +00:00
/* if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) { */
/* */
2013-05-08 21:45:39 +00:00
if ( GetFrameSubType ( ptr ) & BIT ( 6 ) ) {
/* No data, will not indicate to upper layer, temporily count it here */
count_rx_stats ( adapter , precv_frame , * psta ) ;
ret = RTW_RX_HANDLED ;
goto exit ;
}
2013-08-01 02:43:28 +00:00
} else if ( ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) = = true ) & &
( check_fwstate ( pmlmepriv , _FW_LINKED ) = = true ) ) {
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > dst , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > src , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > bssid , GetAddr3Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > ra , pattrib - > dst , ETH_ALEN ) ;
memcpy ( pattrib - > ta , pattrib - > src , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* */
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > bssid , mybssid , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
* psta = rtw_get_stainfo ( pstapriv , pattrib - > bssid ) ; /* get sta_info */
2013-05-08 21:45:39 +00:00
if ( * psta = = NULL ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " can't get psta under MP_MODE ; drop pkt \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-08-01 02:43:28 +00:00
} else if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) ) {
2013-05-08 21:45:39 +00:00
/* Special case */
ret = RTW_RX_HANDLED ;
goto exit ;
2013-08-01 02:43:28 +00:00
} else {
2014-11-16 00:18:30 +00:00
if ( ! memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) & & ( ! bmcast ) ) {
2013-07-09 22:38:46 +00:00
* psta = rtw_get_stainfo ( pstapriv , pattrib - > bssid ) ; /* get sta_info */
2013-08-01 02:43:28 +00:00
if ( * psta = = NULL ) {
DBG_88E ( " issue_deauth to the ap =%pM for the reason(7) \n " , ( pattrib - > bssid ) ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
issue_deauth ( adapter , pattrib - > bssid , WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA ) ;
}
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
}
exit :
return ret ;
}
2013-10-19 17:45:47 +00:00
static int sta2ap_data_frame ( struct adapter * adapter ,
2014-11-16 00:18:30 +00:00
struct recv_frame * precv_frame ,
2013-10-19 17:45:47 +00:00
struct sta_info * * psta )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-08-01 02:43:28 +00:00
struct sta_priv * pstapriv = & adapter - > stapriv ;
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
2014-11-16 00:18:30 +00:00
u8 * ptr = precv_frame - > rx_data ;
2013-05-19 04:28:07 +00:00
unsigned char * mybssid = get_bssid ( pmlmepriv ) ;
2013-08-01 02:43:28 +00:00
int ret = _SUCCESS ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) = = true ) {
/* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
2014-11-16 00:18:30 +00:00
if ( memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) ) {
2013-08-01 02:43:28 +00:00
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
* psta = rtw_get_stainfo ( pstapriv , pattrib - > src ) ;
2013-08-01 02:43:28 +00:00
if ( * psta = = NULL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " can't get psta under AP_MODE; drop pkt \n " ) ) ;
2013-05-30 20:51:53 +00:00
DBG_88E ( " issue_deauth to sta=%pM for the reason(7) \n " , ( pattrib - > src ) ) ;
2013-05-08 21:45:39 +00:00
issue_deauth ( adapter , pattrib - > src , WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA ) ;
ret = RTW_RX_HANDLED ;
goto exit ;
}
process_pwrbit_data ( adapter , precv_frame ) ;
if ( ( GetFrameSubType ( ptr ) & WIFI_QOS_DATA_TYPE ) = = WIFI_QOS_DATA_TYPE ) {
process_wmmps_data ( adapter , precv_frame ) ;
}
if ( GetFrameSubType ( ptr ) & BIT ( 6 ) ) {
/* No data, will not indicate to upper layer, temporily count it here */
count_rx_stats ( adapter , precv_frame , * psta ) ;
ret = RTW_RX_HANDLED ;
goto exit ;
}
2013-08-01 02:43:28 +00:00
} else {
2013-05-08 21:45:39 +00:00
u8 * myhwaddr = myid ( & adapter - > eeprompriv ) ;
2014-11-16 00:18:30 +00:00
if ( memcmp ( pattrib - > ra , myhwaddr , ETH_ALEN ) ) {
2013-05-08 21:45:39 +00:00
ret = RTW_RX_HANDLED ;
goto exit ;
}
2013-05-30 20:51:53 +00:00
DBG_88E ( " issue_deauth to sta=%pM for the reason(7) \n " , ( pattrib - > src ) ) ;
2013-05-08 21:45:39 +00:00
issue_deauth ( adapter , pattrib - > src , WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA ) ;
ret = RTW_RX_HANDLED ;
goto exit ;
}
exit :
return ret ;
}
2013-10-19 17:45:47 +00:00
static int validate_recv_ctrl_frame ( struct adapter * padapter ,
2014-11-16 00:18:30 +00:00
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2013-10-19 17:45:47 +00:00
# ifdef CONFIG_88EU_AP_MODE
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-05-08 21:45:39 +00:00
struct sta_priv * pstapriv = & padapter - > stapriv ;
2014-11-16 00:18:30 +00:00
u8 * pframe = precv_frame - > rx_data ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
if ( GetFrameType ( pframe ) ! = WIFI_CTRL_TYPE )
return _FAIL ;
2013-07-09 22:38:46 +00:00
/* receive the frames that ra(a1) is my address */
2014-11-16 00:18:30 +00:00
if ( memcmp ( GetAddr1Ptr ( pframe ) , myid ( & padapter - > eeprompriv ) , ETH_ALEN ) )
2013-05-08 21:45:39 +00:00
return _FAIL ;
2013-07-09 22:38:46 +00:00
/* only handle ps-poll */
2013-08-01 02:43:28 +00:00
if ( GetFrameSubType ( pframe ) = = WIFI_PSPOLL ) {
2013-05-08 21:45:39 +00:00
u16 aid ;
2013-08-01 02:43:28 +00:00
u8 wmmps_ac = 0 ;
struct sta_info * psta = NULL ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
aid = GetAid ( pframe ) ;
psta = rtw_get_stainfo ( pstapriv , GetAddr2Ptr ( pframe ) ) ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
if ( ( psta = = NULL ) | | ( psta - > aid ! = aid ) )
2013-05-08 21:45:39 +00:00
return _FAIL ;
2013-07-09 22:38:46 +00:00
/* for rx pkt statistics */
2013-05-08 21:45:39 +00:00
psta - > sta_stats . rx_ctrl_pkts + + ;
2013-08-01 02:43:28 +00:00
switch ( pattrib - > priority ) {
case 1 :
case 2 :
wmmps_ac = psta - > uapsd_bk & BIT ( 0 ) ;
break ;
case 4 :
case 5 :
wmmps_ac = psta - > uapsd_vi & BIT ( 0 ) ;
break ;
case 6 :
case 7 :
wmmps_ac = psta - > uapsd_vo & BIT ( 0 ) ;
break ;
case 0 :
case 3 :
default :
wmmps_ac = psta - > uapsd_be & BIT ( 0 ) ;
break ;
2013-05-08 21:45:39 +00:00
}
2013-05-09 04:04:25 +00:00
if ( wmmps_ac )
2013-05-08 21:45:39 +00:00
return _FAIL ;
2013-08-01 02:43:28 +00:00
if ( psta - > state & WIFI_STA_ALIVE_CHK_STATE ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s alive check-rx ps-poll \n " , __func__ ) ;
2013-05-08 21:45:39 +00:00
psta - > expire_to = pstapriv - > expire_to ;
psta - > state ^ = WIFI_STA_ALIVE_CHK_STATE ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( ( psta - > state & WIFI_SLEEP_STATE ) & & ( pstapriv - > sta_dz_bitmap & BIT ( psta - > aid ) ) ) {
2013-07-25 14:49:25 +00:00
struct list_head * xmitframe_plist , * xmitframe_phead ;
2013-08-01 02:43:28 +00:00
struct xmit_frame * pxmitframe = NULL ;
2013-05-19 04:28:07 +00:00
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & psta - > sleep_q . lock ) ;
2013-05-08 21:45:39 +00:00
xmitframe_phead = get_list_head ( & psta - > sleep_q ) ;
2014-11-16 00:18:30 +00:00
xmitframe_plist = xmitframe_phead - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
if ( xmitframe_phead ! = xmitframe_plist ) {
pxmitframe = container_of ( xmitframe_plist , struct xmit_frame , list ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
xmitframe_plist = xmitframe_plist - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
list_del_init ( & pxmitframe - > list ) ;
2013-05-08 21:45:39 +00:00
psta - > sleepq_len - - ;
2013-08-01 02:43:28 +00:00
if ( psta - > sleepq_len > 0 )
2013-05-08 21:45:39 +00:00
pxmitframe - > attrib . mdata = 1 ;
2013-08-01 02:43:28 +00:00
else
2013-05-08 21:45:39 +00:00
pxmitframe - > attrib . mdata = 0 ;
pxmitframe - > attrib . triggered = 1 ;
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & psta - > sleep_q . lock ) ;
2013-05-26 03:02:10 +00:00
if ( rtw_hal_xmit ( padapter , pxmitframe ) = = true )
2013-05-08 21:45:39 +00:00
rtw_os_xmit_complete ( padapter , pxmitframe ) ;
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & psta - > sleep_q . lock ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( psta - > sleepq_len = = 0 ) {
2013-05-08 21:45:39 +00:00
pstapriv - > tim_bitmap & = ~ BIT ( psta - > aid ) ;
2014-11-16 00:18:30 +00:00
/* update BCN for TIM IE */
2013-07-09 22:38:46 +00:00
/* update_BCNTIM(padapter); */
2013-05-26 03:02:10 +00:00
update_beacon ( padapter , _TIM_IE_ , NULL , false ) ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
} else {
if ( pstapriv - > tim_bitmap & BIT ( psta - > aid ) ) {
if ( psta - > sleepq_len = = 0 ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " no buffered packets to xmit \n " ) ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
2013-05-08 21:45:39 +00:00
issue_nulldata ( padapter , psta - > hwaddr , 0 , 0 , 0 ) ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-25 23:35:42 +00:00
DBG_88E ( " error!psta->sleepq_len=%d \n " , psta - > sleepq_len ) ;
2013-08-01 02:43:28 +00:00
psta - > sleepq_len = 0 ;
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
pstapriv - > tim_bitmap & = ~ BIT ( psta - > aid ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
/* update BCN for TIM IE */
2013-07-09 22:38:46 +00:00
/* update_BCNTIM(padapter); */
2013-05-26 03:02:10 +00:00
update_beacon ( padapter , _TIM_IE_ , NULL , false ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-05-19 04:28:07 +00:00
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & psta - > sleep_q . lock ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
# endif
return _FAIL ;
}
2014-11-16 00:18:30 +00:00
struct recv_frame * recvframe_chk_defrag ( struct adapter * padapter ,
struct recv_frame * precv_frame ) ;
2013-07-26 22:56:14 +00:00
2013-10-19 17:45:47 +00:00
static int validate_recv_mgnt_frame ( struct adapter * padapter ,
2014-11-16 00:18:30 +00:00
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2013-10-19 17:45:47 +00:00
struct sta_info * psta ;
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " +validate_recv_mgnt_frame \n " ) ) ;
precv_frame = recvframe_chk_defrag ( padapter , precv_frame ) ;
if ( precv_frame = = NULL ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " %s: fragment packet \n " , __func__ ) ) ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
}
2013-10-19 17:45:47 +00:00
/* for rx pkt statistics */
2014-11-16 00:18:30 +00:00
psta = rtw_get_stainfo ( & padapter - > stapriv ,
GetAddr2Ptr ( precv_frame - > rx_data ) ) ;
2013-10-19 17:45:47 +00:00
if ( psta ) {
psta - > sta_stats . rx_mgnt_pkts + + ;
2014-11-16 00:18:30 +00:00
if ( GetFrameSubType ( precv_frame - > rx_data ) = = WIFI_BEACON ) {
2013-10-19 17:45:47 +00:00
psta - > sta_stats . rx_beacon_pkts + + ;
2014-11-16 00:18:30 +00:00
} else if ( GetFrameSubType ( precv_frame - > rx_data ) = = WIFI_PROBEREQ ) {
2013-10-19 17:45:47 +00:00
psta - > sta_stats . rx_probereq_pkts + + ;
2014-11-16 00:18:30 +00:00
} else if ( GetFrameSubType ( precv_frame - > rx_data ) = = WIFI_PROBERSP ) {
if ( ! memcmp ( padapter - > eeprompriv . mac_addr ,
GetAddr1Ptr ( precv_frame - > rx_data ) , ETH_ALEN ) )
2013-10-19 17:45:47 +00:00
psta - > sta_stats . rx_probersp_pkts + + ;
2014-11-16 00:18:30 +00:00
else if ( is_broadcast_mac_addr ( GetAddr1Ptr ( precv_frame - > rx_data ) ) | |
is_multicast_mac_addr ( GetAddr1Ptr ( precv_frame - > rx_data ) ) )
2013-10-19 17:45:47 +00:00
psta - > sta_stats . rx_probersp_bm_pkts + + ;
else
psta - > sta_stats . rx_probersp_uo_pkts + + ;
2013-05-08 21:45:39 +00:00
}
}
mgt_dispatcher ( padapter , precv_frame ) ;
return _SUCCESS ;
}
2013-10-19 17:45:47 +00:00
static int validate_recv_data_frame ( struct adapter * adapter ,
2014-11-16 00:18:30 +00:00
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
u8 bretry ;
u8 * psa , * pda , * pbssid ;
struct sta_info * psta = NULL ;
2014-11-16 00:18:30 +00:00
u8 * ptr = precv_frame - > rx_data ;
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
2013-05-19 04:28:07 +00:00
struct security_priv * psecuritypriv = & adapter - > securitypriv ;
2013-07-26 22:56:14 +00:00
int ret = _SUCCESS ;
2013-05-08 21:45:39 +00:00
bretry = GetRetry ( ptr ) ;
pda = get_da ( ptr ) ;
psa = get_sa ( ptr ) ;
pbssid = get_hdr_bssid ( ptr ) ;
2013-08-01 02:43:28 +00:00
if ( pbssid = = NULL ) {
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > dst , pda , ETH_ALEN ) ;
memcpy ( pattrib - > src , psa , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > bssid , pbssid , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
switch ( pattrib - > to_fr_ds ) {
case 0 :
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > ra , pda , ETH_ALEN ) ;
memcpy ( pattrib - > ta , psa , ETH_ALEN ) ;
2013-08-01 02:43:28 +00:00
ret = sta2sta_data_frame ( adapter , precv_frame , & psta ) ;
break ;
case 1 :
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > ra , pda , ETH_ALEN ) ;
memcpy ( pattrib - > ta , pbssid , ETH_ALEN ) ;
2013-08-01 02:43:28 +00:00
ret = ap2sta_data_frame ( adapter , precv_frame , & psta ) ;
break ;
case 2 :
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > ra , pbssid , ETH_ALEN ) ;
memcpy ( pattrib - > ta , psa , ETH_ALEN ) ;
2013-08-01 02:43:28 +00:00
ret = sta2ap_data_frame ( adapter , precv_frame , & psta ) ;
break ;
case 3 :
2013-10-19 17:45:47 +00:00
memcpy ( pattrib - > ra , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
memcpy ( pattrib - > ta , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
2013-08-01 02:43:28 +00:00
ret = _FAIL ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " case 3 \n " ) ) ;
break ;
default :
ret = _FAIL ;
break ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
if ( ret = = _FAIL ) {
2013-05-08 21:45:39 +00:00
goto exit ;
} else if ( ret = = RTW_RX_HANDLED ) {
goto exit ;
}
2013-08-01 02:43:28 +00:00
if ( psta = = NULL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " after to_fr_ds_chk; psta==NULL \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-05-19 04:28:07 +00:00
2013-07-09 22:38:46 +00:00
/* psta->rssi = prxcmd->rssi; */
2013-08-01 02:43:28 +00:00
/* psta->signal_quality = prxcmd->sq; */
2014-11-16 00:18:30 +00:00
precv_frame - > psta = psta ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
pattrib - > amsdu = 0 ;
2013-05-08 21:45:39 +00:00
pattrib - > ack_policy = 0 ;
2013-07-09 22:38:46 +00:00
/* parsing QC field */
2013-08-01 02:43:28 +00:00
if ( pattrib - > qos = = 1 ) {
2013-05-08 21:45:39 +00:00
pattrib - > priority = GetPriority ( ( ptr + 24 ) ) ;
pattrib - > ack_policy = GetAckpolicy ( ( ptr + 24 ) ) ;
pattrib - > amsdu = GetAMsdu ( ( ptr + 24 ) ) ;
2013-08-01 02:43:28 +00:00
pattrib - > hdrlen = pattrib - > to_fr_ds = = 3 ? 32 : 26 ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( pattrib - > priority ! = 0 & & pattrib - > priority ! = 3 )
2013-05-26 03:02:10 +00:00
adapter - > recvpriv . bIsAnyNonBEPkts = true ;
2013-08-01 02:43:28 +00:00
} else {
pattrib - > priority = 0 ;
pattrib - > hdrlen = pattrib - > to_fr_ds = = 3 ? 30 : 24 ;
2013-05-08 21:45:39 +00:00
}
2013-07-09 22:38:46 +00:00
if ( pattrib - > order ) /* HT-CTRL 11n */
2013-05-08 21:45:39 +00:00
pattrib - > hdrlen + = 4 ;
2014-11-16 00:18:30 +00:00
precv_frame - > preorder_ctrl = & psta - > recvreorder_ctrl [ pattrib - > priority ] ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* decache, drop duplicate recv packets */
2013-08-01 02:43:28 +00:00
if ( recv_decache ( precv_frame , bretry , & psta - > sta_recvpriv . rxcache ) = = _FAIL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " decache : drop pkt \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-08-01 02:43:28 +00:00
if ( pattrib - > privacy ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " validate_recv_data_frame:pattrib->privacy=%x \n " , pattrib - > privacy ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6 \n " , pattrib - > ra [ 0 ] , IS_MCAST ( pattrib - > ra ) ) ) ;
2013-05-08 21:45:39 +00:00
GET_ENCRY_ALGO ( psecuritypriv , psta , pattrib - > encrypt , IS_MCAST ( pattrib - > ra ) ) ;
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n pattrib->encrypt=%d \n " , pattrib - > encrypt ) ) ;
2013-05-08 21:45:39 +00:00
SET_ICE_IV_LEN ( pattrib - > iv_len , pattrib - > icv_len , pattrib - > encrypt ) ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-08 21:45:39 +00:00
pattrib - > encrypt = 0 ;
2013-08-01 02:43:28 +00:00
pattrib - > iv_len = 0 ;
pattrib - > icv_len = 0 ;
2013-05-08 21:45:39 +00:00
}
exit :
return ret ;
}
2014-11-16 00:18:30 +00:00
static int validate_recv_frame ( struct adapter * adapter ,
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2013-07-09 22:38:46 +00:00
/* shall check frame subtype, to / from ds, da, bssid */
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* then call check if rx seq/frag. duplicated. */
2013-05-08 21:45:39 +00:00
u8 type ;
u8 subtype ;
2013-07-26 22:56:14 +00:00
int retval = _SUCCESS ;
2013-07-27 02:37:57 +00:00
u8 bDumpRxPkt ;
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > attrib ;
u8 * ptr = precv_frame - > rx_data ;
2014-11-28 17:08:37 +00:00
u8 ver = ( unsigned char ) ( * ptr ) & 0x3 ;
2013-05-08 21:45:39 +00:00
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
if ( pmlmeext - > sitesurvey_res . state = = SCAN_PROCESS ) {
int ch_set_idx = rtw_ch_set_search_ch ( pmlmeext - > channel_set , rtw_get_oper_ch ( adapter ) ) ;
if ( ch_set_idx > = 0 )
pmlmeext - > channel_set [ ch_set_idx ] . rx_count + + ;
}
2013-07-09 22:38:46 +00:00
/* add version chk */
2013-08-01 02:43:28 +00:00
if ( ver ! = 0 ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_data_frame fail! (ver!=0) \n " ) ) ;
retval = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
type = GetFrameType ( ptr ) ;
2013-07-09 22:38:46 +00:00
subtype = GetFrameSubType ( ptr ) ; /* bit(7)~bit(2) */
2013-05-08 21:45:39 +00:00
pattrib - > to_fr_ds = get_tofr_ds ( ptr ) ;
pattrib - > frag_num = GetFragNum ( ptr ) ;
pattrib - > seq_num = GetSequence ( ptr ) ;
pattrib - > pw_save = GetPwrMgt ( ptr ) ;
pattrib - > mfrag = GetMFrag ( ptr ) ;
pattrib - > mdata = GetMData ( ptr ) ;
pattrib - > privacy = GetPrivacy ( ptr ) ;
pattrib - > order = GetOrder ( ptr ) ;
2013-07-27 02:37:57 +00:00
/* Dump rx packets */
2013-05-08 21:45:39 +00:00
rtw_hal_get_def_var ( adapter , HAL_DEF_DBG_DUMP_RXPKT , & ( bDumpRxPkt ) ) ;
2013-08-01 02:43:28 +00:00
if ( bDumpRxPkt = = 1 ) { /* dump all rx packets */
2013-05-08 21:45:39 +00:00
int i ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " ############################# \n " ) ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
for ( i = 0 ; i < 64 ; i = i + 8 )
2013-05-25 23:35:42 +00:00
DBG_88E ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: \n " , * ( ptr + i ) ,
2013-08-01 02:43:28 +00:00
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " ############################# \n " ) ;
2013-08-01 02:43:28 +00:00
} else if ( bDumpRxPkt = = 2 ) {
if ( type = = WIFI_MGT_TYPE ) {
2013-05-08 21:45:39 +00:00
int i ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " ############################# \n " ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
for ( i = 0 ; i < 64 ; i = i + 8 )
2013-05-25 23:35:42 +00:00
DBG_88E ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: \n " , * ( ptr + i ) ,
2013-08-01 02:43:28 +00:00
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " ############################# \n " ) ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
} else if ( bDumpRxPkt = = 3 ) {
if ( type = = WIFI_DATA_TYPE ) {
2013-05-08 21:45:39 +00:00
int i ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " ############################# \n " ) ;
2013-05-19 04:28:07 +00:00
2013-08-01 02:43:28 +00:00
for ( i = 0 ; i < 64 ; i = i + 8 )
2013-05-25 23:35:42 +00:00
DBG_88E ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: \n " , * ( ptr + i ) ,
2013-08-01 02:43:28 +00:00
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " ############################# \n " ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-07-27 02:37:57 +00:00
switch ( type ) {
case WIFI_MGT_TYPE : /* mgnt */
retval = validate_recv_mgnt_frame ( adapter , precv_frame ) ;
if ( retval = = _FAIL )
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_mgnt_frame fail \n " ) ) ;
2013-07-27 02:37:57 +00:00
retval = _FAIL ; /* only data frame return _SUCCESS */
break ;
case WIFI_CTRL_TYPE : /* ctrl */
retval = validate_recv_ctrl_frame ( adapter , precv_frame ) ;
if ( retval = = _FAIL )
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_ctrl_frame fail \n " ) ) ;
2013-07-27 02:37:57 +00:00
retval = _FAIL ; /* only data frame return _SUCCESS */
break ;
case WIFI_DATA_TYPE : /* data */
rtw_led_control ( adapter , LED_CTL_RX ) ;
2013-08-01 02:43:28 +00:00
pattrib - > qos = ( subtype & BIT ( 7 ) ) ? 1 : 0 ;
2013-07-27 02:37:57 +00:00
retval = validate_recv_data_frame ( adapter , precv_frame ) ;
if ( retval = = _FAIL ) {
struct recv_priv * precvpriv = & adapter - > recvpriv ;
precvpriv - > rx_drop + + ;
}
break ;
default :
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_data_frame fail! type= 0x%x \n " , type ) ) ;
2013-07-27 02:37:57 +00:00
retval = _FAIL ;
break ;
2013-05-08 21:45:39 +00:00
}
exit :
return retval ;
}
2013-07-09 22:38:46 +00:00
/* remove the wlanhdr and add the eth_hdr */
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
static int wlanhdr_to_ethhdr ( struct recv_frame * precvframe )
2013-05-08 21:45:39 +00:00
{
2013-07-26 22:56:14 +00:00
int rmv_len ;
2013-05-08 21:45:39 +00:00
u16 eth_type , len ;
2013-06-20 15:13:14 +00:00
__be16 be_tmp ;
2013-05-08 21:45:39 +00:00
u8 bsnaphdr ;
u8 * psnap_type ;
struct ieee80211_snap_hdr * psnap ;
2013-05-19 04:28:07 +00:00
2014-11-28 17:08:37 +00:00
int ret = _SUCCESS ;
2014-11-16 00:18:30 +00:00
struct adapter * adapter = precvframe - > adapter ;
2013-05-08 21:45:39 +00:00
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
2014-11-16 00:18:30 +00:00
u8 * ptr = precvframe - > rx_data ;
struct rx_pkt_attrib * pattrib = & precvframe - > attrib ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( pattrib - > encrypt )
2013-05-19 04:28:07 +00:00
recvframe_pull_tail ( precvframe , pattrib - > icv_len ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
psnap = ( struct ieee80211_snap_hdr * ) ( ptr + pattrib - > hdrlen + pattrib - > iv_len ) ;
psnap_type = ptr + pattrib - > hdrlen + pattrib - > iv_len + SNAP_SIZE ;
2013-05-08 21:45:39 +00:00
/* convert hdr + possible LLC headers into Ethernet header */
2014-11-16 00:18:30 +00:00
if ( ( ! memcmp ( psnap , rtw_rfc1042_header , SNAP_SIZE ) & &
( ! memcmp ( psnap_type , SNAP_ETH_TYPE_IPX , 2 ) = = false ) & &
( ! memcmp ( psnap_type , SNAP_ETH_TYPE_APPLETALK_AARP , 2 ) = = false ) ) | |
! memcmp ( psnap , rtw_bridge_tunnel_header , SNAP_SIZE ) ) {
2013-05-08 21:45:39 +00:00
/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
2013-05-26 03:02:10 +00:00
bsnaphdr = true ;
2013-06-20 15:13:14 +00:00
} else {
2013-05-08 21:45:39 +00:00
/* Leave Ethernet header part of hdr and full payload */
2013-05-26 03:02:10 +00:00
bsnaphdr = false ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
rmv_len = pattrib - > hdrlen + pattrib - > iv_len + ( bsnaphdr ? SNAP_SIZE : 0 ) ;
2014-11-16 00:18:30 +00:00
len = precvframe - > len - rmv_len ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " \n ===pattrib->hdrlen: %x, pattrib->iv_len:%x=== \n \n " , pattrib - > hdrlen , pattrib - > iv_len ) ) ;
2013-05-08 21:45:39 +00:00
2013-10-19 17:45:47 +00:00
memcpy ( & be_tmp , ptr + rmv_len , 2 ) ;
2013-07-09 22:38:46 +00:00
eth_type = ntohs ( be_tmp ) ; /* pattrib->ether_type */
2013-05-08 21:45:39 +00:00
pattrib - > eth_type = eth_type ;
2013-08-01 02:43:28 +00:00
if ( ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) ) ) {
ptr + = rmv_len ;
2013-05-08 21:45:39 +00:00
* ptr = 0x87 ;
* ( ptr + 1 ) = 0x12 ;
eth_type = 0x8712 ;
2013-07-09 22:38:46 +00:00
/* append rx status for mp test packets */
2013-05-08 21:45:39 +00:00
ptr = recvframe_pull ( precvframe , ( rmv_len - sizeof ( struct ethhdr ) + 2 ) - 24 ) ;
2013-10-19 17:45:47 +00:00
memcpy ( ptr , get_rxmem ( precvframe ) , 24 ) ;
2013-08-01 02:43:28 +00:00
ptr + = 24 ;
} else {
ptr = recvframe_pull ( precvframe , ( rmv_len - sizeof ( struct ethhdr ) + ( bsnaphdr ? 2 : 0 ) ) ) ;
2013-05-08 21:45:39 +00:00
}
2013-10-19 17:45:47 +00:00
memcpy ( ptr , pattrib - > dst , ETH_ALEN ) ;
memcpy ( ptr + ETH_ALEN , pattrib - > src , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( ! bsnaphdr ) {
2013-06-20 15:13:14 +00:00
be_tmp = htons ( len ) ;
2013-10-19 17:45:47 +00:00
memcpy ( ptr + 12 , & be_tmp , 2 ) ;
2013-05-08 21:45:39 +00:00
}
2014-11-28 17:08:37 +00:00
return ret ;
2013-05-08 21:45:39 +00:00
}
2013-07-09 22:38:46 +00:00
/* perform defrag */
2014-11-16 00:18:30 +00:00
static struct recv_frame * recvframe_defrag ( struct adapter * adapter ,
struct __queue * defrag_q )
2013-05-08 21:45:39 +00:00
{
2013-07-25 14:49:25 +00:00
struct list_head * plist , * phead ;
2013-06-21 18:41:29 +00:00
u8 wlanhdr_offset ;
2013-05-08 21:45:39 +00:00
u8 curfragnum ;
2014-11-16 00:18:30 +00:00
struct recv_frame * pfhdr , * pnfhdr ;
struct recv_frame * prframe , * pnextrframe ;
2013-07-24 22:55:38 +00:00
struct __queue * pfree_recv_queue ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
curfragnum = 0 ;
pfree_recv_queue = & adapter - > recvpriv . free_recv_queue ;
2013-05-08 21:45:39 +00:00
phead = get_list_head ( defrag_q ) ;
2014-11-16 00:18:30 +00:00
plist = phead - > next ;
pfhdr = container_of ( plist , struct recv_frame , list ) ;
prframe = ( struct recv_frame * ) pfhdr ;
list_del_init ( & ( prframe - > list ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( curfragnum ! = pfhdr - > attrib . frag_num ) {
2013-07-09 22:38:46 +00:00
/* the first fragment number must be 0 */
/* free the whole queue */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( prframe , pfree_recv_queue ) ;
rtw_free_recvframe_queue ( defrag_q , pfree_recv_queue ) ;
return NULL ;
}
curfragnum + + ;
2013-08-01 02:43:28 +00:00
plist = get_list_head ( defrag_q ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
plist = plist - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
while ( phead ! = plist ) {
pnfhdr = container_of ( plist , struct recv_frame , list ) ;
pnextrframe = ( struct recv_frame * ) pnfhdr ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* check the fragment sequence (2nd ~n fragment frame) */
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( curfragnum ! = pnfhdr - > attrib . frag_num ) {
2013-07-09 22:38:46 +00:00
/* the fragment number must be increasing (after decache) */
/* release the defrag_q & prframe */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( prframe , pfree_recv_queue ) ;
rtw_free_recvframe_queue ( defrag_q , pfree_recv_queue ) ;
return NULL ;
}
curfragnum + + ;
2013-07-09 22:38:46 +00:00
/* copy the 2nd~n fragment frame's payload to the first fragment */
/* get the 2nd~last fragment frame's payload */
2013-05-08 21:45:39 +00:00
wlanhdr_offset = pnfhdr - > attrib . hdrlen + pnfhdr - > attrib . iv_len ;
recvframe_pull ( pnextrframe , wlanhdr_offset ) ;
2013-07-09 22:38:46 +00:00
/* append to first fragment frame's tail (if privacy frame, pull the ICV) */
2013-05-08 21:45:39 +00:00
recvframe_pull_tail ( prframe , pfhdr - > attrib . icv_len ) ;
2013-07-09 22:38:46 +00:00
/* memcpy */
2013-10-19 17:45:47 +00:00
memcpy ( pfhdr - > rx_tail , pnfhdr - > rx_data , pnfhdr - > len ) ;
2013-05-08 21:45:39 +00:00
recvframe_put ( prframe , pnfhdr - > len ) ;
2013-08-01 02:43:28 +00:00
pfhdr - > attrib . icv_len = pnfhdr - > attrib . icv_len ;
2014-11-16 00:18:30 +00:00
plist = plist - > next ;
2013-11-29 22:10:20 +00:00
}
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* free the defrag_q queue and return the prframe */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe_queue ( defrag_q , pfree_recv_queue ) ;
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " Performance defrag!!!!! \n " ) ) ;
2013-05-08 21:45:39 +00:00
return prframe ;
}
2013-07-09 22:38:46 +00:00
/* check if need to defrag, if needed queue the frame to defrag_q */
2014-11-16 00:18:30 +00:00
struct recv_frame * recvframe_chk_defrag ( struct adapter * padapter ,
struct recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
u8 ismfrag ;
u8 fragnum ;
u8 * psta_addr ;
2014-11-16 00:18:30 +00:00
struct recv_frame * pfhdr ;
2013-05-08 21:45:39 +00:00
struct sta_info * psta ;
struct sta_priv * pstapriv ;
2013-07-25 14:49:25 +00:00
struct list_head * phead ;
2014-11-16 00:18:30 +00:00
struct recv_frame * prtnframe = NULL ;
2013-07-24 22:55:38 +00:00
struct __queue * pfree_recv_queue , * pdefrag_q ;
2013-05-08 21:45:39 +00:00
pstapriv = & padapter - > stapriv ;
2014-11-16 00:18:30 +00:00
pfhdr = precv_frame ;
2013-05-08 21:45:39 +00:00
pfree_recv_queue = & padapter - > recvpriv . free_recv_queue ;
2013-07-09 22:38:46 +00:00
/* need to define struct of wlan header frame ctrl */
2013-05-08 21:45:39 +00:00
ismfrag = pfhdr - > attrib . mfrag ;
fragnum = pfhdr - > attrib . frag_num ;
psta_addr = pfhdr - > attrib . ta ;
psta = rtw_get_stainfo ( pstapriv , psta_addr ) ;
2013-08-01 02:43:28 +00:00
if ( psta = = NULL ) {
2013-05-08 21:45:39 +00:00
u8 type = GetFrameType ( pfhdr - > rx_data ) ;
if ( type ! = WIFI_DATA_TYPE ) {
psta = rtw_get_bcmc_stainfo ( padapter ) ;
pdefrag_q = & psta - > sta_recvpriv . defrag_q ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-08 21:45:39 +00:00
pdefrag_q = NULL ;
2013-08-01 02:43:28 +00:00
}
} else {
2013-05-08 21:45:39 +00:00
pdefrag_q = & psta - > sta_recvpriv . defrag_q ;
2013-08-01 02:43:28 +00:00
}
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( ( ismfrag = = 0 ) & & ( fragnum = = 0 ) )
2013-07-09 22:38:46 +00:00
prtnframe = precv_frame ; /* isn't a fragment frame */
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( ismfrag = = 1 ) {
2013-07-09 22:38:46 +00:00
/* 0~(n-1) fragment frame */
/* enqueue to defraf_g */
2013-08-01 02:43:28 +00:00
if ( pdefrag_q ! = NULL ) {
if ( fragnum = = 0 ) {
2013-07-09 22:38:46 +00:00
/* the first fragment */
2014-11-16 00:18:30 +00:00
if ( ! list_empty ( & pdefrag_q - > queue ) ) {
2013-07-09 22:38:46 +00:00
/* free current defrag_q */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe_queue ( pdefrag_q , pfree_recv_queue ) ;
}
}
2013-07-09 22:38:46 +00:00
/* Then enqueue the 0~(n-1) fragment into the defrag_q */
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pdefrag_q ) ;
2014-11-16 00:18:30 +00:00
list_add_tail ( & pfhdr - > list , phead ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " Enqueuq: ismfrag=%d, fragnum=%d \n " , ismfrag , fragnum ) ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
prtnframe = NULL ;
} else {
2013-07-09 22:38:46 +00:00
/* can't find this ta's defrag_queue, so free this recv_frame */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precv_frame , pfree_recv_queue ) ;
2013-08-01 02:43:28 +00:00
prtnframe = NULL ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " Free because pdefrag_q==NULL: ismfrag=%d, fragnum=%d \n " , ismfrag , fragnum ) ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-08-01 02:43:28 +00:00
if ( ( ismfrag = = 0 ) & & ( fragnum ! = 0 ) ) {
2013-07-09 22:38:46 +00:00
/* the last fragment frame */
/* enqueue the last fragment */
2013-08-01 02:43:28 +00:00
if ( pdefrag_q ! = NULL ) {
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pdefrag_q ) ;
2014-11-16 00:18:30 +00:00
list_add_tail ( & pfhdr - > list , phead ) ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* call recvframe_defrag to defrag */
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " defrag: ismfrag=%d, fragnum=%d \n " , ismfrag , fragnum ) ) ;
2013-05-08 21:45:39 +00:00
precv_frame = recvframe_defrag ( padapter , pdefrag_q ) ;
2013-08-01 02:43:28 +00:00
prtnframe = precv_frame ;
} else {
2013-07-09 22:38:46 +00:00
/* can't find this ta's defrag_queue, so free this recv_frame */
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precv_frame , pfree_recv_queue ) ;
2013-08-01 02:43:28 +00:00
prtnframe = NULL ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " Free because pdefrag_q==NULL: ismfrag=%d, fragnum=%d \n " , ismfrag , fragnum ) ) ;
2013-05-08 21:45:39 +00:00
}
}
2014-11-16 00:18:30 +00:00
if ( ( prtnframe ! = NULL ) & & ( prtnframe - > attrib . privacy ) ) {
2013-07-09 22:38:46 +00:00
/* after defrag we must check tkip mic code */
2013-08-01 02:43:28 +00:00
if ( recvframe_chkmic ( padapter , prtnframe ) = = _FAIL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recvframe_chkmic(padapter, prtnframe)==_FAIL \n " ) ) ;
rtw_free_recvframe ( prtnframe , pfree_recv_queue ) ;
prtnframe = NULL ;
2013-05-08 21:45:39 +00:00
}
}
return prtnframe ;
}
2014-11-16 00:18:30 +00:00
static int amsdu_to_msdu ( struct adapter * padapter , struct recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
int a_len , padding_len ;
2013-05-19 04:28:07 +00:00
u16 eth_type , nSubframe_Length ;
2013-05-08 21:45:39 +00:00
u8 nr_subframes , i ;
unsigned char * pdata ;
struct rx_pkt_attrib * pattrib ;
unsigned char * data_ptr ;
2013-08-01 02:43:28 +00:00
struct sk_buff * sub_skb , * subframes [ MAX_SUBFRAME_COUNT ] ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-07-24 22:55:38 +00:00
struct __queue * pfree_recv_queue = & ( precvpriv - > free_recv_queue ) ;
2014-11-28 17:08:37 +00:00
int ret = _SUCCESS ;
2013-05-08 21:45:39 +00:00
nr_subframes = 0 ;
2014-11-16 00:18:30 +00:00
pattrib = & prframe - > attrib ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
recvframe_pull ( prframe , prframe - > attrib . hdrlen ) ;
2013-05-19 04:28:07 +00:00
2014-11-16 00:18:30 +00:00
if ( prframe - > attrib . iv_len > 0 )
recvframe_pull ( prframe , prframe - > attrib . iv_len ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
a_len = prframe - > len ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
pdata = prframe - > rx_data ;
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
while ( a_len > ETH_HLEN ) {
2013-05-08 21:45:39 +00:00
/* Offset 12 denote 2 mac address */
2014-11-16 00:18:30 +00:00
nSubframe_Length = get_unaligned_be16 ( pdata + 12 ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( a_len < ( ETHERNET_HEADER_SIZE + nSubframe_Length ) ) {
DBG_88E ( " nRemain_Length is %d and nSubframe_Length is : %d \n " , a_len , nSubframe_Length ) ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
/* move the data point to data content */
pdata + = ETH_HLEN ;
a_len - = ETH_HLEN ;
/* Allocate new skb for releasing to upper layer */
sub_skb = dev_alloc_skb ( nSubframe_Length + 12 ) ;
2013-07-18 17:10:12 +00:00
if ( sub_skb ) {
2013-05-08 21:45:39 +00:00
skb_reserve ( sub_skb , 12 ) ;
data_ptr = ( u8 * ) skb_put ( sub_skb , nSubframe_Length ) ;
2013-10-19 17:45:47 +00:00
memcpy ( data_ptr , pdata , nSubframe_Length ) ;
2013-07-18 17:10:12 +00:00
} else {
2014-11-16 00:18:30 +00:00
sub_skb = skb_clone ( prframe - > pkt , GFP_ATOMIC ) ;
2013-07-18 17:10:12 +00:00
if ( sub_skb ) {
2013-05-08 21:45:39 +00:00
sub_skb - > data = pdata ;
sub_skb - > len = nSubframe_Length ;
skb_set_tail_pointer ( sub_skb , nSubframe_Length ) ;
2013-07-18 17:10:12 +00:00
} else {
2013-08-01 02:43:28 +00:00
DBG_88E ( " skb_clone() Fail!!! , nr_subframes=%d \n " , nr_subframes ) ;
2013-05-08 21:45:39 +00:00
break ;
}
}
subframes [ nr_subframes + + ] = sub_skb ;
2013-05-09 04:04:25 +00:00
if ( nr_subframes > = MAX_SUBFRAME_COUNT ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " ParseSubframe(): Too many Subframes! Packets dropped! \n " ) ;
2013-05-08 21:45:39 +00:00
break ;
}
pdata + = nSubframe_Length ;
a_len - = nSubframe_Length ;
2013-05-09 04:04:25 +00:00
if ( a_len ! = 0 ) {
2013-05-08 21:45:39 +00:00
padding_len = 4 - ( ( nSubframe_Length + ETH_HLEN ) & ( 4 - 1 ) ) ;
2013-05-09 04:04:25 +00:00
if ( padding_len = = 4 ) {
2013-05-08 21:45:39 +00:00
padding_len = 0 ;
}
2013-05-09 04:04:25 +00:00
if ( a_len < padding_len ) {
2013-05-08 21:45:39 +00:00
goto exit ;
}
pdata + = padding_len ;
a_len - = padding_len ;
}
}
2013-08-01 02:43:28 +00:00
for ( i = 0 ; i < nr_subframes ; i + + ) {
2013-05-08 21:45:39 +00:00
sub_skb = subframes [ i ] ;
/* convert hdr + possible LLC headers into Ethernet header */
2014-11-16 00:18:30 +00:00
eth_type = get_unaligned_be16 ( & sub_skb - > data [ 6 ] ) ;
2013-05-08 21:45:39 +00:00
if ( sub_skb - > len > = 8 & &
2014-11-16 00:18:30 +00:00
( ( ! memcmp ( sub_skb - > data , rtw_rfc1042_header , SNAP_SIZE ) & &
2013-05-08 21:45:39 +00:00
eth_type ! = ETH_P_AARP & & eth_type ! = ETH_P_IPX ) | |
2014-11-16 00:18:30 +00:00
! memcmp ( sub_skb - > data , rtw_bridge_tunnel_header , SNAP_SIZE ) ) ) {
2013-05-08 21:45:39 +00:00
/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
skb_pull ( sub_skb , SNAP_SIZE ) ;
2013-10-19 17:45:47 +00:00
memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > src , ETH_ALEN ) ;
memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > dst , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
} else {
2013-06-20 15:13:14 +00:00
__be16 len ;
2013-05-08 21:45:39 +00:00
/* Leave Ethernet header part of hdr and full payload */
len = htons ( sub_skb - > len ) ;
2013-10-19 17:45:47 +00:00
memcpy ( skb_push ( sub_skb , 2 ) , & len , 2 ) ;
memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > src , ETH_ALEN ) ;
memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > dst , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
}
2013-11-29 22:10:20 +00:00
/* Indicate the packets to upper layer */
2014-11-16 00:18:30 +00:00
/* Insert NAT2.5 RX here! */
sub_skb - > protocol = eth_type_trans ( sub_skb , padapter - > pnetdev ) ;
sub_skb - > dev = padapter - > pnetdev ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
sub_skb - > ip_summed = CHECKSUM_NONE ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
netif_rx ( sub_skb ) ;
}
2013-05-08 21:45:39 +00:00
exit :
2014-11-16 00:18:30 +00:00
prframe - > len = 0 ;
2013-07-09 22:38:46 +00:00
rtw_free_recvframe ( prframe , pfree_recv_queue ) ; /* free this recv_frame */
2013-05-19 04:28:07 +00:00
2014-11-28 17:08:37 +00:00
return ret ;
2013-05-08 21:45:39 +00:00
}
2013-06-03 19:52:18 +00:00
static int check_indicate_seq ( struct recv_reorder_ctrl * preorder_ctrl , u16 seq_num )
2013-05-08 21:45:39 +00:00
{
u8 wsize = preorder_ctrl - > wsize_b ;
2013-08-01 02:43:28 +00:00
u16 wend = ( preorder_ctrl - > indicate_seq + wsize - 1 ) & 0xFFF ; /* 4096; */
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* Rx Reorder initialize condition. */
2013-05-08 21:45:39 +00:00
if ( preorder_ctrl - > indicate_seq = = 0xFFFF )
preorder_ctrl - > indicate_seq = seq_num ;
2013-07-09 22:38:46 +00:00
/* Drop out the packet which SeqNum is smaller than WinStart */
2013-08-01 02:43:28 +00:00
if ( SN_LESS ( seq_num , preorder_ctrl - > indicate_seq ) )
2013-05-26 03:02:10 +00:00
return false ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* */
/* Sliding window manipulation. Conditions includes: */
/* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
/* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */
/* */
2013-08-01 02:43:28 +00:00
if ( SN_EQUAL ( seq_num , preorder_ctrl - > indicate_seq ) ) {
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = ( preorder_ctrl - > indicate_seq + 1 ) & 0xFFF ;
2013-08-01 02:43:28 +00:00
} else if ( SN_LESS ( wend , seq_num ) ) {
2013-05-09 04:04:25 +00:00
if ( seq_num > = ( wsize - 1 ) )
2013-08-01 02:43:28 +00:00
preorder_ctrl - > indicate_seq = seq_num + 1 - wsize ;
2013-05-08 21:45:39 +00:00
else
preorder_ctrl - > indicate_seq = 0xFFF - ( wsize - ( seq_num + 1 ) ) + 1 ;
}
2013-05-26 03:02:10 +00:00
return true ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
static int enqueue_reorder_recvframe ( struct recv_reorder_ctrl * preorder_ctrl ,
struct recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & prframe - > attrib ;
2013-07-24 22:55:38 +00:00
struct __queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-07-25 14:49:25 +00:00
struct list_head * phead , * plist ;
2014-11-16 00:18:30 +00:00
struct recv_frame * hdr ;
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * pnextattrib ;
phead = get_list_head ( ppending_recvframe_queue ) ;
2014-11-16 00:18:30 +00:00
plist = phead - > next ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
while ( phead ! = plist ) {
hdr = container_of ( plist , struct recv_frame , list ) ;
pnextattrib = & hdr - > attrib ;
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( SN_LESS ( pnextattrib - > seq_num , pattrib - > seq_num ) )
2014-11-16 00:18:30 +00:00
plist = plist - > next ;
2013-08-01 02:43:28 +00:00
else if ( SN_EQUAL ( pnextattrib - > seq_num , pattrib - > seq_num ) )
2013-05-26 03:02:10 +00:00
return false ;
2013-05-08 21:45:39 +00:00
else
break ;
}
2014-11-16 00:18:30 +00:00
list_del_init ( & ( prframe - > list ) ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
list_add_tail ( & ( prframe - > list ) , plist ) ;
2013-05-26 03:02:10 +00:00
return true ;
2013-05-08 21:45:39 +00:00
}
2013-07-27 01:08:39 +00:00
static int recv_indicatepkts_in_order ( struct adapter * padapter , struct recv_reorder_ctrl * preorder_ctrl , int bforced )
2013-05-08 21:45:39 +00:00
{
2013-07-25 14:49:25 +00:00
struct list_head * phead , * plist ;
2014-11-16 00:18:30 +00:00
struct recv_frame * prframe ;
struct recv_frame * prhdr ;
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * pattrib ;
2013-05-26 03:02:10 +00:00
int bPktInBuf = false ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-07-24 22:55:38 +00:00
struct __queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-05-08 21:45:39 +00:00
2013-05-19 04:28:07 +00:00
phead = get_list_head ( ppending_recvframe_queue ) ;
2014-11-16 00:18:30 +00:00
plist = phead - > next ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* Handling some condition for forced indicate case. */
2013-08-01 02:43:28 +00:00
if ( bforced ) {
2014-11-16 00:18:30 +00:00
if ( list_empty ( phead ) )
2013-05-26 03:02:10 +00:00
return true ;
2013-05-19 04:28:07 +00:00
2014-11-16 00:18:30 +00:00
prhdr = container_of ( plist , struct recv_frame , list ) ;
pattrib = & prhdr - > attrib ;
2013-05-19 04:28:07 +00:00
preorder_ctrl - > indicate_seq = pattrib - > seq_num ;
2013-05-08 21:45:39 +00:00
}
2013-07-09 22:38:46 +00:00
/* Prepare indication list and indication. */
/* Check if there is any packet need indicate. */
2014-11-16 00:18:30 +00:00
while ( ! list_empty ( phead ) ) {
prhdr = container_of ( plist , struct recv_frame , list ) ;
prframe = ( struct recv_frame * ) prhdr ;
pattrib = & prframe - > attrib ;
2013-05-08 21:45:39 +00:00
2013-06-03 19:52:18 +00:00
if ( ! SN_LESS ( preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ) {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ ,
( " recv_indicatepkts_in_order: indicate=%d seq=%d amsdu=%d \n " ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num , pattrib - > amsdu ) ) ;
2014-11-16 00:18:30 +00:00
plist = plist - > next ;
list_del_init ( & ( prframe - > list ) ) ;
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( SN_EQUAL ( preorder_ctrl - > indicate_seq , pattrib - > seq_num ) )
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = ( preorder_ctrl - > indicate_seq + 1 ) & 0xFFF ;
2013-07-09 22:38:46 +00:00
/* Set this as a lock to make sure that only one thread is indicating packet. */
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* indicate this recv_frame */
2013-08-01 02:43:28 +00:00
if ( ! pattrib - > amsdu ) {
if ( ( ! padapter - > bDriverStopped ) & &
( ! padapter - > bSurpriseRemoved ) )
2013-07-09 22:38:46 +00:00
rtw_recv_indicatepkt ( padapter , prframe ) ; /* indicate this recv_frame */
2013-08-01 02:43:28 +00:00
} else if ( pattrib - > amsdu = = 1 ) {
if ( amsdu_to_msdu ( padapter , prframe ) ! = _SUCCESS )
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( prframe , & precvpriv - > free_recv_queue ) ;
2013-08-01 02:43:28 +00:00
} else {
2013-07-09 22:38:46 +00:00
/* error condition; */
2013-05-08 21:45:39 +00:00
}
2013-07-09 22:38:46 +00:00
/* Update local variables. */
2013-05-26 03:02:10 +00:00
bPktInBuf = false ;
2013-08-01 02:43:28 +00:00
} else {
2013-05-26 03:02:10 +00:00
bPktInBuf = true ;
2013-05-08 21:45:39 +00:00
break ;
}
}
return bPktInBuf ;
}
2014-11-16 00:18:30 +00:00
static int recv_indicatepkt_reorder ( struct adapter * padapter ,
struct recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
int retval = _SUCCESS ;
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * pattrib = & prframe - > attrib ;
struct recv_reorder_ctrl * preorder_ctrl = prframe - > preorder_ctrl ;
2013-07-24 22:55:38 +00:00
struct __queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( ! pattrib - > amsdu ) {
2013-07-09 22:38:46 +00:00
/* s1. */
2013-05-08 21:45:39 +00:00
wlanhdr_to_ethhdr ( prframe ) ;
2013-08-01 02:43:28 +00:00
if ( ( pattrib - > qos ! = 1 ) | | ( pattrib - > eth_type = = 0x0806 ) | |
( pattrib - > ack_policy ! = 0 ) ) {
if ( ( ! padapter - > bDriverStopped ) & &
( ! padapter - > bSurpriseRemoved ) ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " @@@@ recv_indicatepkt_reorder -recv_func recv_indicatepkt \n " ) ) ;
2013-05-08 21:45:39 +00:00
rtw_recv_indicatepkt ( padapter , prframe ) ;
return _SUCCESS ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
return _FAIL ;
}
2013-08-01 02:43:28 +00:00
if ( ! preorder_ctrl - > enable ) {
2013-07-09 22:38:46 +00:00
/* indicate this recv_frame */
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = pattrib - > seq_num ;
2013-05-19 04:28:07 +00:00
rtw_recv_indicatepkt ( padapter , prframe ) ;
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = ( preorder_ctrl - > indicate_seq + 1 ) % 4096 ;
2013-05-19 04:28:07 +00:00
return _SUCCESS ;
}
2013-08-01 02:43:28 +00:00
} else if ( pattrib - > amsdu = = 1 ) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
if ( ! preorder_ctrl - > enable ) {
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = pattrib - > seq_num ;
retval = amsdu_to_msdu ( padapter , prframe ) ;
preorder_ctrl - > indicate_seq = ( preorder_ctrl - > indicate_seq + 1 ) % 4096 ;
return retval ;
}
}
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & ppending_recvframe_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ ,
( " recv_indicatepkt_reorder: indicate=%d seq=%d \n " ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ) ;
2013-07-09 22:38:46 +00:00
/* s2. check if winstart_b(indicate_seq) needs to been updated */
2013-08-01 02:43:28 +00:00
if ( ! check_indicate_seq ( preorder_ctrl , pattrib - > seq_num ) ) {
2013-05-08 21:45:39 +00:00
rtw_recv_indicatepkt ( padapter , prframe ) ;
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & ppending_recvframe_queue - > lock ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
goto _success_exit ;
}
2013-07-09 22:38:46 +00:00
/* s3. Insert all packet into Reorder Queue to maintain its ordering. */
2013-05-09 04:04:25 +00:00
if ( ! enqueue_reorder_recvframe ( preorder_ctrl , prframe ) )
2013-05-08 21:45:39 +00:00
goto _err_exit ;
2013-07-09 22:38:46 +00:00
/* s4. */
/* Indication process. */
/* After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */
/* with the SeqNum smaller than latest WinStart and buffer other packets. */
/* */
/* For Rx Reorder condition: */
/* 1. All packets with SeqNum smaller than WinStart => Indicate */
/* 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */
/* */
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */
2013-08-01 02:43:28 +00:00
if ( recv_indicatepkts_in_order ( padapter , preorder_ctrl , false ) ) {
2013-05-08 21:45:39 +00:00
_set_timer ( & preorder_ctrl - > reordering_ctrl_timer , REORDER_WAIT_TIME ) ;
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & ppending_recvframe_queue - > lock ) ;
2013-08-01 02:43:28 +00:00
} else {
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & ppending_recvframe_queue - > lock ) ;
del_timer_sync ( & preorder_ctrl - > reordering_ctrl_timer ) ;
2013-05-08 21:45:39 +00:00
}
_success_exit :
return _SUCCESS ;
_err_exit :
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & ppending_recvframe_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
return _FAIL ;
}
void rtw_reordering_ctrl_timeout_handler ( void * pcontext )
{
2014-11-28 17:08:37 +00:00
struct recv_reorder_ctrl * preorder_ctrl = ( struct recv_reorder_ctrl * ) pcontext ;
2013-07-27 01:08:39 +00:00
struct adapter * padapter = preorder_ctrl - > padapter ;
2013-07-24 22:55:38 +00:00
struct __queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( padapter - > bDriverStopped | | padapter - > bSurpriseRemoved )
2013-05-08 21:45:39 +00:00
return ;
2014-11-16 00:18:30 +00:00
spin_lock_bh ( & ppending_recvframe_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
if ( recv_indicatepkts_in_order ( padapter , preorder_ctrl , true ) = = true )
2013-05-19 04:28:07 +00:00
_set_timer ( & preorder_ctrl - > reordering_ctrl_timer , REORDER_WAIT_TIME ) ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
spin_unlock_bh ( & ppending_recvframe_queue - > lock ) ;
2013-05-08 21:45:39 +00:00
}
2014-11-16 00:18:30 +00:00
static int process_recv_indicatepkts ( struct adapter * padapter ,
struct recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
int retval = _SUCCESS ;
struct mlme_priv * pmlmepriv = & padapter - > mlmepriv ;
struct ht_priv * phtpriv = & pmlmepriv - > htpriv ;
2013-08-01 02:43:28 +00:00
if ( phtpriv - > ht_option ) { /* B/G/N Mode */
if ( recv_indicatepkt_reorder ( padapter , prframe ) ! = _SUCCESS ) {
/* including perform A-MPDU Rx Ordering Buffer Control */
if ( ( ! padapter - > bDriverStopped ) & &
( ! padapter - > bSurpriseRemoved ) ) {
2013-05-08 21:45:39 +00:00
retval = _FAIL ;
return retval ;
}
}
2013-08-01 02:43:28 +00:00
} else { /* B/G mode */
2014-11-28 17:08:37 +00:00
retval = wlanhdr_to_ethhdr ( prframe ) ;
2013-08-01 02:43:28 +00:00
if ( retval ! = _SUCCESS ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " wlanhdr_to_ethhdr: drop pkt \n " ) ) ;
2013-05-08 21:45:39 +00:00
return retval ;
}
2013-08-19 18:10:26 +00:00
if ( ( ! padapter - > bDriverStopped ) & &
( ! padapter - > bSurpriseRemoved ) ) {
2013-07-09 22:38:46 +00:00
/* indicate this recv_frame */
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " @@@@ process_recv_indicatepkts- recv_func recv_indicatepkt \n " ) ) ;
2013-05-08 21:45:39 +00:00
rtw_recv_indicatepkt ( padapter , prframe ) ;
2013-08-01 02:43:28 +00:00
} else {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " @@@@ process_recv_indicatepkts- recv_func free_indicatepkt \n " ) ) ;
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d) " , padapter - > bDriverStopped , padapter - > bSurpriseRemoved ) ) ;
retval = _FAIL ;
return retval ;
}
}
return retval ;
}
2014-11-16 00:18:30 +00:00
static int recv_func_prehandle ( struct adapter * padapter ,
struct recv_frame * rframe )
2013-05-08 21:45:39 +00:00
{
int ret = _SUCCESS ;
2013-07-24 22:55:38 +00:00
struct __queue * pfree_recv_queue = & padapter - > recvpriv . free_recv_queue ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:38:46 +00:00
/* check the frame crtl field and decache */
2013-05-08 21:45:39 +00:00
ret = validate_recv_frame ( padapter , rframe ) ;
2013-08-01 02:43:28 +00:00
if ( ret ! = _SUCCESS ) {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " recv_func: validate_recv_frame fail! drop pkt \n " ) ) ;
2013-07-09 22:38:46 +00:00
rtw_free_recvframe ( rframe , pfree_recv_queue ) ; /* free this recv_frame */
2013-05-08 21:45:39 +00:00
goto exit ;
}
exit :
return ret ;
}
2014-11-16 00:18:30 +00:00
static int recv_func_posthandle ( struct adapter * padapter ,
struct recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
int ret = _SUCCESS ;
2014-11-16 00:18:30 +00:00
struct recv_frame * orig_prframe = prframe ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-07-24 22:55:38 +00:00
struct __queue * pfree_recv_queue = & padapter - > recvpriv . free_recv_queue ;
2013-05-19 04:28:07 +00:00
2013-07-09 22:38:46 +00:00
/* DATA FRAME */
2013-05-08 21:45:39 +00:00
rtw_led_control ( padapter , LED_CTL_RX ) ;
prframe = decryptor ( padapter , prframe ) ;
if ( prframe = = NULL ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " decryptor: drop pkt \n " ) ) ;
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
goto _recv_data_drop ;
}
prframe = recvframe_chk_defrag ( padapter , prframe ) ;
2013-08-01 02:43:28 +00:00
if ( prframe = = NULL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recvframe_chk_defrag: drop pkt \n " ) ) ;
2013-05-19 04:28:07 +00:00
goto _recv_data_drop ;
2013-05-08 21:45:39 +00:00
}
2013-08-01 02:43:28 +00:00
prframe = portctrl ( padapter , prframe ) ;
2013-05-08 21:45:39 +00:00
if ( prframe = = NULL ) {
2013-08-01 02:43:28 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " portctrl: drop pkt \n " ) ) ;
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
goto _recv_data_drop ;
}
count_rx_stats ( padapter , prframe , NULL ) ;
ret = process_recv_indicatepkts ( padapter , prframe ) ;
2013-08-01 02:43:28 +00:00
if ( ret ! = _SUCCESS ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recv_func: process_recv_indicatepkts fail! \n " ) ) ;
2013-07-09 22:38:46 +00:00
rtw_free_recvframe ( orig_prframe , pfree_recv_queue ) ; /* free this recv_frame */
2013-05-08 21:45:39 +00:00
goto _recv_data_drop ;
}
return ret ;
_recv_data_drop :
precvpriv - > rx_drop + + ;
return ret ;
}
2014-11-16 00:18:30 +00:00
static int recv_func ( struct adapter * padapter , struct recv_frame * rframe )
2013-05-08 21:45:39 +00:00
{
int ret ;
2014-11-16 00:18:30 +00:00
struct rx_pkt_attrib * prxattrib = & rframe - > attrib ;
2013-08-01 02:43:28 +00:00
struct security_priv * psecuritypriv = & padapter - > securitypriv ;
2013-05-08 21:45:39 +00:00
struct mlme_priv * mlmepriv = & padapter - > mlmepriv ;
/* check if need to handle uc_swdec_pending_queue*/
2013-08-01 02:43:28 +00:00
if ( check_fwstate ( mlmepriv , WIFI_STATION_STATE ) & & psecuritypriv - > busetkipkey ) {
2014-11-16 00:18:30 +00:00
struct recv_frame * pending_frame ;
2013-05-08 21:45:39 +00:00
2013-08-01 02:43:28 +00:00
while ( ( pending_frame = rtw_alloc_recvframe ( & padapter - > recvpriv . uc_swdec_pending_queue ) ) ) {
2013-05-08 21:45:39 +00:00
if ( recv_func_posthandle ( padapter , pending_frame ) = = _SUCCESS )
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s: dequeue uc_swdec_pending_queue \n " , __func__ ) ;
2013-05-08 21:45:39 +00:00
}
}
ret = recv_func_prehandle ( padapter , rframe ) ;
2013-05-09 04:04:25 +00:00
if ( ret = = _SUCCESS ) {
2013-05-08 21:45:39 +00:00
/* check if need to enqueue into uc_swdec_pending_queue*/
if ( check_fwstate ( mlmepriv , WIFI_STATION_STATE ) & &
2013-08-01 02:43:28 +00:00
! IS_MCAST ( prxattrib - > ra ) & & prxattrib - > encrypt > 0 & &
( prxattrib - > bdecrypted = = 0 | | psecuritypriv - > sw_decrypt ) & &
! is_wep_enc ( psecuritypriv - > dot11PrivacyAlgrthm ) & &
! psecuritypriv - > busetkipkey ) {
2013-05-08 21:45:39 +00:00
rtw_enqueue_recvframe ( rframe , & padapter - > recvpriv . uc_swdec_pending_queue ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s: no key, enqueue uc_swdec_pending_queue \n " , __func__ ) ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
ret = recv_func_posthandle ( padapter , rframe ) ;
}
exit :
return ret ;
}
2014-11-16 00:18:30 +00:00
s32 rtw_recv_entry ( struct recv_frame * precvframe )
2013-05-08 21:45:39 +00:00
{
2013-07-27 01:08:39 +00:00
struct adapter * padapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv ;
2013-08-01 02:43:28 +00:00
s32 ret = _SUCCESS ;
2013-05-08 21:45:39 +00:00
2014-11-16 00:18:30 +00:00
padapter = precvframe - > adapter ;
2013-05-08 21:45:39 +00:00
precvpriv = & padapter - > recvpriv ;
2013-08-01 02:43:28 +00:00
ret = recv_func ( padapter , precvframe ) ;
if ( ret = = _FAIL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " rtw_recv_entry: recv_func return fail!!! \n " ) ) ;
2013-05-08 21:45:39 +00:00
goto _recv_entry_drop ;
}
precvpriv - > rx_pkts + + ;
return ret ;
_recv_entry_drop :
return ret ;
}
2013-08-01 02:43:28 +00:00
void rtw_signal_stat_timer_hdl ( RTW_TIMER_HDL_ARGS )
{
2013-07-27 01:08:39 +00:00
struct adapter * adapter = ( struct adapter * ) FunctionContext ;
2013-05-08 21:45:39 +00:00
struct recv_priv * recvpriv = & adapter - > recvpriv ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
u32 tmp_s , tmp_q ;
u8 avg_signal_strength = 0 ;
u8 avg_signal_qual = 0 ;
2013-07-09 22:38:46 +00:00
u8 _alpha = 3 ; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( adapter - > recvpriv . is_signal_dbg ) {
2013-07-09 22:38:46 +00:00
/* update the user specific value, signal_strength_dbg, to signal_strength, rssi */
2013-08-01 02:43:28 +00:00
adapter - > recvpriv . signal_strength = adapter - > recvpriv . signal_strength_dbg ;
adapter - > recvpriv . rssi = ( s8 ) translate_percentage_to_dbm ( ( u8 ) adapter - > recvpriv . signal_strength_dbg ) ;
2013-05-08 21:45:39 +00:00
} else {
2013-07-09 22:38:46 +00:00
if ( recvpriv - > signal_strength_data . update_req = = 0 ) { /* update_req is clear, means we got rx */
2013-05-08 21:45:39 +00:00
avg_signal_strength = recvpriv - > signal_strength_data . avg_val ;
2014-11-16 00:18:30 +00:00
/* after avg_vals are acquired, we can re-stat the signal values */
2013-05-08 21:45:39 +00:00
recvpriv - > signal_strength_data . update_req = 1 ;
}
2013-05-19 04:28:07 +00:00
2013-07-09 22:38:46 +00:00
if ( recvpriv - > signal_qual_data . update_req = = 0 ) { /* update_req is clear, means we got rx */
2013-05-08 21:45:39 +00:00
avg_signal_qual = recvpriv - > signal_qual_data . avg_val ;
2014-11-16 00:18:30 +00:00
/* after avg_vals are acquired, we can re-stat the signal values */
2013-05-08 21:45:39 +00:00
recvpriv - > signal_qual_data . update_req = 1 ;
}
2013-07-09 22:38:46 +00:00
/* update value of signal_strength, rssi, signal_qual */
2013-05-26 03:02:10 +00:00
if ( check_fwstate ( & adapter - > mlmepriv , _FW_UNDER_SURVEY ) = = false ) {
2013-05-08 21:45:39 +00:00
tmp_s = ( avg_signal_strength + ( _alpha - 1 ) * recvpriv - > signal_strength ) ;
2013-08-01 02:43:28 +00:00
if ( tmp_s % _alpha )
2013-05-08 21:45:39 +00:00
tmp_s = tmp_s / _alpha + 1 ;
else
tmp_s = tmp_s / _alpha ;
2013-08-01 02:43:28 +00:00
if ( tmp_s > 100 )
2013-05-08 21:45:39 +00:00
tmp_s = 100 ;
tmp_q = ( avg_signal_qual + ( _alpha - 1 ) * recvpriv - > signal_qual ) ;
2013-08-01 02:43:28 +00:00
if ( tmp_q % _alpha )
2013-05-08 21:45:39 +00:00
tmp_q = tmp_q / _alpha + 1 ;
else
tmp_q = tmp_q / _alpha ;
2013-08-01 02:43:28 +00:00
if ( tmp_q > 100 )
2013-05-08 21:45:39 +00:00
tmp_q = 100 ;
recvpriv - > signal_strength = tmp_s ;
recvpriv - > rssi = ( s8 ) translate_percentage_to_dbm ( tmp_s ) ;
recvpriv - > signal_qual = tmp_q ;
}
}
rtw_set_signal_stat_timer ( recvpriv ) ;
}