2013-05-08 21:45:39 +00:00
/******************************************************************************
*
* Copyright ( c ) 2007 - 2012 Realtek Corporation . All rights reserved .
2014-12-11 21:15:04 +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_
2014-12-11 21:15:04 +00:00
# include <drv_conf.h>
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 <ip.h>
# include <if_ether.h>
# include <ethernet.h>
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_USB_HCI
2013-05-08 21:45:39 +00:00
# include <usb_ops.h>
2014-12-11 21:15:04 +00:00
# endif
# ifdef CONFIG_BT_COEXIST
# include <rtl8723a_hal.h>
# endif
# if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# error "Shall be Linux or Windows, but not both!\n"
2013-09-06 10:09:58 +00:00
2014-12-11 21:15:04 +00:00
# endif
2013-10-19 17:45:47 +00:00
2014-12-11 21:15:04 +00:00
# include <wifi.h>
# include <circ_buf.h>
2013-09-06 10:09:58 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
2013-05-08 21:45:39 +00:00
void rtw_signal_stat_timer_hdl ( RTW_TIMER_HDL_ARGS ) ;
2014-12-11 21:15:04 +00:00
# endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
2013-05-08 21:45:39 +00:00
void _rtw_init_sta_recv_priv ( struct sta_recv_priv * psta_recvpriv )
{
2014-12-01 22:31:15 +00:00
2014-12-11 21:15:04 +00:00
_func_enter_ ;
2013-05-08 21:45:39 +00:00
_rtw_memset ( ( u8 * ) psta_recvpriv , 0 , sizeof ( struct sta_recv_priv ) ) ;
2014-12-11 21:15:04 +00:00
_rtw_spinlock_init ( & psta_recvpriv - > lock ) ;
//for(i=0; i<MAX_RX_NUMBLKS; i++)
// _rtw_init_queue(&psta_recvpriv->blk_strms[i]);
2013-05-08 21:45:39 +00:00
_rtw_init_queue ( & psta_recvpriv - > defrag_q ) ;
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint _rtw_init_recv_priv ( struct recv_priv * precvpriv , _adapter * padapter )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
sint i ;
2013-05-08 21:45:39 +00:00
union recv_frame * precvframe ;
2014-12-11 21:15:04 +00:00
sint res = _SUCCESS ;
_func_enter_ ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
// We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
//_rtw_memset((unsigned char *)precvpriv, 0, sizeof (struct recv_priv));
_rtw_spinlock_init ( & precvpriv - > lock ) ;
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 ;
rtw_os_recv_resource_init ( precvpriv , padapter ) ;
precvpriv - > pallocated_frame_buf = rtw_zvmalloc ( NR_RECVFRAME * sizeof ( union recv_frame ) + RXFRAME_ALIGN_SZ ) ;
2014-12-11 21:15:04 +00:00
if ( precvpriv - > pallocated_frame_buf = = NULL ) {
res = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
//_rtw_memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
precvpriv - > precv_frame_buf = ( u8 * ) N_BYTE_ALIGMENT ( ( SIZE_PTR ) ( precvpriv - > pallocated_frame_buf ) , RXFRAME_ALIGN_SZ ) ;
//precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ -
// ((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1));
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
precvframe = ( union recv_frame * ) precvpriv - > precv_frame_buf ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
for ( i = 0 ; i < NR_RECVFRAME ; i + + )
{
2013-05-08 21:45:39 +00:00
_rtw_init_listhead ( & ( precvframe - > u . list ) ) ;
rtw_list_insert_tail ( & ( precvframe - > u . list ) , & ( precvpriv - > free_recv_queue . queue ) ) ;
res = rtw_os_recv_resource_alloc ( padapter , precvframe ) ;
precvframe - > u . hdr . len = 0 ;
2014-12-11 21:15:04 +00:00
precvframe - > u . hdr . adapter = padapter ;
2013-05-08 21:45:39 +00:00
precvframe + + ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_USB_HCI
precvpriv - > rx_pending_cnt = 1 ;
2013-05-08 21:45:39 +00:00
_rtw_init_sema ( & precvpriv - > allrxreturnevt , 0 ) ;
2014-12-11 21:15:04 +00:00
# endif
2013-05-08 21:45:39 +00:00
res = rtw_hal_init_recv_priv ( padapter ) ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
# ifdef PLATFORM_LINUX
2013-05-08 21:45:39 +00:00
_init_timer ( & precvpriv - > signal_stat_timer , padapter - > pnetdev , RTW_TIMER_HDL_NAME ( signal_stat ) , padapter ) ;
2014-12-11 21:15:04 +00:00
# elif defined(PLATFORM_OS_CE) || defined(PLATFORM_WINDOWS)
_init_timer ( & precvpriv - > signal_stat_timer , padapter - > hndis_adapter , RTW_TIMER_HDL_NAME ( signal_stat ) , padapter ) ;
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
precvpriv - > signal_stat_sampling_interval = 1000 ; //ms
//precvpriv->signal_stat_converging_constant = 5000; //ms
2013-05-08 21:45:39 +00:00
rtw_set_signal_stat_timer ( precvpriv ) ;
2014-12-11 21:15:04 +00:00
# endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
2013-05-08 21:45:39 +00:00
exit :
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return res ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
void rtw_mfree_recv_priv_lock ( struct recv_priv * precvpriv ) ;
void rtw_mfree_recv_priv_lock ( struct recv_priv * precvpriv )
2013-05-08 21:45:39 +00:00
{
_rtw_spinlock_free ( & precvpriv - > lock ) ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_RECV_THREAD_MODE
_rtw_free_sema ( & precvpriv - > recv_sema ) ;
_rtw_free_sema ( & precvpriv - > terminate_recvthread_sema ) ;
# endif
2013-05-08 21:45:39 +00:00
_rtw_spinlock_free ( & precvpriv - > free_recv_queue . lock ) ;
_rtw_spinlock_free ( & precvpriv - > recv_pending_queue . lock ) ;
_rtw_spinlock_free ( & precvpriv - > free_recv_buf_queue . lock ) ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
_rtw_spinlock_free ( & precvpriv - > recv_buf_pending_queue . lock ) ;
# endif // CONFIG_USE_USB_BUFFER_ALLOC_RX
2013-05-08 21:45:39 +00:00
}
void _rtw_free_recv_priv ( struct recv_priv * precvpriv )
{
2014-12-11 21:15:04 +00:00
_adapter * padapter = precvpriv - > adapter ;
_func_enter_ ;
2013-05-08 21:45:39 +00:00
rtw_free_uc_swdec_pending_queue ( padapter ) ;
rtw_mfree_recv_priv_lock ( precvpriv ) ;
rtw_os_recv_resource_free ( precvpriv ) ;
2014-12-11 21:15:04 +00:00
if ( precvpriv - > pallocated_frame_buf ) {
2013-05-08 21:45:39 +00:00
rtw_vmfree ( precvpriv - > pallocated_frame_buf , NR_RECVFRAME * sizeof ( union recv_frame ) + RXFRAME_ALIGN_SZ ) ;
}
rtw_hal_free_recv_priv ( padapter ) ;
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
union recv_frame * _rtw_alloc_recvframe ( _queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
union recv_frame * precvframe ;
2014-12-11 21:15:04 +00:00
_list * plist , * phead ;
_adapter * padapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv ;
2014-12-11 21:15:04 +00:00
_func_enter_ ;
2014-12-01 22:31:15 +00:00
2014-12-11 21:15:04 +00:00
if ( _rtw_queue_empty ( pfree_recv_queue ) = = _TRUE )
{
2013-05-08 21:45:39 +00:00
precvframe = NULL ;
2014-12-11 21:15:04 +00:00
}
else
{
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pfree_recv_queue ) ;
plist = get_next ( phead ) ;
precvframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
rtw_list_delete ( & precvframe - > u . hdr . list ) ;
2014-12-11 21:15:04 +00:00
padapter = precvframe - > u . hdr . adapter ;
if ( padapter ! = NULL ) {
precvpriv = & padapter - > recvpriv ;
if ( pfree_recv_queue = = & precvpriv - > free_recv_queue )
2013-05-08 21:45:39 +00:00
precvpriv - > free_recvframe_cnt - - ;
}
}
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return precvframe ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
union recv_frame * rtw_alloc_recvframe ( _queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_irqL irqL ;
2013-05-08 21:45:39 +00:00
union recv_frame * precvframe ;
2014-12-11 21:15:04 +00:00
_enter_critical_bh ( & pfree_recv_queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
precvframe = _rtw_alloc_recvframe ( pfree_recv_queue ) ;
2014-12-11 21:15:04 +00:00
_exit_critical_bh ( & pfree_recv_queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
return precvframe ;
}
void rtw_init_recvframe ( union recv_frame * precvframe , struct recv_priv * precvpriv )
{
/* Perry: This can be removed */
_rtw_init_listhead ( & precvframe - > u . hdr . list ) ;
2014-12-11 21:15:04 +00:00
precvframe - > u . hdr . len = 0 ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
int rtw_free_recvframe ( union recv_frame * precvframe , _queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_irqL irqL ;
_adapter * padapter = precvframe - > u . hdr . adapter ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
_func_enter_ ;
# ifdef CONFIG_CONCURRENT_MODE
if ( padapter - > adapter_type > PRIMARY_ADAPTER )
{
padapter = padapter - > pbuddy_adapter ; //get primary_padapter
precvpriv = & padapter - > recvpriv ;
pfree_recv_queue = & precvpriv - > free_recv_queue ;
precvframe - > u . hdr . adapter = padapter ;
}
# endif
# ifdef PLATFORM_WINDOWS
rtw_os_read_port ( padapter , precvframe - > u . hdr . precvbuf ) ;
# endif
# if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
if ( precvframe - > u . hdr . pkt )
{
# ifdef CONFIG_BSD_RX_USE_MBUF
m_freem ( precvframe - > u . hdr . pkt ) ;
# else // CONFIG_BSD_RX_USE_MBUF
rtw_skb_free ( precvframe - > u . hdr . pkt ) ; //free skb by driver
# endif // CONFIG_BSD_RX_USE_MBUF
2013-05-08 21:45:39 +00:00
precvframe - > u . hdr . pkt = NULL ;
}
2014-12-11 21:15:04 +00:00
# endif //defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
_enter_critical_bh ( & pfree_recv_queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
rtw_list_delete ( & ( precvframe - > u . hdr . list ) ) ;
precvframe - > u . hdr . len = 0 ;
rtw_list_insert_tail ( & ( precvframe - > u . hdr . list ) , get_list_head ( pfree_recv_queue ) ) ;
2014-12-11 21:15:04 +00:00
if ( padapter ! = NULL ) {
if ( pfree_recv_queue = = & precvpriv - > free_recv_queue )
2013-05-08 21:45:39 +00:00
precvpriv - > free_recvframe_cnt + + ;
}
2014-12-11 21:15:04 +00:00
_exit_critical_bh ( & pfree_recv_queue - > lock , & irqL ) ;
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint _rtw_enqueue_recvframe ( union recv_frame * precvframe , _queue * queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_adapter * padapter = precvframe - > u . hdr . adapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2014-12-11 21:15:04 +00:00
_func_enter_ ;
//_rtw_init_listhead(&(precvframe->u.hdr.list));
2013-05-08 21:45:39 +00:00
rtw_list_delete ( & ( precvframe - > u . hdr . list ) ) ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
rtw_list_insert_tail ( & ( precvframe - > u . hdr . list ) , get_list_head ( queue ) ) ;
if ( padapter ! = NULL ) {
if ( queue = = & precvpriv - > free_recv_queue )
precvpriv - > free_recvframe_cnt + + ;
}
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
}
2014-12-11 21:15:04 +00:00
sint rtw_enqueue_recvframe ( union recv_frame * precvframe , _queue * queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
sint ret ;
_irqL irqL ;
//_spinlock(&pfree_recv_queue->lock);
_enter_critical_bh ( & queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
ret = _rtw_enqueue_recvframe ( precvframe , queue ) ;
2014-12-11 21:15:04 +00:00
//_rtw_spinunlock(&pfree_recv_queue->lock);
_exit_critical_bh ( & queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
return ret ;
}
2014-12-11 21:15:04 +00:00
/*
sint rtw_enqueue_recvframe ( union recv_frame * precvframe , _queue * queue )
{
return rtw_free_recvframe ( precvframe , queue ) ;
}
*/
2013-05-08 21:45:39 +00:00
/*
caller : defrag ; recvframe_chk_defrag in recv_thread ( passive )
pframequeue : defrag_queue : will be accessed in recv_thread ( passive )
using spinlock to protect
*/
2014-12-11 21:15:04 +00:00
void rtw_free_recvframe_queue ( _queue * pframequeue , _queue * pfree_recv_queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
union recv_frame * precvframe ;
_list * plist , * phead ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
_func_enter_ ;
_rtw_spinlock ( & pframequeue - > lock ) ;
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pframequeue ) ;
plist = get_next ( phead ) ;
2014-12-11 21:15:04 +00:00
while ( rtw_end_of_queue_search ( phead , plist ) = = _FALSE )
{
2013-05-08 21:45:39 +00:00
precvframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
plist = get_next ( plist ) ;
2014-12-11 21:15:04 +00:00
//rtw_list_delete(&precvframe->u.hdr.list); // will do this in rtw_free_recvframe()
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
}
2014-12-11 21:15:04 +00:00
_rtw_spinunlock ( & pframequeue - > lock ) ;
_func_exit_ ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
u32 rtw_free_uc_swdec_pending_queue ( _adapter * adapter )
2013-05-08 21:45:39 +00:00
{
u32 cnt = 0 ;
union recv_frame * pending_frame ;
2014-12-11 21:15:04 +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 ) ;
cnt + + ;
}
2014-12-11 21:15:04 +00:00
if ( cnt )
DBG_871X ( FUNC_ADPT_FMT " dequeue %d \n " , FUNC_ADPT_ARG ( adapter ) , cnt ) ;
2013-05-08 21:45:39 +00:00
return cnt ;
}
2014-12-11 21:15:04 +00:00
sint rtw_enqueue_recvbuf_to_head ( struct recv_buf * precvbuf , _queue * queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_irqL irqL ;
_enter_critical_bh ( & queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
rtw_list_delete ( & precvbuf - > list ) ;
rtw_list_insert_head ( & precvbuf - > list , get_list_head ( queue ) ) ;
2014-12-11 21:15:04 +00:00
_exit_critical_bh ( & queue - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
}
2014-12-11 21:15:04 +00:00
sint rtw_enqueue_recvbuf ( struct recv_buf * precvbuf , _queue * queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_irqL irqL ;
# ifdef CONFIG_SDIO_HCI
_enter_critical_bh ( & queue - > lock , & irqL ) ;
# else
_enter_critical_ex ( & queue - > lock , & irqL ) ;
# endif /*#ifdef CONFIG_SDIO_HCI*/
2013-05-08 21:45:39 +00:00
rtw_list_delete ( & precvbuf - > list ) ;
rtw_list_insert_tail ( & precvbuf - > list , get_list_head ( queue ) ) ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_SDIO_HCI
_exit_critical_bh ( & queue - > lock , & irqL ) ;
# else
_exit_critical_ex ( & queue - > lock , & irqL ) ;
# endif /*#ifdef CONFIG_SDIO_HCI*/
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
struct recv_buf * rtw_dequeue_recvbuf ( _queue * queue )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_irqL irqL ;
2013-05-08 21:45:39 +00:00
struct recv_buf * precvbuf ;
2014-12-11 21:15:04 +00:00
_list * plist , * phead ;
# ifdef CONFIG_SDIO_HCI
_enter_critical_bh ( & queue - > lock , & irqL ) ;
# else
_enter_critical_ex ( & queue - > lock , & irqL ) ;
# endif /*#ifdef CONFIG_SDIO_HCI*/
if ( _rtw_queue_empty ( queue ) = = _TRUE )
{
2013-05-08 21:45:39 +00:00
precvbuf = NULL ;
2014-12-11 21:15:04 +00:00
}
else
{
2013-05-08 21:45:39 +00:00
phead = get_list_head ( queue ) ;
plist = get_next ( phead ) ;
precvbuf = LIST_CONTAINOR ( plist , struct recv_buf , list ) ;
rtw_list_delete ( & precvbuf - > list ) ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_SDIO_HCI
_exit_critical_bh ( & queue - > lock , & irqL ) ;
# else
_exit_critical_ex ( & queue - > lock , & irqL ) ;
# endif /*#ifdef CONFIG_SDIO_HCI*/
2013-05-08 21:45:39 +00:00
return precvbuf ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint recvframe_chkmic ( _adapter * adapter , union recv_frame * precvframe ) ;
sint recvframe_chkmic ( _adapter * adapter , union recv_frame * precvframe ) {
sint i , res = _SUCCESS ;
2013-05-08 21:45:39 +00:00
u32 datalen ;
u8 miccode [ 8 ] ;
2014-12-11 21:15:04 +00:00
u8 bmic_err = _FALSE , brpt_micerror = _TRUE ;
u8 * pframe , * payload , * pframemic ;
2013-05-08 21:45:39 +00:00
u8 * mickey ;
2014-12-11 21:15:04 +00:00
//u8 *iv,rxdata_key_idx=0;
2013-05-08 21:45:39 +00:00
struct sta_info * stainfo ;
2014-12-11 21:15:04 +00:00
struct rx_pkt_attrib * prxattrib = & precvframe - > u . hdr . attrib ;
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 ) ;
2014-12-11 21:15:04 +00:00
_func_enter_ ;
stainfo = rtw_get_stainfo ( & adapter - > stapriv , & prxattrib - > ta [ 0 ] ) ;
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 ] ) ) ;
//calculate mic code
if ( stainfo ! = NULL )
{
if ( IS_MCAST ( prxattrib - > ra ) )
{
//mickey=&psecuritypriv->dot118021XGrprxmickey.skey[0];
//iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen;
//rxdata_key_idx =( ((iv[3])>>6)&0x3) ;
mickey = & psecuritypriv - > dot118021XGrprxmickey [ prxattrib - > key_index ] . skey [ 0 ] ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " \n recvframe_chkmic: bcmc key \n " ) ) ;
//DBG_871X("\n recvframe_chkmic: bcmc key psecuritypriv->dot118021XGrpKeyid(%d),pmlmeinfo->key_index(%d) ,recv key_id(%d)\n",
// psecuritypriv->dot118021XGrpKeyid,pmlmeinfo->key_index,rxdata_key_idx);
if ( psecuritypriv - > binstallGrpkey = = _FALSE )
{
res = _FAIL ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " \n recvframe_chkmic:didn't install group key!!!!!!!!!! \n " ) ) ;
DBG_871X ( " \n recvframe_chkmic:didn't install group key!!!!!!!!!! \n " ) ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
datalen = precvframe - > u . hdr . len - prxattrib - > hdrlen - prxattrib - > iv_len - prxattrib - > icv_len - 8 ; //icv_len included the mic code
pframe = precvframe - > u . hdr . rx_data ;
payload = pframe + prxattrib - > hdrlen + prxattrib - > iv_len ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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 ) ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//rtw_seccalctkipmic(&stainfo->dot11tkiprxmickey.skey[0],pframe,payload, datalen ,&miccode[0],(unsigned char)prxattrib->priority); //care the length of the data
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
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
2014-12-11 21:15:04 +00:00
pframemic = payload + datalen ;
bmic_err = _FALSE ;
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
}
}
2014-12-11 21:15:04 +00:00
if ( bmic_err = = _TRUE ) {
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-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " \n ======demp packet (len=%d)====== \n " , precvframe - > u . hdr . len ) ) ;
for ( i = 0 ; i < precvframe - > u . hdr . len ; i = 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 - > u . hdr . rx_data + i ) , * ( precvframe - > u . hdr . rx_data + i + 1 ) ,
* ( precvframe - > u . hdr . rx_data + i + 2 ) , * ( precvframe - > u . hdr . rx_data + i + 3 ) ,
* ( precvframe - > u . hdr . rx_data + i + 4 ) , * ( precvframe - > u . hdr . rx_data + i + 5 ) ,
* ( precvframe - > u . hdr . rx_data + i + 6 ) , * ( precvframe - > u . hdr . rx_data + i + 7 ) ) ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " \n ======demp packet end [len=%d]====== \n " , precvframe - > u . hdr . len ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " \n hrdlen=%d, \n " , prxattrib - > hdrlen ) ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +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 ) ) ;
// double check key_index for some timing issue ,
// cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue
if ( ( IS_MCAST ( prxattrib - > ra ) = = _TRUE ) & & ( prxattrib - > key_index ! = pmlmeinfo - > key_index ) )
brpt_micerror = _FALSE ;
if ( ( prxattrib - > bdecrypted = = _TRUE ) & & ( brpt_micerror = = _TRUE ) )
{
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_871X ( " mic error :prxattrib->bdecrypted=%d \n " , prxattrib - > bdecrypted ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
else
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " mic error :prxattrib->bdecrypted=%d " , prxattrib - > bdecrypted ) ) ;
DBG_871X ( " mic error :prxattrib->bdecrypted=%d \n " , prxattrib - > bdecrypted ) ;
}
res = _FAIL ;
}
else {
//mic checked ok
if ( ( psecuritypriv - > bcheck_grpkey = = _FALSE ) & & ( IS_MCAST ( prxattrib - > ra ) = = _TRUE ) ) {
psecuritypriv - > bcheck_grpkey = _TRUE ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " psecuritypriv->bcheck_grpkey =_TRUE " ) ) ;
2013-05-08 21:45:39 +00:00
}
}
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
exit :
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return res ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//decrypt and set the ivlen,icvlen of the recv_frame
union recv_frame * decryptor ( _adapter * padapter , union recv_frame * precv_frame ) ;
union recv_frame * decryptor ( _adapter * padapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * prxattrib = & precv_frame - > u . hdr . attrib ;
2014-12-11 21:15:04 +00:00
struct security_priv * psecuritypriv = & padapter - > securitypriv ;
union recv_frame * return_packet = precv_frame ;
u32 res = _SUCCESS ;
_func_enter_ ;
2014-12-01 22:31:15 +00:00
2014-12-11 21:15:04 +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
2014-12-11 21:15:04 +00:00
if ( prxattrib - > encrypt > 0 )
{
2013-05-08 21:45:39 +00:00
u8 * iv = precv_frame - > u . hdr . rx_data + prxattrib - > hdrlen ;
2014-12-11 21:15:04 +00:00
prxattrib - > key_index = ( ( ( iv [ 3 ] ) > > 6 ) & 0x3 ) ;
if ( prxattrib - > key_index > WEP_KEYS )
{
DBG_871X ( " 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-08-01 02:43:28 +00:00
2014-12-11 21:15:04 +00:00
if ( ( prxattrib - > encrypt > 0 ) & & ( ( prxattrib - > bdecrypted = = 0 ) | | ( psecuritypriv - > sw_decrypt = = _TRUE ) ) )
{
2013-08-01 02:43:28 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_CONCURRENT_MODE
if ( ! IS_MCAST ( prxattrib - > ra ) ) //bc/mc packets use sw decryption for concurrent mode
# endif
psecuritypriv - > hw_decrypted = _FALSE ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_DECRYPTOR
DBG_871X ( " prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d \n "
, prxattrib - > bdecrypted , prxattrib - > encrypt , psecuritypriv - > hw_decrypted ) ;
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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_ :
2014-12-11 21:15:04 +00:00
res = rtw_aes_decrypt ( padapter , ( u8 * ) precv_frame ) ;
2013-05-08 21:45:39 +00:00
break ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_WAPI_SUPPORT
case _SMS4_ :
rtw_sms4_decrypt ( padapter , ( u8 * ) precv_frame ) ;
2013-07-12 06:29:15 +00:00
break ;
2014-12-11 21:15:04 +00:00
# endif
default :
break ;
}
}
else if ( prxattrib - > bdecrypted = = 1
& & prxattrib - > encrypt > 0
& & ( psecuritypriv - > busetkipkey = = 1 | | prxattrib - > encrypt ! = _TKIP_ )
)
{
#if 0
if ( ( prxstat - > icv = = 1 ) & & ( prxattrib - > encrypt ! = _AES_ ) )
{
psecuritypriv - > hw_decrypted = _FALSE ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " psecuritypriv->hw_decrypted=_FALSE " ) ) ;
rtw_free_recvframe ( precv_frame , & padapter - > recvpriv . free_recv_queue ) ;
return_packet = NULL ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
else
# endif
{
psecuritypriv - > hw_decrypted = _TRUE ;
# ifdef DBG_RX_DECRYPTOR
DBG_871X ( " prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d \n "
, prxattrib - > bdecrypted , prxattrib - > encrypt , psecuritypriv - > hw_decrypted ) ;
# endif
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
}
}
else {
# ifdef DBG_RX_DECRYPTOR
DBG_871X ( " prxstat->bdecrypted:%d, prxattrib->encrypt:%d, psecuritypriv->hw_decrypted:%d \n "
, prxattrib - > bdecrypted , prxattrib - > encrypt , psecuritypriv - > hw_decrypted ) ;
# endif
}
if ( res = = _FAIL )
{
rtw_free_recvframe ( return_packet , & padapter - > recvpriv . free_recv_queue ) ;
2013-05-08 21:45:39 +00:00
return_packet = NULL ;
2014-12-11 21:15:04 +00:00
}
else {
prxattrib - > bdecrypted = _TRUE ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//recvframe_chkmic(adapter, precv_frame); //move to recvframme_defrag function
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return return_packet ;
2013-07-20 21:35:29 +00:00
2014-12-11 21:15:04 +00:00
}
//###set the security information in the recv_frame
union recv_frame * portctrl ( _adapter * adapter , union recv_frame * precv_frame ) ;
union recv_frame * portctrl ( _adapter * adapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
u8 * psta_addr , * ptr ;
2013-05-08 21:45:39 +00:00
uint auth_alg ;
struct recv_frame_hdr * pfhdr ;
struct sta_info * psta ;
2014-12-11 21:15:04 +00:00
struct sta_priv * pstapriv ;
2013-05-08 21:45:39 +00:00
union recv_frame * prtnframe ;
2014-12-11 21:15:04 +00:00
u16 ether_type = 0 ;
u16 eapol_type = 0x888e ; //for Funia BD's WPA issue
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * pattrib ;
2014-12-11 21:15:04 +00:00
_func_enter_ ;
2013-05-08 21:45:39 +00:00
pstapriv = & adapter - > stapriv ;
auth_alg = adapter - > securitypriv . dot11AuthAlgrthm ;
ptr = get_recvframe_data ( precv_frame ) ;
pfhdr = & precv_frame - > u . hdr ;
pattrib = & pfhdr - > attrib ;
psta_addr = pattrib - > ta ;
prtnframe = NULL ;
2014-11-20 06:12:27 +00:00
psta = rtw_get_stainfo ( pstapriv , psta_addr ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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
2014-12-11 21:15:04 +00:00
if ( auth_alg = = 2 )
{
if ( ( psta ! = NULL ) & & ( psta - > ieee8021x_blocked ) )
{
//blocked
//only accept EAPOL frame
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ########portctrl:psta->ieee8021x_blocked==1 \n " ) ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
prtnframe = precv_frame ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//get ether_type
ptr = ptr + pfhdr - > attrib . hdrlen + pfhdr - > attrib . iv_len + LLC_HEADER_SIZE ;
_rtw_memcpy ( & ether_type , ptr , 2 ) ;
ether_type = ntohs ( ( unsigned short ) ether_type ) ;
if ( ether_type = = eapol_type ) {
prtnframe = precv_frame ;
}
else {
//free this frame
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precv_frame , & adapter - > recvpriv . free_recv_queue ) ;
2014-12-11 21:15:04 +00:00
prtnframe = NULL ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
}
else
{
//allowed
//check decryption status, and decrypt the frame if needed
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ########portctrl:psta->ieee8021x_blocked==0 \n " ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " portctrl:precv_frame->hdr.attrib.privacy=%x \n " , precv_frame - > u . hdr . attrib . privacy ) ) ;
2013-05-08 21:45:39 +00:00
if ( pattrib - > bdecrypted = = 0 )
2014-12-11 21:15:04 +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
2014-12-11 21:15:04 +00:00
prtnframe = precv_frame ;
//check is the EAPOL frame or not (Rekey)
if ( ether_type = = eapol_type ) {
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " ########portctrl:ether_type == 0x888e \n " ) ) ;
//check Rekey
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
}
}
2014-12-11 21:15:04 +00:00
}
else
{
prtnframe = precv_frame ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return prtnframe ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint recv_decache ( union recv_frame * precv_frame , u8 bretry , struct stainfo_rxcache * prxcache ) ;
sint recv_decache ( union recv_frame * precv_frame , u8 bretry , struct stainfo_rxcache * prxcache )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
sint tid = precv_frame - > u . hdr . attrib . priority ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
u16 seq_ctrl = ( ( precv_frame - > u . hdr . attrib . seq_num & 0xffff ) < < 4 ) |
2013-05-08 21:45:39 +00:00
( precv_frame - > u . hdr . attrib . frag_num & 0xf ) ;
2014-12-11 21:15:04 +00:00
_func_enter_ ;
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 ;
}
2014-12-11 21:15:04 +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 ;
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
void process_pwrbit_data ( _adapter * padapter , union recv_frame * precv_frame ) ;
void process_pwrbit_data ( _adapter * padapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_AP_MODE
2013-05-08 21:45:39 +00:00
unsigned char pwrbit ;
u8 * ptr = precv_frame - > u . hdr . rx_data ;
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
struct sta_priv * pstapriv = & padapter - > stapriv ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
if ( psta )
{
if ( pwrbit )
{
if ( ! ( psta - > state & WIFI_SLEEP_STATE ) )
{
//psta->state |= WIFI_SLEEP_STATE;
//pstapriv->sta_dz_bitmap |= BIT(psta->aid);
2013-05-08 21:45:39 +00:00
stop_sta_xmit ( padapter , psta ) ;
2014-12-11 21:15:04 +00:00
//DBG_871X("to sleep, sta_dz_bitmap=%x\n", pstapriv->sta_dz_bitmap);
}
}
else
{
if ( psta - > state & WIFI_SLEEP_STATE )
{
//psta->state ^= WIFI_SLEEP_STATE;
//pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
2013-05-08 21:45:39 +00:00
wakeup_sta_to_xmit ( padapter , psta ) ;
2014-12-11 21:15:04 +00:00
//DBG_871X("to wakeup, sta_dz_bitmap=%x\n", pstapriv->sta_dz_bitmap);
}
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
# endif
}
2014-12-11 21:15:04 +00:00
void process_wmmps_data ( _adapter * padapter , union recv_frame * precv_frame ) ;
void process_wmmps_data ( _adapter * padapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_AP_MODE
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
struct sta_priv * pstapriv = & padapter - > stapriv ;
2014-12-11 21:15:04 +00:00
struct sta_info * psta = NULL ;
2013-05-08 21:45:39 +00:00
psta = rtw_get_stainfo ( pstapriv , pattrib - > src ) ;
2014-12-11 21:15:04 +00:00
if ( ! psta ) return ;
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
if ( ! ( psta - > tdls_sta_state & TDLS_LINKED_STATE ) )
{
# endif //CONFIG_TDLS
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( ! psta - > qos_option )
2013-05-08 21:45:39 +00:00
return ;
2014-12-11 21:15:04 +00:00
if ( ! ( psta - > qos_info & 0xf ) )
2013-05-08 21:45:39 +00:00
return ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
}
# endif //CONFIG_TDLS
if ( psta - > state & WIFI_SLEEP_STATE )
{
u8 wmmps_ac = 0 ;
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-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
if ( wmmps_ac )
{
if ( psta - > sleepq_ac_len > 0 )
{
//process received triggered frame
xmit_delivery_enabled_frames ( padapter , psta ) ;
}
else
{
//issue one qos null frame with More data bit = 0 and the EOSP bit set (=1)
issue_qos_nulldata ( padapter , psta - > hwaddr , ( u16 ) pattrib - > priority , 0 , 0 ) ;
}
}
}
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
# endif
}
# ifdef CONFIG_TDLS
sint OnTDLS ( _adapter * adapter , union recv_frame * precv_frame )
{
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
sint ret = _SUCCESS ;
u8 * paction = get_recvframe_data ( precv_frame ) ;
u8 category_field = 1 ;
# ifdef CONFIG_WFD
u8 WFA_OUI [ 3 ] = { 0x50 , 0x6f , 0x9a } ;
# endif //CONFIG_WFD
struct tdls_info * ptdlsinfo = & ( adapter - > tdlsinfo ) ;
//point to action field
paction + = pattrib - > hdrlen
+ pattrib - > iv_len
+ SNAP_SIZE
+ ETH_TYPE_LEN
+ PAYLOAD_TYPE_LEN
+ category_field ;
if ( ptdlsinfo - > enable = = 0 )
{
DBG_871X ( " recv tdls frame, "
" but tdls haven't enabled \n " ) ;
ret = _FAIL ;
return ret ;
}
switch ( * paction ) {
case TDLS_SETUP_REQUEST :
DBG_871X ( " recv tdls setup request frame \n " ) ;
ret = On_TDLS_Setup_Req ( adapter , precv_frame ) ;
2013-08-01 02:43:28 +00:00
break ;
2014-12-11 21:15:04 +00:00
case TDLS_SETUP_RESPONSE :
DBG_871X ( " recv tdls setup response frame \n " ) ;
ret = On_TDLS_Setup_Rsp ( adapter , precv_frame ) ;
2013-08-01 02:43:28 +00:00
break ;
2014-12-11 21:15:04 +00:00
case TDLS_SETUP_CONFIRM :
DBG_871X ( " recv tdls setup confirm frame \n " ) ;
ret = On_TDLS_Setup_Cfm ( adapter , precv_frame ) ;
2013-08-01 02:43:28 +00:00
break ;
2014-12-11 21:15:04 +00:00
case TDLS_TEARDOWN :
DBG_871X ( " recv tdls teardown, free sta_info \n " ) ;
ret = On_TDLS_Teardown ( adapter , precv_frame ) ;
2013-08-01 02:43:28 +00:00
break ;
2014-12-11 21:15:04 +00:00
case TDLS_DISCOVERY_REQUEST :
DBG_871X ( " recv tdls discovery request frame \n " ) ;
ret = On_TDLS_Dis_Req ( adapter , precv_frame ) ;
break ;
case TDLS_PEER_TRAFFIC_RESPONSE :
DBG_871X ( " recv tdls peer traffic response frame \n " ) ;
ret = On_TDLS_Peer_Traffic_Rsp ( adapter , precv_frame ) ;
break ;
case TDLS_CHANNEL_SWITCH_REQUEST :
DBG_871X ( " recv tdls channel switch request frame \n " ) ;
ret = On_TDLS_Ch_Switch_Req ( adapter , precv_frame ) ;
break ;
case TDLS_CHANNEL_SWITCH_RESPONSE :
DBG_871X ( " recv tdls channel switch response frame \n " ) ;
ret = On_TDLS_Ch_Switch_Rsp ( adapter , precv_frame ) ;
break ;
# ifdef CONFIG_WFD
case 0x50 : //First byte of WFA OUI
if ( _rtw_memcmp ( WFA_OUI , ( paction ) , 3 ) )
{
if ( * ( paction + 3 ) = = 0x04 ) //Probe request frame
{
//WFDTDLS: for sigma test, do not setup direct link automatically
ptdlsinfo - > dev_discovered = 1 ;
DBG_871X ( " recv tunneled probe request frame \n " ) ;
issue_tunneled_probe_rsp ( adapter , precv_frame ) ;
}
if ( * ( paction + 3 ) = = 0x05 ) //Probe response frame
{
//WFDTDLS: for sigma test, do not setup direct link automatically
ptdlsinfo - > dev_discovered = 1 ;
DBG_871X ( " recv tunneled probe response frame \n " ) ;
}
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
break ;
# endif //CONFIG_WFD
default :
DBG_871X ( " receive TDLS frame but not supported \n " ) ;
ret = _FAIL ;
break ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
exit :
return ret ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
void count_rx_stats ( _adapter * padapter , union recv_frame * prframe , struct sta_info * sta ) ;
void count_rx_stats ( _adapter * padapter , union 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-12-11 21:15:04 +00:00
struct rx_pkt_attrib * pattrib = & prframe - > u . hdr . attrib ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-05-08 21:45:39 +00:00
sz = get_recvframe_len ( prframe ) ;
precvpriv - > rx_bytes + = sz ;
padapter - > mlmepriv . LinkDetectInfo . NumRxOkInPeriod + + ;
2014-12-11 21:15:04 +00:00
if ( ( ! MacAddr_isBcst ( pattrib - > dst ) ) & & ( ! IS_MCAST ( pattrib - > dst ) ) ) {
2013-05-08 21:45:39 +00:00
padapter - > mlmepriv . LinkDetectInfo . NumRxUnicastOkInPeriod + + ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( sta )
2013-05-08 21:45:39 +00:00
psta = sta ;
else
psta = prframe - > u . hdr . psta ;
2014-12-11 21:15:04 +00:00
if ( psta )
{
2013-05-08 21:45:39 +00:00
pstats = & psta - > sta_stats ;
pstats - > rx_data_pkts + + ;
pstats - > rx_bytes + = sz ;
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint sta2sta_data_frame (
_adapter * adapter ,
2013-05-08 21:45:39 +00:00
union recv_frame * precv_frame ,
2014-12-11 21:15:04 +00:00
struct sta_info * * psta
2013-05-08 21:45:39 +00:00
) ;
2014-12-11 21:15:04 +00:00
sint sta2sta_data_frame (
_adapter * adapter ,
union recv_frame * precv_frame ,
struct sta_info * * psta
)
2013-05-08 21:45:39 +00:00
{
u8 * ptr = precv_frame - > u . hdr . rx_data ;
2014-12-11 21:15:04 +00:00
sint ret = _SUCCESS ;
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
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 ) ;
2014-12-11 21:15:04 +00:00
u8 * sta_addr = NULL ;
sint bmcast = IS_MCAST ( pattrib - > dst ) ;
# ifdef CONFIG_TDLS
struct tdls_info * ptdlsinfo = & adapter - > tdlsinfo ;
struct sta_info * ptdls_sta = NULL ;
u8 * psnap_type = ptr + pattrib - > hdrlen + pattrib - > iv_len + SNAP_SIZE ;
//frame body located after [+2]: ether-type, [+1]: payload type
u8 * pframe_body = psnap_type + 2 + 1 ;
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
_func_enter_ ;
if ( ( check_fwstate ( pmlmepriv , WIFI_ADHOC_STATE ) = = _TRUE ) | |
( check_fwstate ( pmlmepriv , WIFI_ADHOC_MASTER_STATE ) = = _TRUE ) )
{
// filter packets that SA is myself or multicast or broadcast
if ( _rtw_memcmp ( myhwaddr , pattrib - > src , ETH_ALEN ) ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " SA==myself \n " ) ) ;
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
if ( ( ! _rtw_memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) ) & & ( ! bmcast ) ) {
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
if ( _rtw_memcmp ( pattrib - > bssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
_rtw_memcmp ( mybssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
( ! _rtw_memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) ) ) {
ret = _FAIL ;
2013-07-12 01:13:07 +00:00
goto exit ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sta_addr = pattrib - > src ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
else if ( check_fwstate ( pmlmepriv , WIFI_STATION_STATE ) = = _TRUE )
{
# ifdef CONFIG_TDLS
//direct link data transfer
if ( ptdlsinfo - > setup_state = = TDLS_LINKED_STATE ) {
ptdls_sta = rtw_get_stainfo ( pstapriv , pattrib - > src ) ;
if ( ptdls_sta = = NULL )
{
ret = _FAIL ;
goto exit ;
}
else if ( ptdls_sta - > tdls_sta_state & TDLS_LINKED_STATE )
{
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//drop QoS-SubType Data, including QoS NULL, excluding QoS-Data
if ( ( GetFrameSubType ( ptr ) & WIFI_QOS_DATA_TYPE ) = = WIFI_QOS_DATA_TYPE )
{
if ( GetFrameSubType ( ptr ) & ( BIT ( 4 ) | BIT ( 5 ) | BIT ( 6 ) ) )
{
DBG_871X ( " drop QoS-Sybtype Data \n " ) ;
ret = _FAIL ;
goto exit ;
}
}
// filter packets that SA is myself or multicast or broadcast
if ( _rtw_memcmp ( myhwaddr , pattrib - > src , ETH_ALEN ) ) {
ret = _FAIL ;
goto exit ;
}
// da should be for me
if ( ( ! _rtw_memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) ) & & ( ! bmcast ) )
{
ret = _FAIL ;
goto exit ;
}
// check BSSID
if ( _rtw_memcmp ( pattrib - > bssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
_rtw_memcmp ( mybssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
( ! _rtw_memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) ) )
{
ret = _FAIL ;
goto exit ;
}
//process UAPSD tdls sta
process_pwrbit_data ( adapter , precv_frame ) ;
// if NULL-frame, check pwrbit
if ( ( GetFrameSubType ( ptr ) ) = = WIFI_DATA_NULL )
{
//NULL-frame with pwrbit=1, buffer_STA should buffer frames for sleep_STA
if ( GetPwrMgt ( ptr ) )
{
DBG_871X ( " TDLS: recv peer null frame with pwr bit 1 \n " ) ;
ptdls_sta - > tdls_sta_state | = TDLS_PEER_SLEEP_STATE ;
// it would be triggered when we are off channel and receiving NULL DATA
// we can confirm that peer STA is at off channel
}
else if ( ptdls_sta - > tdls_sta_state & TDLS_CH_SWITCH_ON_STATE )
{
if ( ( ptdls_sta - > tdls_sta_state & TDLS_PEER_AT_OFF_STATE ) ! = TDLS_PEER_AT_OFF_STATE )
{
issue_nulldata_to_TDLS_peer_STA ( adapter , ptdls_sta , 0 ) ;
ptdls_sta - > tdls_sta_state | = TDLS_PEER_AT_OFF_STATE ;
On_TDLS_Peer_Traffic_Rsp ( adapter , precv_frame ) ;
}
}
ret = _FAIL ;
goto exit ;
}
//receive some of all TDLS management frames, process it at ON_TDLS
if ( ( _rtw_memcmp ( psnap_type , SNAP_ETH_TYPE_TDLS , 2 ) ) ) {
ret = OnTDLS ( adapter , precv_frame ) ;
goto exit ;
}
}
sta_addr = pattrib - > src ;
}
else
# endif //CONFIG_TDLS
{
// For Station mode, sa and bssid should always be BSSID, and DA is my mac-address
if ( ! _rtw_memcmp ( pattrib - > bssid , pattrib - > src , ETH_ALEN ) )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " bssid != TA under STATION_MODE; drop pkt \n " ) ) ;
ret = _FAIL ;
goto exit ;
}
sta_addr = pattrib - > bssid ;
}
}
else if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) = = _TRUE )
{
if ( bmcast )
{
// For AP mode, if DA == MCAST, then BSSID should be also MCAST
if ( ! IS_MCAST ( pattrib - > bssid ) ) {
ret = _FAIL ;
goto exit ;
}
}
else // not mc-frame
{
// For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID
if ( ! _rtw_memcmp ( pattrib - > bssid , pattrib - > dst , ETH_ALEN ) ) {
ret = _FAIL ;
goto exit ;
}
sta_addr = pattrib - > src ;
}
}
else if ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) = = _TRUE )
{
_rtw_memcpy ( pattrib - > dst , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > src , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > bssid , GetAddr3Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ra , pattrib - > dst , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , pattrib - > src , ETH_ALEN ) ;
sta_addr = mybssid ;
}
else
{
ret = _FAIL ;
}
if ( bmcast )
* psta = rtw_get_bcmc_stainfo ( adapter ) ;
else
* psta = rtw_get_stainfo ( pstapriv , sta_addr ) ; // get ap_info
# ifdef CONFIG_TDLS
if ( ptdls_sta ! = NULL )
* psta = ptdls_sta ;
# endif //CONFIG_TDLS
if ( * psta = = NULL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " can't get psta under sta2sta_data_frame ; drop pkt \n " ) ) ;
# ifdef CONFIG_MP_INCLUDED
if ( adapter - > registrypriv . mp_mode = = 1 )
{
if ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) = = _TRUE )
2013-05-08 21:45:39 +00:00
adapter - > mppriv . rx_pktloss + + ;
}
2014-12-11 21:15:04 +00:00
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
exit :
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint ap2sta_data_frame (
_adapter * adapter ,
2013-05-08 21:45:39 +00:00
union recv_frame * precv_frame ,
2014-12-11 21:15:04 +00:00
struct sta_info * * psta ) ;
sint ap2sta_data_frame (
_adapter * adapter ,
union recv_frame * precv_frame ,
struct sta_info * * psta )
2013-05-08 21:45:39 +00:00
{
u8 * ptr = precv_frame - > u . hdr . rx_data ;
2014-12-11 21:15:04 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
sint ret = _SUCCESS ;
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 ) ;
2014-12-11 21:15:04 +00:00
sint bmcast = IS_MCAST ( pattrib - > dst ) ;
_func_enter_ ;
if ( ( check_fwstate ( pmlmepriv , WIFI_STATION_STATE ) = = _TRUE )
& & ( check_fwstate ( pmlmepriv , _FW_LINKED ) = = _TRUE
| | check_fwstate ( pmlmepriv , _FW_UNDER_LINKING ) = = _TRUE )
)
{
// filter packets that SA is myself or multicast or broadcast
if ( _rtw_memcmp ( myhwaddr , pattrib - > src , ETH_ALEN ) ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " SA==myself \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s SA= " MAC_FMT " , myhwaddr= " MAC_FMT " \n " ,
__FUNCTION__ , MAC_ARG ( pattrib - > src ) , MAC_ARG ( myhwaddr ) ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
// da should be for me
if ( ( ! _rtw_memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) ) & & ( ! bmcast ) )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " ap2sta_data_frame: compare DA fail; DA= " MAC_FMT " \n " , MAC_ARG ( pattrib - > dst ) ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s DA= " MAC_FMT " \n " , __func__ , MAC_ARG ( pattrib - > dst ) ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-08-01 02:43:28 +00:00
2014-12-11 21:15:04 +00:00
// check BSSID
if ( _rtw_memcmp ( pattrib - > bssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
_rtw_memcmp ( mybssid , " \ x0 \ x0 \ x0 \ x0 \ x0 \ x0 " , ETH_ALEN ) | |
( ! _rtw_memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) ) )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " ap2sta_data_frame: compare BSSID fail ; BSSID= " MAC_FMT " \n " , MAC_ARG ( pattrib - > bssid ) ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " mybssid= " MAC_FMT " \n " , MAC_ARG ( mybssid ) ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s BSSID= " MAC_FMT " , mybssid= " MAC_FMT " \n " ,
__FUNCTION__ , MAC_ARG ( pattrib - > bssid ) , MAC_ARG ( mybssid ) ) ;
DBG_871X ( " this adapter = %d, buddy adapter = %d \n " , adapter - > adapter_type , adapter - > pbuddy_adapter - > adapter_type ) ;
# endif
if ( ! bmcast )
{
DBG_871X ( " issue_deauth to the nonassociated ap= " MAC_FMT " for the reason(7) \n " , MAC_ARG ( pattrib - > bssid ) ) ;
2013-05-08 21:45:39 +00:00
issue_deauth ( adapter , pattrib - > bssid , WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA ) ;
}
2014-12-11 21:15:04 +00:00
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
if ( bmcast )
2013-05-08 21:45:39 +00:00
* psta = rtw_get_bcmc_stainfo ( adapter ) ;
else
2014-12-11 21:15:04 +00:00
* psta = rtw_get_stainfo ( pstapriv , pattrib - > bssid ) ; // get ap_info
2013-05-08 21:45:39 +00:00
if ( * psta = = NULL ) {
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " ap2sta: can't get psta under STATION_MODE ; drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s can't get psta under STATION_MODE ; drop pkt \n " , __FUNCTION__ ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +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 ;
}
2014-12-11 21:15:04 +00:00
}
else if ( ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) = = _TRUE ) & &
( check_fwstate ( pmlmepriv , _FW_LINKED ) = = _TRUE ) )
{
_rtw_memcpy ( pattrib - > dst , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > src , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > bssid , GetAddr3Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ra , pattrib - > dst , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , pattrib - > src , ETH_ALEN ) ;
//
_rtw_memcpy ( pattrib - > bssid , mybssid , ETH_ALEN ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
* psta = rtw_get_stainfo ( pstapriv , pattrib - > bssid ) ; // get sta_info
2013-05-08 21:45:39 +00:00
if ( * psta = = NULL ) {
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " can't get psta under MP_MODE ; drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt \n " , __FUNCTION__ ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
}
else if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) = = _TRUE )
{
2013-05-08 21:45:39 +00:00
/* Special case */
ret = RTW_RX_HANDLED ;
goto exit ;
2014-12-11 21:15:04 +00:00
}
else
{
if ( _rtw_memcmp ( myhwaddr , pattrib - > dst , ETH_ALEN ) & & ( ! bmcast ) )
{
* psta = rtw_get_stainfo ( pstapriv , pattrib - > bssid ) ; // get sta_info
if ( * psta = = NULL )
{
DBG_871X ( " issue_deauth to the ap= " MAC_FMT " for the reason(7) \n " , MAC_ARG ( pattrib - > bssid ) ) ;
2013-05-08 21:45:39 +00:00
issue_deauth ( adapter , pattrib - > bssid , WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA ) ;
}
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s fw_state:0x%x \n " , __FUNCTION__ , get_fwstate ( pmlmepriv ) ) ;
# endif
2013-05-08 21:45:39 +00:00
}
exit :
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint sta2ap_data_frame (
_adapter * adapter ,
union recv_frame * precv_frame ,
struct sta_info * * psta ) ;
sint sta2ap_data_frame (
_adapter * adapter ,
union recv_frame * precv_frame ,
struct sta_info * * psta )
2013-05-08 21:45:39 +00:00
{
2013-10-19 17:45:47 +00:00
u8 * ptr = precv_frame - > u . hdr . rx_data ;
2014-12-11 21:15:04 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
struct sta_priv * pstapriv = & adapter - > stapriv ;
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
unsigned char * mybssid = get_bssid ( pmlmepriv ) ;
sint ret = _SUCCESS ;
_func_enter_ ;
if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) = = _TRUE )
{
//For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR
if ( ! _rtw_memcmp ( pattrib - > bssid , mybssid , ETH_ALEN ) )
{
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
* psta = rtw_get_stainfo ( pstapriv , pattrib - > src ) ;
2014-12-11 21:15:04 +00:00
if ( * psta = = NULL )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " can't get psta under AP_MODE; drop pkt \n " ) ) ;
DBG_871X ( " issue_deauth to sta= " MAC_FMT " for the reason(7) \n " , MAC_ARG ( 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 ;
}
2014-12-11 21:15:04 +00:00
}
else {
2013-05-08 21:45:39 +00:00
u8 * myhwaddr = myid ( & adapter - > eeprompriv ) ;
if ( ! _rtw_memcmp ( pattrib - > ra , myhwaddr , ETH_ALEN ) ) {
ret = RTW_RX_HANDLED ;
goto exit ;
}
2014-12-11 21:15:04 +00:00
DBG_871X ( " issue_deauth to sta= " MAC_FMT " for the reason(7) \n " , MAC_ARG ( 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 :
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint validate_recv_ctrl_frame ( _adapter * padapter , union recv_frame * precv_frame ) ;
sint validate_recv_ctrl_frame ( _adapter * padapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_AP_MODE
2013-05-08 21:45:39 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
struct sta_priv * pstapriv = & padapter - > stapriv ;
u8 * pframe = precv_frame - > u . hdr . rx_data ;
2014-12-11 21:15:04 +00:00
//uint len = precv_frame->u.hdr.len;
//DBG_871X("+validate_recv_ctrl_frame\n");
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
if ( GetFrameType ( pframe ) ! = WIFI_CTRL_TYPE )
2014-12-11 21:15:04 +00:00
{
2013-05-08 21:45:39 +00:00
return _FAIL ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//receive the frames that ra(a1) is my address
2013-05-08 21:45:39 +00:00
if ( ! _rtw_memcmp ( GetAddr1Ptr ( pframe ) , myid ( & padapter - > eeprompriv ) , ETH_ALEN ) )
2014-12-11 21:15:04 +00:00
{
2013-05-08 21:45:39 +00:00
return _FAIL ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//only handle ps-poll
if ( GetFrameSubType ( pframe ) = = WIFI_PSPOLL )
{
2013-05-08 21:45:39 +00:00
u16 aid ;
2014-12-11 21:15:04 +00:00
u8 wmmps_ac = 0 ;
struct sta_info * psta = NULL ;
2013-05-08 21:45:39 +00:00
aid = GetAid ( pframe ) ;
psta = rtw_get_stainfo ( pstapriv , GetAddr2Ptr ( pframe ) ) ;
2014-12-11 21:15:04 +00:00
if ( ( psta = = NULL ) | | ( psta - > aid ! = aid ) )
{
2013-05-08 21:45:39 +00:00
return _FAIL ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//for rx pkt statistics
2013-05-08 21:45:39 +00:00
psta - > sta_stats . rx_ctrl_pkts + + ;
2014-12-11 21:15:04 +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
}
2014-12-11 21:15:04 +00:00
if ( wmmps_ac )
2013-05-08 21:45:39 +00:00
return _FAIL ;
2014-12-11 21:15:04 +00:00
if ( psta - > state & WIFI_STA_ALIVE_CHK_STATE )
{
DBG_871X ( " %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 ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( ( psta - > state & WIFI_SLEEP_STATE ) & & ( pstapriv - > sta_dz_bitmap & BIT ( psta - > aid ) ) )
{
_irqL irqL ;
_list * xmitframe_plist , * xmitframe_phead ;
struct xmit_frame * pxmitframe = NULL ;
2014-11-20 06:12:27 +00:00
struct xmit_priv * pxmitpriv = & padapter - > xmitpriv ;
2014-12-11 21:15:04 +00:00
//_enter_critical_bh(&psta->sleep_q.lock, &irqL);
_enter_critical_bh ( & pxmitpriv - > lock , & irqL ) ;
2013-05-08 21:45:39 +00:00
xmitframe_phead = get_list_head ( & psta - > sleep_q ) ;
xmitframe_plist = get_next ( xmitframe_phead ) ;
2014-12-11 21:15:04 +00:00
if ( ( rtw_end_of_queue_search ( xmitframe_phead , xmitframe_plist ) ) = = _FALSE )
{
2013-05-08 21:45:39 +00:00
pxmitframe = LIST_CONTAINOR ( xmitframe_plist , struct xmit_frame , list ) ;
xmitframe_plist = get_next ( xmitframe_plist ) ;
rtw_list_delete ( & pxmitframe - > list ) ;
psta - > sleepq_len - - ;
2014-12-11 21:15:04 +00:00
if ( psta - > sleepq_len > 0 )
2013-05-08 21:45:39 +00:00
pxmitframe - > attrib . mdata = 1 ;
2014-12-11 21:15:04 +00:00
else
2013-05-08 21:45:39 +00:00
pxmitframe - > attrib . mdata = 0 ;
pxmitframe - > attrib . triggered = 1 ;
2014-12-11 21:15:04 +00:00
//DBG_871X("handling ps-poll, q_len=%d, tim=%x\n", psta->sleepq_len, pstapriv->tim_bitmap);
#if 0
_exit_critical_bh ( & psta - > sleep_q . lock , & irqL ) ;
if ( rtw_hal_xmit ( padapter , pxmitframe ) = = _TRUE )
{
rtw_os_xmit_complete ( padapter , pxmitframe ) ;
}
_enter_critical_bh ( & psta - > sleep_q . lock , & irqL ) ;
# endif
2014-11-20 06:12:27 +00:00
rtw_hal_xmitframe_enqueue ( padapter , pxmitframe ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( psta - > sleepq_len = = 0 )
{
2013-05-08 21:45:39 +00:00
pstapriv - > tim_bitmap & = ~ BIT ( psta - > aid ) ;
2014-12-11 21:15:04 +00:00
//DBG_871X("after handling ps-poll, tim=%x\n", pstapriv->tim_bitmap);
//upate BCN for TIM IE
//update_BCNTIM(padapter);
update_beacon ( padapter , _TIM_IE_ , NULL , _FALSE ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//_exit_critical_bh(&psta->sleep_q.lock, &irqL);
_exit_critical_bh ( & pxmitpriv - > lock , & irqL ) ;
}
else
{
//_exit_critical_bh(&psta->sleep_q.lock, &irqL);
_exit_critical_bh ( & pxmitpriv - > lock , & irqL ) ;
//DBG_871X("no buffered packets to xmit\n");
if ( pstapriv - > tim_bitmap & BIT ( psta - > aid ) )
{
if ( psta - > sleepq_len = = 0 )
{
DBG_871X ( " no buffered packets to xmit \n " ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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 ) ;
}
2014-12-11 21:15:04 +00:00
else
{
DBG_871X ( " error!psta->sleepq_len=%d \n " , psta - > sleepq_len ) ;
psta - > sleepq_len = 0 ;
}
pstapriv - > tim_bitmap & = ~ BIT ( psta - > aid ) ;
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
//upate BCN for TIM IE
//update_BCNTIM(padapter);
update_beacon ( padapter , _TIM_IE_ , NULL , _FALSE ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
# endif
return _FAIL ;
2014-12-11 21:15:04 +00:00
}
2013-07-26 22:56:14 +00:00
2014-12-11 21:15:04 +00:00
union recv_frame * recvframe_chk_defrag ( PADAPTER padapter , union recv_frame * precv_frame ) ;
sint validate_recv_mgnt_frame ( PADAPTER padapter , union recv_frame * precv_frame ) ;
sint validate_recv_mgnt_frame ( PADAPTER padapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
//struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2013-10-19 17:45:47 +00:00
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " +validate_recv_mgnt_frame \n " ) ) ;
2014-12-11 21:15:04 +00:00
#if 0
if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) = = _TRUE )
{
# ifdef CONFIG_NATIVEAP_MLME
mgt_dispatcher ( padapter , precv_frame ) ;
# else
rtw_hostapd_mlme_rx ( padapter , precv_frame ) ;
# endif
}
else
{
mgt_dispatcher ( padapter , precv_frame ) ;
}
# endif
2013-05-08 21:45:39 +00:00
precv_frame = recvframe_chk_defrag ( padapter , precv_frame ) ;
if ( precv_frame = = NULL ) {
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_notice_ , ( " %s: fragment packet \n " , __FUNCTION__ ) ) ;
2013-05-08 21:45:39 +00:00
return _SUCCESS ;
}
2014-12-11 21:15:04 +00:00
{
//for rx pkt statistics
struct sta_info * psta = rtw_get_stainfo ( & padapter - > stapriv , GetAddr2Ptr ( precv_frame - > u . hdr . rx_data ) ) ;
if ( psta ) {
psta - > sta_stats . rx_mgnt_pkts + + ;
if ( GetFrameSubType ( precv_frame - > u . hdr . rx_data ) = = WIFI_BEACON )
psta - > sta_stats . rx_beacon_pkts + + ;
else if ( GetFrameSubType ( precv_frame - > u . hdr . rx_data ) = = WIFI_PROBEREQ )
psta - > sta_stats . rx_probereq_pkts + + ;
else if ( GetFrameSubType ( precv_frame - > u . hdr . rx_data ) = = WIFI_PROBERSP ) {
if ( _rtw_memcmp ( padapter - > eeprompriv . mac_addr , GetAddr1Ptr ( precv_frame - > u . hdr . rx_data ) , ETH_ALEN ) = = _TRUE )
psta - > sta_stats . rx_probersp_pkts + + ;
else if ( is_broadcast_mac_addr ( GetAddr1Ptr ( precv_frame - > u . hdr . rx_data ) )
| | is_multicast_mac_addr ( GetAddr1Ptr ( precv_frame - > u . hdr . rx_data ) ) )
psta - > sta_stats . rx_probersp_bm_pkts + + ;
else
psta - > sta_stats . rx_probersp_uo_pkts + + ;
}
2013-05-08 21:45:39 +00:00
}
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_INTEL_PROXIM
if ( padapter - > proximity . proxim_on = = _TRUE )
{
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
struct recv_stat * prxstat = ( struct recv_stat * ) precv_frame - > u . hdr . rx_head ;
u8 * pda , * psa , * pbssid , * ptr ;
ptr = precv_frame - > u . hdr . rx_data ;
pda = get_da ( ptr ) ;
psa = get_sa ( ptr ) ;
pbssid = get_hdr_bssid ( ptr ) ;
_rtw_memcpy ( pattrib - > dst , pda , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > src , psa , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > bssid , pbssid , ETH_ALEN ) ;
switch ( pattrib - > to_fr_ds )
{
case 0 :
_rtw_memcpy ( pattrib - > ra , pda , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , psa , ETH_ALEN ) ;
break ;
case 1 :
_rtw_memcpy ( pattrib - > ra , pda , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , pbssid , ETH_ALEN ) ;
break ;
case 2 :
_rtw_memcpy ( pattrib - > ra , pbssid , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , psa , ETH_ALEN ) ;
break ;
case 3 :
_rtw_memcpy ( pattrib - > ra , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " case 3 \n " ) ) ;
break ;
default :
break ;
}
pattrib - > priority = 0 ;
pattrib - > hdrlen = pattrib - > to_fr_ds = = 3 ? 30 : 24 ;
padapter - > proximity . proxim_rx ( padapter , precv_frame ) ;
}
# endif
2013-05-08 21:45:39 +00:00
mgt_dispatcher ( padapter , precv_frame ) ;
return _SUCCESS ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
sint validate_recv_data_frame ( _adapter * adapter , union recv_frame * precv_frame ) ;
sint validate_recv_data_frame ( _adapter * adapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
u8 bretry ;
u8 * psa , * pda , * pbssid ;
struct sta_info * psta = NULL ;
u8 * ptr = precv_frame - > u . hdr . rx_data ;
2014-12-11 21:15:04 +00:00
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
struct sta_priv * pstapriv = & adapter - > stapriv ;
struct security_priv * psecuritypriv = & adapter - > securitypriv ;
sint ret = _SUCCESS ;
# ifdef CONFIG_TDLS
struct tdls_info * ptdlsinfo = & adapter - > tdlsinfo ;
# endif //CONFIG_TDLS
_func_enter_ ;
2013-05-08 21:45:39 +00:00
bretry = GetRetry ( ptr ) ;
pda = get_da ( ptr ) ;
psa = get_sa ( ptr ) ;
pbssid = get_hdr_bssid ( ptr ) ;
2014-12-11 21:15:04 +00:00
if ( pbssid = = NULL ) {
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s pbssid == NULL \n " , __func__ ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
_rtw_memcpy ( pattrib - > dst , pda , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > src , psa , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > bssid , pbssid , ETH_ALEN ) ;
switch ( pattrib - > to_fr_ds )
{
case 0 :
_rtw_memcpy ( pattrib - > ra , pda , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , psa , ETH_ALEN ) ;
ret = sta2sta_data_frame ( adapter , precv_frame , & psta ) ;
break ;
case 1 :
_rtw_memcpy ( pattrib - > ra , pda , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , pbssid , ETH_ALEN ) ;
ret = ap2sta_data_frame ( adapter , precv_frame , & psta ) ;
break ;
case 2 :
_rtw_memcpy ( pattrib - > ra , pbssid , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , psa , ETH_ALEN ) ;
ret = sta2ap_data_frame ( adapter , precv_frame , & psta ) ;
break ;
case 3 :
_rtw_memcpy ( pattrib - > ra , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
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
}
2014-12-11 21:15:04 +00:00
if ( ret = = _FAIL ) {
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s case:%d, res:%d \n " , __FUNCTION__ , pattrib - > to_fr_ds , ret ) ;
# endif
2013-05-08 21:45:39 +00:00
goto exit ;
} else if ( ret = = RTW_RX_HANDLED ) {
goto exit ;
}
2014-12-11 21:15:04 +00:00
if ( psta = = NULL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " after to_fr_ds_chk; psta==NULL \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s psta == NULL \n " , __func__ ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
//psta->rssi = prxcmd->rssi;
//psta->signal_quality= prxcmd->sq;
2013-05-08 21:45:39 +00:00
precv_frame - > u . hdr . psta = psta ;
2014-12-11 21:15:04 +00:00
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
pattrib - > amsdu = 0 ;
2013-05-08 21:45:39 +00:00
pattrib - > ack_policy = 0 ;
2014-12-11 21:15:04 +00:00
//parsing QC field
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 ) ) ;
2014-12-11 21:15:04 +00:00
pattrib - > hdrlen = pattrib - > to_fr_ds = = 3 ? 32 : 26 ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( pattrib - > priority ! = 0 & & pattrib - > priority ! = 3 )
{
adapter - > recvpriv . bIsAnyNonBEPkts = _TRUE ;
}
}
else
{
pattrib - > priority = 0 ;
pattrib - > hdrlen = pattrib - > to_fr_ds = = 3 ? 30 : 24 ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
if ( pattrib - > order ) //HT-CTRL 11n
{
2013-05-08 21:45:39 +00:00
pattrib - > hdrlen + = 4 ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
precv_frame - > u . hdr . preorder_ctrl = & psta - > recvreorder_ctrl [ pattrib - > priority ] ;
2014-12-11 21:15:04 +00:00
// decache, drop duplicate recv packets
if ( recv_decache ( precv_frame , bretry , & psta - > sta_recvpriv . rxcache ) = = _FAIL )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " decache : drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s recv_decache return _FAIL \n " , __func__ ) ;
# endif
ret = _FAIL ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
#if 0
if ( psta - > tdls_sta_state & TDLS_LINKED_STATE )
{
if ( psta - > dot118021XPrivacy = = _AES_ )
pattrib - > encrypt = psta - > dot118021XPrivacy ;
}
# endif //CONFIG_TDLS
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
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
if ( ( psta - > tdls_sta_state & TDLS_LINKED_STATE ) & & ( psta - > dot118021XPrivacy = = _AES_ ) )
{
pattrib - > encrypt = psta - > dot118021XPrivacy ;
}
else
# endif //CONFIG_TDLS
2013-05-08 21:45:39 +00:00
GET_ENCRY_ALGO ( psecuritypriv , psta , pattrib - > encrypt , IS_MCAST ( pattrib - > ra ) ) ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
}
else
{
2013-05-08 21:45:39 +00:00
pattrib - > encrypt = 0 ;
2014-12-11 21:15:04 +00:00
pattrib - > iv_len = pattrib - > icv_len = 0 ;
2013-05-08 21:45:39 +00:00
}
exit :
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_IEEE80211W
static sint validate_80211w_mgmt ( _adapter * adapter , union recv_frame * precv_frame )
{
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
u8 * ptr = precv_frame - > u . hdr . rx_data ;
u8 type ;
u8 subtype ;
type = GetFrameType ( ptr ) ;
subtype = GetFrameSubType ( ptr ) ; //bit(7)~bit(2)
//only support station mode
if ( check_fwstate ( pmlmepriv , WIFI_STATION_STATE ) & & check_fwstate ( pmlmepriv , _FW_LINKED )
& & adapter - > securitypriv . binstallBIPkey = = _TRUE )
{
//unicast management frame decrypt
if ( pattrib - > privacy & & ! ( IS_MCAST ( GetAddr1Ptr ( ptr ) ) ) & &
( subtype = = WIFI_DEAUTH | | subtype = = WIFI_DISASSOC | | subtype = = WIFI_ACTION ) )
{
u8 * ppp , * mgmt_DATA ;
u32 data_len = 0 ;
ppp = GetAddr2Ptr ( ptr ) ;
pattrib - > bdecrypted = 0 ;
pattrib - > encrypt = _AES_ ;
pattrib - > hdrlen = sizeof ( struct rtw_ieee80211_hdr_3addr ) ;
//set iv and icv length
SET_ICE_IV_LEN ( pattrib - > iv_len , pattrib - > icv_len , pattrib - > encrypt ) ;
_rtw_memcpy ( pattrib - > ra , GetAddr1Ptr ( ptr ) , ETH_ALEN ) ;
_rtw_memcpy ( pattrib - > ta , GetAddr2Ptr ( ptr ) , ETH_ALEN ) ;
//actual management data frame body
data_len = pattrib - > pkt_len - pattrib - > hdrlen - pattrib - > iv_len - pattrib - > icv_len ;
mgmt_DATA = rtw_zmalloc ( data_len ) ;
if ( mgmt_DATA = = NULL )
{
DBG_871X ( " %s mgmt allocate fail !!!!!!!!! \n " , __FUNCTION__ ) ;
goto validate_80211w_fail ;
}
/*//dump the packet content before decrypt
{
int pp ;
printk ( " pattrib->pktlen = %d => " , pattrib - > pkt_len ) ;
for ( pp = 0 ; pp < pattrib - > pkt_len ; pp + + )
printk ( " %02x " , ptr [ pp ] ) ;
printk ( " \n " ) ;
} */
precv_frame = decryptor ( adapter , precv_frame ) ;
//save actual management data frame body
_rtw_memcpy ( mgmt_DATA , ptr + pattrib - > hdrlen + pattrib - > iv_len , data_len ) ;
//overwrite the iv field
_rtw_memcpy ( ptr + pattrib - > hdrlen , mgmt_DATA , data_len ) ;
//remove the iv and icv length
pattrib - > pkt_len = pattrib - > pkt_len - pattrib - > iv_len - pattrib - > icv_len ;
rtw_mfree ( mgmt_DATA , data_len ) ;
/*//print packet content after decryption
{
int pp ;
printk ( " after decryption pattrib->pktlen = %d @@=> " , pattrib - > pkt_len ) ;
for ( pp = 0 ; pp < pattrib - > pkt_len ; pp + + )
printk ( " %02x " , ptr [ pp ] ) ;
printk ( " \n " ) ;
} */
if ( ! precv_frame )
{
DBG_871X ( " %s mgmt descrypt fail !!!!!!!!! \n " , __FUNCTION__ ) ;
goto validate_80211w_fail ;
}
}
else if ( IS_MCAST ( GetAddr1Ptr ( ptr ) ) & &
( subtype = = WIFI_DEAUTH | | subtype = = WIFI_DISASSOC ) )
{
sint BIP_ret = _SUCCESS ;
//verify BIP MME IE of broadcast/multicast de-auth/disassoc packet
BIP_ret = rtw_BIP_verify ( adapter , ( u8 * ) precv_frame ) ;
if ( BIP_ret = = _FAIL )
{
//DBG_871X("802.11w BIP verify fail\n");
goto validate_80211w_fail ;
}
else if ( BIP_ret = = RTW_RX_HANDLED )
{
//DBG_871X("802.11w recv none protected packet\n");
//issue sa query request
issue_action_SA_Query ( adapter , NULL , 0 , 0 ) ;
goto validate_80211w_fail ;
}
} //802.11w protect
else
{
if ( subtype = = WIFI_ACTION )
{
//according 802.11-2012 standard, these five types are not robust types
if ( ptr [ WLAN_HDR_A3_LEN ] ! = RTW_WLAN_CATEGORY_PUBLIC & &
ptr [ WLAN_HDR_A3_LEN ] ! = RTW_WLAN_CATEGORY_HT & &
ptr [ WLAN_HDR_A3_LEN ] ! = RTW_WLAN_CATEGORY_UNPROTECTED_WNM & &
ptr [ WLAN_HDR_A3_LEN ] ! = RTW_WLAN_CATEGORY_SELF_PROTECTED & &
ptr [ WLAN_HDR_A3_LEN ] ! = RTW_WLAN_CATEGORY_P2P )
{
DBG_871X ( " action frame category=%d should robust \n " , ptr [ WLAN_HDR_A3_LEN ] ) ;
goto validate_80211w_fail ;
}
}
else if ( subtype = = WIFI_DEAUTH | | subtype = = WIFI_DISASSOC )
{
DBG_871X ( " 802.11w recv none protected packet \n " ) ;
//issue sa query request
issue_action_SA_Query ( adapter , NULL , 0 , 0 ) ;
goto validate_80211w_fail ;
}
}
}
return _SUCCESS ;
validate_80211w_fail :
return _FAIL ;
}
# endif //CONFIG_IEEE80211W
sint validate_recv_frame ( _adapter * adapter , union recv_frame * precv_frame ) ;
sint validate_recv_frame ( _adapter * adapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
//shall check frame subtype, to / from ds, da, bssid
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//then call check if rx seq/frag. duplicated.
2013-05-08 21:45:39 +00:00
u8 type ;
u8 subtype ;
2014-12-11 21:15:04 +00:00
sint retval = _SUCCESS ;
struct rx_pkt_attrib * pattrib = & precv_frame - > u . hdr . attrib ;
2013-05-08 21:45:39 +00:00
u8 * ptr = precv_frame - > u . hdr . rx_data ;
2014-12-11 21:15:04 +00:00
u8 ver = ( unsigned char ) ( * ptr ) & 0x3 ;
# ifdef CONFIG_FIND_BEST_CHANNEL
2013-05-08 21:45:39 +00:00
struct mlme_ext_priv * pmlmeext = & adapter - > mlmeextpriv ;
2014-12-11 21:15:04 +00:00
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
struct tdls_info * ptdlsinfo = & adapter - > tdlsinfo ;
# endif //CONFIG_TDLS
# ifdef CONFIG_WAPI_SUPPORT
PRT_WAPI_T pWapiInfo = & adapter - > wapiInfo ;
struct recv_frame_hdr * phdr = & precv_frame - > u . hdr ;
u8 wai_pkt = 0 ;
u16 sc ;
u8 external_len = 0 ;
# endif
_func_enter_ ;
# ifdef CONFIG_FIND_BEST_CHANNEL
2013-05-08 21:45:39 +00:00
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 + + ;
}
2014-12-11 21:15:04 +00:00
# endif
# ifdef CONFIG_TDLS
if ( ptdlsinfo - > ch_sensing = = 1 & & ptdlsinfo - > cur_channel ! = 0 ) {
ptdlsinfo - > collect_pkt_num [ ptdlsinfo - > cur_channel - 1 ] + + ;
}
# endif //CONFIG_TDLS
# ifdef RTK_DMP_PLATFORM
if ( 0 )
{
DBG_871X ( " ++ \n " ) ;
{
int i ;
for ( i = 0 ; i < 64 ; i = i + 8 )
DBG_871X ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: " , * ( ptr + i ) ,
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
}
DBG_871X ( " -- \n " ) ;
}
# endif //RTK_DMP_PLATFORM
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//add version chk
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 ) ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_WAPI_SUPPORT
sc = ( pattrib - > seq_num < < 4 ) | pattrib - > frag_num ;
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# if 1 //Dump rx packets
{
u8 bDumpRxPkt ;
2013-05-08 21:45:39 +00:00
rtw_hal_get_def_var ( adapter , HAL_DEF_DBG_DUMP_RXPKT , & ( bDumpRxPkt ) ) ;
2014-12-11 21:15:04 +00:00
if ( bDumpRxPkt = = 1 ) { //dump all rx packets
2013-05-08 21:45:39 +00:00
int i ;
2014-12-11 21:15:04 +00:00
DBG_871X ( " ############################# \n " ) ;
for ( i = 0 ; i < 64 ; i = i + 8 )
DBG_871X ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: \n " , * ( ptr + i ) ,
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
DBG_871X ( " ############################# \n " ) ;
}
else if ( bDumpRxPkt = = 2 ) {
if ( type = = WIFI_MGT_TYPE ) {
2013-05-08 21:45:39 +00:00
int i ;
2014-12-11 21:15:04 +00:00
DBG_871X ( " ############################# \n " ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
for ( i = 0 ; i < 64 ; i = i + 8 )
DBG_871X ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: \n " , * ( ptr + i ) ,
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
DBG_871X ( " ############################# \n " ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
}
else if ( bDumpRxPkt = = 3 ) {
if ( type = = WIFI_DATA_TYPE ) {
2013-05-08 21:45:39 +00:00
int i ;
2014-12-11 21:15:04 +00:00
DBG_871X ( " ############################# \n " ) ;
for ( i = 0 ; i < 64 ; i = i + 8 )
DBG_871X ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: \n " , * ( ptr + i ) ,
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
DBG_871X ( " ############################# \n " ) ;
}
2013-05-08 21:45:39 +00:00
}
}
2014-12-11 21:15:04 +00:00
# endif
switch ( type )
{
case WIFI_MGT_TYPE : //mgnt
# ifdef CONFIG_IEEE80211W
if ( validate_80211w_mgmt ( adapter , precv_frame ) = = _FAIL )
{
retval = _FAIL ;
break ;
}
# endif //CONFIG_IEEE80211W
retval = validate_recv_mgnt_frame ( adapter , precv_frame ) ;
if ( retval = = _FAIL )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_mgnt_frame fail \n " ) ) ;
}
retval = _FAIL ; // only data frame return _SUCCESS
break ;
case WIFI_CTRL_TYPE : //ctrl
retval = validate_recv_ctrl_frame ( adapter , precv_frame ) ;
if ( retval = = _FAIL )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_ctrl_frame fail \n " ) ) ;
}
retval = _FAIL ; // only data frame return _SUCCESS
break ;
case WIFI_DATA_TYPE : //data
# ifdef CONFIG_WAPI_SUPPORT
if ( pattrib - > qos )
external_len = 2 ;
else
external_len = 0 ;
wai_pkt = rtw_wapi_is_wai_packet ( adapter , ptr ) ;
phdr - > bIsWaiPacket = wai_pkt ;
if ( wai_pkt ! = 0 ) {
if ( sc ! = adapter - > wapiInfo . wapiSeqnumAndFragNum )
{
adapter - > wapiInfo . wapiSeqnumAndFragNum = sc ;
}
else
{
retval = _FAIL ;
break ;
}
}
else {
if ( rtw_wapi_drop_for_key_absent ( adapter , GetAddr2Ptr ( ptr ) ) ) {
retval = _FAIL ;
WAPI_TRACE ( WAPI_RX , " drop for key absent for rx \n " ) ;
break ;
}
}
# endif
rtw_led_control ( adapter , LED_CTL_RX ) ;
pattrib - > qos = ( subtype & BIT ( 7 ) ) ? 1 : 0 ;
retval = validate_recv_data_frame ( adapter , precv_frame ) ;
if ( retval = = _FAIL )
{
struct recv_priv * precvpriv = & adapter - > recvpriv ;
//RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail\n"));
precvpriv - > rx_drop + + ;
}
break ;
default :
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " validate_recv_data_frame fail! type=0x%x \n " , type ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME validate_recv_data_frame fail! type=0x%x \n " , type ) ;
# endif
retval = _FAIL ;
break ;
}
exit :
_func_exit_ ;
return retval ;
}
//remove the wlanhdr and add the eth_hdr
# if 1
sint wlanhdr_to_ethhdr ( union recv_frame * precvframe ) ;
sint wlanhdr_to_ethhdr ( union recv_frame * precvframe )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
sint rmv_len ;
2013-05-08 21:45:39 +00:00
u16 eth_type , len ;
u8 bsnaphdr ;
u8 * psnap_type ;
struct ieee80211_snap_hdr * psnap ;
2014-12-11 21:15:04 +00:00
sint ret = _SUCCESS ;
_adapter * adapter = precvframe - > u . hdr . adapter ;
2013-05-08 21:45:39 +00:00
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
2014-12-11 21:15:04 +00:00
u8 * ptr = get_recvframe_data ( precvframe ) ; // point to frame_ctrl field
struct rx_pkt_attrib * pattrib = & precvframe - > u . hdr . attrib ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
_func_enter_ ;
if ( pattrib - > encrypt ) {
recvframe_pull_tail ( precvframe , pattrib - > icv_len ) ;
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
//eth_type = (psnap_type[0] << 8) | psnap_type[1];
if ( ( _rtw_memcmp ( psnap , rtw_rfc1042_header , SNAP_SIZE ) & &
( _rtw_memcmp ( psnap_type , SNAP_ETH_TYPE_IPX , 2 ) = = _FALSE ) & &
( _rtw_memcmp ( psnap_type , SNAP_ETH_TYPE_APPLETALK_AARP , 2 ) = = _FALSE ) ) | |
//eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
_rtw_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 */
2014-12-11 21:15:04 +00:00
bsnaphdr = _TRUE ;
}
else {
2013-05-08 21:45:39 +00:00
/* Leave Ethernet header part of hdr and full payload */
2014-12-11 21:15:04 +00:00
bsnaphdr = _FALSE ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
rmv_len = pattrib - > hdrlen + pattrib - > iv_len + ( bsnaphdr ? SNAP_SIZE : 0 ) ;
2013-05-08 21:45:39 +00:00
len = precvframe - > u . hdr . len - rmv_len ;
2014-12-11 21:15:04 +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
2014-12-11 21:15:04 +00:00
_rtw_memcpy ( & eth_type , ptr + rmv_len , 2 ) ;
eth_type = ntohs ( ( unsigned short ) eth_type ) ; //pattrib->ether_type
2013-05-08 21:45:39 +00:00
pattrib - > eth_type = eth_type ;
2014-12-11 21:15:04 +00:00
if ( ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) = = _TRUE ) )
{
ptr + = rmv_len ;
2013-05-08 21:45:39 +00:00
* ptr = 0x87 ;
* ( ptr + 1 ) = 0x12 ;
eth_type = 0x8712 ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
_rtw_memcpy ( ptr , get_rxmem ( precvframe ) , 24 ) ;
ptr + = 24 ;
}
else {
ptr = recvframe_pull ( precvframe , ( rmv_len - sizeof ( struct ethhdr ) + ( bsnaphdr ? 2 : 0 ) ) ) ;
}
_rtw_memcpy ( ptr , pattrib - > dst , ETH_ALEN ) ;
_rtw_memcpy ( ptr + ETH_ALEN , pattrib - > src , ETH_ALEN ) ;
if ( ! bsnaphdr ) {
len = htons ( len ) ;
_rtw_memcpy ( ptr + 12 , & len , 2 ) ;
}
_func_exit_ ;
return ret ;
}
# else
sint wlanhdr_to_ethhdr ( union recv_frame * precvframe )
{
sint rmv_len ;
u16 eth_type ;
u8 bsnaphdr ;
u8 * psnap_type ;
struct ieee80211_snap_hdr * psnap ;
sint ret = _SUCCESS ;
_adapter * adapter = precvframe - > u . hdr . adapter ;
struct mlme_priv * pmlmepriv = & adapter - > mlmepriv ;
u8 * ptr = get_recvframe_data ( precvframe ) ; // point to frame_ctrl field
struct rx_pkt_attrib * pattrib = & precvframe - > u . hdr . attrib ;
struct _vlan * pvlan = NULL ;
_func_enter_ ;
psnap = ( struct ieee80211_snap_hdr * ) ( ptr + pattrib - > hdrlen + pattrib - > iv_len ) ;
psnap_type = ptr + pattrib - > hdrlen + pattrib - > iv_len + SNAP_SIZE ;
if ( psnap - > dsap = = 0xaa & & psnap - > ssap = = 0xaa & & psnap - > ctrl = = 0x03 )
{
if ( _rtw_memcmp ( psnap - > oui , oui_rfc1042 , WLAN_IEEE_OUI_LEN ) )
bsnaphdr = _TRUE ; //wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042;
else if ( _rtw_memcmp ( psnap - > oui , SNAP_HDR_APPLETALK_DDP , WLAN_IEEE_OUI_LEN ) & &
_rtw_memcmp ( psnap_type , SNAP_ETH_TYPE_APPLETALK_DDP , 2 ) )
bsnaphdr = _TRUE ; //wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK;
else if ( _rtw_memcmp ( psnap - > oui , oui_8021h , WLAN_IEEE_OUI_LEN ) )
bsnaphdr = _TRUE ; //wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL;
else {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " drop pkt due to invalid frame format! \n " ) ) ;
ret = _FAIL ;
goto exit ;
}
} else
bsnaphdr = _FALSE ; //wlan_pkt_format = WLAN_PKT_FORMAT_OTHERS;
rmv_len = pattrib - > hdrlen + pattrib - > iv_len + ( bsnaphdr ? SNAP_SIZE : 0 ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " ===pattrib->hdrlen: %x, pattrib->iv_len:%x === \n " , pattrib - > hdrlen , pattrib - > iv_len ) ) ;
if ( check_fwstate ( pmlmepriv , WIFI_MP_STATE ) = = _TRUE )
{
ptr + = rmv_len ;
* ptr = 0x87 ;
* ( ptr + 1 ) = 0x12 ;
//back to original pointer
ptr - = rmv_len ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
ptr + = rmv_len ;
_rtw_memcpy ( & eth_type , ptr , 2 ) ;
eth_type = ntohs ( ( unsigned short ) eth_type ) ; //pattrib->ether_type
ptr + = 2 ;
if ( pattrib - > encrypt ) {
recvframe_pull_tail ( precvframe , pattrib - > icv_len ) ;
}
if ( eth_type = = 0x8100 ) //vlan
{
pvlan = ( struct _vlan * ) ptr ;
//eth_type = get_vlan_encap_proto(pvlan);
//eth_type = pvlan->h_vlan_encapsulated_proto;//?
rmv_len + = 4 ;
ptr + = 4 ;
}
if ( eth_type = = 0x0800 ) //ip
{
//struct iphdr* piphdr = (struct iphdr*) ptr;
//__u8 tos = (unsigned char)(pattrib->priority & 0xff);
//piphdr->tos = tos;
//if (piphdr->protocol == 0x06)
//{
// RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("@@@===recv tcp len:%d @@@===\n", precvframe->u.hdr.len));
//}
}
else if ( eth_type = = 0x8712 ) // append rx status for mp test packets
{
//ptr -= 16;
//_rtw_memcpy(ptr, get_rxmem(precvframe), 16);
}
else
{
# ifdef PLATFORM_OS_XP
NDIS_PACKET_8021Q_INFO VlanPriInfo ;
UINT32 UserPriority = precvframe - > u . hdr . attrib . priority ;
UINT32 VlanID = ( pvlan ! = NULL ? get_vlan_id ( pvlan ) : 0 ) ;
VlanPriInfo . Value = // Get current value.
NDIS_PER_PACKET_INFO_FROM_PACKET ( precvframe - > u . hdr . pkt , Ieee8021QInfo ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
VlanPriInfo . TagHeader . UserPriority = UserPriority ;
VlanPriInfo . TagHeader . VlanId = VlanID ;
VlanPriInfo . TagHeader . CanonicalFormatId = 0 ; // Should be zero.
VlanPriInfo . TagHeader . Reserved = 0 ; // Should be zero.
NDIS_PER_PACKET_INFO_FROM_PACKET ( precvframe - > u . hdr . pkt , Ieee8021QInfo ) = VlanPriInfo . Value ;
# endif
}
if ( eth_type = = 0x8712 ) // append rx status for mp test packets
{
ptr = recvframe_pull ( precvframe , ( rmv_len - sizeof ( struct ethhdr ) + 2 ) - 24 ) ;
_rtw_memcpy ( ptr , get_rxmem ( precvframe ) , 24 ) ;
ptr + = 24 ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
else
ptr = recvframe_pull ( precvframe , ( rmv_len - sizeof ( struct ethhdr ) + 2 ) ) ;
_rtw_memcpy ( ptr , pattrib - > dst , ETH_ALEN ) ;
_rtw_memcpy ( ptr + ETH_ALEN , pattrib - > src , ETH_ALEN ) ;
eth_type = htons ( ( unsigned short ) eth_type ) ;
_rtw_memcpy ( ptr + 12 , & eth_type , 2 ) ;
exit :
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
}
2014-12-11 21:15:04 +00:00
# endif
# if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
# ifdef PLATFORM_LINUX
static void recvframe_expand_pkt (
PADAPTER padapter ,
union recv_frame * prframe )
{
struct recv_frame_hdr * pfhdr ;
_pkt * ppkt ;
u8 shift_sz ;
u32 alloc_sz ;
pfhdr = & prframe - > u . hdr ;
// 6 is for IP header 8 bytes alignment in QoS packet case.
if ( pfhdr - > attrib . qos )
shift_sz = 6 ;
else
shift_sz = 0 ;
// for first fragment packet, need to allocate
// (1536 + RXDESC_SIZE + drvinfo_sz) to reassemble packet
// 8 is for skb->data 8 bytes alignment.
// alloc_sz = _RND(1536 + RXDESC_SIZE + pfhdr->attrib.drvinfosize + shift_sz + 8, 128);
alloc_sz = 1664 ; // round (1536 + 24 + 32 + shift_sz + 8) to 128 bytes alignment
//3 1. alloc new skb
// prepare extra space for 4 bytes alignment
ppkt = rtw_skb_alloc ( alloc_sz ) ;
if ( ! ppkt ) return ; // no way to expand
//3 2. Prepare new skb to replace & release old skb
// force ppkt->data at 8-byte alignment address
skb_reserve ( ppkt , 8 - ( ( SIZE_PTR ) ppkt - > data & 7 ) ) ;
// force ip_hdr at 8-byte alignment address according to shift_sz
skb_reserve ( ppkt , shift_sz ) ;
// copy data to new pkt
_rtw_memcpy ( skb_put ( ppkt , pfhdr - > len ) , pfhdr - > rx_data , pfhdr - > len ) ;
rtw_skb_free ( pfhdr - > pkt ) ;
// attach new pkt to recvframe
pfhdr - > pkt = ppkt ;
pfhdr - > rx_head = ppkt - > head ;
pfhdr - > rx_data = ppkt - > data ;
pfhdr - > rx_tail = skb_tail_pointer ( ppkt ) ;
pfhdr - > rx_end = skb_end_pointer ( ppkt ) ;
}
# else
# warning "recvframe_expand_pkt not implement, defrag may crash system"
# endif
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//perform defrag
union recv_frame * recvframe_defrag ( _adapter * adapter , _queue * defrag_q ) ;
union recv_frame * recvframe_defrag ( _adapter * adapter , _queue * defrag_q )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_list * plist , * phead ;
u8 * data , wlanhdr_offset ;
2013-05-08 21:45:39 +00:00
u8 curfragnum ;
2014-12-11 21:15:04 +00:00
struct recv_frame_hdr * pfhdr , * pnfhdr ;
union recv_frame * prframe , * pnextrframe ;
_queue * pfree_recv_queue ;
_func_enter_ ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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 ) ;
plist = get_next ( phead ) ;
prframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
2014-12-11 21:15:04 +00:00
pfhdr = & prframe - > u . hdr ;
2013-05-08 21:45:39 +00:00
rtw_list_delete ( & ( prframe - > u . list ) ) ;
2014-12-11 21:15:04 +00:00
if ( curfragnum ! = pfhdr - > attrib . frag_num )
{
//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 ;
}
2014-12-11 21:15:04 +00:00
# if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
# ifndef CONFIG_SDIO_RX_COPY
recvframe_expand_pkt ( adapter , prframe ) ;
# endif
# endif
2013-05-08 21:45:39 +00:00
curfragnum + + ;
2014-12-11 21:15:04 +00:00
plist = get_list_head ( defrag_q ) ;
2013-05-08 21:45:39 +00:00
plist = get_next ( plist ) ;
2014-12-11 21:15:04 +00:00
data = get_recvframe_data ( prframe ) ;
while ( rtw_end_of_queue_search ( phead , plist ) = = _FALSE )
{
2013-05-08 21:45:39 +00:00
pnextrframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
2014-12-11 21:15:04 +00:00
pnfhdr = & pnextrframe - > u . hdr ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//check the fragment sequence (2nd ~n fragment frame)
if ( curfragnum ! = pnfhdr - > attrib . frag_num )
{
//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 + + ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
//memcpy
_rtw_memcpy ( pfhdr - > rx_tail , pnfhdr - > rx_data , pnfhdr - > len ) ;
2013-05-08 21:45:39 +00:00
recvframe_put ( prframe , pnfhdr - > len ) ;
2014-12-11 21:15:04 +00:00
pfhdr - > attrib . icv_len = pnfhdr - > attrib . icv_len ;
2013-05-08 21:45:39 +00:00
plist = get_next ( plist ) ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " Performance defrag!!!!! \n " ) ) ;
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return prframe ;
}
2014-12-11 21:15:04 +00:00
//check if need to defrag, if needed queue the frame to defrag_q
union recv_frame * recvframe_chk_defrag ( PADAPTER padapter , union recv_frame * precv_frame )
2013-05-08 21:45:39 +00:00
{
u8 ismfrag ;
u8 fragnum ;
u8 * psta_addr ;
struct recv_frame_hdr * pfhdr ;
struct sta_info * psta ;
struct sta_priv * pstapriv ;
2014-12-11 21:15:04 +00:00
_list * phead ;
2013-05-08 21:45:39 +00:00
union recv_frame * prtnframe = NULL ;
2014-12-11 21:15:04 +00:00
_queue * pfree_recv_queue , * pdefrag_q ;
_func_enter_ ;
2013-05-08 21:45:39 +00:00
pstapriv = & padapter - > stapriv ;
pfhdr = & precv_frame - > u . hdr ;
pfree_recv_queue = & padapter - > recvpriv . free_recv_queue ;
2014-12-11 21:15:04 +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 ) ;
2014-12-11 21:15:04 +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 ;
2014-12-11 21:15:04 +00:00
} else
2013-05-08 21:45:39 +00:00
pdefrag_q = NULL ;
2013-08-01 02:43:28 +00:00
}
2014-12-11 21:15:04 +00:00
else
pdefrag_q = & psta - > sta_recvpriv . defrag_q ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( ( ismfrag = = 0 ) & & ( fragnum = = 0 ) )
{
prtnframe = precv_frame ; //isn't a fragment frame
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( ismfrag = = 1 )
{
//0~(n-1) fragment frame
//enqueue to defraf_g
if ( pdefrag_q ! = NULL )
{
if ( fragnum = = 0 )
{
//the first fragment
if ( _rtw_queue_empty ( pdefrag_q ) = = _FALSE )
{
//free current defrag_q
2013-05-08 21:45:39 +00:00
rtw_free_recvframe_queue ( pdefrag_q , pfree_recv_queue ) ;
}
}
2014-12-11 21:15:04 +00:00
//Then enqueue the 0~(n-1) fragment into the defrag_q
//_rtw_spinlock(&pdefrag_q->lock);
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pdefrag_q ) ;
rtw_list_insert_tail ( & pfhdr - > list , phead ) ;
2014-12-11 21:15:04 +00:00
//_rtw_spinunlock(&pdefrag_q->lock);
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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
2014-12-11 21:15:04 +00:00
prtnframe = NULL ;
}
else
{
//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 ) ;
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
if ( ( ismfrag = = 0 ) & & ( fragnum ! = 0 ) )
{
//the last fragment frame
//enqueue the last fragment
if ( pdefrag_q ! = NULL )
{
//_rtw_spinlock(&pdefrag_q->lock);
2013-05-08 21:45:39 +00:00
phead = get_list_head ( pdefrag_q ) ;
2014-12-11 21:15:04 +00:00
rtw_list_insert_tail ( & pfhdr - > list , phead ) ;
//_rtw_spinunlock(&pdefrag_q->lock);
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//call recvframe_defrag to defrag
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 ) ;
2014-12-11 21:15:04 +00:00
prtnframe = precv_frame ;
}
else
{
//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 ) ;
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
if ( ( prtnframe ! = NULL ) & & ( prtnframe - > u . hdr . attrib . privacy ) )
{
//after defrag we must check tkip mic code
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
}
}
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return prtnframe ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# define ENDIAN_FREE 1
int amsdu_to_msdu ( _adapter * padapter , union recv_frame * prframe ) ;
int amsdu_to_msdu ( _adapter * padapter , union recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
# if defined (PLATFORM_LINUX) || defined (PLATFORM_FREEBSD) //for amsdu TP improvement,Creator: Thomas
2013-05-08 21:45:39 +00:00
int a_len , padding_len ;
2014-12-11 21:15:04 +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 ;
2014-12-11 21:15:04 +00:00
# ifndef PLATFORM_FREEBSD
2013-05-08 21:45:39 +00:00
unsigned char * data_ptr ;
2014-12-11 21:15:04 +00:00
_pkt * sub_skb , * subframes [ MAX_SUBFRAME_COUNT ] ;
# endif //PLATFORM_FREEBSD
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2014-12-11 21:15:04 +00:00
_queue * pfree_recv_queue = & ( precvpriv - > free_recv_queue ) ;
2013-05-08 21:45:39 +00:00
int ret = _SUCCESS ;
2014-12-11 21:15:04 +00:00
# ifdef PLATFORM_FREEBSD
struct mbuf * sub_m = NULL , * subframes [ MAX_SUBFRAME_COUNT ] ;
u8 * ptr , offset ;
# endif //PLATFORM_FREEBSD
2013-05-08 21:45:39 +00:00
nr_subframes = 0 ;
2014-12-11 21:15:04 +00:00
pattrib = & prframe - > u . hdr . attrib ;
recvframe_pull ( prframe , prframe - > u . hdr . attrib . hdrlen ) ;
if ( prframe - > u . hdr . attrib . iv_len > 0 )
{
recvframe_pull ( prframe , prframe - > u . hdr . attrib . iv_len ) ;
}
a_len = prframe - > u . hdr . len ;
pdata = prframe - > u . hdr . rx_data ;
while ( a_len > ETH_HLEN ) {
/* Offset 12 denote 2 mac address */
# ifdef ENDIAN_FREE
//nSubframe_Length = ntohs(*((u16*)(pdata + 12)));
nSubframe_Length = RTW_GET_BE16 ( pdata + 12 ) ;
# else // ENDIAN_FREE
nSubframe_Length = * ( ( u16 * ) ( pdata + 12 ) ) ;
//==m==>change the length order
nSubframe_Length = ( nSubframe_Length > > 8 ) + ( nSubframe_Length < < 8 ) ;
//ntohs(nSubframe_Length);
# endif // ENDIAN_FREE
if ( a_len < ( ETHERNET_HEADER_SIZE + nSubframe_Length ) ) {
DBG_871X ( " nRemain_Length is %d and nSubframe_Length is : %d \n " , a_len , nSubframe_Length ) ;
goto exit ;
}
# ifndef PLATFORM_FREEBSD
/* move the data point to data content */
pdata + = ETH_HLEN ;
a_len - = ETH_HLEN ;
/* Allocate new skb for releasing to upper layer */
# ifdef CONFIG_SKB_COPY
sub_skb = rtw_skb_alloc ( nSubframe_Length + 12 ) ;
if ( sub_skb )
{
skb_reserve ( sub_skb , 12 ) ;
data_ptr = ( u8 * ) skb_put ( sub_skb , nSubframe_Length ) ;
_rtw_memcpy ( data_ptr , pdata , nSubframe_Length ) ;
}
else
# endif // CONFIG_SKB_COPY
{
sub_skb = rtw_skb_clone ( prframe - > u . hdr . pkt ) ;
if ( sub_skb )
{
sub_skb - > data = pdata ;
sub_skb - > len = nSubframe_Length ;
skb_set_tail_pointer ( sub_skb , nSubframe_Length ) ;
}
else
{
DBG_871X ( " rtw_skb_clone() Fail!!! , nr_subframes = %d \n " , nr_subframes ) ;
break ;
}
}
# else // PLATFORM_FREEBSD
//PLATFORM_FREEBSD
//Allocate a mbuff,
//sub_m =m_devget(pdata, nSubframe_Length+12, 12, padapter->pifp,NULL);
sub_m = m_devget ( pdata , nSubframe_Length + ETH_HLEN , ETHER_ALIGN , padapter - > pifp , NULL ) ;
pdata + = ETH_HLEN ;
a_len - = ETH_HLEN ;
# endif // PLATFORM_FREEBSD
# ifndef PLATFORM_FREEBSD
//sub_skb->dev = padapter->pnetdev;
subframes [ nr_subframes + + ] = sub_skb ;
# else //PLATFORM_FREEBSD
//PLATFORM_FREEBSD
subframes [ nr_subframes + + ] = sub_m ;
# endif //PLATFORM_FREEBSD
if ( nr_subframes > = MAX_SUBFRAME_COUNT ) {
DBG_871X ( " ParseSubframe(): Too many Subframes! Packets dropped! \n " ) ;
break ;
}
pdata + = nSubframe_Length ;
a_len - = nSubframe_Length ;
if ( a_len ! = 0 ) {
padding_len = 4 - ( ( nSubframe_Length + ETH_HLEN ) & ( 4 - 1 ) ) ;
if ( padding_len = = 4 ) {
padding_len = 0 ;
}
if ( a_len < padding_len ) {
goto exit ;
}
pdata + = padding_len ;
a_len - = padding_len ;
}
}
for ( i = 0 ; i < nr_subframes ; i + + ) {
# ifndef PLATFORM_FREEBSD
sub_skb = subframes [ i ] ;
/* convert hdr + possible LLC headers into Ethernet header */
# ifdef ENDIAN_FREE
//eth_type = ntohs(*(u16*)&sub_skb->data[6]);
eth_type = RTW_GET_BE16 ( & sub_skb - > data [ 6 ] ) ;
# else // ENDIAN_FREE
eth_type = ( sub_skb - > data [ 6 ] < < 8 ) | sub_skb - > data [ 7 ] ;
# endif // ENDIAN_FREE
if ( sub_skb - > len > = 8 & &
( ( _rtw_memcmp ( sub_skb - > data , rtw_rfc1042_header , SNAP_SIZE ) & &
eth_type ! = ETH_P_AARP & & eth_type ! = ETH_P_IPX ) | |
_rtw_memcmp ( sub_skb - > data , rtw_bridge_tunnel_header , SNAP_SIZE ) ) ) {
/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
skb_pull ( sub_skb , SNAP_SIZE ) ;
_rtw_memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > src , ETH_ALEN ) ;
_rtw_memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > dst , ETH_ALEN ) ;
} else {
u16 len ;
/* Leave Ethernet header part of hdr and full payload */
len = htons ( sub_skb - > len ) ;
_rtw_memcpy ( skb_push ( sub_skb , 2 ) , & len , 2 ) ;
_rtw_memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > src , ETH_ALEN ) ;
_rtw_memcpy ( skb_push ( sub_skb , ETH_ALEN ) , pattrib - > dst , ETH_ALEN ) ;
}
/* Indicat the packets to upper layer */
if ( sub_skb ) {
//memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
# ifdef CONFIG_BR_EXT
// Insert NAT2.5 RX here!
struct mlme_priv * pmlmepriv = & padapter - > mlmepriv ;
void * br_port = NULL ;
# if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
br_port = padapter - > pnetdev - > br_port ;
# else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
rcu_read_lock ( ) ;
br_port = rcu_dereference ( padapter - > pnetdev - > rx_handler_data ) ;
rcu_read_unlock ( ) ;
# endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
if ( br_port & & ( check_fwstate ( pmlmepriv , WIFI_STATION_STATE | WIFI_ADHOC_STATE ) = = _TRUE ) )
{
int nat25_handle_frame ( _adapter * priv , struct sk_buff * skb ) ;
if ( nat25_handle_frame ( padapter , sub_skb ) = = - 1 ) {
//priv->ext_stats.rx_data_drops++;
//DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n");
//return FAIL;
# if 1
// bypass this frame to upper layer!!
# else
rtw_skb_free ( sub_skb ) ;
continue ;
# endif
}
}
# endif // CONFIG_BR_EXT
sub_skb - > protocol = eth_type_trans ( sub_skb , padapter - > pnetdev ) ;
sub_skb - > dev = padapter - > pnetdev ;
# ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
if ( ( pattrib - > tcpchk_valid = = 1 ) & & ( pattrib - > tcp_chkrpt = = 1 ) ) {
sub_skb - > ip_summed = CHECKSUM_UNNECESSARY ;
} else {
sub_skb - > ip_summed = CHECKSUM_NONE ;
}
# else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
sub_skb - > ip_summed = CHECKSUM_NONE ;
# endif //CONFIG_TCP_CSUM_OFFLOAD_RX
rtw_netif_rx ( padapter - > pnetdev , sub_skb ) ;
}
# else //PLATFORM_FREEBSD
//PLATFORM_FREEBSD
sub_m = subframes [ i ] ;
ptr = mtod ( sub_m , u8 * ) ;
offset = ETH_HLEN ;
/* convert hdr + possible LLC headers into Ethernet header */
# ifdef ENDIAN_FREE
eth_type = ntohs ( * ( u16 * ) & ptr [ offset + 6 ] ) ;
# else // ENDIAN_FREE
eth_type = ( ptr [ offset + 6 ] < < 8 ) | ptr [ offset + 7 ] ;
# endif // ENDIAN_FREE
if ( sub_m - > m_pkthdr . len > = ETH_HLEN + 8 & &
( ( _rtw_memcmp ( ptr + ETH_HLEN , rtw_rfc1042_header , SNAP_SIZE ) & &
eth_type ! = ETH_P_AARP & & eth_type ! = ETH_P_IPX ) | |
_rtw_memcmp ( ptr + ETH_HLEN , rtw_bridge_tunnel_header , SNAP_SIZE ) ) ) {
/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
offset + = SNAP_SIZE ;
_rtw_memcpy ( & ptr [ offset - ETH_ALEN ] , pattrib - > src , ETH_ALEN ) ;
offset - = ETH_ALEN ;
_rtw_memcpy ( & ptr [ offset - ETH_ALEN ] , pattrib - > dst , ETH_ALEN ) ;
offset - = ETH_ALEN ;
} else {
u16 len ;
/* Leave Ethernet header part of hdr and full payload */
len = htons ( sub_m - > m_pkthdr . len - offset ) ;
_rtw_memcpy ( & ptr [ offset - 2 ] , & len , 2 ) ;
offset - = 2 ;
_rtw_memcpy ( & ptr [ offset - ETH_ALEN ] , pattrib - > src , ETH_ALEN ) ;
offset - = ETH_ALEN ;
_rtw_memcpy ( & ptr [ offset - ETH_ALEN ] , pattrib - > dst , ETH_ALEN ) ;
offset - = ETH_ALEN ;
}
m_adj ( sub_m , offset ) ;
/* Indicat the packets to upper layer */
if ( sub_m ) {
#if 0
# ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
if ( ( pattrib - > tcpchk_valid = = 1 ) & & ( pattrib - > tcp_chkrpt = = 1 ) ) {
sub_skb - > ip_summed = CHECKSUM_UNNECESSARY ;
} else {
sub_skb - > ip_summed = CHECKSUM_NONE ;
}
# else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
sub_skb - > ip_summed = CHECKSUM_NONE ;
# endif //CONFIG_TCP_CSUM_OFFLOAD_RX
# endif //0
if ( ( ( u32 ) ( mtod ( sub_m , caddr_t ) + 14 ) % 4 ) ! = 0 )
printf ( " %s()-%d: mtod(sub_m) = %p \n " , __FUNCTION__ , __LINE__ , mtod ( sub_m , caddr_t ) ) ;
# ifdef CONFIG_RX_INDICATE_QUEUE
IF_ENQUEUE ( & precvpriv - > rx_indicate_queue , sub_m ) ;
if ( _IF_QLEN ( & precvpriv - > rx_indicate_queue ) < = 1 ) {
taskqueue_enqueue ( taskqueue_thread , & precvpriv - > rx_indicate_tasklet ) ;
}
# else // CONFIG_RX_INDICATE_QUEUE
( * padapter - > pifp - > if_input ) ( padapter - > pifp , sub_m ) ;
# endif // CONFIG_RX_INDICATE_QUEUE
}
# endif //PLATFORM_FREEBSD
}
exit :
prframe - > u . hdr . len = 0 ;
rtw_free_recvframe ( prframe , pfree_recv_queue ) ; //free this recv_frame
return ret ;
# else // || defined (PLATFORM_LINUX) || defined (PLATFORM_FREEBSD)
# ifdef PLATFORM_WINDOWS
_irqL irql ;
# endif //PLATFORM_WINDOWS
unsigned char * ptr , * pdata , * pbuf , * psnap_type ;
union recv_frame * pnrframe , * pnrframe_new ;
int a_len , mv_len , padding_len ;
u16 eth_type , type_len ;
u8 bsnaphdr ;
struct ieee80211_snap_hdr * psnap ;
struct _vlan * pvlan ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
_queue * pfree_recv_queue = & ( precvpriv - > free_recv_queue ) ;
int ret = _SUCCESS ;
# ifdef PLATFORM_WINDOWS
struct recv_buf * precvbuf = prframe - > u . hdr . precvbuf ;
# endif //PLATFORM_WINDOWS
a_len = prframe - > u . hdr . len - prframe - > u . hdr . attrib . hdrlen ;
recvframe_pull ( prframe , prframe - > u . hdr . attrib . hdrlen ) ;
if ( prframe - > u . hdr . attrib . iv_len > 0 )
{
recvframe_pull ( prframe , prframe - > u . hdr . attrib . iv_len ) ;
}
pdata = prframe - > u . hdr . rx_data ;
prframe - > u . hdr . len = 0 ;
pnrframe = prframe ;
do {
mv_len = 0 ;
pnrframe - > u . hdr . rx_data = pnrframe - > u . hdr . rx_tail = pdata ;
ptr = pdata ;
_rtw_memcpy ( pnrframe - > u . hdr . attrib . dst , ptr , ETH_ALEN ) ;
ptr + = ETH_ALEN ;
_rtw_memcpy ( pnrframe - > u . hdr . attrib . src , ptr , ETH_ALEN ) ;
ptr + = ETH_ALEN ;
_rtw_memcpy ( & type_len , ptr , 2 ) ;
type_len = ntohs ( ( unsigned short ) type_len ) ;
ptr + = 2 ;
mv_len + = ETH_HLEN ;
recvframe_put ( pnrframe , type_len + ETH_HLEN ) ; //update tail;
if ( pnrframe - > u . hdr . rx_data > = pnrframe - > u . hdr . rx_tail | | type_len < 8 )
{
//panic("pnrframe->u.hdr.rx_data >= pnrframe->u.hdr.rx_tail || type_len<8\n");
rtw_free_recvframe ( pnrframe , pfree_recv_queue ) ;
goto exit ;
}
psnap = ( struct ieee80211_snap_hdr * ) ( ptr ) ;
psnap_type = ptr + SNAP_SIZE ;
if ( psnap - > dsap = = 0xaa & & psnap - > ssap = = 0xaa & & psnap - > ctrl = = 0x03 )
{
if ( _rtw_memcmp ( psnap - > oui , oui_rfc1042 , WLAN_IEEE_OUI_LEN ) )
{
bsnaphdr = _TRUE ; //wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042;
}
else if ( _rtw_memcmp ( psnap - > oui , SNAP_HDR_APPLETALK_DDP , WLAN_IEEE_OUI_LEN ) & &
_rtw_memcmp ( psnap_type , SNAP_ETH_TYPE_APPLETALK_DDP , 2 ) )
{
bsnaphdr = _TRUE ; //wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK;
}
else if ( _rtw_memcmp ( psnap - > oui , oui_8021h , WLAN_IEEE_OUI_LEN ) )
{
bsnaphdr = _TRUE ; //wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL;
}
else
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " drop pkt due to invalid frame format! \n " ) ) ;
//KeBugCheckEx(0x87123333, 0xe0, 0x4c, 0x87, 0xdd);
//panic("0x87123333, 0xe0, 0x4c, 0x87, 0xdd\n");
rtw_free_recvframe ( pnrframe , pfree_recv_queue ) ;
goto exit ;
}
}
else
{
bsnaphdr = _FALSE ; //wlan_pkt_format = WLAN_PKT_FORMAT_OTHERS;
}
ptr + = ( bsnaphdr ? SNAP_SIZE : 0 ) ;
_rtw_memcpy ( & eth_type , ptr , 2 ) ;
eth_type = ntohs ( ( unsigned short ) eth_type ) ; //pattrib->ether_type
mv_len + = 2 + ( bsnaphdr ? SNAP_SIZE : 0 ) ;
ptr + = 2 ; //now move to iphdr;
pvlan = NULL ;
if ( eth_type = = 0x8100 ) //vlan
{
pvlan = ( struct _vlan * ) ptr ;
ptr + = 4 ;
mv_len + = 4 ;
}
if ( eth_type = = 0x0800 ) //ip
{
struct iphdr * piphdr = ( struct iphdr * ) ptr ;
if ( piphdr - > protocol = = 0x06 )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " @@@===recv tcp len:%d @@@=== \n " , pnrframe - > u . hdr . len ) ) ;
}
}
# ifdef PLATFORM_OS_XP
else
{
NDIS_PACKET_8021Q_INFO VlanPriInfo ;
UINT32 UserPriority = pnrframe - > u . hdr . attrib . priority ;
UINT32 VlanID = ( pvlan ! = NULL ? get_vlan_id ( pvlan ) : 0 ) ;
VlanPriInfo . Value = // Get current value.
NDIS_PER_PACKET_INFO_FROM_PACKET ( pnrframe - > u . hdr . pkt , Ieee8021QInfo ) ;
VlanPriInfo . TagHeader . UserPriority = UserPriority ;
VlanPriInfo . TagHeader . VlanId = VlanID ;
VlanPriInfo . TagHeader . CanonicalFormatId = 0 ; // Should be zero.
VlanPriInfo . TagHeader . Reserved = 0 ; // Should be zero.
NDIS_PER_PACKET_INFO_FROM_PACKET ( pnrframe - > u . hdr . pkt , Ieee8021QInfo ) = VlanPriInfo . Value ;
}
# endif //PLATFORM_OS_XP
pbuf = recvframe_pull ( pnrframe , ( mv_len - sizeof ( struct ethhdr ) ) ) ;
_rtw_memcpy ( pbuf , pnrframe - > u . hdr . attrib . dst , ETH_ALEN ) ;
_rtw_memcpy ( pbuf + ETH_ALEN , pnrframe - > u . hdr . attrib . src , ETH_ALEN ) ;
eth_type = htons ( ( unsigned short ) eth_type ) ;
_rtw_memcpy ( pbuf + 12 , & eth_type , 2 ) ;
padding_len = ( 4 ) - ( ( type_len + ETH_HLEN ) & ( 4 - 1 ) ) ;
a_len - = ( type_len + ETH_HLEN + padding_len ) ;
#if 0
if ( a_len > ETH_HLEN )
{
pnrframe_new = rtw_alloc_recvframe ( pfree_recv_queue ) ;
if ( pnrframe_new )
{
_pkt * pskb_copy ;
unsigned int copy_len = pnrframe - > u . hdr . len ;
_rtw_init_listhead ( & pnrframe_new - > u . hdr . list ) ;
pskb_copy = rtw_skb_alloc ( copy_len + 64 ) ;
if ( pskb_copy = = NULL )
{
DBG_871X ( " amsdu_to_msdu:can not all(ocate memory for skb copy \n " ) ;
}
pnrframe_new - > u . hdr . pkt = pskb_copy ;
_rtw_memcpy ( pskb_copy - > data , pnrframe - > u . hdr . rx_data , copy_len ) ;
pnrframe_new - > u . hdr . rx_data = pnrframe - > u . hdr . rx_data ;
pnrframe_new - > u . hdr . rx_tail = pnrframe - > u . hdr . rx_data + copy_len ;
if ( ( padapter - > bDriverStopped = = _FALSE ) & & ( padapter - > bSurpriseRemoved = = _FALSE ) )
{
rtw_recv_indicatepkt ( padapter , pnrframe_new ) ; //indicate this recv_frame
}
else
{
rtw_free_recvframe ( pnrframe_new , pfree_recv_queue ) ; //free this recv_frame
}
}
else
{
DBG_871X ( " amsdu_to_msdu:can not allocate memory for pnrframe_new \n " ) ;
}
}
else
{
if ( ( padapter - > bDriverStopped = = _FALSE ) & & ( padapter - > bSurpriseRemoved = = _FALSE ) )
{
rtw_recv_indicatepkt ( padapter , pnrframe ) ; //indicate this recv_frame
}
else
{
rtw_free_recvframe ( pnrframe , pfree_recv_queue ) ; //free this recv_frame
}
pnrframe = NULL ;
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# else // 0
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
//padding_len = (4) - ((type_len + ETH_HLEN)&(4-1));
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//a_len -= (type_len + ETH_HLEN + padding_len) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
pnrframe_new = NULL ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( a_len > ETH_HLEN )
{
pnrframe_new = rtw_alloc_recvframe ( pfree_recv_queue ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( pnrframe_new )
{
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//pnrframe_new->u.hdr.precvbuf = precvbuf;//precvbuf is assigned before call rtw_init_recvframe()
//rtw_init_recvframe(pnrframe_new, precvpriv);
{
# ifdef PLATFORM_LINUX
_pkt * pskb = pnrframe - > u . hdr . pkt ;
# endif //PLATFORM_LINUX
_rtw_init_listhead ( & pnrframe_new - > u . hdr . list ) ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
pnrframe_new - > u . hdr . len = 0 ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# ifdef PLATFORM_LINUX
if ( pskb )
{
pnrframe_new - > u . hdr . pkt = rtw_skb_clone ( pskb ) ;
}
# endif //PLATFORM_LINUX
}
pdata + = ( type_len + ETH_HLEN + padding_len ) ;
pnrframe_new - > u . hdr . rx_head = pnrframe_new - > u . hdr . rx_data = pnrframe_new - > u . hdr . rx_tail = pdata ;
pnrframe_new - > u . hdr . rx_end = pdata + a_len + padding_len ; //
# ifdef PLATFORM_WINDOWS
pnrframe_new - > u . hdr . precvbuf = precvbuf ;
_enter_critical_bh ( & precvbuf - > recvbuf_lock , & irql ) ;
precvbuf - > ref_cnt + + ;
_exit_critical_bh ( & precvbuf - > recvbuf_lock , & irql ) ;
# endif //PLATFORM_WINDOWS
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
else
{
//panic("pnrframe_new=%x\n", pnrframe_new);
}
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
if ( ( padapter - > bDriverStopped = = _FALSE ) & & ( padapter - > bSurpriseRemoved = = _FALSE ) )
{
rtw_recv_indicatepkt ( padapter , pnrframe ) ; //indicate this recv_frame
}
else
{
rtw_free_recvframe ( pnrframe , pfree_recv_queue ) ; //free this recv_frame
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
pnrframe = NULL ;
if ( pnrframe_new )
{
pnrframe = pnrframe_new ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# endif // end defined (PLATFORM_LINUX) || defined (PLATFORM_FREEBSD)
} while ( pnrframe ) ;
exit :
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
return ret ;
2014-12-11 21:15:04 +00:00
# endif
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
int check_indicate_seq ( struct recv_reorder_ctrl * preorder_ctrl , u16 seq_num ) ;
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 ;
2014-12-11 21:15:04 +00:00
u16 wend = ( preorder_ctrl - > indicate_seq + wsize - 1 ) & 0xFFF ; //% 4096;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
// Rx Reorder initialize condition.
2013-05-08 21:45:39 +00:00
if ( preorder_ctrl - > indicate_seq = = 0xFFFF )
2014-12-11 21:15:04 +00:00
{
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = seq_num ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d init IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , seq_num ) ;
# endif
//DbgPrint("check_indicate_seq, 1st->indicate_seq=%d\n", precvpriv->indicate_seq);
}
//DbgPrint("enter->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
// Drop out the packet which SeqNum is smaller than WinStart
if ( SN_LESS ( seq_num , preorder_ctrl - > indicate_seq ) )
{
//RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
//DbgPrint("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " %s IndicateSeq: %d > NewSeq: %d \n " , __FUNCTION__ ,
preorder_ctrl - > indicate_seq , seq_num ) ;
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
return _FALSE ;
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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
//
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 ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d SN_EQUAL IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , seq_num ) ;
# endif
}
else if ( SN_LESS ( wend , seq_num ) )
{
//RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
//DbgPrint("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
// boundary situation, when seq_num cross 0xFFF
if ( seq_num > = ( wsize - 1 ) )
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 ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d SN_LESS(wend, seq_num) IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , seq_num ) ;
# endif
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//DbgPrint("exit->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
return _TRUE ;
2013-05-08 21:45:39 +00:00
}
int enqueue_reorder_recvframe ( struct recv_reorder_ctrl * preorder_ctrl , union recv_frame * prframe ) ;
int enqueue_reorder_recvframe ( struct recv_reorder_ctrl * preorder_ctrl , union recv_frame * prframe )
{
struct rx_pkt_attrib * pattrib = & prframe - > u . hdr . attrib ;
2014-12-11 21:15:04 +00:00
_queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
_list * phead , * plist ;
2013-05-08 21:45:39 +00:00
union recv_frame * pnextrframe ;
struct rx_pkt_attrib * pnextattrib ;
2014-12-11 21:15:04 +00:00
//DbgPrint("+enqueue_reorder_recvframe()\n");
//_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
//_rtw_spinlock_ex(&ppending_recvframe_queue->lock);
2013-05-08 21:45:39 +00:00
phead = get_list_head ( ppending_recvframe_queue ) ;
plist = get_next ( phead ) ;
2014-12-11 21:15:04 +00:00
while ( rtw_end_of_queue_search ( phead , plist ) = = _FALSE )
{
2013-05-08 21:45:39 +00:00
pnextrframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
pnextattrib = & pnextrframe - > u . hdr . attrib ;
2014-12-11 21:15:04 +00:00
if ( SN_LESS ( pnextattrib - > seq_num , pattrib - > seq_num ) )
{
2013-05-08 21:45:39 +00:00
plist = get_next ( plist ) ;
2014-12-11 21:15:04 +00:00
}
else if ( SN_EQUAL ( pnextattrib - > seq_num , pattrib - > seq_num ) )
{
//Duplicate entry is found!! Do not insert current entry.
//RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum));
//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
return _FALSE ;
}
2013-05-08 21:45:39 +00:00
else
2014-12-11 21:15:04 +00:00
{
2013-05-08 21:45:39 +00:00
break ;
2014-12-11 21:15:04 +00:00
}
//DbgPrint("enqueue_reorder_recvframe():while\n");
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
//_rtw_spinlock_ex(&ppending_recvframe_queue->lock);
2013-05-08 21:45:39 +00:00
rtw_list_delete ( & ( prframe - > u . hdr . list ) ) ;
rtw_list_insert_tail ( & ( prframe - > u . hdr . list ) , plist ) ;
2014-12-11 21:15:04 +00:00
//_rtw_spinunlock_ex(&ppending_recvframe_queue->lock);
//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
//RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum));
return _TRUE ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
int recv_indicatepkts_in_order ( _adapter * padapter , struct recv_reorder_ctrl * preorder_ctrl , int bforced ) ;
int recv_indicatepkts_in_order ( _adapter * padapter , struct recv_reorder_ctrl * preorder_ctrl , int bforced )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
//_irqL irql;
//u8 bcancelled;
_list * phead , * plist ;
2013-05-08 21:45:39 +00:00
union recv_frame * prframe ;
struct rx_pkt_attrib * pattrib ;
2014-12-11 21:15:04 +00:00
//u8 index = 0;
int bPktInBuf = _FALSE ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2014-12-11 21:15:04 +00:00
_queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//DbgPrint("+recv_indicatepkts_in_order\n");
//_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
//_rtw_spinlock_ex(&ppending_recvframe_queue->lock);
phead = get_list_head ( ppending_recvframe_queue ) ;
2013-05-08 21:45:39 +00:00
plist = get_next ( phead ) ;
2014-12-11 21:15:04 +00:00
#if 0
// Check if there is any other indication thread running.
if ( pTS - > RxIndicateState = = RXTS_INDICATE_PROCESSING )
return ;
# endif
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +00:00
// Handling some condition for forced indicate case.
if ( bforced = = _TRUE )
{
if ( rtw_is_list_empty ( phead ) )
{
// _exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
//_rtw_spinunlock_ex(&ppending_recvframe_queue->lock);
return _TRUE ;
}
prframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
pattrib = & prframe - > u . hdr . attrib ;
preorder_ctrl - > indicate_seq = pattrib - > seq_num ;
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ;
# endif
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
// Prepare indication list and indication.
// Check if there is any packet need indicate.
while ( ! rtw_is_list_empty ( phead ) )
{
2013-05-08 21:45:39 +00:00
prframe = LIST_CONTAINOR ( plist , union recv_frame , u ) ;
pattrib = & prframe - > u . hdr . attrib ;
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
#if 0
// This protect buffer from overflow.
if ( index > = REORDER_WIN_SIZE )
{
RT_ASSERT ( FALSE , ( " IndicateRxReorderList(): Buffer overflow!! \n " ) ) ;
bPktInBuf = TRUE ;
break ;
}
# endif
2013-05-08 21:45:39 +00:00
plist = get_next ( plist ) ;
rtw_list_delete ( & ( prframe - > u . hdr . list ) ) ;
2014-12-11 21:15:04 +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 ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ;
# endif
}
#if 0
index + + ;
if ( index = = 1 )
{
//Cancel previous pending timer.
//PlatformCancelTimer(Adapter, &pTS->RxPktPendingTimer);
if ( bforced ! = _TRUE )
{
//DBG_871X("_cancel_timer(&preorder_ctrl->reordering_ctrl_timer, &bcancelled);\n");
_cancel_timer ( & preorder_ctrl - > reordering_ctrl_timer , & bcancelled ) ;
}
}
# endif
//Set this as a lock to make sure that only one thread is indicating packet.
//pTS->RxIndicateState = RXTS_INDICATE_PROCESSING;
// Indicate packets
//RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"));
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//indicate this recv_frame
//DbgPrint("recv_indicatepkts_in_order, indicate_seq=%d, seq_num=%d\n", precvpriv->indicate_seq, pattrib->seq_num);
if ( ! pattrib - > amsdu )
{
//DBG_871X("recv_indicatepkts_in_order, amsdu!=1, indicate_seq=%d, seq_num=%d\n", preorder_ctrl->indicate_seq, pattrib->seq_num);
if ( ( padapter - > bDriverStopped = = _FALSE ) & &
( padapter - > bSurpriseRemoved = = _FALSE ) )
{
rtw_recv_indicatepkt ( padapter , prframe ) ; //indicate this recv_frame
}
}
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 ) ;
2014-12-11 21:15:04 +00:00
}
}
else
{
//error condition;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//Update local variables.
bPktInBuf = _FALSE ;
}
else
{
bPktInBuf = _TRUE ;
2013-05-08 21:45:39 +00:00
break ;
}
2014-12-11 21:15:04 +00:00
//DbgPrint("recv_indicatepkts_in_order():while\n");
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
//_rtw_spinunlock_ex(&ppending_recvframe_queue->lock);
//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
/*
//Release the indication lock and set to new indication step.
if ( bPktInBuf )
{
// Set new pending timer.
//pTS->RxIndicateState = RXTS_INDICATE_REORDER;
//PlatformSetTimer(Adapter, &pTS->RxPktPendingTimer, pHTInfo->RxReorderPendingTime);
//DBG_871X("_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME)\n");
_set_timer ( & preorder_ctrl - > reordering_ctrl_timer , REORDER_WAIT_TIME ) ;
}
else
{
//pTS->RxIndicateState = RXTS_INDICATE_IDLE;
}
*/
//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
//return _TRUE;
2013-05-08 21:45:39 +00:00
return bPktInBuf ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
int recv_indicatepkt_reorder ( _adapter * padapter , union recv_frame * prframe ) ;
int recv_indicatepkt_reorder ( _adapter * padapter , union recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
2014-12-11 21:15:04 +00:00
_irqL irql ;
2013-05-08 21:45:39 +00:00
int retval = _SUCCESS ;
struct rx_pkt_attrib * pattrib = & prframe - > u . hdr . attrib ;
struct recv_reorder_ctrl * preorder_ctrl = prframe - > u . hdr . preorder_ctrl ;
2014-12-11 21:15:04 +00:00
_queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( ! pattrib - > amsdu )
{
//s1.
2013-05-08 21:45:39 +00:00
wlanhdr_to_ethhdr ( prframe ) ;
2014-12-11 21:15:04 +00:00
//if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/
// || (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0))
if ( pattrib - > qos ! = 1 )
{
if ( ( padapter - > bDriverStopped = = _FALSE ) & &
( padapter - > bSurpriseRemoved = = _FALSE ) )
{
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
2014-12-11 21:15:04 +00:00
}
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s pattrib->qos !=1 \n " , __FUNCTION__ ) ;
# endif
2013-05-08 21:45:39 +00:00
return _FAIL ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
if ( preorder_ctrl - > enable = = _FALSE )
{
//indicate this recv_frame
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = pattrib - > seq_num ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ;
# endif
rtw_recv_indicatepkt ( padapter , prframe ) ;
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = ( preorder_ctrl - > indicate_seq + 1 ) % 4096 ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ;
# endif
return _SUCCESS ;
}
# ifndef CONFIG_RECV_REORDERING_CTRL
//indicate this recv_frame
rtw_recv_indicatepkt ( padapter , prframe ) ;
return _SUCCESS ;
# endif
}
else if ( pattrib - > amsdu = = 1 ) //temp filter -> means didn't support A-MSDUs in a A-MPDU
{
if ( preorder_ctrl - > enable = = _FALSE )
{
2013-05-08 21:45:39 +00:00
preorder_ctrl - > indicate_seq = pattrib - > seq_num ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ;
# endif
2013-05-08 21:45:39 +00:00
retval = amsdu_to_msdu ( padapter , prframe ) ;
preorder_ctrl - > indicate_seq = ( preorder_ctrl - > indicate_seq + 1 ) % 4096 ;
2014-12-11 21:15:04 +00:00
# ifdef DBG_RX_SEQ
DBG_871X ( " DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d \n " , __FUNCTION__ , __LINE__ ,
preorder_ctrl - > indicate_seq , pattrib - > seq_num ) ;
# endif
if ( retval ! = _SUCCESS ) {
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s amsdu_to_msdu fail \n " , __FUNCTION__ ) ;
# endif
}
2013-05-08 21:45:39 +00:00
return retval ;
}
}
2014-12-11 21:15:04 +00:00
else
{
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
_enter_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
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 ) ) ;
2014-12-11 21:15:04 +00:00
//s2. check if winstart_b(indicate_seq) needs to been updated
if ( ! check_indicate_seq ( preorder_ctrl , pattrib - > seq_num ) )
{
//pHTInfo->RxReorderDropCounter++;
//ReturnRFDList(Adapter, pRfd);
//RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("RxReorderIndicatePacket() ==> Packet Drop!!\n"));
//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
//return _FAIL;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s check_indicate_seq fail \n " , __FUNCTION__ ) ;
# endif
#if 0
rtw_recv_indicatepkt ( padapter , prframe ) ;
_exit_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
goto _success_exit ;
# else
2014-11-20 06:12:27 +00:00
goto _err_exit ;
2014-12-11 21:15:04 +00:00
# endif
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//s3. Insert all packet into Reorder Queue to maintain its ordering.
if ( ! enqueue_reorder_recvframe ( preorder_ctrl , prframe ) )
{
//DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n");
//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
//return _FAIL;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s enqueue_reorder_recvframe fail \n " , __FUNCTION__ ) ;
# endif
2013-05-08 21:45:39 +00:00
goto _err_exit ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +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.
//
//recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE);
if ( recv_indicatepkts_in_order ( padapter , preorder_ctrl , _FALSE ) = = _TRUE )
{
2013-05-08 21:45:39 +00:00
_set_timer ( & preorder_ctrl - > reordering_ctrl_timer , REORDER_WAIT_TIME ) ;
2014-12-11 21:15:04 +00:00
_exit_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
}
else
{
_exit_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
2013-05-08 21:45:39 +00:00
_cancel_timer_ex ( & preorder_ctrl - > reordering_ctrl_timer ) ;
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
_success_exit :
return _SUCCESS ;
_err_exit :
2014-12-11 21:15:04 +00:00
_exit_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
2013-05-08 21:45:39 +00:00
return _FAIL ;
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
void rtw_reordering_ctrl_timeout_handler ( void * pcontext )
{
2014-12-11 21:15:04 +00:00
_irqL irql ;
2013-05-08 21:45:39 +00:00
struct recv_reorder_ctrl * preorder_ctrl = ( struct recv_reorder_ctrl * ) pcontext ;
2014-12-11 21:15:04 +00:00
_adapter * padapter = preorder_ctrl - > padapter ;
_queue * ppending_recvframe_queue = & preorder_ctrl - > pending_recvframe_queue ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( padapter - > bDriverStopped | | padapter - > bSurpriseRemoved )
{
2013-05-08 21:45:39 +00:00
return ;
2014-12-11 21:15:04 +00:00
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//DBG_871X("+rtw_reordering_ctrl_timeout_handler()=>\n");
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
_enter_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
if ( recv_indicatepkts_in_order ( padapter , preorder_ctrl , _TRUE ) = = _TRUE )
{
_set_timer ( & preorder_ctrl - > reordering_ctrl_timer , REORDER_WAIT_TIME ) ;
}
_exit_critical_bh ( & ppending_recvframe_queue - > lock , & irql ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
int process_recv_indicatepkts ( _adapter * padapter , union recv_frame * prframe ) ;
int process_recv_indicatepkts ( _adapter * padapter , union recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
int retval = _SUCCESS ;
2014-12-11 21:15:04 +00:00
//struct recv_priv *precvpriv = &padapter->recvpriv;
//struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
2013-05-08 21:45:39 +00:00
struct mlme_priv * pmlmepriv = & padapter - > mlmepriv ;
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
struct sta_info * psta = prframe - > u . hdr . psta ;
# endif //CONFIG_TDLS
# ifdef CONFIG_80211N_HT
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
struct ht_priv * phtpriv = & pmlmepriv - > htpriv ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
if ( ( phtpriv - > ht_option = = _TRUE ) | |
( ( psta - > tdls_sta_state & TDLS_LINKED_STATE ) & &
( psta - > htpriv . ht_option = = _TRUE ) & &
( psta - > htpriv . ampdu_enable = = _TRUE ) ) ) //B/G/N Mode
# else
if ( phtpriv - > ht_option = = _TRUE ) //B/G/N Mode
# endif //CONFIG_TDLS
{
//prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority];
if ( recv_indicatepkt_reorder ( padapter , prframe ) ! = _SUCCESS ) // including perform A-MPDU Rx Ordering Buffer Control
{
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s recv_indicatepkt_reorder error! \n " , __FUNCTION__ ) ;
# endif
if ( ( padapter - > bDriverStopped = = _FALSE ) & &
( padapter - > bSurpriseRemoved = = _FALSE ) )
{
2013-05-08 21:45:39 +00:00
retval = _FAIL ;
return retval ;
}
}
2014-12-11 21:15:04 +00:00
}
else //B/G mode
# endif
{
retval = wlanhdr_to_ethhdr ( prframe ) ;
if ( retval ! = _SUCCESS )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " wlanhdr_to_ethhdr: drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr error! \n " , __FUNCTION__ ) ;
# endif
2013-05-08 21:45:39 +00:00
return retval ;
}
2014-12-11 21:15:04 +00:00
if ( ( padapter - > bDriverStopped = = _FALSE ) & & ( padapter - > bSurpriseRemoved = = _FALSE ) )
{
//indicate this recv_frame
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 ) ;
2014-12-11 21:15:04 +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 ;
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
return retval ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
int recv_func_prehandle ( _adapter * padapter , union recv_frame * rframe )
2013-05-08 21:45:39 +00:00
{
int ret = _SUCCESS ;
struct rx_pkt_attrib * pattrib = & rframe - > u . hdr . attrib ;
2014-12-11 21:15:04 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
_queue * pfree_recv_queue = & padapter - > recvpriv . free_recv_queue ;
# ifdef CONFIG_MP_INCLUDED
2013-05-08 21:45:39 +00:00
struct mlme_priv * pmlmepriv = & padapter - > mlmepriv ;
2014-12-11 21:15:04 +00:00
# endif //CONFIG_MP_INCLUDED
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_MP_INCLUDED
if ( padapter - > registrypriv . mp_mode = = 1 )
{
2014-11-20 06:12:27 +00:00
if ( pattrib - > crc_err = = 1 )
2014-12-11 21:15:04 +00:00
{
2014-11-20 06:12:27 +00:00
padapter - > mppriv . rx_crcerrpktcount + + ;
2014-12-11 21:15:04 +00:00
}
2014-11-20 06:12:27 +00:00
else
2014-12-11 21:15:04 +00:00
{
2014-11-20 06:12:27 +00:00
padapter - > mppriv . rx_pktcount + + ;
2014-12-11 21:15:04 +00:00
}
if ( check_fwstate ( pmlmepriv , WIFI_MP_LPBK_STATE ) = = _FALSE ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_alert_ , ( " MP - Not in loopback mode , drop pkt \n " ) ) ;
2014-11-20 06:12:27 +00:00
ret = _FAIL ;
2014-12-11 21:15:04 +00:00
rtw_free_recvframe ( rframe , pfree_recv_queue ) ; //free this recv_frame
2014-11-20 06:12:27 +00:00
goto exit ;
2013-05-08 21:45:39 +00:00
}
}
2014-12-11 21:15:04 +00:00
# endif
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
//check the frame crtl field and decache
2013-05-08 21:45:39 +00:00
ret = validate_recv_frame ( padapter , rframe ) ;
2014-12-11 21:15:04 +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 " ) ) ;
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
int recv_func_posthandle ( _adapter * padapter , union recv_frame * prframe )
2013-05-08 21:45:39 +00:00
{
int ret = _SUCCESS ;
union recv_frame * orig_prframe = prframe ;
2014-12-11 21:15:04 +00:00
struct rx_pkt_attrib * pattrib = & prframe - > u . hdr . attrib ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2014-12-11 21:15:04 +00:00
_queue * pfree_recv_queue = & padapter - > recvpriv . free_recv_queue ;
# ifdef CONFIG_TDLS
u8 * psnap_type , * pcategory ;
struct sta_info * ptdls_sta = NULL ;
# endif //CONFIG_TDLS
2013-05-19 04:28:07 +00:00
2014-12-11 21:15:04 +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 ) {
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " decryptor: drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s decryptor: drop pkt \n " , __FUNCTION__ ) ;
# endif
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
goto _recv_data_drop ;
}
2014-12-11 21:15:04 +00:00
#if 0
if ( padapter - > adapter_type = = PRIMARY_ADAPTER )
{
DBG_871X ( " +++ \n " ) ;
{
int i ;
u8 * ptr = get_recvframe_data ( prframe ) ;
for ( i = 0 ; i < 140 ; i = i + 8 )
DBG_871X ( " %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X: " , * ( ptr + i ) ,
* ( ptr + i + 1 ) , * ( ptr + i + 2 ) , * ( ptr + i + 3 ) , * ( ptr + i + 4 ) , * ( ptr + i + 5 ) , * ( ptr + i + 6 ) , * ( ptr + i + 7 ) ) ;
}
DBG_871X ( " --- \n " ) ;
}
# endif
# ifdef CONFIG_TDLS
//check TDLS frame
psnap_type = get_recvframe_data ( orig_prframe ) ;
psnap_type + = pattrib - > hdrlen + pattrib - > iv_len + SNAP_SIZE ;
pcategory = psnap_type + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN ;
if ( ( _rtw_memcmp ( psnap_type , SNAP_ETH_TYPE_TDLS , ETH_TYPE_LEN ) ) & &
( ( * pcategory = = RTW_WLAN_CATEGORY_TDLS ) | | ( * pcategory = = RTW_WLAN_CATEGORY_P2P ) ) ) {
ret = OnTDLS ( padapter , prframe ) ; //all of functions will return _FAIL
goto _exit_recv_func ;
}
# endif //CONFIG_TDLS
2013-05-08 21:45:39 +00:00
prframe = recvframe_chk_defrag ( padapter , prframe ) ;
2014-12-11 21:15:04 +00:00
if ( prframe = = NULL ) {
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recvframe_chk_defrag: drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s recvframe_chk_defrag: drop pkt \n " , __FUNCTION__ ) ;
# endif
goto _recv_data_drop ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
prframe = portctrl ( padapter , prframe ) ;
2013-05-08 21:45:39 +00:00
if ( prframe = = NULL ) {
2014-12-11 21:15:04 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " portctrl: drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s portctrl: drop pkt \n " , __FUNCTION__ ) ;
# endif
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
goto _recv_data_drop ;
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_TDLS
if ( padapter - > tdlsinfo . setup_state = = TDLS_LINKED_STATE )
ptdls_sta = rtw_get_stainfo ( & padapter - > stapriv , pattrib - > src ) ;
count_rx_stats ( padapter , prframe , ptdls_sta ) ;
# else
2013-05-08 21:45:39 +00:00
count_rx_stats ( padapter , prframe , NULL ) ;
2014-12-11 21:15:04 +00:00
# endif //CONFIG_TDLS
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_WAPI_SUPPORT
rtw_wapi_update_info ( padapter , prframe ) ;
# endif
# ifdef CONFIG_80211N_HT
2013-05-08 21:45:39 +00:00
ret = process_recv_indicatepkts ( padapter , prframe ) ;
2014-12-11 21:15:04 +00:00
if ( ret ! = _SUCCESS )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recv_func: process_recv_indicatepkts fail! \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s process_recv_indicatepkts fail! \n " , __FUNCTION__ ) ;
# endif
rtw_free_recvframe ( orig_prframe , pfree_recv_queue ) ; //free this recv_frame
goto _recv_data_drop ;
}
# else // CONFIG_80211N_HT
if ( ! pattrib - > amsdu )
{
ret = wlanhdr_to_ethhdr ( prframe ) ;
if ( ret ! = _SUCCESS )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " wlanhdr_to_ethhdr: drop pkt \n " ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr: drop pkt \n " , __FUNCTION__ ) ;
# endif
rtw_free_recvframe ( orig_prframe , pfree_recv_queue ) ; //free this recv_frame
goto _recv_data_drop ;
}
if ( ( padapter - > bDriverStopped = = _FALSE ) & & ( padapter - > bSurpriseRemoved = = _FALSE ) )
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_alert_ , ( " @@@@ recv_func: recv_func rtw_recv_indicatepkt \n " ) ) ;
//indicate this recv_frame
ret = rtw_recv_indicatepkt ( padapter , prframe ) ;
if ( ret ! = _SUCCESS )
{
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s rtw_recv_indicatepkt fail! \n " , __FUNCTION__ ) ;
# endif
goto _recv_data_drop ;
}
}
else
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_alert_ , ( " @@@@ recv_func: rtw_free_recvframe \n " ) ) ;
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_debug_ , ( " recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d) " , padapter - > bDriverStopped , padapter - > bSurpriseRemoved ) ) ;
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s ecv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d) \n " , __FUNCTION__ ,
padapter - > bDriverStopped , padapter - > bSurpriseRemoved ) ;
# endif
ret = _FAIL ;
rtw_free_recvframe ( orig_prframe , pfree_recv_queue ) ; //free this recv_frame
}
}
else if ( pattrib - > amsdu = = 1 )
{
ret = amsdu_to_msdu ( padapter , prframe ) ;
if ( ret ! = _SUCCESS )
{
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s amsdu_to_msdu fail \n " , __FUNCTION__ ) ;
# endif
rtw_free_recvframe ( orig_prframe , pfree_recv_queue ) ;
goto _recv_data_drop ;
}
}
else
{
# ifdef DBG_RX_DROP_FRAME
DBG_871X ( " DBG_RX_DROP_FRAME %s what is this condition?? \n " , __FUNCTION__ ) ;
# endif
2013-05-08 21:45:39 +00:00
goto _recv_data_drop ;
}
2014-12-11 21:15:04 +00:00
# endif // CONFIG_80211N_HT
_exit_recv_func :
2013-05-08 21:45:39 +00:00
return ret ;
_recv_data_drop :
precvpriv - > rx_drop + + ;
return ret ;
}
2014-12-11 21:15:04 +00:00
int recv_func ( _adapter * padapter , union recv_frame * rframe ) ;
int recv_func ( _adapter * padapter , union recv_frame * rframe )
2013-05-08 21:45:39 +00:00
{
int ret ;
struct rx_pkt_attrib * prxattrib = & rframe - > u . hdr . attrib ;
2014-11-20 06:12:27 +00:00
struct recv_priv * recvpriv = & padapter - > recvpriv ;
2014-12-11 21:15:04 +00:00
struct security_priv * psecuritypriv = & padapter - > securitypriv ;
struct mlme_priv * mlmepriv = & padapter - > mlmepriv ;
2013-05-08 21:45:39 +00:00
/* check if need to handle uc_swdec_pending_queue*/
2014-12-11 21:15:04 +00:00
if ( check_fwstate ( mlmepriv , WIFI_STATION_STATE ) & & psecuritypriv - > busetkipkey )
{
2013-05-08 21:45:39 +00:00
union recv_frame * pending_frame ;
2014-11-20 06:12:27 +00:00
int cnt = 0 ;
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
while ( ( pending_frame = rtw_alloc_recvframe ( & padapter - > recvpriv . uc_swdec_pending_queue ) ) ) {
2014-11-20 06:12:27 +00:00
cnt + + ;
recv_func_posthandle ( padapter , pending_frame ) ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
if ( cnt )
DBG_871X ( FUNC_ADPT_FMT " dequeue %d from uc_swdec_pending_queue \n " ,
FUNC_ADPT_ARG ( padapter ) , cnt ) ;
2013-05-08 21:45:39 +00:00
}
ret = recv_func_prehandle ( padapter , rframe ) ;
2014-12-11 21:15:04 +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 ) & &
2014-12-11 21:15:04 +00:00
! IS_MCAST ( prxattrib - > ra ) & & prxattrib - > encrypt > 0 & &
( prxattrib - > bdecrypted = = 0 | | psecuritypriv - > sw_decrypt = = _TRUE ) & &
psecuritypriv - > ndisauthtype = = Ndis802_11AuthModeWPAPSK & &
! psecuritypriv - > busetkipkey )
{
2013-05-08 21:45:39 +00:00
rtw_enqueue_recvframe ( rframe , & padapter - > recvpriv . uc_swdec_pending_queue ) ;
2014-12-11 21:15:04 +00:00
//DBG_871X("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
2014-11-20 06:12:27 +00:00
if ( recvpriv - > free_recvframe_cnt < NR_RECVFRAME / 4 ) {
2014-12-11 21:15:04 +00:00
/* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt */
2014-11-20 06:12:27 +00:00
rframe = rtw_alloc_recvframe ( & padapter - > recvpriv . uc_swdec_pending_queue ) ;
if ( rframe )
goto do_posthandle ;
}
2013-05-08 21:45:39 +00:00
goto exit ;
}
2014-12-11 21:15:04 +00:00
2014-11-20 06:12:27 +00:00
do_posthandle :
2013-05-08 21:45:39 +00:00
ret = recv_func_posthandle ( padapter , rframe ) ;
}
exit :
return ret ;
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
s32 rtw_recv_entry ( union recv_frame * precvframe )
{
2014-12-11 21:15:04 +00:00
_adapter * padapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv ;
2014-12-11 21:15:04 +00:00
s32 ret = _SUCCESS ;
_func_enter_ ;
// RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("+rtw_recv_entry\n"));
2013-05-08 21:45:39 +00:00
padapter = precvframe - > u . hdr . adapter ;
precvpriv = & padapter - > recvpriv ;
2014-12-11 21:15:04 +00:00
if ( ( ret = recv_func ( padapter , precvframe ) ) = = _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 ;
}
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
precvpriv - > rx_pkts + + ;
2014-12-11 21:15:04 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
_recv_entry_drop :
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_MP_INCLUDED
2013-05-08 21:45:39 +00:00
if ( padapter - > registrypriv . mp_mode = = 1 )
padapter - > mppriv . rx_pktloss = precvpriv - > rx_drop ;
2014-12-11 21:15:04 +00:00
# endif
//RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("_recv_entry_drop\n"));
_func_exit_ ;
2013-05-08 21:45:39 +00:00
return ret ;
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
void rtw_signal_stat_timer_hdl ( RTW_TIMER_HDL_ARGS ) {
_adapter * adapter = ( _adapter * ) FunctionContext ;
2013-05-08 21:45:39 +00:00
struct recv_priv * recvpriv = & adapter - > recvpriv ;
2014-12-11 21:15:04 +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 ;
2014-12-11 21:15:04 +00:00
u32 num_signal_strength = 0 ;
u32 num_signal_qual = 0 ;
u8 _alpha = 3 ; // this value is based on converging_constant = 5000 and sampling_interval = 1000
if ( adapter - > recvpriv . is_signal_dbg ) {
//update the user specific value, signal_strength_dbg, to signal_strength, rssi
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 {
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
num_signal_strength = recvpriv - > signal_strength_data . total_num ;
// after avg_vals are accquired, we can re-stat the signal values
2013-05-08 21:45:39 +00:00
recvpriv - > signal_strength_data . update_req = 1 ;
}
2014-12-11 21:15:04 +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-12-11 21:15:04 +00:00
num_signal_qual = recvpriv - > signal_qual_data . total_num ;
// after avg_vals are accquired, we can re-stat the signal values
2013-05-08 21:45:39 +00:00
recvpriv - > signal_qual_data . update_req = 1 ;
}
2014-12-11 21:15:04 +00:00
if ( num_signal_strength = = 0 ) {
if ( rtw_get_on_cur_ch_time ( adapter ) = = 0
| | rtw_get_passing_time_ms ( rtw_get_on_cur_ch_time ( adapter ) ) < 2 * adapter - > mlmeextpriv . mlmext_info . bcn_interval
# ifdef CONFIG_BT_COEXIST
| | ( ( BTDM_IsBtDisabled ( adapter ) = = _FALSE ) & & ( BT_IsBtInquiryPage ( adapter ) = = _TRUE ) )
# endif
) {
goto set_timer ;
}
}
2013-05-08 21:45:39 +00:00
2014-12-11 21:15:04 +00:00
if ( check_fwstate ( & adapter - > mlmepriv , _FW_UNDER_SURVEY ) = = _TRUE
| | check_fwstate ( & adapter - > mlmepriv , _FW_LINKED ) = = _FALSE
) {
goto set_timer ;
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# ifdef CONFIG_CONCURRENT_MODE
if ( check_buddy_fwstate ( adapter , _FW_UNDER_SURVEY ) = = _TRUE )
goto set_timer ;
# endif
//update value of signal_strength, rssi, signal_qual
tmp_s = ( avg_signal_strength + ( _alpha - 1 ) * recvpriv - > signal_strength ) ;
if ( tmp_s % _alpha )
tmp_s = tmp_s / _alpha + 1 ;
else
tmp_s = tmp_s / _alpha ;
if ( tmp_s > 100 )
tmp_s = 100 ;
tmp_q = ( avg_signal_qual + ( _alpha - 1 ) * recvpriv - > signal_qual ) ;
if ( tmp_q % _alpha )
tmp_q = tmp_q / _alpha + 1 ;
else
tmp_q = tmp_q / _alpha ;
if ( tmp_q > 100 )
tmp_q = 100 ;
recvpriv - > signal_strength = tmp_s ;
recvpriv - > rssi = ( s8 ) translate_percentage_to_dbm ( tmp_s ) ;
recvpriv - > signal_qual = tmp_q ;
# if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
DBG_871X ( FUNC_ADPT_FMT " signal_strength:%3u, rssi:%3d, signal_qual:%3u "
" , num_signal_strength:%u, num_signal_qual:%u "
" , on_cur_ch_ms:%d "
" \n "
, FUNC_ADPT_ARG ( adapter )
, recvpriv - > signal_strength
, recvpriv - > rssi
, recvpriv - > signal_qual
, num_signal_strength , num_signal_qual
, rtw_get_on_cur_ch_time ( adapter ) ? rtw_get_passing_time_ms ( rtw_get_on_cur_ch_time ( adapter ) ) : 0
) ;
# endif
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
set_timer :
2013-05-08 21:45:39 +00:00
rtw_set_signal_stat_timer ( recvpriv ) ;
2014-12-11 21:15:04 +00:00
2013-05-08 21:45:39 +00:00
}
2014-12-11 21:15:04 +00:00
# endif //CONFIG_NEW_SIGNAL_STAT_PROCESS