2013-05-08 21:45:39 +00:00
/******************************************************************************
*
* Copyright ( c ) 2007 - 2011 Realtek Corporation . All rights reserved .
2013-05-19 04:28:07 +00:00
*
2013-05-08 21:45:39 +00:00
* This program is free software ; you can redistribute it and / or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 , USA
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define _HCI_OPS_OS_C_
# include <drv_conf.h>
# include <osdep_service.h>
# include <drv_types.h>
# include <osdep_intf.h>
# include <usb_ops.h>
# include <circ_buf.h>
# include <recv_osdep.h>
# include <rtl8188e_hal.h>
static int usbctrl_vendorreq ( struct intf_hdl * pintfhdl , u8 request , u16 value , u16 index , void * pdata , u16 len , u8 requesttype )
{
_adapter * padapter = pintfhdl - > padapter ;
struct dvobj_priv * pdvobjpriv = adapter_to_dvobj ( padapter ) ;
2013-07-09 22:40:50 +00:00
struct usb_device * udev = pdvobjpriv - > pusbdev ;
2013-05-08 21:45:39 +00:00
unsigned int pipe ;
int status = 0 ;
u32 tmp_buflen = 0 ;
u8 reqtype ;
u8 * pIo_buf ;
int vendorreq_times = 0 ;
# ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
2013-07-09 22:40:50 +00:00
u8 * tmp_buf ;
2013-07-10 18:25:07 +00:00
# else /* use stack memory */
2013-07-09 22:40:50 +00:00
u8 tmp_buf [ MAX_USB_IO_CTL_SIZE ] ;
2013-05-08 21:45:39 +00:00
# endif
# ifdef CONFIG_CONCURRENT_MODE
2013-05-09 04:04:25 +00:00
if ( padapter - > adapter_type > PRIMARY_ADAPTER )
2013-05-08 21:45:39 +00:00
{
padapter = padapter - > pbuddy_adapter ;
pdvobjpriv = adapter_to_dvobj ( padapter ) ;
udev = pdvobjpriv - > pusbdev ;
}
# endif
2013-05-09 04:04:25 +00:00
if ( ( padapter - > bSurpriseRemoved ) | | ( padapter - > pwrctrlpriv . pnp_bstop_trx ) ) {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usbctrl_vendorreq:(padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!! \n " ) ) ;
2013-05-19 04:28:07 +00:00
status = - EPERM ;
2013-05-08 21:45:39 +00:00
goto exit ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( len > MAX_VENDOR_REQ_CMD_SIZE ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " [%s] Buffer len error ,vendor request failed \n " , __func__ ) ;
2013-05-08 21:45:39 +00:00
status = - EINVAL ;
goto exit ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
# ifdef CONFIG_USB_VENDOR_REQ_MUTEX
_enter_critical_mutex ( & pdvobjpriv - > usb_vendor_req_mutex , NULL ) ;
# endif
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
/* Acquire IO memory for vendorreq */
2013-05-08 21:45:39 +00:00
# ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC
pIo_buf = pdvobjpriv - > usb_vendor_req_buf ;
# else
# ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
tmp_buf = rtw_malloc ( ( u32 ) len + ALIGNMENT_UNIT ) ;
tmp_buflen = ( u32 ) len + ALIGNMENT_UNIT ;
2013-07-10 18:25:07 +00:00
# else /* use stack memory */
2013-05-08 21:45:39 +00:00
tmp_buflen = MAX_USB_IO_CTL_SIZE ;
# endif
2013-07-10 18:25:07 +00:00
/* Added by Albert 2010/02/09 */
/* For mstar platform, mstar suggests the address for USB IO should be 16 bytes alignment. */
/* Trying to fix it here. */
2013-05-19 04:28:07 +00:00
pIo_buf = ( tmp_buf = = NULL ) ? NULL : tmp_buf + ALIGNMENT_UNIT - ( ( SIZE_PTR ) ( tmp_buf ) & 0x0f ) ;
2013-05-08 21:45:39 +00:00
# endif
if ( pIo_buf = = NULL ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " [%s] pIo_buf == NULL \n " , __func__ ) ;
2013-05-08 21:45:39 +00:00
status = - ENOMEM ;
goto release_mutex ;
}
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
while ( + + vendorreq_times < = MAX_USBCTRL_VENDORREQ_TIMES )
2013-05-08 21:45:39 +00:00
{
_rtw_memset ( pIo_buf , 0 , len ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
if ( requesttype = = 0x01 )
{
2013-07-10 18:25:07 +00:00
pipe = usb_rcvctrlpipe ( udev , 0 ) ; /* read_in */
2013-05-19 04:28:07 +00:00
reqtype = REALTEK_USB_VENQT_READ ;
}
else
2013-05-08 21:45:39 +00:00
{
2013-07-10 18:25:07 +00:00
pipe = usb_sndctrlpipe ( udev , 0 ) ; /* write_out */
2013-05-19 04:28:07 +00:00
reqtype = REALTEK_USB_VENQT_WRITE ;
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( pIo_buf , pdata , len ) ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
status = rtw_usb_control_msg ( udev , pipe , request , reqtype , value , index , pIo_buf , len , RTW_USB_CONTROL_MSG_TIMEOUT ) ;
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
if ( status = = len ) /* Success this control transfer. */
2013-05-08 21:45:39 +00:00
{
rtw_reset_continual_urb_error ( pdvobjpriv ) ;
if ( requesttype = = 0x01 )
2013-07-10 18:25:07 +00:00
{ /* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( pdata , pIo_buf , len ) ;
}
}
2013-07-10 18:25:07 +00:00
else { /* error cases */
2013-05-25 23:35:42 +00:00
DBG_88E ( " reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d \n "
2013-05-08 21:45:39 +00:00
, value , ( requesttype = = 0x01 ) ? " read " : " write " , len , status , * ( u32 * ) pdata , vendorreq_times ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
if ( status < 0 ) {
2013-05-09 04:04:25 +00:00
if ( status = = ( - ESHUTDOWN ) | | status = = - ENODEV )
2013-05-19 04:28:07 +00:00
{
2013-05-26 03:02:10 +00:00
padapter - > bSurpriseRemoved = true ;
2013-05-08 21:45:39 +00:00
} else {
# ifdef DBG_CONFIG_ERROR_DETECT
{
HAL_DATA_TYPE * pHalData = GET_HAL_DATA ( padapter ) ;
pHalData - > srestpriv . Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL ;
}
# endif
}
}
2013-07-10 18:25:07 +00:00
else /* status != len && status >= 0 */
2013-05-08 21:45:39 +00:00
{
2013-05-09 04:04:25 +00:00
if ( status > 0 ) {
2013-05-08 21:45:39 +00:00
if ( requesttype = = 0x01 )
2013-07-10 18:25:07 +00:00
{ /* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( pdata , pIo_buf , len ) ;
}
}
}
2013-05-26 03:02:10 +00:00
if ( rtw_inc_and_chk_continual_urb_error ( pdvobjpriv ) = = true ) {
padapter - > bSurpriseRemoved = true ;
2013-05-08 21:45:39 +00:00
break ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
/* firmware download is checksumed, don't retry */
2013-05-09 04:04:25 +00:00
if ( ( value > = FW_8188E_START_ADDRESS & & value < = FW_8188E_END_ADDRESS ) | | status = = len )
2013-05-08 21:45:39 +00:00
break ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
/* release IO memory used by vendorreq */
2013-05-08 21:45:39 +00:00
# ifdef CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE
rtw_mfree ( tmp_buf , tmp_buflen ) ;
# endif
release_mutex :
# ifdef CONFIG_USB_VENDOR_REQ_MUTEX
_exit_critical_mutex ( & pdvobjpriv - > usb_vendor_req_mutex , NULL ) ;
# endif
exit :
return status ;
}
static u8 usb_read8 ( struct intf_hdl * pintfhdl , u32 addr )
{
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
u8 data = 0 ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_enter_ ;
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x01 ; /* read_in */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
2013-05-19 04:28:07 +00:00
len = 1 ;
2013-05-08 21:45:39 +00:00
usbctrl_vendorreq ( pintfhdl , request , wvalue , index , & data , len , requesttype ) ;
_func_exit_ ;
return data ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
static u16 usb_read16 ( struct intf_hdl * pintfhdl , u32 addr )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
2013-07-09 22:40:50 +00:00
__le32 data ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:40:50 +00:00
_func_enter_ ;
2013-05-08 21:45:39 +00:00
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x01 ; /* read_in */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
2013-05-19 04:28:07 +00:00
len = 2 ;
2013-05-08 21:45:39 +00:00
usbctrl_vendorreq ( pintfhdl , request , wvalue , index , & data , len , requesttype ) ;
2013-07-09 22:40:50 +00:00
_func_exit_ ;
2013-05-08 21:45:39 +00:00
2013-07-09 22:40:50 +00:00
return ( u16 ) ( le32_to_cpu ( data ) & 0xffff ) ;
2013-05-08 21:45:39 +00:00
}
static u32 usb_read32 ( struct intf_hdl * pintfhdl , u32 addr )
{
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
2013-07-09 22:40:50 +00:00
__le32 data ;
2013-05-19 04:28:07 +00:00
2013-07-09 22:40:50 +00:00
_func_enter_ ;
2013-05-08 21:45:39 +00:00
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x01 ; /* read_in */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
2013-05-19 04:28:07 +00:00
len = 4 ;
2013-05-08 21:45:39 +00:00
usbctrl_vendorreq ( pintfhdl , request , wvalue , index , & data , len , requesttype ) ;
2013-07-09 22:40:50 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-07-09 22:40:50 +00:00
return le32_to_cpu ( data ) ;
2013-05-08 21:45:39 +00:00
}
static int usb_write8 ( struct intf_hdl * pintfhdl , u32 addr , u8 val )
{
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
u8 data ;
int ret ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_enter_ ;
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x00 ; /* write_out */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
len = 1 ;
2013-05-19 04:28:07 +00:00
data = val ;
2013-05-08 21:45:39 +00:00
ret = usbctrl_vendorreq ( pintfhdl , request , wvalue , index , & data , len , requesttype ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
return ret ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
static int usb_write16 ( struct intf_hdl * pintfhdl , u32 addr , u16 val )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
2013-07-09 22:40:50 +00:00
__le32 data ;
2013-05-08 21:45:39 +00:00
int ret ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_enter_ ;
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x00 ; /* write_out */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
len = 2 ;
2013-05-19 04:28:07 +00:00
2013-07-09 22:40:50 +00:00
data = cpu_to_le32 ( val & 0x0000ffff ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
ret = usbctrl_vendorreq ( pintfhdl , request , wvalue , index , & data , len , requesttype ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
return ret ;
}
static int usb_write32 ( struct intf_hdl * pintfhdl , u32 addr , u32 val )
{
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
2013-07-09 22:40:50 +00:00
__le32 data ;
2013-05-08 21:45:39 +00:00
int ret ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_enter_ ;
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x00 ; /* write_out */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
len = 4 ;
2013-07-09 22:40:50 +00:00
data = cpu_to_le32 ( val ) ;
2013-05-08 21:45:39 +00:00
ret = usbctrl_vendorreq ( pintfhdl , request , wvalue , index , & data , len , requesttype ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
return ret ;
}
static int usb_writeN ( struct intf_hdl * pintfhdl , u32 addr , u32 length , u8 * pdata )
{
u8 request ;
u8 requesttype ;
u16 wvalue ;
u16 index ;
u16 len ;
u8 buf [ VENDOR_CMD_MAX_DATA_LEN ] = { 0 } ;
int ret ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_enter_ ;
request = 0x05 ;
2013-07-10 18:25:07 +00:00
requesttype = 0x00 ; /* write_out */
index = 0 ; /* n/a */
2013-05-08 21:45:39 +00:00
wvalue = ( u16 ) ( addr & 0x0000ffff ) ;
len = length ;
_rtw_memcpy ( buf , pdata , len ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
ret = usbctrl_vendorreq ( pintfhdl , request , wvalue , index , buf , len , requesttype ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
return ret ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
# ifdef CONFIG_SUPPORT_USB_INT
2013-06-03 19:52:18 +00:00
static void interrupt_handler_8188eu ( _adapter * padapter , u16 pkt_len , u8 * pbuf )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
HAL_DATA_TYPE * pHalData = GET_HAL_DATA ( padapter ) ;
struct reportpwrstate_parm pwr_rpt ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
if ( pkt_len ! = INTERRUPT_MSG_FORMAT_LEN )
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s Invalid interrupt content length (%d)! \n " , __func__ , pkt_len ) ;
2013-05-08 21:45:39 +00:00
return ;
}
2013-07-10 18:25:07 +00:00
/* HISR */
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( & ( pHalData - > IntArray [ 0 ] ) , & ( pbuf [ USB_INTR_CONTENT_HISR_OFFSET ] ) , 4 ) ;
_rtw_memcpy ( & ( pHalData - > IntArray [ 1 ] ) , & ( pbuf [ USB_INTR_CONTENT_HISRE_OFFSET ] ) , 4 ) ;
# ifdef CONFIG_LPS_LCLK
2013-05-09 04:04:25 +00:00
if ( pHalData - > IntArray [ 0 ] & IMR_CPWM_88E )
2013-05-08 21:45:39 +00:00
{
_rtw_memcpy ( & pwr_rpt . state , & ( pbuf [ USB_INTR_CONTENT_CPWM1_OFFSET ] ) , 1 ) ;
2013-07-10 18:25:07 +00:00
/* 88e's cpwm value only change BIT0, so driver need to add PS_STATE_S2 for LPS flow. */
2013-05-19 04:28:07 +00:00
pwr_rpt . state | = PS_STATE_S2 ;
2013-05-08 21:45:39 +00:00
_set_workitem ( & padapter - > pwrctrlpriv . cpwm_event ) ;
}
2013-07-10 18:25:07 +00:00
# endif /* CONFIG_LPS_LCLK */
2013-05-08 21:45:39 +00:00
# ifdef CONFIG_INTERRUPT_BASED_TXBCN
# ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT
if ( pHalData - > IntArray [ 0 ] & IMR_BCNDMAINT0_88E )
# endif
# ifdef CONFIG_INTERRUPT_BASED_TXBCN_BCN_OK_ERR
if ( pHalData - > IntArray [ 0 ] & ( IMR_TBDER_88E | IMR_TBDOK_88E ) )
2013-05-19 04:28:07 +00:00
# endif
{
2013-05-08 21:45:39 +00:00
struct mlme_priv * pmlmepriv = & padapter - > mlmepriv ;
2013-05-18 21:16:10 +00:00
if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) ) {
2013-05-26 03:02:10 +00:00
if ( pmlmepriv - > update_bcn = = true )
2013-05-08 21:45:39 +00:00
set_tx_beacon_cmd ( padapter ) ;
}
# ifdef CONFIG_CONCURRENT_MODE
2013-05-18 21:16:10 +00:00
if ( check_buddy_fwstate ( padapter , WIFI_AP_STATE ) ) {
2013-05-26 03:02:10 +00:00
if ( padapter - > pbuddy_adapter - > mlmepriv . update_bcn = = true )
2013-05-08 21:45:39 +00:00
set_tx_beacon_cmd ( padapter - > pbuddy_adapter ) ;
}
# endif
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-07-10 18:25:07 +00:00
# endif /* CONFIG_INTERRUPT_BASED_TXBCN */
2013-05-08 21:45:39 +00:00
# ifdef DBG_CONFIG_ERROR_DETECT_INT
2013-05-09 04:04:25 +00:00
if ( pHalData - > IntArray [ 1 ] & IMR_TXERR_88E )
2013-05-25 23:35:42 +00:00
DBG_88E ( " ===> %s Tx Error Flag Interrupt Status \n " , __func__ ) ;
2013-05-09 04:04:25 +00:00
if ( pHalData - > IntArray [ 1 ] & IMR_RXERR_88E )
2013-05-25 23:35:42 +00:00
DBG_88E ( " ===> %s Rx Error Flag INT Status \n " , __func__ ) ;
2013-05-09 04:04:25 +00:00
if ( pHalData - > IntArray [ 1 ] & IMR_TXFOVW_88E )
2013-05-25 23:35:42 +00:00
DBG_88E ( " ===> %s Transmit FIFO Overflow \n " , __func__ ) ;
2013-05-09 04:04:25 +00:00
if ( pHalData - > IntArray [ 1 ] & IMR_RXFOVW_88E )
2013-05-25 23:35:42 +00:00
DBG_88E ( " ===> %s Receive FIFO Overflow \n " , __func__ ) ;
2013-07-10 18:25:07 +00:00
# endif /* DBG_CONFIG_ERROR_DETECT_INT */
2013-05-08 21:45:39 +00:00
2013-07-10 18:25:07 +00:00
/* C2H Event */
2013-05-09 04:04:25 +00:00
if ( pbuf [ 0 ] ! = 0 ) {
2013-05-19 04:28:07 +00:00
_rtw_memcpy ( & ( pHalData - > C2hArray [ 0 ] ) , & ( pbuf [ USB_INTR_CONTENT_C2H_OFFSET ] ) , 16 ) ;
2013-07-10 18:25:07 +00:00
/* rtw_c2h_wk_cmd(padapter); to do.. */
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
}
# endif
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
# ifdef CONFIG_USB_INTERRUPT_IN_PIPE
static void usb_read_interrupt_complete ( struct urb * purb , struct pt_regs * regs )
{
int err ;
_adapter * padapter = ( _adapter * ) purb - > context ;
2013-05-09 04:04:25 +00:00
if ( padapter - > bSurpriseRemoved | | padapter - > bDriverStopped | | padapter - > bReadPortCancel )
2013-05-08 21:45:39 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d) \n " ,
2013-05-09 16:23:32 +00:00
__func__ , padapter - > bDriverStopped , padapter - > bSurpriseRemoved , padapter - > bReadPortCancel ) ;
2013-05-08 21:45:39 +00:00
return ;
}
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
if ( purb - > status = = 0 ) /* SUCCESS */
2013-05-08 21:45:39 +00:00
{
if ( purb - > actual_length > INTERRUPT_MSG_FORMAT_LEN )
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " usb_read_interrupt_complete: purb->actual_length > INTERRUPT_MSG_FORMAT_LEN(%d) \n " , INTERRUPT_MSG_FORMAT_LEN ) ;
2013-05-08 21:45:39 +00:00
}
interrupt_handler_8188eu ( padapter , purb - > actual_length , purb - > transfer_buffer ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
err = usb_submit_urb ( purb , GFP_ATOMIC ) ;
2013-05-09 04:04:25 +00:00
if ( ( err ) & & ( err ! = ( - EPERM ) ) )
2013-05-08 21:45:39 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " cannot submit interrupt in-token(err = 0x%08x),urb_status = %d \n " , err , purb - > status ) ;
2013-05-08 21:45:39 +00:00
}
}
else
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " ###=> usb_read_interrupt_complete => urb status(%d) \n " , purb - > status ) ;
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
switch ( purb - > status ) {
2013-05-08 21:45:39 +00:00
case - EINVAL :
2013-05-19 04:28:07 +00:00
case - EPIPE :
2013-05-08 21:45:39 +00:00
case - ENODEV :
case - ESHUTDOWN :
2013-05-27 22:32:24 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bSurpriseRemoved=true \n " ) ) ;
2013-07-10 18:25:07 +00:00
/* fall through here */
2013-05-08 21:45:39 +00:00
case - ENOENT :
2013-05-26 03:02:10 +00:00
padapter - > bDriverStopped = true ;
2013-05-27 22:32:24 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bDriverStopped=true \n " ) ) ;
2013-05-08 21:45:39 +00:00
break ;
case - EPROTO :
break ;
case - EINPROGRESS :
2013-05-25 23:35:42 +00:00
DBG_88E ( " ERROR: URB IS IN PROGRESS!/n " ) ;
2013-05-08 21:45:39 +00:00
break ;
default :
2013-05-19 04:28:07 +00:00
break ;
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
}
static u32 usb_read_interrupt ( struct intf_hdl * pintfhdl , u32 addr )
{
int err ;
unsigned int pipe ;
u32 ret = _SUCCESS ;
_adapter * adapter = pintfhdl - > padapter ;
struct dvobj_priv * pdvobj = adapter_to_dvobj ( adapter ) ;
struct recv_priv * precvpriv = & adapter - > recvpriv ;
struct usb_device * pusbd = pdvobj - > pusbdev ;
_func_enter_ ;
2013-07-10 18:25:07 +00:00
/* translate DMA FIFO addr to pipehandle */
2013-05-08 21:45:39 +00:00
pipe = ffaddr2pipehdl ( pdvobj , addr ) ;
2013-05-19 04:28:07 +00:00
usb_fill_int_urb ( precvpriv - > int_in_urb , pusbd , pipe ,
2013-05-08 21:45:39 +00:00
precvpriv - > int_in_buf ,
2013-05-19 04:28:07 +00:00
INTERRUPT_MSG_FORMAT_LEN ,
usb_read_interrupt_complete ,
adapter ,
1 ) ;
2013-05-08 21:45:39 +00:00
err = usb_submit_urb ( precvpriv - > int_in_urb , GFP_ATOMIC ) ;
2013-05-09 04:04:25 +00:00
if ( ( err ) & & ( err ! = ( - EPERM ) ) )
2013-05-08 21:45:39 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " cannot submit interrupt in-token(err = 0x%08x),urb_status = %d \n " , err , precvpriv - > int_in_urb - > status ) ;
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
}
_func_exit_ ;
return ret ;
}
# endif
static s32 pre_recv_entry ( union recv_frame * precvframe , struct recv_stat * prxstat , struct phy_stat * pphy_status )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
s32 ret = _SUCCESS ;
2013-05-19 04:28:07 +00:00
# ifdef CONFIG_CONCURRENT_MODE
2013-05-08 21:45:39 +00:00
u8 * primary_myid , * secondary_myid , * paddr1 ;
union recv_frame * precvframe_if2 = NULL ;
_adapter * primary_padapter = precvframe - > u . hdr . adapter ;
_adapter * secondary_padapter = primary_padapter - > pbuddy_adapter ;
struct recv_priv * precvpriv = & primary_padapter - > recvpriv ;
_queue * pfree_recv_queue = & precvpriv - > free_recv_queue ;
u8 * pbuf = precvframe - > u . hdr . rx_data ;
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
if ( ! secondary_padapter )
2013-05-08 21:45:39 +00:00
return ret ;
2013-05-19 04:28:07 +00:00
paddr1 = GetAddr1Ptr ( precvframe - > u . hdr . rx_data ) ;
2013-05-08 21:45:39 +00:00
2013-07-10 18:25:07 +00:00
if ( IS_MCAST ( paddr1 ) = = false ) /* unicast packets */
2013-05-08 21:45:39 +00:00
{
secondary_myid = myid ( & secondary_padapter - > eeprompriv ) ;
2013-05-09 04:04:25 +00:00
if ( _rtw_memcmp ( paddr1 , secondary_myid , ETH_ALEN ) )
2013-05-19 04:28:07 +00:00
{
2013-07-10 18:25:07 +00:00
/* change to secondary interface */
2013-05-08 21:45:39 +00:00
precvframe - > u . hdr . adapter = secondary_padapter ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
}
2013-07-10 18:25:07 +00:00
else /* Handle BC/MC Packets */
2013-05-08 21:45:39 +00:00
{
2013-05-26 03:02:10 +00:00
u8 clone = true ;
2013-05-08 21:45:39 +00:00
2013-05-26 03:02:10 +00:00
if ( true = = clone )
2013-05-08 21:45:39 +00:00
{
2013-07-10 18:25:07 +00:00
/* clone/copy to if2 */
2013-05-08 21:45:39 +00:00
u8 shift_sz = 0 ;
2013-05-19 04:28:07 +00:00
u32 alloc_sz , skb_len ;
2013-05-08 21:45:39 +00:00
_pkt * pkt_copy = NULL ;
struct rx_pkt_attrib * pattrib = NULL ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
precvframe_if2 = rtw_alloc_recvframe ( pfree_recv_queue ) ;
2013-05-09 04:04:25 +00:00
if ( precvframe_if2 )
2013-05-08 21:45:39 +00:00
{
precvframe_if2 - > u . hdr . adapter = secondary_padapter ;
2013-05-19 04:28:07 +00:00
_rtw_init_listhead ( & precvframe_if2 - > u . hdr . list ) ;
2013-07-10 18:25:07 +00:00
precvframe_if2 - > u . hdr . precvbuf = NULL ; /* can't access the precvbuf for new arch. */
2013-05-08 21:45:39 +00:00
precvframe_if2 - > u . hdr . len = 0 ;
_rtw_memcpy ( & precvframe_if2 - > u . hdr . attrib , & precvframe - > u . hdr . attrib , sizeof ( struct rx_pkt_attrib ) ) ;
pattrib = & precvframe_if2 - > u . hdr . attrib ;
2013-07-10 18:25:07 +00:00
/* Modified by Albert 20101213 */
/* For 8 bytes IP header alignment. */
if ( pattrib - > qos ) /* Qos data, wireless lan header length is 26 */
2013-05-08 21:45:39 +00:00
{
shift_sz = 6 ;
}
else
{
shift_sz = 0 ;
}
skb_len = pattrib - > pkt_len ;
2013-07-10 18:25:07 +00:00
/* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
/* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > mfrag = = 1 ) & & ( pattrib - > frag_num = = 0 ) ) {
if ( skb_len < = 1650 )
2013-05-08 21:45:39 +00:00
alloc_sz = 1664 ;
else
alloc_sz = skb_len + 14 ;
}
else {
alloc_sz = skb_len ;
2013-07-10 18:25:07 +00:00
/* 6 is for IP header 8 bytes alignment in QoS packet case. */
/* 8 is for skb->data 4 bytes alignment. */
2013-05-08 21:45:39 +00:00
alloc_sz + = 14 ;
}
2013-07-10 18:25:07 +00:00
# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) /* www.mail-archive.com/netdev@vger.kernel.org/msg17214.html */
2013-05-08 21:45:39 +00:00
pkt_copy = dev_alloc_skb ( alloc_sz ) ;
2013-05-19 04:28:07 +00:00
# else
2013-05-08 21:45:39 +00:00
pkt_copy = netdev_alloc_skb ( secondary_padapter - > pnetdev , alloc_sz ) ;
2013-05-19 04:28:07 +00:00
# endif
2013-05-09 04:04:25 +00:00
if ( pkt_copy )
2013-05-08 21:45:39 +00:00
{
pkt_copy - > dev = secondary_padapter - > pnetdev ;
precvframe_if2 - > u . hdr . pkt = pkt_copy ;
precvframe_if2 - > u . hdr . rx_head = pkt_copy - > data ;
precvframe_if2 - > u . hdr . rx_end = pkt_copy - > data + alloc_sz ;
2013-07-10 18:25:07 +00:00
skb_reserve ( pkt_copy , 8 - ( ( SIZE_PTR ) ( pkt_copy - > data ) & 7 ) ) ; /* force pkt_copy->data at 8-byte alignment address */
skb_reserve ( pkt_copy , shift_sz ) ; /* force ip_hdr at 8-byte alignment address according to shift_sz. */
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( pkt_copy - > data , pbuf , skb_len ) ;
precvframe_if2 - > u . hdr . rx_data = precvframe_if2 - > u . hdr . rx_tail = pkt_copy - > data ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
recvframe_put ( precvframe_if2 , skb_len ) ;
2013-05-19 04:28:07 +00:00
if ( pattrib - > physt )
2013-05-08 21:45:39 +00:00
update_recvframe_phyinfo_88e ( precvframe_if2 , ( struct phy_stat * ) pphy_status ) ;
2013-05-19 04:28:07 +00:00
ret = rtw_recv_entry ( precvframe_if2 ) ;
2013-05-08 21:45:39 +00:00
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
else {
rtw_free_recvframe ( precvframe_if2 , pfree_recv_queue ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s()-%d: alloc_skb() failed! \n " , __func__ , __LINE__ ) ;
2013-05-08 21:45:39 +00:00
}
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
if ( precvframe - > u . hdr . attrib . physt )
2013-05-19 04:28:07 +00:00
update_recvframe_phyinfo_88e ( precvframe , ( struct phy_stat * ) pphy_status ) ;
2013-05-08 21:45:39 +00:00
ret = rtw_recv_entry ( precvframe ) ;
# endif
return ret ;
}
# ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
static int recvbuf2recvframe ( _adapter * padapter , struct recv_buf * precvbuf )
{
u8 * pbuf ;
u8 shift_sz = 0 ;
u16 pkt_cnt , drvinfo_sz ;
u32 pkt_offset , skb_len , alloc_sz ;
s32 transfer_len ;
struct recv_stat * prxstat ;
struct phy_stat * pphy_status = NULL ;
_pkt * pkt_copy = NULL ;
union recv_frame * precvframe = NULL ;
struct rx_pkt_attrib * pattrib = NULL ;
HAL_DATA_TYPE * pHalData = GET_HAL_DATA ( padapter ) ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
_queue * pfree_recv_queue = & precvpriv - > free_recv_queue ;
2013-05-19 04:28:07 +00:00
transfer_len = ( s32 ) precvbuf - > transfer_len ;
2013-05-08 21:45:39 +00:00
pbuf = precvbuf - > pbuf ;
2013-05-19 04:28:07 +00:00
prxstat = ( struct recv_stat * ) pbuf ;
2013-05-08 21:45:39 +00:00
pkt_cnt = ( le32_to_cpu ( prxstat - > rxdw2 ) > > 16 ) & 0xff ;
2013-05-19 04:28:07 +00:00
do {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x \n " ,
prxstat - > rxdw0 , prxstat - > rxdw1 , prxstat - > rxdw2 , prxstat - > rxdw4 ) ) ;
prxstat = ( struct recv_stat * ) pbuf ;
precvframe = rtw_alloc_recvframe ( pfree_recv_queue ) ;
2013-05-09 04:04:25 +00:00
if ( precvframe = = NULL )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recvbuf2recvframe: precvframe==NULL \n " ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s()-%d: rtw_alloc_recvframe() failed! RX Drop! \n " , __func__ , __LINE__ ) ;
2013-05-08 21:45:39 +00:00
goto _exit_recvbuf2recvframe ;
}
2013-05-19 04:28:07 +00:00
_rtw_init_listhead ( & precvframe - > u . hdr . list ) ;
2013-07-10 18:25:07 +00:00
precvframe - > u . hdr . precvbuf = NULL ; /* can't access the precvbuf for new arch. */
2013-05-08 21:45:39 +00:00
precvframe - > u . hdr . len = 0 ;
update_recvframe_attrib_88e ( precvframe , prxstat ) ;
pattrib = & precvframe - > u . hdr . attrib ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
if ( ( pattrib - > crc_err ) | | ( pattrib - > icv_err ) )
{
2013-05-09 04:04:25 +00:00
if ( pattrib - > pkt_len > 2000 ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s: RX Warning! crc_err=%d icv_err=%d, skip! \n " , __func__ , pattrib - > crc_err , pattrib - > icv_err ) ;
2013-05-19 04:28:07 +00:00
# ifdef CONFIG_SPECIAL_SETTING_FOR_FUNAI_TV
2013-05-09 16:23:32 +00:00
printk ( " %s: RX Warning!pkt_len= %d, data rate=0x%02x \n " , __func__ , pattrib - > pkt_len , pattrib - > mcs_rate ) ;
2013-05-08 21:45:39 +00:00
# endif
}
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > physt ) & & ( pattrib - > pkt_rpt_type = = NORMAL_RX ) )
2013-05-08 21:45:39 +00:00
{
pphy_status = ( struct phy_stat * ) ( pbuf + RXDESC_OFFSET ) ;
}
pkt_offset = RXDESC_SIZE + pattrib - > drvinfo_sz + pattrib - > shift_sz + pattrib - > pkt_len ;
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > pkt_len < = 0 ) | | ( pkt_offset > transfer_len ) )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " recvbuf2recvframe: pkt_len<=0 \n " ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s()-%d: RX Warning! \n " , __func__ , __LINE__ ) ;
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
2013-07-10 18:25:07 +00:00
/* Modified by Albert 20101213 */
/* For 8 bytes IP header alignment. */
if ( pattrib - > qos ) /* Qos data, wireless lan header length is 26 */
2013-05-08 21:45:39 +00:00
{
shift_sz = 6 ;
}
else
{
shift_sz = 0 ;
}
skb_len = pattrib - > pkt_len ;
2013-07-10 18:25:07 +00:00
/* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
/* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > mfrag = = 1 ) & & ( pattrib - > frag_num = = 0 ) ) {
if ( skb_len < = 1650 )
2013-05-08 21:45:39 +00:00
alloc_sz = 1664 ;
else
alloc_sz = skb_len + 14 ;
}
else {
alloc_sz = skb_len ;
2013-07-10 18:25:07 +00:00
/* 6 is for IP header 8 bytes alignment in QoS packet case. */
/* 8 is for skb->data 4 bytes alignment. */
2013-05-08 21:45:39 +00:00
alloc_sz + = 14 ;
}
2013-07-10 18:25:07 +00:00
# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) /* www.mail-archive.com/netdev@vger.kernel.org/msg17214.html */
2013-05-08 21:45:39 +00:00
pkt_copy = dev_alloc_skb ( alloc_sz ) ;
2013-05-19 04:28:07 +00:00
# else
2013-05-08 21:45:39 +00:00
pkt_copy = netdev_alloc_skb ( padapter - > pnetdev , alloc_sz ) ;
2013-05-19 04:28:07 +00:00
# endif
2013-05-09 04:04:25 +00:00
if ( pkt_copy )
2013-05-08 21:45:39 +00:00
{
pkt_copy - > dev = padapter - > pnetdev ;
precvframe - > u . hdr . pkt = pkt_copy ;
precvframe - > u . hdr . rx_head = pkt_copy - > data ;
precvframe - > u . hdr . rx_end = pkt_copy - > data + alloc_sz ;
2013-07-10 18:25:07 +00:00
skb_reserve ( pkt_copy , 8 - ( ( SIZE_PTR ) ( pkt_copy - > data ) & 7 ) ) ; /* force pkt_copy->data at 8-byte alignment address */
skb_reserve ( pkt_copy , shift_sz ) ; /* force ip_hdr at 8-byte alignment address according to shift_sz. */
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( pkt_copy - > data , ( pbuf + pattrib - > drvinfo_sz + RXDESC_SIZE ) , skb_len ) ;
precvframe - > u . hdr . rx_data = precvframe - > u . hdr . rx_tail = pkt_copy - > data ;
}
else
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " recvbuf2recvframe:can not allocate memory for skb copy \n " ) ;
2013-05-08 21:45:39 +00:00
precvframe - > u . hdr . pkt = NULL ;
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
recvframe_put ( precvframe , skb_len ) ;
# ifdef CONFIG_USB_RX_AGGREGATION
2013-05-09 04:04:25 +00:00
switch ( pHalData - > UsbRxAggMode )
2013-05-08 21:45:39 +00:00
{
case USB_RX_AGG_DMA :
case USB_RX_AGG_MIX :
pkt_offset = ( u16 ) _RND128 ( pkt_offset ) ;
break ;
case USB_RX_AGG_USB :
pkt_offset = ( u16 ) _RND4 ( pkt_offset ) ;
break ;
2013-05-19 04:28:07 +00:00
case USB_RX_AGG_DISABLE :
default :
2013-05-08 21:45:39 +00:00
break ;
}
# endif
2013-07-10 18:25:07 +00:00
if ( pattrib - > pkt_rpt_type = = NORMAL_RX ) /* Normal rx packet */
2013-05-08 21:45:39 +00:00
{
# ifdef CONFIG_CONCURRENT_MODE
2013-05-09 04:04:25 +00:00
if ( rtw_buddy_adapter_up ( padapter ) )
2013-05-08 21:45:39 +00:00
{
2013-05-09 04:04:25 +00:00
if ( pre_recv_entry ( precvframe , prxstat , pphy_status ) ! = _SUCCESS )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS \n " ) ) ;
}
}
else
2013-05-19 04:28:07 +00:00
# endif
2013-05-08 21:45:39 +00:00
{
2013-05-19 04:28:07 +00:00
if ( pattrib - > physt )
2013-05-08 21:45:39 +00:00
update_recvframe_phyinfo_88e ( precvframe , ( struct phy_stat * ) pphy_status ) ;
2013-05-09 04:04:25 +00:00
if ( rtw_recv_entry ( precvframe ) ! = _SUCCESS )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS \n " ) ) ;
}
}
}
2013-07-10 18:25:07 +00:00
else { /* pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP */
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
/* enqueue recvframe to txrtp queue */
2013-05-09 04:04:25 +00:00
if ( pattrib - > pkt_rpt_type = = TX_REPORT1 ) {
2013-07-10 18:25:07 +00:00
/* CCX-TXRPT ack for xmit mgmt frames. */
2013-05-08 21:45:39 +00:00
handle_txrpt_ccx_88e ( padapter , precvframe - > u . hdr . rx_data ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-09 04:04:25 +00:00
else if ( pattrib - > pkt_rpt_type = = TX_REPORT2 ) {
2013-05-08 21:45:39 +00:00
ODM_RA_TxRPT2Handle_8188E (
& pHalData - > odmpriv ,
precvframe - > u . hdr . rx_data ,
pattrib - > pkt_len ,
pattrib - > MacIDValidEntry [ 0 ] ,
pattrib - > MacIDValidEntry [ 1 ]
) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-09 04:04:25 +00:00
else if ( pattrib - > pkt_rpt_type = = HIS_REPORT )
2013-05-08 21:45:39 +00:00
{
# ifdef CONFIG_SUPPORT_USB_INT
interrupt_handler_8188eu ( padapter , pattrib - > pkt_len , precvframe - > u . hdr . rx_data ) ;
# endif
2013-05-19 04:28:07 +00:00
}
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
}
2013-05-08 21:45:39 +00:00
pkt_cnt - - ;
transfer_len - = pkt_offset ;
2013-05-19 04:28:07 +00:00
pbuf + = pkt_offset ;
2013-05-08 21:45:39 +00:00
precvframe = NULL ;
pkt_copy = NULL ;
2013-05-09 04:04:25 +00:00
if ( transfer_len > 0 & & pkt_cnt = = 0 )
2013-05-08 21:45:39 +00:00
pkt_cnt = ( le32_to_cpu ( prxstat - > rxdw2 ) > > 16 ) & 0xff ;
2013-05-09 04:04:25 +00:00
} while ( ( transfer_len > 0 ) & & ( pkt_cnt > 0 ) ) ;
2013-05-08 21:45:39 +00:00
_exit_recvbuf2recvframe :
return _SUCCESS ;
}
void rtl8188eu_recv_tasklet ( void * priv )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
struct recv_buf * precvbuf = NULL ;
_adapter * padapter = ( _adapter * ) priv ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
while ( NULL ! = ( precvbuf = rtw_dequeue_recvbuf ( & precvpriv - > recv_buf_pending_queue ) ) )
{
2013-05-26 03:02:10 +00:00
if ( ( padapter - > bDriverStopped = = true ) | | ( padapter - > bSurpriseRemoved = = true ) )
2013-05-08 21:45:39 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " recv_tasklet => bDriverStopped or bSurpriseRemoved \n " ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
break ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
recvbuf2recvframe ( padapter , precvbuf ) ;
rtw_read_port ( padapter , precvpriv - > ff_hwaddr , 0 , ( unsigned char * ) precvbuf ) ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
}
static void usb_read_port_complete ( struct urb * purb , struct pt_regs * regs )
2013-05-19 04:28:07 +00:00
{
struct recv_buf * precvbuf = ( struct recv_buf * ) purb - > context ;
_adapter * padapter = ( _adapter * ) precvbuf - > adapter ;
2013-05-08 21:45:39 +00:00
struct recv_priv * precvpriv = & padapter - > recvpriv ;
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete!!! \n " ) ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
precvpriv - > rx_pending_cnt - - ;
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
if ( padapter - > bSurpriseRemoved | | padapter - > bDriverStopped | | padapter - > bReadPortCancel )
2013-05-08 21:45:39 +00:00
{
2013-05-19 04:28:07 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d) \n " , padapter - > bDriverStopped , padapter - > bSurpriseRemoved ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d) \n " ,
2013-05-19 04:28:07 +00:00
__func__ , padapter - > bDriverStopped , padapter - > bSurpriseRemoved , padapter - > bReadPortCancel ) ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-07-10 18:25:07 +00:00
if ( purb - > status = = 0 ) /* SUCCESS */
2013-05-08 21:45:39 +00:00
{
if ( ( purb - > actual_length > MAX_RECVBUF_SZ ) | | ( purb - > actual_length < RXDESC_SIZE ) )
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE) \n " ) ) ;
rtw_read_port ( padapter , precvpriv - > ff_hwaddr , 0 , ( unsigned char * ) precvbuf ) ;
}
2013-05-19 04:28:07 +00:00
else
{
2013-05-08 21:45:39 +00:00
rtw_reset_continual_urb_error ( adapter_to_dvobj ( padapter ) ) ;
2013-05-19 04:28:07 +00:00
precvbuf - > transfer_len = purb - > actual_length ;
2013-05-08 21:45:39 +00:00
rtw_enqueue_recvbuf ( precvbuf , & precvpriv - > recv_buf_pending_queue ) ;
2013-05-19 04:28:07 +00:00
tasklet_schedule ( & precvpriv - > recv_tasklet ) ;
}
2013-05-08 21:45:39 +00:00
}
else
{
2013-05-09 04:09:18 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete : purb->status(%d) != 0 \n " , purb - > status ) ) ;
2013-05-19 04:28:07 +00:00
2013-05-25 23:35:42 +00:00
DBG_88E ( " ###=> usb_read_port_complete => urb status(%d) \n " , purb - > status ) ;
2013-05-08 21:45:39 +00:00
2013-05-26 03:02:10 +00:00
if ( rtw_inc_and_chk_continual_urb_error ( adapter_to_dvobj ( padapter ) ) = = true ) {
padapter - > bSurpriseRemoved = true ;
2013-05-08 21:45:39 +00:00
}
2013-05-09 04:04:25 +00:00
switch ( purb - > status ) {
2013-05-08 21:45:39 +00:00
case - EINVAL :
2013-05-19 04:28:07 +00:00
case - EPIPE :
2013-05-08 21:45:39 +00:00
case - ENODEV :
case - ESHUTDOWN :
2013-05-27 22:32:24 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bSurpriseRemoved=true \n " ) ) ;
2013-07-10 18:25:07 +00:00
/* fall through here */
2013-05-08 21:45:39 +00:00
case - ENOENT :
2013-05-26 03:02:10 +00:00
padapter - > bDriverStopped = true ;
2013-05-27 22:32:24 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bDriverStopped=true \n " ) ) ;
2013-05-08 21:45:39 +00:00
break ;
case - EPROTO :
case - EOVERFLOW :
2013-05-19 04:28:07 +00:00
# ifdef DBG_CONFIG_ERROR_DETECT
{
2013-05-08 21:45:39 +00:00
HAL_DATA_TYPE * pHalData = GET_HAL_DATA ( padapter ) ;
2013-05-19 04:28:07 +00:00
pHalData - > srestpriv . Wifi_Error_Status = USB_READ_PORT_FAIL ;
2013-05-08 21:45:39 +00:00
}
# endif
2013-05-19 04:28:07 +00:00
rtw_read_port ( padapter , precvpriv - > ff_hwaddr , 0 , ( unsigned char * ) precvbuf ) ;
2013-05-08 21:45:39 +00:00
break ;
case - EINPROGRESS :
2013-05-25 23:35:42 +00:00
DBG_88E ( " ERROR: URB IS IN PROGRESS!/n " ) ;
2013-05-08 21:45:39 +00:00
break ;
default :
2013-05-19 04:28:07 +00:00
break ;
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
}
exit :
2013-05-08 21:45:39 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
static u32 usb_read_port ( struct intf_hdl * pintfhdl , u32 addr , u32 cnt , u8 * rmem )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
int err ;
unsigned int pipe ;
u32 ret = _SUCCESS ;
2013-05-19 04:28:07 +00:00
PURB purb = NULL ;
2013-05-08 21:45:39 +00:00
struct recv_buf * precvbuf = ( struct recv_buf * ) rmem ;
_adapter * adapter = pintfhdl - > padapter ;
struct dvobj_priv * pdvobj = adapter_to_dvobj ( adapter ) ;
struct recv_priv * precvpriv = & adapter - > recvpriv ;
struct usb_device * pusbd = pdvobj - > pusbdev ;
_func_enter_ ;
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
if ( adapter - > bDriverStopped | | adapter - > bSurpriseRemoved | | adapter - > pwrctrlpriv . pnp_bstop_trx )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!! \n " ) ) ;
return _FAIL ;
}
2013-05-09 04:04:25 +00:00
if ( precvbuf ! = NULL )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
rtl8188eu_init_recvbuf ( adapter , precvbuf ) ;
2013-05-09 04:04:25 +00:00
if ( precvbuf - > pbuf )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
precvpriv - > rx_pending_cnt + + ;
2013-05-19 04:28:07 +00:00
purb = precvbuf - > purb ;
2013-05-08 21:45:39 +00:00
2013-07-10 18:25:07 +00:00
/* translate DMA FIFO addr to pipehandle */
2013-05-19 04:28:07 +00:00
pipe = ffaddr2pipehdl ( pdvobj , addr ) ;
2013-05-08 21:45:39 +00:00
2013-05-19 04:28:07 +00:00
usb_fill_bulk_urb ( purb , pusbd , pipe ,
2013-05-08 21:45:39 +00:00
precvbuf - > pbuf ,
2013-05-19 04:28:07 +00:00
MAX_RECVBUF_SZ ,
usb_read_port_complete ,
2013-07-10 18:25:07 +00:00
precvbuf ) ; /* context is precvbuf */
2013-05-08 21:45:39 +00:00
purb - > transfer_dma = precvbuf - > dma_transfer_addr ;
2013-05-19 04:28:07 +00:00
purb - > transfer_flags | = URB_NO_TRANSFER_DMA_MAP ;
2013-05-08 21:45:39 +00:00
2013-05-19 04:28:07 +00:00
err = usb_submit_urb ( purb , GFP_ATOMIC ) ;
2013-05-09 04:04:25 +00:00
if ( ( err ) & & ( err ! = ( - EPERM ) ) )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x " , err , purb - > status ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " cannot submit rx in-token(err = 0x%08x),urb_status = %d \n " , err , purb - > status ) ;
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
else
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port:precvbuf ==NULL \n " ) ) ;
ret = _FAIL ;
}
_func_exit_ ;
return ret ;
}
2013-07-10 18:25:07 +00:00
# else /* CONFIG_USE_USB_BUFFER_ALLOC_RX */
2013-05-08 21:45:39 +00:00
static int recvbuf2recvframe ( _adapter * padapter , _pkt * pskb )
{
u8 * pbuf ;
u8 shift_sz = 0 ;
u16 pkt_cnt ;
u32 pkt_offset , skb_len , alloc_sz ;
s32 transfer_len ;
struct recv_stat * prxstat ;
struct phy_stat * pphy_status = NULL ;
_pkt * pkt_copy = NULL ;
union recv_frame * precvframe = NULL ;
struct rx_pkt_attrib * pattrib = NULL ;
HAL_DATA_TYPE * pHalData = GET_HAL_DATA ( padapter ) ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
_queue * pfree_recv_queue = & precvpriv - > free_recv_queue ;
2013-05-19 04:28:07 +00:00
transfer_len = ( s32 ) pskb - > len ;
2013-05-08 21:45:39 +00:00
pbuf = pskb - > data ;
2013-05-19 04:28:07 +00:00
prxstat = ( struct recv_stat * ) pbuf ;
2013-05-08 21:45:39 +00:00
pkt_cnt = ( le32_to_cpu ( prxstat - > rxdw2 ) > > 16 ) & 0xff ;
2013-05-19 04:28:07 +00:00
do {
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ ,
( " recvbuf2recvframe: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x \n " ,
prxstat - > rxdw0 , prxstat - > rxdw1 , prxstat - > rxdw2 , prxstat - > rxdw4 ) ) ;
prxstat = ( struct recv_stat * ) pbuf ;
precvframe = rtw_alloc_recvframe ( pfree_recv_queue ) ;
2013-05-09 04:04:25 +00:00
if ( precvframe = = NULL )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ , ( " recvbuf2recvframe: precvframe==NULL \n " ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s()-%d: rtw_alloc_recvframe() failed! RX Drop! \n " , __func__ , __LINE__ ) ;
2013-05-08 21:45:39 +00:00
goto _exit_recvbuf2recvframe ;
}
2013-05-19 04:28:07 +00:00
_rtw_init_listhead ( & precvframe - > u . hdr . list ) ;
2013-07-10 18:25:07 +00:00
precvframe - > u . hdr . precvbuf = NULL ; /* can't access the precvbuf for new arch. */
2013-05-08 21:45:39 +00:00
precvframe - > u . hdr . len = 0 ;
update_recvframe_attrib_88e ( precvframe , prxstat ) ;
2013-05-19 04:28:07 +00:00
pattrib = & precvframe - > u . hdr . attrib ;
2013-05-08 21:45:39 +00:00
if ( ( pattrib - > crc_err ) | | ( pattrib - > icv_err ) )
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s: RX Warning! crc_err=%d icv_err=%d, skip! \n " , __func__ , pattrib - > crc_err , pattrib - > icv_err ) ;
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > physt ) & & ( pattrib - > pkt_rpt_type = = NORMAL_RX ) )
2013-05-08 21:45:39 +00:00
{
pphy_status = ( struct phy_stat * ) ( pbuf + RXDESC_OFFSET ) ;
}
pkt_offset = RXDESC_SIZE + pattrib - > drvinfo_sz + pattrib - > shift_sz + pattrib - > pkt_len ;
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > pkt_len < = 0 ) | | ( pkt_offset > transfer_len ) )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_info_ , ( " recvbuf2recvframe: pkt_len<=0 \n " ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfoer_len \n " , __func__ , __LINE__ ) ;
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
/* Modified by Albert 20101213 */
/* For 8 bytes IP header alignment. */
if ( pattrib - > qos ) /* Qos data, wireless lan header length is 26 */
2013-05-08 21:45:39 +00:00
{
shift_sz = 6 ;
}
else
{
shift_sz = 0 ;
}
skb_len = pattrib - > pkt_len ;
2013-07-10 18:25:07 +00:00
/* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
/* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > mfrag = = 1 ) & & ( pattrib - > frag_num = = 0 ) ) {
if ( skb_len < = 1650 )
2013-05-08 21:45:39 +00:00
alloc_sz = 1664 ;
else
alloc_sz = skb_len + 14 ;
}
else {
alloc_sz = skb_len ;
2013-07-10 18:25:07 +00:00
/* 6 is for IP header 8 bytes alignment in QoS packet case. */
/* 8 is for skb->data 4 bytes alignment. */
2013-05-08 21:45:39 +00:00
alloc_sz + = 14 ;
}
2013-07-10 18:25:07 +00:00
# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) /* www.mail-archive.com/netdev@vger.kernel.org/msg17214.html */
2013-05-08 21:45:39 +00:00
pkt_copy = dev_alloc_skb ( alloc_sz ) ;
2013-05-19 04:28:07 +00:00
# else
2013-05-08 21:45:39 +00:00
pkt_copy = netdev_alloc_skb ( padapter - > pnetdev , alloc_sz ) ;
2013-05-19 04:28:07 +00:00
# endif
2013-05-09 04:04:25 +00:00
if ( pkt_copy )
2013-05-08 21:45:39 +00:00
{
pkt_copy - > dev = padapter - > pnetdev ;
precvframe - > u . hdr . pkt = pkt_copy ;
precvframe - > u . hdr . rx_head = pkt_copy - > data ;
precvframe - > u . hdr . rx_end = pkt_copy - > data + alloc_sz ;
2013-07-10 18:25:07 +00:00
skb_reserve ( pkt_copy , 8 - ( ( SIZE_PTR ) ( pkt_copy - > data ) & 7 ) ) ; /* force pkt_copy->data at 8-byte alignment address */
skb_reserve ( pkt_copy , shift_sz ) ; /* force ip_hdr at 8-byte alignment address according to shift_sz. */
2013-05-08 21:45:39 +00:00
_rtw_memcpy ( pkt_copy - > data , ( pbuf + pattrib - > drvinfo_sz + RXDESC_SIZE ) , skb_len ) ;
precvframe - > u . hdr . rx_data = precvframe - > u . hdr . rx_tail = pkt_copy - > data ;
}
else
{
2013-05-09 04:04:25 +00:00
if ( ( pattrib - > mfrag = = 1 ) & & ( pattrib - > frag_num = = 0 ) )
2013-05-19 04:28:07 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " recvbuf2recvframe: alloc_skb fail , drop frag frame \n " ) ;
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
precvframe - > u . hdr . pkt = skb_clone ( pskb , GFP_ATOMIC ) ;
2013-05-09 04:04:25 +00:00
if ( precvframe - > u . hdr . pkt )
2013-05-08 21:45:39 +00:00
{
2013-05-19 04:28:07 +00:00
precvframe - > u . hdr . rx_head = precvframe - > u . hdr . rx_data = precvframe - > u . hdr . rx_tail
2013-05-08 21:45:39 +00:00
= pbuf + pattrib - > drvinfo_sz + RXDESC_SIZE ;
precvframe - > u . hdr . rx_end = pbuf + pattrib - > drvinfo_sz + RXDESC_SIZE + alloc_sz ;
}
else
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " recvbuf2recvframe: skb_clone fail \n " ) ;
2013-05-08 21:45:39 +00:00
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
goto _exit_recvbuf2recvframe ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
recvframe_put ( precvframe , skb_len ) ;
# ifdef CONFIG_USB_RX_AGGREGATION
2013-05-09 04:04:25 +00:00
switch ( pHalData - > UsbRxAggMode )
2013-05-08 21:45:39 +00:00
{
case USB_RX_AGG_DMA :
case USB_RX_AGG_MIX :
pkt_offset = ( u16 ) _RND128 ( pkt_offset ) ;
break ;
case USB_RX_AGG_USB :
pkt_offset = ( u16 ) _RND4 ( pkt_offset ) ;
break ;
2013-05-19 04:28:07 +00:00
case USB_RX_AGG_DISABLE :
default :
2013-05-08 21:45:39 +00:00
break ;
}
# endif
2013-07-10 18:25:07 +00:00
if ( pattrib - > pkt_rpt_type = = NORMAL_RX ) /* Normal rx packet */
2013-05-08 21:45:39 +00:00
{
# ifdef CONFIG_CONCURRENT_MODE
2013-05-09 04:04:25 +00:00
if ( rtw_buddy_adapter_up ( padapter ) )
2013-05-08 21:45:39 +00:00
{
2013-05-09 04:04:25 +00:00
if ( pre_recv_entry ( precvframe , prxstat , pphy_status ) ! = _SUCCESS )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " recvbuf2recvframe: recv_entry(precvframe) != _SUCCESS \n " ) ) ;
}
}
else
# endif
{
2013-05-19 04:28:07 +00:00
if ( pattrib - > physt )
2013-05-08 21:45:39 +00:00
update_recvframe_phyinfo_88e ( precvframe , ( struct phy_stat * ) pphy_status ) ;
2013-05-09 04:04:25 +00:00
if ( rtw_recv_entry ( precvframe ) ! = _SUCCESS )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_rtl871x_recv_c_ , _drv_err_ ,
( " recvbuf2recvframe: rtw_recv_entry(precvframe) != _SUCCESS \n " ) ) ;
}
}
}
2013-07-10 18:25:07 +00:00
else { /* pkt_rpt_type == TX_REPORT1-CCX, TX_REPORT2-TX RTP,HIS_REPORT-USB HISR RTP */
2013-05-19 04:28:07 +00:00
2013-07-10 18:25:07 +00:00
/* enqueue recvframe to txrtp queue */
2013-05-09 04:04:25 +00:00
if ( pattrib - > pkt_rpt_type = = TX_REPORT1 ) {
2013-07-10 18:25:07 +00:00
/* CCX-TXRPT ack for xmit mgmt frames. */
2013-05-08 21:45:39 +00:00
handle_txrpt_ccx_88e ( padapter , precvframe - > u . hdr . rx_data ) ;
}
2013-05-09 04:04:25 +00:00
else if ( pattrib - > pkt_rpt_type = = TX_REPORT2 ) {
2013-05-08 21:45:39 +00:00
ODM_RA_TxRPT2Handle_8188E (
& pHalData - > odmpriv ,
precvframe - > u . hdr . rx_data ,
pattrib - > pkt_len ,
pattrib - > MacIDValidEntry [ 0 ] ,
pattrib - > MacIDValidEntry [ 1 ]
) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-09 04:04:25 +00:00
else if ( pattrib - > pkt_rpt_type = = HIS_REPORT )
2013-05-08 21:45:39 +00:00
{
# ifdef CONFIG_SUPPORT_USB_INT
interrupt_handler_8188eu ( padapter , pattrib - > pkt_len , precvframe - > u . hdr . rx_data ) ;
# endif
2013-05-19 04:28:07 +00:00
}
rtw_free_recvframe ( precvframe , pfree_recv_queue ) ;
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
pkt_cnt - - ;
transfer_len - = pkt_offset ;
2013-05-19 04:28:07 +00:00
pbuf + = pkt_offset ;
2013-05-08 21:45:39 +00:00
precvframe = NULL ;
pkt_copy = NULL ;
2013-05-09 04:04:25 +00:00
if ( transfer_len > 0 & & pkt_cnt = = 0 )
2013-05-08 21:45:39 +00:00
pkt_cnt = ( le32_to_cpu ( prxstat - > rxdw2 ) > > 16 ) & 0xff ;
2013-05-09 04:04:25 +00:00
} while ( ( transfer_len > 0 ) & & ( pkt_cnt > 0 ) ) ;
2013-05-08 21:45:39 +00:00
_exit_recvbuf2recvframe :
2013-05-19 04:28:07 +00:00
return _SUCCESS ;
2013-05-08 21:45:39 +00:00
}
void rtl8188eu_recv_tasklet ( void * priv )
{
_pkt * pskb ;
_adapter * padapter = ( _adapter * ) priv ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
while ( NULL ! = ( pskb = skb_dequeue ( & precvpriv - > rx_skb_queue ) ) )
{
2013-05-26 03:02:10 +00:00
if ( ( padapter - > bDriverStopped = = true ) | | ( padapter - > bSurpriseRemoved = = true ) )
2013-05-08 21:45:39 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " recv_tasklet => bDriverStopped or bSurpriseRemoved \n " ) ;
2013-05-08 21:45:39 +00:00
dev_kfree_skb_any ( pskb ) ;
break ;
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
recvbuf2recvframe ( padapter , pskb ) ;
# ifdef CONFIG_PREALLOC_RECV_SKB
skb_reset_tail_pointer ( pskb ) ;
pskb - > len = 0 ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
skb_queue_tail ( & precvpriv - > free_recv_skb_queue , pskb ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
# else
dev_kfree_skb_any ( pskb ) ;
# endif
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
static void usb_read_port_complete ( struct urb * purb , struct pt_regs * regs )
{
_irqL irqL ;
uint isevt , * pbuf ;
2013-05-19 04:28:07 +00:00
struct recv_buf * precvbuf = ( struct recv_buf * ) purb - > context ;
_adapter * padapter = ( _adapter * ) precvbuf - > adapter ;
struct recv_priv * precvpriv = & padapter - > recvpriv ;
2013-05-08 21:45:39 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete!!! \n " ) ) ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
precvpriv - > rx_pending_cnt - - ;
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
if ( padapter - > bSurpriseRemoved | | padapter - > bDriverStopped | | padapter - > bReadPortCancel )
2013-05-08 21:45:39 +00:00
{
2013-05-19 04:28:07 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d) \n " , padapter - > bDriverStopped , padapter - > bSurpriseRemoved ) ) ;
2013-05-08 21:45:39 +00:00
# ifdef CONFIG_PREALLOC_RECV_SKB
2013-05-26 03:02:10 +00:00
precvbuf - > reuse = true ;
2013-05-08 21:45:39 +00:00
# else
2013-05-09 04:04:25 +00:00
if ( precvbuf - > pskb ) {
2013-05-25 23:35:42 +00:00
DBG_88E ( " ==> free skb(%p) \n " , precvbuf - > pskb ) ;
2013-05-19 04:28:07 +00:00
dev_kfree_skb_any ( precvbuf - > pskb ) ;
}
2013-05-08 21:45:39 +00:00
# endif
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d) \n " ,
2013-05-19 04:28:07 +00:00
__func__ , padapter - > bDriverStopped , padapter - > bSurpriseRemoved , padapter - > bReadPortCancel ) ;
2013-05-08 21:45:39 +00:00
goto exit ;
}
2013-07-10 18:25:07 +00:00
if ( purb - > status = = 0 ) /* SUCCESS */
2013-05-08 21:45:39 +00:00
{
if ( ( purb - > actual_length > MAX_RECVBUF_SZ ) | | ( purb - > actual_length < RXDESC_SIZE ) )
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE) \n " ) ) ;
2013-05-26 03:02:10 +00:00
precvbuf - > reuse = true ;
2013-05-08 21:45:39 +00:00
rtw_read_port ( padapter , precvpriv - > ff_hwaddr , 0 , ( unsigned char * ) precvbuf ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " %s()-%d: RX Warning! \n " , __func__ , __LINE__ ) ;
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
else
{
2013-05-08 21:45:39 +00:00
rtw_reset_continual_urb_error ( adapter_to_dvobj ( padapter ) ) ;
2013-05-19 04:28:07 +00:00
precvbuf - > transfer_len = purb - > actual_length ;
skb_put ( precvbuf - > pskb , purb - > actual_length ) ;
2013-05-08 21:45:39 +00:00
skb_queue_tail ( & precvpriv - > rx_skb_queue , precvbuf - > pskb ) ;
if ( skb_queue_len ( & precvpriv - > rx_skb_queue ) < = 1 )
tasklet_schedule ( & precvpriv - > recv_tasklet ) ;
precvbuf - > pskb = NULL ;
2013-05-26 03:02:10 +00:00
precvbuf - > reuse = false ;
2013-05-19 04:28:07 +00:00
rtw_read_port ( padapter , precvpriv - > ff_hwaddr , 0 , ( unsigned char * ) precvbuf ) ;
}
2013-05-08 21:45:39 +00:00
}
else
{
2013-05-09 04:09:18 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete : purb->status(%d) != 0 \n " , purb - > status ) ) ;
2013-05-19 04:28:07 +00:00
2013-05-25 23:35:42 +00:00
DBG_88E ( " ###=> usb_read_port_complete => urb status(%d) \n " , purb - > status ) ;
2013-05-08 21:45:39 +00:00
2013-05-26 03:02:10 +00:00
if ( rtw_inc_and_chk_continual_urb_error ( adapter_to_dvobj ( padapter ) ) = = true ) {
padapter - > bSurpriseRemoved = true ;
2013-05-08 21:45:39 +00:00
}
2013-05-09 04:04:25 +00:00
switch ( purb - > status ) {
2013-05-08 21:45:39 +00:00
case - EINVAL :
2013-05-19 04:28:07 +00:00
case - EPIPE :
2013-05-08 21:45:39 +00:00
case - ENODEV :
case - ESHUTDOWN :
2013-05-27 22:32:24 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bSurpriseRemoved=true \n " ) ) ;
2013-05-08 21:45:39 +00:00
case - ENOENT :
2013-05-26 03:02:10 +00:00
padapter - > bDriverStopped = true ;
2013-05-27 22:32:24 +00:00
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port_complete:bDriverStopped=true \n " ) ) ;
2013-05-08 21:45:39 +00:00
break ;
case - EPROTO :
case - EOVERFLOW :
2013-05-19 04:28:07 +00:00
# ifdef DBG_CONFIG_ERROR_DETECT
{
2013-05-08 21:45:39 +00:00
HAL_DATA_TYPE * pHalData = GET_HAL_DATA ( padapter ) ;
2013-05-19 04:28:07 +00:00
pHalData - > srestpriv . Wifi_Error_Status = USB_READ_PORT_FAIL ;
2013-05-08 21:45:39 +00:00
}
# endif
2013-05-26 03:02:10 +00:00
precvbuf - > reuse = true ;
2013-05-19 04:28:07 +00:00
rtw_read_port ( padapter , precvpriv - > ff_hwaddr , 0 , ( unsigned char * ) precvbuf ) ;
2013-05-08 21:45:39 +00:00
break ;
case - EINPROGRESS :
2013-05-25 23:35:42 +00:00
DBG_88E ( " ERROR: URB IS IN PROGRESS!/n " ) ;
2013-05-08 21:45:39 +00:00
break ;
default :
2013-05-19 04:28:07 +00:00
break ;
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
}
exit :
2013-05-08 21:45:39 +00:00
_func_exit_ ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
static u32 usb_read_port ( struct intf_hdl * pintfhdl , u32 addr , u32 cnt , u8 * rmem )
2013-05-19 04:28:07 +00:00
{
2013-05-08 21:45:39 +00:00
_irqL irqL ;
int err ;
unsigned int pipe ;
SIZE_PTR tmpaddr = 0 ;
SIZE_PTR alignment = 0 ;
u32 ret = _SUCCESS ;
PURB purb = NULL ;
struct recv_buf * precvbuf = ( struct recv_buf * ) rmem ;
_adapter * adapter = pintfhdl - > padapter ;
struct dvobj_priv * pdvobj = adapter_to_dvobj ( adapter ) ;
struct recv_priv * precvpriv = & adapter - > recvpriv ;
struct usb_device * pusbd = pdvobj - > pusbdev ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
_func_enter_ ;
2013-05-19 04:28:07 +00:00
2013-05-09 04:04:25 +00:00
if ( adapter - > bDriverStopped | | adapter - > bSurpriseRemoved | | adapter - > pwrctrlpriv . pnp_bstop_trx )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!! \n " ) ) ;
return _FAIL ;
}
# ifdef CONFIG_PREALLOC_RECV_SKB
2013-05-26 03:02:10 +00:00
if ( ( precvbuf - > reuse = = false ) | | ( precvbuf - > pskb = = NULL ) )
2013-05-08 21:45:39 +00:00
{
if ( NULL ! = ( precvbuf - > pskb = skb_dequeue ( & precvpriv - > free_recv_skb_queue ) ) )
{
2013-05-26 03:02:10 +00:00
precvbuf - > reuse = true ;
2013-05-08 21:45:39 +00:00
}
}
# endif
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
2013-05-09 04:04:25 +00:00
if ( precvbuf ! = NULL )
2013-05-19 04:28:07 +00:00
{
rtl8188eu_init_recvbuf ( adapter , precvbuf ) ;
2013-05-08 21:45:39 +00:00
2013-07-10 18:25:07 +00:00
/* re-assign for linux based on skb */
2013-05-26 03:02:10 +00:00
if ( ( precvbuf - > reuse = = false ) | | ( precvbuf - > pskb = = NULL ) )
2013-05-08 21:45:39 +00:00
{
2013-07-10 18:25:07 +00:00
# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) /* www.mail-archive.com/netdev@vger.kernel.org/msg17214.html */
2013-05-08 21:45:39 +00:00
precvbuf - > pskb = dev_alloc_skb ( MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ ) ;
2013-05-19 04:28:07 +00:00
# else
2013-05-08 21:45:39 +00:00
precvbuf - > pskb = netdev_alloc_skb ( adapter - > pnetdev , MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ ) ;
2013-05-19 04:28:07 +00:00
# endif
if ( precvbuf - > pskb = = NULL )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " init_recvbuf(): alloc_skb fail! \n " ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " #### usb_read_port() alloc_skb fail!##### \n " ) ;
2013-05-08 21:45:39 +00:00
return _FAIL ;
2013-05-19 04:28:07 +00:00
}
2013-05-08 21:45:39 +00:00
tmpaddr = ( SIZE_PTR ) precvbuf - > pskb - > data ;
2013-05-19 04:28:07 +00:00
alignment = tmpaddr & ( RECVBUFF_ALIGN_SZ - 1 ) ;
2013-05-08 21:45:39 +00:00
skb_reserve ( precvbuf - > pskb , ( RECVBUFF_ALIGN_SZ - alignment ) ) ;
precvbuf - > phead = precvbuf - > pskb - > head ;
2013-05-19 04:28:07 +00:00
precvbuf - > pdata = precvbuf - > pskb - > data ;
2013-05-08 21:45:39 +00:00
precvbuf - > ptail = skb_tail_pointer ( precvbuf - > pskb ) ;
precvbuf - > pend = skb_end_pointer ( precvbuf - > pskb ) ;
precvbuf - > pbuf = precvbuf - > pskb - > data ;
2013-05-19 04:28:07 +00:00
}
2013-07-10 18:25:07 +00:00
else /* reuse skb */
2013-05-08 21:45:39 +00:00
{
precvbuf - > phead = precvbuf - > pskb - > head ;
precvbuf - > pdata = precvbuf - > pskb - > data ;
precvbuf - > ptail = skb_tail_pointer ( precvbuf - > pskb ) ;
precvbuf - > pend = skb_end_pointer ( precvbuf - > pskb ) ;
2013-05-19 04:28:07 +00:00
precvbuf - > pbuf = precvbuf - > pskb - > data ;
2013-05-08 21:45:39 +00:00
2013-05-26 03:02:10 +00:00
precvbuf - > reuse = false ;
2013-05-08 21:45:39 +00:00
}
precvpriv - > rx_pending_cnt + + ;
purb = precvbuf - > purb ;
2013-07-10 18:25:07 +00:00
/* translate DMA FIFO addr to pipehandle */
2013-05-08 21:45:39 +00:00
pipe = ffaddr2pipehdl ( pdvobj , addr ) ;
2013-05-19 04:28:07 +00:00
usb_fill_bulk_urb ( purb , pusbd , pipe ,
2013-05-08 21:45:39 +00:00
precvbuf - > pbuf ,
2013-05-19 04:28:07 +00:00
MAX_RECVBUF_SZ ,
usb_read_port_complete ,
2013-07-10 18:25:07 +00:00
precvbuf ) ; /* context is precvbuf */
2013-05-08 21:45:39 +00:00
err = usb_submit_urb ( purb , GFP_ATOMIC ) ;
2013-05-09 04:04:25 +00:00
if ( ( err ) & & ( err ! = ( - EPERM ) ) )
2013-05-08 21:45:39 +00:00
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x " , err , purb - > status ) ) ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " cannot submit rx in-token(err = 0x%08x),urb_status = %d \n " , err , purb - > status ) ;
2013-05-08 21:45:39 +00:00
ret = _FAIL ;
}
}
else
{
RT_TRACE ( _module_hci_ops_os_c_ , _drv_err_ , ( " usb_read_port:precvbuf ==NULL \n " ) ) ;
ret = _FAIL ;
}
_func_exit_ ;
return ret ;
}
2013-07-10 18:25:07 +00:00
# endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */
2013-05-08 21:45:39 +00:00
void rtl8188eu_xmit_tasklet ( void * priv )
2013-05-19 04:28:07 +00:00
{
2013-05-26 03:02:10 +00:00
int ret = false ;
2013-05-08 21:45:39 +00:00
_adapter * padapter = ( _adapter * ) priv ;
struct xmit_priv * pxmitpriv = & padapter - > xmitpriv ;
2013-05-26 03:02:10 +00:00
if ( check_fwstate ( & padapter - > mlmepriv , _FW_UNDER_SURVEY ) = = true )
2013-05-08 21:45:39 +00:00
return ;
2013-05-09 04:04:25 +00:00
while ( 1 )
2013-05-08 21:45:39 +00:00
{
2013-05-26 03:02:10 +00:00
if ( ( padapter - > bDriverStopped = = true ) | | ( padapter - > bSurpriseRemoved = = true ) | | ( padapter - > bWritePortCancel = = true ) )
2013-05-08 21:45:39 +00:00
{
2013-05-25 23:35:42 +00:00
DBG_88E ( " xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel \n " ) ;
2013-05-08 21:45:39 +00:00
break ;
}
ret = rtl8188eu_xmitframe_complete ( padapter , pxmitpriv , NULL ) ;
2013-05-26 03:02:10 +00:00
if ( ret = = false )
2013-05-08 21:45:39 +00:00
break ;
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
2013-05-19 04:28:07 +00:00
2013-05-08 21:45:39 +00:00
}
void rtl8188eu_set_intf_ops ( struct _io_ops * pops )
2013-05-19 04:28:07 +00:00
{
_func_enter_ ;
2013-05-08 21:45:39 +00:00
2013-05-19 04:28:07 +00:00
_rtw_memset ( ( u8 * ) pops , 0 , sizeof ( struct _io_ops ) ) ;
2013-05-08 21:45:39 +00:00
pops - > _read8 = & usb_read8 ;
pops - > _read16 = & usb_read16 ;
pops - > _read32 = & usb_read32 ;
pops - > _read_mem = & usb_read_mem ;
2013-05-19 04:28:07 +00:00
pops - > _read_port = & usb_read_port ;
2013-05-08 21:45:39 +00:00
pops - > _write8 = & usb_write8 ;
pops - > _write16 = & usb_write16 ;
pops - > _write32 = & usb_write32 ;
pops - > _writeN = & usb_writeN ;
2013-05-19 04:28:07 +00:00
# ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
2013-05-08 21:45:39 +00:00
pops - > _write8_async = & usb_async_write8 ;
pops - > _write16_async = & usb_async_write16 ;
pops - > _write32_async = & usb_async_write32 ;
2013-05-19 04:28:07 +00:00
# endif
2013-05-08 21:45:39 +00:00
pops - > _write_mem = & usb_write_mem ;
pops - > _write_port = & usb_write_port ;
pops - > _read_port_cancel = & usb_read_port_cancel ;
pops - > _write_port_cancel = & usb_write_port_cancel ;
# ifdef CONFIG_USB_INTERRUPT_IN_PIPE
pops - > _read_interrupt = & usb_read_interrupt ;
# endif
_func_exit_ ;
}
void rtl8188eu_set_hw_type ( _adapter * padapter )
{
padapter - > chip_type = RTL8188E ;
padapter - > HardwareType = HARDWARE_TYPE_RTL8188EU ;
2013-05-25 23:35:42 +00:00
DBG_88E ( " CHIP TYPE: RTL8188E \n " ) ;
2013-05-08 21:45:39 +00:00
}