2010-12-08 11:12:31 -06:00
/******************************************************************************
*
2012-01-07 20:46:42 -06:00
* Copyright ( c ) 2009 - 2012 Realtek Corporation .
2010-12-08 11:12:31 -06: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
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE .
*
* Contact Information :
* wlanfae < wlanfae @ realtek . com >
* Realtek Corporation , No . 2 , Innovation Road II , Hsinchu Science Park ,
* Hsinchu 300 , Taiwan .
*
* Larry Finger < Larry . Finger @ lwfinger . net >
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "wifi.h"
2012-01-27 13:59:25 -06:00
# include "core.h"
2010-12-08 11:12:31 -06:00
# include "pci.h"
# include "base.h"
# include "ps.h"
2011-04-25 13:23:15 -05:00
# include "efuse.h"
2012-01-27 13:59:25 -06:00
# include <linux/export.h>
2012-04-13 13:57:43 -05:00
# include <linux/kmemleak.h>
2010-12-08 11:12:31 -06:00
static const u16 pcibridge_vendors [ PCI_BRIDGE_VENDOR_MAX ] = {
2011-06-27 13:03:44 -05:00
PCI_VENDOR_ID_INTEL ,
PCI_VENDOR_ID_ATI ,
PCI_VENDOR_ID_AMD ,
PCI_VENDOR_ID_SI
2010-12-08 11:12:31 -06:00
} ;
2011-04-25 13:23:15 -05:00
static const u8 ac_to_hwq [ ] = {
VO_QUEUE ,
VI_QUEUE ,
BE_QUEUE ,
BK_QUEUE
} ;
2011-04-25 13:23:20 -05:00
static u8 _rtl_mac_to_hwqueue ( struct ieee80211_hw * hw ,
2011-04-25 13:23:15 -05:00
struct sk_buff * skb )
{
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
2011-04-25 13:23:20 -05:00
__le16 fc = rtl_get_fc ( skb ) ;
2011-04-25 13:23:15 -05:00
u8 queue_index = skb_get_queue_mapping ( skb ) ;
if ( unlikely ( ieee80211_is_beacon ( fc ) ) )
return BEACON_QUEUE ;
if ( ieee80211_is_mgmt ( fc ) )
return MGNT_QUEUE ;
if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192SE )
if ( ieee80211_is_nullfunc ( fc ) )
return HIGH_QUEUE ;
return ac_to_hwq [ queue_index ] ;
}
2010-12-08 11:12:31 -06:00
/* Update PCI dependent default settings*/
static void _rtl_pci_update_default_setting ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
u8 pcibridge_vendor = pcipriv - > ndis_adapter . pcibridge_vendor ;
2011-04-25 13:23:15 -05:00
u8 init_aspm ;
2010-12-08 11:12:31 -06:00
ppsc - > reg_rfps_level = 0 ;
2011-12-19 13:56:45 +00:00
ppsc - > support_aspm = false ;
2010-12-08 11:12:31 -06:00
/*Update PCI ASPM setting */
ppsc - > const_amdpci_aspm = rtlpci - > const_amdpci_aspm ;
switch ( rtlpci - > const_pci_aspm ) {
case 0 :
/*No ASPM */
break ;
case 1 :
/*ASPM dynamically enabled/disable. */
ppsc - > reg_rfps_level | = RT_RF_LPS_LEVEL_ASPM ;
break ;
case 2 :
/*ASPM with Clock Req dynamically enabled/disable. */
ppsc - > reg_rfps_level | = ( RT_RF_LPS_LEVEL_ASPM |
RT_RF_OFF_LEVL_CLK_REQ ) ;
break ;
case 3 :
/*
* Always enable ASPM and Clock Req
* from initialization to halt .
* */
ppsc - > reg_rfps_level & = ~ ( RT_RF_LPS_LEVEL_ASPM ) ;
ppsc - > reg_rfps_level | = ( RT_RF_PS_LEVEL_ALWAYS_ASPM |
RT_RF_OFF_LEVL_CLK_REQ ) ;
break ;
case 4 :
/*
* Always enable ASPM without Clock Req
* from initialization to halt .
* */
ppsc - > reg_rfps_level & = ~ ( RT_RF_LPS_LEVEL_ASPM |
RT_RF_OFF_LEVL_CLK_REQ ) ;
ppsc - > reg_rfps_level | = RT_RF_PS_LEVEL_ALWAYS_ASPM ;
break ;
}
ppsc - > reg_rfps_level | = RT_RF_OFF_LEVL_HALT_NIC ;
/*Update Radio OFF setting */
switch ( rtlpci - > const_hwsw_rfoff_d3 ) {
case 1 :
if ( ppsc - > reg_rfps_level & RT_RF_LPS_LEVEL_ASPM )
ppsc - > reg_rfps_level | = RT_RF_OFF_LEVL_ASPM ;
break ;
case 2 :
if ( ppsc - > reg_rfps_level & RT_RF_LPS_LEVEL_ASPM )
ppsc - > reg_rfps_level | = RT_RF_OFF_LEVL_ASPM ;
ppsc - > reg_rfps_level | = RT_RF_OFF_LEVL_HALT_NIC ;
break ;
case 3 :
ppsc - > reg_rfps_level | = RT_RF_OFF_LEVL_PCI_D3 ;
break ;
}
/*Set HW definition to determine if it supports ASPM. */
switch ( rtlpci - > const_support_pciaspm ) {
2011-04-25 13:23:15 -05:00
case 0 : {
/*Not support ASPM. */
bool support_aspm = false ;
ppsc - > support_aspm = support_aspm ;
break ;
}
case 1 : {
/*Support ASPM. */
bool support_aspm = true ;
bool support_backdoor = true ;
ppsc - > support_aspm = support_aspm ;
/*if (priv->oem_id == RT_CID_TOSHIBA &&
! priv - > ndis_adapter . amd_l1_patch )
support_backdoor = false ; */
ppsc - > support_backdoor = support_backdoor ;
break ;
}
2010-12-08 11:12:31 -06:00
case 2 :
/*ASPM value set by chipset. */
2011-04-25 13:23:15 -05:00
if ( pcibridge_vendor = = PCI_BRIDGE_VENDOR_INTEL ) {
bool support_aspm = true ;
ppsc - > support_aspm = support_aspm ;
}
2010-12-08 11:12:31 -06:00
break ;
default :
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" switch case not processed \n " ) ;
2010-12-08 11:12:31 -06:00
break ;
}
2011-04-25 13:23:15 -05:00
/* toshiba aspm issue, toshiba will set aspm selfly
* so we should not set aspm in driver */
pci_read_config_byte ( rtlpci - > pdev , 0x80 , & init_aspm ) ;
if ( rtlpriv - > rtlhal . hw_type = = HARDWARE_TYPE_RTL8192SE & &
init_aspm = = 0x43 )
ppsc - > support_aspm = false ;
}
2010-12-08 11:12:31 -06:00
static bool _rtl_pci_platform_switch_device_pci_aspm (
struct ieee80211_hw * hw ,
u8 value )
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
2011-04-25 13:23:15 -05:00
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
if ( rtlhal - > hw_type ! = HARDWARE_TYPE_RTL8192SE )
value | = 0x40 ;
2010-12-08 11:12:31 -06:00
pci_write_config_byte ( rtlpci - > pdev , 0x80 , value ) ;
2011-03-27 16:19:57 -05:00
return false ;
2010-12-08 11:12:31 -06:00
}
/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/
2012-01-31 01:28:15 -05:00
static void _rtl_pci_switch_clk_req ( struct ieee80211_hw * hw , u8 value )
2010-12-08 11:12:31 -06:00
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
2011-04-25 13:23:15 -05:00
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
2010-12-08 11:12:31 -06:00
pci_write_config_byte ( rtlpci - > pdev , 0x81 , value ) ;
2011-04-25 13:23:15 -05:00
if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192SE )
udelay ( 100 ) ;
2010-12-08 11:12:31 -06:00
}
/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/
static void rtl_pci_disable_aspm ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
u8 pcibridge_vendor = pcipriv - > ndis_adapter . pcibridge_vendor ;
u8 num4bytes = pcipriv - > ndis_adapter . num4bytes ;
/*Retrieve original configuration settings. */
u8 linkctrl_reg = pcipriv - > ndis_adapter . linkctrl_reg ;
u16 pcibridge_linkctrlreg = pcipriv - > ndis_adapter .
pcibridge_linkctrlreg ;
u16 aspmlevel = 0 ;
2011-03-27 16:19:57 -05:00
u8 tmp_u1b = 0 ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
if ( ! ppsc - > support_aspm )
return ;
2010-12-08 11:12:31 -06:00
if ( pcibridge_vendor = = PCI_BRIDGE_VENDOR_UNKNOWN ) {
RT_TRACE ( rtlpriv , COMP_POWER , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" PCI(Bridge) UNKNOWN \n " ) ;
2010-12-08 11:12:31 -06:00
return ;
}
if ( ppsc - > reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ ) {
RT_CLEAR_PS_LEVEL ( ppsc , RT_RF_OFF_LEVL_CLK_REQ ) ;
_rtl_pci_switch_clk_req ( hw , 0x0 ) ;
}
2011-03-27 16:19:57 -05:00
/*for promising device will in L0 state after an I/O. */
pci_read_config_byte ( rtlpci - > pdev , 0x80 , & tmp_u1b ) ;
2010-12-08 11:12:31 -06:00
/*Set corresponding value. */
aspmlevel | = BIT ( 0 ) | BIT ( 1 ) ;
linkctrl_reg & = ~ aspmlevel ;
pcibridge_linkctrlreg & = ~ ( BIT ( 0 ) | BIT ( 1 ) ) ;
_rtl_pci_platform_switch_device_pci_aspm ( hw , linkctrl_reg ) ;
udelay ( 50 ) ;
/*4 Disable Pci Bridge ASPM */
2011-08-06 05:55:18 -05:00
pci_write_config_byte ( rtlpci - > pdev , ( num4bytes < < 2 ) ,
pcibridge_linkctrlreg ) ;
2010-12-08 11:12:31 -06:00
udelay ( 50 ) ;
}
/*
* Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
* power saving We should follow the sequence to enable
* RTL8192SE first then enable Pci Bridge ASPM
* or the system will show bluescreen .
*/
static void rtl_pci_enable_aspm ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
u8 pcibridge_busnum = pcipriv - > ndis_adapter . pcibridge_busnum ;
u8 pcibridge_devnum = pcipriv - > ndis_adapter . pcibridge_devnum ;
u8 pcibridge_funcnum = pcipriv - > ndis_adapter . pcibridge_funcnum ;
u8 pcibridge_vendor = pcipriv - > ndis_adapter . pcibridge_vendor ;
u8 num4bytes = pcipriv - > ndis_adapter . num4bytes ;
u16 aspmlevel ;
u8 u_pcibridge_aspmsetting ;
u8 u_device_aspmsetting ;
2011-04-25 13:23:15 -05:00
if ( ! ppsc - > support_aspm )
return ;
2010-12-08 11:12:31 -06:00
if ( pcibridge_vendor = = PCI_BRIDGE_VENDOR_UNKNOWN ) {
RT_TRACE ( rtlpriv , COMP_POWER , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" PCI(Bridge) UNKNOWN \n " ) ;
2010-12-08 11:12:31 -06:00
return ;
}
/*4 Enable Pci Bridge ASPM */
u_pcibridge_aspmsetting =
pcipriv - > ndis_adapter . pcibridge_linkctrlreg |
rtlpci - > const_hostpci_aspm_setting ;
if ( pcibridge_vendor = = PCI_BRIDGE_VENDOR_INTEL )
u_pcibridge_aspmsetting & = ~ BIT ( 0 ) ;
2011-08-06 05:55:18 -05:00
pci_write_config_byte ( rtlpci - > pdev , ( num4bytes < < 2 ) ,
u_pcibridge_aspmsetting ) ;
2010-12-08 11:12:31 -06:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" PlatformEnableASPM():PciBridge busnumber[%x], DevNumbe[%x], funcnumber[%x], Write reg[%x] = %x \n " ,
pcibridge_busnum , pcibridge_devnum , pcibridge_funcnum ,
( pcipriv - > ndis_adapter . pcibridge_pciehdr_offset + 0x10 ) ,
u_pcibridge_aspmsetting ) ;
2010-12-08 11:12:31 -06:00
udelay ( 50 ) ;
/*Get ASPM level (with/without Clock Req) */
aspmlevel = rtlpci - > const_devicepci_aspm_setting ;
u_device_aspmsetting = pcipriv - > ndis_adapter . linkctrl_reg ;
/*_rtl_pci_platform_switch_device_pci_aspm(dev,*/
/*(priv->ndis_adapter.linkctrl_reg | ASPMLevel)); */
u_device_aspmsetting | = aspmlevel ;
_rtl_pci_platform_switch_device_pci_aspm ( hw , u_device_aspmsetting ) ;
if ( ppsc - > reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ ) {
_rtl_pci_switch_clk_req ( hw , ( ppsc - > reg_rfps_level &
RT_RF_OFF_LEVL_CLK_REQ ) ? 1 : 0 ) ;
RT_SET_PS_LEVEL ( ppsc , RT_RF_OFF_LEVL_CLK_REQ ) ;
}
2011-04-25 13:23:15 -05:00
udelay ( 100 ) ;
2010-12-08 11:12:31 -06:00
}
static bool rtl_pci_get_amd_l1_patch ( struct ieee80211_hw * hw )
{
2011-08-06 05:55:18 -05:00
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
2010-12-08 11:12:31 -06:00
bool status = false ;
u8 offset_e0 ;
unsigned offset_e4 ;
2011-08-06 05:55:18 -05:00
pci_write_config_byte ( rtlpci - > pdev , 0xe0 , 0xa0 ) ;
2010-12-08 11:12:31 -06:00
2011-08-06 05:55:18 -05:00
pci_read_config_byte ( rtlpci - > pdev , 0xe0 , & offset_e0 ) ;
2010-12-08 11:12:31 -06:00
if ( offset_e0 = = 0xA0 ) {
2011-08-06 05:55:18 -05:00
pci_read_config_dword ( rtlpci - > pdev , 0xe4 , & offset_e4 ) ;
2010-12-08 11:12:31 -06:00
if ( offset_e4 & BIT ( 23 ) )
status = true ;
}
return status ;
}
2011-04-25 13:23:20 -05:00
static void rtl_pci_get_linkcontrol_field ( struct ieee80211_hw * hw )
2010-12-08 11:12:31 -06:00
{
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
2011-08-06 05:55:18 -05:00
struct rtl_pci * rtlpci = rtl_pcidev ( pcipriv ) ;
2010-12-08 11:12:31 -06:00
u8 capabilityoffset = pcipriv - > ndis_adapter . pcibridge_pciehdr_offset ;
u8 linkctrl_reg ;
2011-04-25 13:23:15 -05:00
u8 num4bbytes ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
num4bbytes = ( capabilityoffset + 0x10 ) / 4 ;
2010-12-08 11:12:31 -06:00
/*Read Link Control Register */
2011-08-06 05:55:18 -05:00
pci_read_config_byte ( rtlpci - > pdev , ( num4bbytes < < 2 ) , & linkctrl_reg ) ;
2010-12-08 11:12:31 -06:00
pcipriv - > ndis_adapter . pcibridge_linkctrlreg = linkctrl_reg ;
}
static void rtl_pci_parse_configuration ( struct pci_dev * pdev ,
struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
u8 tmp ;
2012-08-20 14:18:08 -06:00
u16 linkctrl_reg ;
2010-12-08 11:12:31 -06:00
/*Link Control Register */
2012-08-20 14:18:08 -06:00
pcie_capability_read_word ( pdev , PCI_EXP_LNKCTL , & linkctrl_reg ) ;
pcipriv - > ndis_adapter . linkctrl_reg = ( u8 ) linkctrl_reg ;
2010-12-08 11:12:31 -06:00
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_TRACE , " Link Control Register =%x \n " ,
pcipriv - > ndis_adapter . linkctrl_reg ) ;
2010-12-08 11:12:31 -06:00
pci_read_config_byte ( pdev , 0x98 , & tmp ) ;
tmp | = BIT ( 4 ) ;
pci_write_config_byte ( pdev , 0x98 , tmp ) ;
tmp = 0x17 ;
pci_write_config_byte ( pdev , 0x70f , tmp ) ;
}
2011-04-25 13:23:15 -05:00
static void rtl_pci_init_aspm ( struct ieee80211_hw * hw )
2010-12-08 11:12:31 -06:00
{
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
_rtl_pci_update_default_setting ( hw ) ;
if ( ppsc - > reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM ) {
/*Always enable ASPM & Clock Req. */
rtl_pci_enable_aspm ( hw ) ;
RT_SET_PS_LEVEL ( ppsc , RT_RF_PS_LEVEL_ALWAYS_ASPM ) ;
}
}
static void _rtl_pci_io_handler_init ( struct device * dev ,
struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
rtlpriv - > io . dev = dev ;
rtlpriv - > io . write8_async = pci_write8_async ;
rtlpriv - > io . write16_async = pci_write16_async ;
rtlpriv - > io . write32_async = pci_write32_async ;
rtlpriv - > io . read8_sync = pci_read8_sync ;
rtlpriv - > io . read16_sync = pci_read16_sync ;
rtlpriv - > io . read32_sync = pci_read32_sync ;
}
static void _rtl_pci_io_handler_release ( struct ieee80211_hw * hw )
{
}
2011-04-25 13:23:15 -05:00
static bool _rtl_update_earlymode_info ( struct ieee80211_hw * hw ,
struct sk_buff * skb , struct rtl_tcb_desc * tcb_desc , u8 tid )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct ieee80211_tx_info * info = IEEE80211_SKB_CB ( skb ) ;
u8 additionlen = FCS_LEN ;
struct sk_buff * next_skb ;
/* here open is 4, wep/tkip is 8, aes is 12*/
if ( info - > control . hw_key )
additionlen + = info - > control . hw_key - > icv_len ;
/* The most skb num is 6 */
tcb_desc - > empkt_num = 0 ;
spin_lock_bh ( & rtlpriv - > locks . waitq_lock ) ;
skb_queue_walk ( & rtlpriv - > mac80211 . skb_waitq [ tid ] , next_skb ) {
struct ieee80211_tx_info * next_info ;
next_info = IEEE80211_SKB_CB ( next_skb ) ;
if ( next_info - > flags & IEEE80211_TX_CTL_AMPDU ) {
tcb_desc - > empkt_len [ tcb_desc - > empkt_num ] =
next_skb - > len + additionlen ;
tcb_desc - > empkt_num + + ;
} else {
break ;
}
if ( skb_queue_is_last ( & rtlpriv - > mac80211 . skb_waitq [ tid ] ,
next_skb ) )
break ;
if ( tcb_desc - > empkt_num > = 5 )
break ;
}
spin_unlock_bh ( & rtlpriv - > locks . waitq_lock ) ;
return true ;
}
/* just for early mode now */
static void _rtl_pci_tx_chk_waitq ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_mac * mac = rtl_mac ( rtl_priv ( hw ) ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct sk_buff * skb = NULL ;
struct ieee80211_tx_info * info = NULL ;
2011-06-23 20:01:55 +03:00
int tid ;
2011-04-25 13:23:15 -05:00
if ( ! rtlpriv - > rtlhal . earlymode_enable )
return ;
/* we juse use em for BE/BK/VI/VO */
for ( tid = 7 ; tid > = 0 ; tid - - ) {
2012-07-11 14:32:33 -05:00
u8 hw_queue = ac_to_hwq [ rtl_tid_to_ac ( tid ) ] ;
2011-04-25 13:23:15 -05:00
struct rtl8192_tx_ring * ring = & rtlpci - > tx_ring [ hw_queue ] ;
while ( ! mac - > act_scanning & &
rtlpriv - > psc . rfpwr_state = = ERFON ) {
struct rtl_tcb_desc tcb_desc ;
memset ( & tcb_desc , 0 , sizeof ( struct rtl_tcb_desc ) ) ;
spin_lock_bh ( & rtlpriv - > locks . waitq_lock ) ;
if ( ! skb_queue_empty ( & mac - > skb_waitq [ tid ] ) & &
( ring - > entries - skb_queue_len ( & ring - > queue ) > 5 ) ) {
skb = skb_dequeue ( & mac - > skb_waitq [ tid ] ) ;
} else {
spin_unlock_bh ( & rtlpriv - > locks . waitq_lock ) ;
break ;
}
spin_unlock_bh ( & rtlpriv - > locks . waitq_lock ) ;
/* Some macaddr can't do early mode. like
* multicast / broadcast / no_qos data */
info = IEEE80211_SKB_CB ( skb ) ;
if ( info - > flags & IEEE80211_TX_CTL_AMPDU )
_rtl_update_earlymode_info ( hw , skb ,
& tcb_desc , tid ) ;
2012-07-23 21:33:42 +02:00
rtlpriv - > intf_ops - > adapter_tx ( hw , NULL , skb , & tcb_desc ) ;
2011-04-25 13:23:15 -05:00
}
}
}
2010-12-08 11:12:31 -06:00
static void _rtl_pci_tx_isr ( struct ieee80211_hw * hw , int prio )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl8192_tx_ring * ring = & rtlpci - > tx_ring [ prio ] ;
while ( skb_queue_len ( & ring - > queue ) ) {
struct rtl_tx_desc * entry = & ring - > desc [ ring - > idx ] ;
struct sk_buff * skb ;
struct ieee80211_tx_info * info ;
2011-04-25 13:23:15 -05:00
__le16 fc ;
u8 tid ;
2010-12-08 11:12:31 -06:00
u8 own = ( u8 ) rtlpriv - > cfg - > ops - > get_desc ( ( u8 * ) entry , true ,
HW_DESC_OWN ) ;
/*
* beacon packet will only use the first
* descriptor defautly , and the own may not
* be cleared by the hardware
*/
if ( own )
return ;
ring - > idx = ( ring - > idx + 1 ) % ring - > entries ;
skb = __skb_dequeue ( & ring - > queue ) ;
pci_unmap_single ( rtlpci - > pdev ,
2011-04-25 13:23:20 -05:00
rtlpriv - > cfg - > ops - >
2010-12-08 11:12:31 -06:00
get_desc ( ( u8 * ) entry , true ,
2011-04-25 13:23:20 -05:00
HW_DESC_TXBUFF_ADDR ) ,
2010-12-08 11:12:31 -06:00
skb - > len , PCI_DMA_TODEVICE ) ;
2011-04-25 13:23:15 -05:00
/* remove early mode header */
if ( rtlpriv - > rtlhal . earlymode_enable )
skb_pull ( skb , EM_HDR_LEN ) ;
2010-12-08 11:12:31 -06:00
RT_TRACE ( rtlpriv , ( COMP_INTR | COMP_SEND ) , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" new ring->idx:%d, free: skb_queue_len:%d, free: seq:%x \n " ,
ring - > idx ,
skb_queue_len ( & ring - > queue ) ,
* ( u16 * ) ( skb - > data + 22 ) ) ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
if ( prio = = TXCMD_QUEUE ) {
dev_kfree_skb ( skb ) ;
goto tx_status_ok ;
}
/* for sw LPS, just after NULL skb send out, we can
* sure AP kown we are sleeped , our we should not let
* rf to sleep */
fc = rtl_get_fc ( skb ) ;
if ( ieee80211_is_nullfunc ( fc ) ) {
if ( ieee80211_has_pm ( fc ) ) {
2011-06-20 10:44:58 +09:00
rtlpriv - > mac80211 . offchan_delay = true ;
2011-12-19 13:56:45 +00:00
rtlpriv - > psc . state_inap = true ;
2011-04-25 13:23:15 -05:00
} else {
2011-12-19 13:56:45 +00:00
rtlpriv - > psc . state_inap = false ;
2011-04-25 13:23:15 -05:00
}
}
/* update tid tx pkt num */
tid = rtl_get_tid ( skb ) ;
if ( tid < = 7 )
rtlpriv - > link_info . tidtx_inperiod [ tid ] + + ;
2010-12-08 11:12:31 -06:00
info = IEEE80211_SKB_CB ( skb ) ;
ieee80211_tx_info_clear_status ( info ) ;
info - > flags | = IEEE80211_TX_STAT_ACK ;
/*info->status.rates[0].count = 1; */
ieee80211_tx_status_irqsafe ( hw , skb ) ;
if ( ( ring - > entries - skb_queue_len ( & ring - > queue ) )
= = 2 ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%d \n " ,
prio , ring - > idx ,
skb_queue_len ( & ring - > queue ) ) ;
2010-12-08 11:12:31 -06:00
ieee80211_wake_queue ( hw ,
skb_get_queue_mapping
( skb ) ) ;
}
2011-04-25 13:23:15 -05:00
tx_status_ok :
2010-12-08 11:12:31 -06:00
skb = NULL ;
}
if ( ( ( rtlpriv - > link_info . num_rx_inperiod +
rtlpriv - > link_info . num_tx_inperiod ) > 8 ) | |
( rtlpriv - > link_info . num_rx_inperiod > 2 ) ) {
2011-12-12 12:43:23 +01:00
schedule_work ( & rtlpriv - > works . lps_leave_work ) ;
2010-12-08 11:12:31 -06:00
}
}
2011-06-06 23:13:06 +09:00
static void _rtl_receive_one ( struct ieee80211_hw * hw , struct sk_buff * skb ,
struct ieee80211_rx_status rx_status )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct ieee80211_hdr * hdr = rtl_get_hdr ( skb ) ;
__le16 fc = rtl_get_fc ( skb ) ;
bool unicast = false ;
struct sk_buff * uskb = NULL ;
u8 * pdata ;
memcpy ( IEEE80211_SKB_RXCB ( skb ) , & rx_status , sizeof ( rx_status ) ) ;
if ( is_broadcast_ether_addr ( hdr - > addr1 ) ) {
; /*TODO*/
} else if ( is_multicast_ether_addr ( hdr - > addr1 ) ) {
; /*TODO*/
} else {
unicast = true ;
rtlpriv - > stats . rxbytesunicast + = skb - > len ;
}
rtl_is_special_data ( hw , skb , false ) ;
if ( ieee80211_is_data ( fc ) ) {
rtlpriv - > cfg - > ops - > led_control ( hw , LED_CTL_RX ) ;
if ( unicast )
rtlpriv - > link_info . num_rx_inperiod + + ;
}
/* for sw lps */
rtl_swlps_beacon ( hw , ( void * ) skb - > data , skb - > len ) ;
rtl_recognize_peer ( hw , ( void * ) skb - > data , skb - > len ) ;
if ( ( rtlpriv - > mac80211 . opmode = = NL80211_IFTYPE_AP ) & &
( rtlpriv - > rtlhal . current_bandtype = = BAND_ON_2_4G ) & &
( ieee80211_is_beacon ( fc ) | | ieee80211_is_probe_resp ( fc ) ) )
return ;
if ( unlikely ( ! rtl_action_proc ( hw , skb , false ) ) )
return ;
uskb = dev_alloc_skb ( skb - > len + 128 ) ;
2012-01-07 20:46:40 -06:00
if ( ! uskb )
return ; /* exit if allocation failed */
2011-06-06 23:13:06 +09:00
memcpy ( IEEE80211_SKB_RXCB ( uskb ) , & rx_status , sizeof ( rx_status ) ) ;
pdata = ( u8 * ) skb_put ( uskb , skb - > len ) ;
memcpy ( pdata , skb - > data , skb - > len ) ;
ieee80211_rx_irqsafe ( hw , uskb ) ;
}
2010-12-08 11:12:31 -06:00
static void _rtl_pci_rx_interrupt ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
int rx_queue_idx = RTL_PCI_RX_MPDU_QUEUE ;
struct ieee80211_rx_status rx_status = { 0 } ;
unsigned int count = rtlpci - > rxringcount ;
u8 own ;
u8 tmp_one ;
u32 bufferaddress ;
struct rtl_stats stats = {
. signal = 0 ,
. noise = - 98 ,
. rate = 0 ,
} ;
2011-05-31 08:49:07 +09:00
int index = rtlpci - > rx_ring [ rx_queue_idx ] . idx ;
2010-12-08 11:12:31 -06:00
/*RX NORMAL PKT */
while ( count - - ) {
/*rx descriptor */
struct rtl_rx_desc * pdesc = & rtlpci - > rx_ring [ rx_queue_idx ] . desc [
2011-05-31 08:49:07 +09:00
index ] ;
2010-12-08 11:12:31 -06:00
/*rx pkt */
struct sk_buff * skb = rtlpci - > rx_ring [ rx_queue_idx ] . rx_buf [
2011-05-31 08:49:07 +09:00
index ] ;
2011-06-06 23:12:08 +09:00
struct sk_buff * new_skb = NULL ;
2010-12-08 11:12:31 -06:00
own = ( u8 ) rtlpriv - > cfg - > ops - > get_desc ( ( u8 * ) pdesc ,
false , HW_DESC_OWN ) ;
2011-06-06 23:12:08 +09:00
/*wait data to be filled by hardware */
if ( own )
2011-05-31 08:49:07 +09:00
break ;
2011-06-07 08:58:31 +09:00
2011-06-06 23:12:08 +09:00
rtlpriv - > cfg - > ops - > query_rx_desc ( hw , & stats ,
& rx_status ,
( u8 * ) pdesc , skb ) ;
2011-06-06 23:12:42 +09:00
if ( stats . crc | | stats . hwerror )
goto done ;
2011-06-06 23:12:08 +09:00
new_skb = dev_alloc_skb ( rtlpci - > rxbuffersize ) ;
if ( unlikely ( ! new_skb ) ) {
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , ( COMP_INTR | COMP_RECV ) , DBG_DMESG ,
" can't alloc skb for rx \n " ) ;
2011-06-06 23:12:08 +09:00
goto done ;
}
pci_unmap_single ( rtlpci - > pdev ,
* ( ( dma_addr_t * ) skb - > cb ) ,
rtlpci - > rxbuffersize ,
PCI_DMA_FROMDEVICE ) ;
skb_put ( skb , rtlpriv - > cfg - > ops - > get_desc ( ( u8 * ) pdesc , false ,
HW_DESC_RXPKT_LEN ) ) ;
skb_reserve ( skb , stats . rx_drvinfo_size + stats . rx_bufshift ) ;
/*
* NOTICE This can not be use for mac80211 ,
* this is done in mac80211 code ,
* if you done here sec DHCP will fail
* skb_trim ( skb , skb - > len - 4 ) ;
*/
2011-06-06 23:13:06 +09:00
_rtl_receive_one ( hw , skb , rx_status ) ;
2010-12-08 11:12:31 -06:00
2011-06-06 23:12:08 +09:00
if ( ( ( rtlpriv - > link_info . num_rx_inperiod +
rtlpriv - > link_info . num_tx_inperiod ) > 8 ) | |
( rtlpriv - > link_info . num_rx_inperiod > 2 ) ) {
2011-12-12 12:43:23 +01:00
schedule_work ( & rtlpriv - > works . lps_leave_work ) ;
2011-06-06 23:12:08 +09:00
}
2010-12-08 11:12:31 -06:00
2011-06-06 23:12:53 +09:00
dev_kfree_skb_any ( skb ) ;
2011-06-06 23:12:08 +09:00
skb = new_skb ;
2010-12-08 11:12:31 -06:00
2011-06-06 23:12:08 +09:00
rtlpci - > rx_ring [ rx_queue_idx ] . rx_buf [ index ] = skb ;
* ( ( dma_addr_t * ) skb - > cb ) =
2010-12-08 11:12:31 -06:00
pci_map_single ( rtlpci - > pdev , skb_tail_pointer ( skb ) ,
rtlpci - > rxbuffersize ,
PCI_DMA_FROMDEVICE ) ;
done :
2011-04-25 13:23:20 -05:00
bufferaddress = ( * ( ( dma_addr_t * ) skb - > cb ) ) ;
2010-12-08 11:12:31 -06:00
tmp_one = 1 ;
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) pdesc , false ,
HW_DESC_RXBUFF_ADDR ,
( u8 * ) & bufferaddress ) ;
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) pdesc , false ,
HW_DESC_RXPKT_LEN ,
( u8 * ) & rtlpci - > rxbuffersize ) ;
2011-05-31 08:49:07 +09:00
if ( index = = rtlpci - > rxringcount - 1 )
2010-12-08 11:12:31 -06:00
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) pdesc , false ,
HW_DESC_RXERO ,
2012-06-04 12:44:17 +00:00
& tmp_one ) ;
2010-12-08 11:12:31 -06:00
2011-05-31 08:49:51 +09:00
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) pdesc , false , HW_DESC_RXOWN ,
2012-06-04 12:44:17 +00:00
& tmp_one ) ;
2011-05-31 08:49:51 +09:00
2011-05-31 08:49:07 +09:00
index = ( index + 1 ) % rtlpci - > rxringcount ;
2010-12-08 11:12:31 -06:00
}
2011-05-31 08:49:07 +09:00
rtlpci - > rx_ring [ rx_queue_idx ] . idx = index ;
2010-12-08 11:12:31 -06:00
}
static irqreturn_t _rtl_pci_interrupt ( int irq , void * dev_id )
{
struct ieee80211_hw * hw = dev_id ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
2011-04-25 13:23:15 -05:00
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
2010-12-08 11:12:31 -06:00
unsigned long flags ;
u32 inta = 0 ;
u32 intb = 0 ;
2011-11-23 21:30:19 -06:00
irqreturn_t ret = IRQ_HANDLED ;
2010-12-08 11:12:31 -06:00
spin_lock_irqsave ( & rtlpriv - > locks . irq_th_lock , flags ) ;
/*read ISR: 4/8bytes */
rtlpriv - > cfg - > ops - > interrupt_recognized ( hw , & inta , & intb ) ;
/*Shared IRQ or HW disappared */
2011-11-23 21:30:19 -06:00
if ( ! inta | | inta = = 0xffff ) {
ret = IRQ_NONE ;
2010-12-08 11:12:31 -06:00
goto done ;
2011-11-23 21:30:19 -06:00
}
2010-12-08 11:12:31 -06:00
/*<1> beacon related */
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_TBDOK ] ) {
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" beacon ok interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
}
if ( unlikely ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_TBDER ] ) ) {
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" beacon err interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_BDOK ] ) {
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE , " beacon interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_BcnInt ] ) {
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" prepare beacon for interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
tasklet_schedule ( & rtlpriv - > works . irq_prepare_bcn_tasklet ) ;
}
/*<3> Tx related */
if ( unlikely ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_TXFOVW ] ) )
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING , " IMR_TXFOVW! \n " ) ;
2010-12-08 11:12:31 -06:00
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_MGNTDOK ] ) {
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" Manage ok interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
_rtl_pci_tx_isr ( hw , MGNT_QUEUE ) ;
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_HIGHDOK ] ) {
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" HIGH_QUEUE ok interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
_rtl_pci_tx_isr ( hw , HIGH_QUEUE ) ;
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_BKDOK ] ) {
rtlpriv - > link_info . num_tx_inperiod + + ;
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" BK Tx OK interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
_rtl_pci_tx_isr ( hw , BK_QUEUE ) ;
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_BEDOK ] ) {
rtlpriv - > link_info . num_tx_inperiod + + ;
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" BE TX OK interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
_rtl_pci_tx_isr ( hw , BE_QUEUE ) ;
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_VIDOK ] ) {
rtlpriv - > link_info . num_tx_inperiod + + ;
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" VI TX OK interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
_rtl_pci_tx_isr ( hw , VI_QUEUE ) ;
}
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_VODOK ] ) {
rtlpriv - > link_info . num_tx_inperiod + + ;
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" Vo TX OK interrupt! \n " ) ;
2010-12-08 11:12:31 -06:00
_rtl_pci_tx_isr ( hw , VO_QUEUE ) ;
}
2011-04-25 13:23:15 -05:00
if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192SE ) {
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_COMDOK ] ) {
rtlpriv - > link_info . num_tx_inperiod + + ;
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE ,
2012-01-04 19:40:41 -08:00
" CMD TX OK interrupt! \n " ) ;
2011-04-25 13:23:15 -05:00
_rtl_pci_tx_isr ( hw , TXCMD_QUEUE ) ;
}
}
2010-12-08 11:12:31 -06:00
/*<2> Rx related */
if ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_ROK ] ) {
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INTR , DBG_TRACE , " Rx ok interrupt! \n " ) ;
2011-04-25 13:23:15 -05:00
_rtl_pci_rx_interrupt ( hw ) ;
2010-12-08 11:12:31 -06:00
}
if ( unlikely ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_RDU ] ) ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING ,
2012-01-04 19:40:41 -08:00
" rx descriptor unavailable! \n " ) ;
2011-04-25 13:23:15 -05:00
_rtl_pci_rx_interrupt ( hw ) ;
2010-12-08 11:12:31 -06:00
}
if ( unlikely ( inta & rtlpriv - > cfg - > maps [ RTL_IMR_RXFOVW ] ) ) {
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING , " rx overflow ! \n " ) ;
2011-04-25 13:23:15 -05:00
_rtl_pci_rx_interrupt ( hw ) ;
2010-12-08 11:12:31 -06:00
}
2011-04-25 13:23:15 -05:00
if ( rtlpriv - > rtlhal . earlymode_enable )
tasklet_schedule ( & rtlpriv - > works . irq_tasklet ) ;
2010-12-08 11:12:31 -06:00
done :
spin_unlock_irqrestore ( & rtlpriv - > locks . irq_th_lock , flags ) ;
2011-11-23 21:30:19 -06:00
return ret ;
2010-12-08 11:12:31 -06:00
}
static void _rtl_pci_irq_tasklet ( struct ieee80211_hw * hw )
{
2011-04-25 13:23:15 -05:00
_rtl_pci_tx_chk_waitq ( hw ) ;
2010-12-08 11:12:31 -06:00
}
static void _rtl_pci_prepare_bcn_tasklet ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl_mac * mac = rtl_mac ( rtl_priv ( hw ) ) ;
2011-04-25 13:23:15 -05:00
struct rtl8192_tx_ring * ring = NULL ;
2010-12-08 11:12:31 -06:00
struct ieee80211_hdr * hdr = NULL ;
struct ieee80211_tx_info * info = NULL ;
struct sk_buff * pskb = NULL ;
struct rtl_tx_desc * pdesc = NULL ;
2011-04-25 13:23:15 -05:00
struct rtl_tcb_desc tcb_desc ;
2010-12-08 11:12:31 -06:00
u8 temp_one = 1 ;
2011-04-25 13:23:15 -05:00
memset ( & tcb_desc , 0 , sizeof ( struct rtl_tcb_desc ) ) ;
2010-12-08 11:12:31 -06:00
ring = & rtlpci - > tx_ring [ BEACON_QUEUE ] ;
pskb = __skb_dequeue ( & ring - > queue ) ;
2012-03-26 10:48:20 -05:00
if ( pskb ) {
struct rtl_tx_desc * entry = & ring - > desc [ ring - > idx ] ;
pci_unmap_single ( rtlpci - > pdev , rtlpriv - > cfg - > ops - > get_desc (
( u8 * ) entry , true , HW_DESC_TXBUFF_ADDR ) ,
pskb - > len , PCI_DMA_TODEVICE ) ;
2010-12-08 11:12:31 -06:00
kfree_skb ( pskb ) ;
2012-03-26 10:48:20 -05:00
}
2010-12-08 11:12:31 -06:00
/*NB: the beacon data buffer must be 32-bit aligned. */
pskb = ieee80211_beacon_get ( hw , mac - > vif ) ;
if ( pskb = = NULL )
return ;
2011-04-25 13:23:15 -05:00
hdr = rtl_get_hdr ( pskb ) ;
2010-12-08 11:12:31 -06:00
info = IEEE80211_SKB_CB ( pskb ) ;
pdesc = & ring - > desc [ 0 ] ;
rtlpriv - > cfg - > ops - > fill_tx_desc ( hw , hdr , ( u8 * ) pdesc ,
2012-07-23 21:33:42 +02:00
info , NULL , pskb , BEACON_QUEUE , & tcb_desc ) ;
2010-12-08 11:12:31 -06:00
__skb_queue_tail ( & ring - > queue , pskb ) ;
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) pdesc , true , HW_DESC_OWN ,
2012-06-04 12:44:17 +00:00
& temp_one ) ;
2010-12-08 11:12:31 -06:00
return ;
}
2011-12-12 12:43:23 +01:00
static void rtl_lps_leave_work_callback ( struct work_struct * work )
{
struct rtl_works * rtlworks =
container_of ( work , struct rtl_works , lps_leave_work ) ;
struct ieee80211_hw * hw = rtlworks - > hw ;
rtl_lps_leave ( hw ) ;
}
2010-12-08 11:12:31 -06:00
static void _rtl_pci_init_trx_var ( struct ieee80211_hw * hw )
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
u8 i ;
for ( i = 0 ; i < RTL_PCI_MAX_TX_QUEUE_COUNT ; i + + )
rtlpci - > txringcount [ i ] = RT_TXDESC_NUM ;
/*
* we just alloc 2 desc for beacon queue ,
* because we just need first desc in hw beacon .
*/
rtlpci - > txringcount [ BEACON_QUEUE ] = 2 ;
/*
* BE queue need more descriptor for performance
* consideration or , No more tx desc will happen ,
* and may cause mac80211 mem leakage .
*/
rtlpci - > txringcount [ BE_QUEUE ] = RT_TXDESC_NUM_BE_QUEUE ;
rtlpci - > rxbuffersize = 9100 ; /*2048/1024; */
rtlpci - > rxringcount = RTL_PCI_MAX_RX_COUNT ; /*64; */
}
static void _rtl_pci_init_struct ( struct ieee80211_hw * hw ,
struct pci_dev * pdev )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_mac * mac = rtl_mac ( rtl_priv ( hw ) ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
rtlpci - > up_first_time = true ;
rtlpci - > being_init_adapter = false ;
rtlhal - > hw = hw ;
rtlpci - > pdev = pdev ;
/*Tx/Rx related var */
_rtl_pci_init_trx_var ( hw ) ;
2011-04-25 13:23:15 -05:00
/*IBSS*/ mac - > beacon_interval = 100 ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
/*AMPDU*/
mac - > min_space_cfg = 0 ;
2010-12-08 11:12:31 -06:00
mac - > max_mss_density = 0 ;
/*set sane AMPDU defaults */
mac - > current_ampdu_density = 7 ;
mac - > current_ampdu_factor = 3 ;
2011-04-25 13:23:15 -05:00
/*QOS*/
rtlpci - > acm_method = eAcmWay2_SW ;
2010-12-08 11:12:31 -06:00
/*task */
tasklet_init ( & rtlpriv - > works . irq_tasklet ,
( void ( * ) ( unsigned long ) ) _rtl_pci_irq_tasklet ,
( unsigned long ) hw ) ;
tasklet_init ( & rtlpriv - > works . irq_prepare_bcn_tasklet ,
( void ( * ) ( unsigned long ) ) _rtl_pci_prepare_bcn_tasklet ,
( unsigned long ) hw ) ;
2011-12-12 12:43:23 +01:00
INIT_WORK ( & rtlpriv - > works . lps_leave_work , rtl_lps_leave_work_callback ) ;
2010-12-08 11:12:31 -06:00
}
static int _rtl_pci_init_tx_ring ( struct ieee80211_hw * hw ,
unsigned int prio , unsigned int entries )
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_tx_desc * ring ;
dma_addr_t dma ;
u32 nextdescaddress ;
int i ;
ring = pci_alloc_consistent ( rtlpci - > pdev ,
sizeof ( * ring ) * entries , & dma ) ;
if ( ! ring | | ( unsigned long ) ring & 0xFF ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" Cannot allocate TX ring (prio = %d) \n " , prio ) ;
2010-12-08 11:12:31 -06:00
return - ENOMEM ;
}
memset ( ring , 0 , sizeof ( * ring ) * entries ) ;
rtlpci - > tx_ring [ prio ] . desc = ring ;
rtlpci - > tx_ring [ prio ] . dma = dma ;
rtlpci - > tx_ring [ prio ] . idx = 0 ;
rtlpci - > tx_ring [ prio ] . entries = entries ;
skb_queue_head_init ( & rtlpci - > tx_ring [ prio ] . queue ) ;
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_LOUD , " queue:%d, ring_addr:%p \n " ,
prio , ring ) ;
2010-12-08 11:12:31 -06:00
for ( i = 0 ; i < entries ; i + + ) {
2011-04-25 13:23:20 -05:00
nextdescaddress = ( u32 ) dma +
2011-05-01 22:30:54 -05:00
( ( i + 1 ) % entries ) *
2011-04-25 13:23:20 -05:00
sizeof ( * ring ) ;
2010-12-08 11:12:31 -06:00
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) & ( ring [ i ] ) ,
true , HW_DESC_TX_NEXTDESC_ADDR ,
( u8 * ) & nextdescaddress ) ;
}
return 0 ;
}
static int _rtl_pci_init_rx_ring ( struct ieee80211_hw * hw )
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_rx_desc * entry = NULL ;
int i , rx_queue_idx ;
u8 tmp_one = 1 ;
/*
* rx_queue_idx 0 : RX_MPDU_QUEUE
* rx_queue_idx 1 : RX_CMD_QUEUE
*/
for ( rx_queue_idx = 0 ; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE ;
rx_queue_idx + + ) {
rtlpci - > rx_ring [ rx_queue_idx ] . desc =
pci_alloc_consistent ( rtlpci - > pdev ,
sizeof ( * rtlpci - > rx_ring [ rx_queue_idx ] .
desc ) * rtlpci - > rxringcount ,
& rtlpci - > rx_ring [ rx_queue_idx ] . dma ) ;
if ( ! rtlpci - > rx_ring [ rx_queue_idx ] . desc | |
( unsigned long ) rtlpci - > rx_ring [ rx_queue_idx ] . desc & 0xFF ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" Cannot allocate RX ring \n " ) ;
2010-12-08 11:12:31 -06:00
return - ENOMEM ;
}
memset ( rtlpci - > rx_ring [ rx_queue_idx ] . desc , 0 ,
sizeof ( * rtlpci - > rx_ring [ rx_queue_idx ] . desc ) *
rtlpci - > rxringcount ) ;
rtlpci - > rx_ring [ rx_queue_idx ] . idx = 0 ;
2011-05-19 11:48:45 -05:00
/* If amsdu_8k is disabled, set buffersize to 4096. This
* change will reduce memory fragmentation .
*/
if ( rtlpci - > rxbuffersize > 4096 & &
rtlpriv - > rtlhal . disable_amsdu_8k )
rtlpci - > rxbuffersize = 4096 ;
2010-12-08 11:12:31 -06:00
for ( i = 0 ; i < rtlpci - > rxringcount ; i + + ) {
struct sk_buff * skb =
dev_alloc_skb ( rtlpci - > rxbuffersize ) ;
u32 bufferaddress ;
if ( ! skb )
return 0 ;
2012-04-13 13:57:43 -05:00
kmemleak_not_leak ( skb ) ;
2011-01-21 13:40:54 -06:00
entry = & rtlpci - > rx_ring [ rx_queue_idx ] . desc [ i ] ;
2010-12-08 11:12:31 -06:00
/*skb->dev = dev; */
rtlpci - > rx_ring [ rx_queue_idx ] . rx_buf [ i ] = skb ;
/*
* just set skb - > cb to mapping addr
* for pci_unmap_single use
*/
* ( ( dma_addr_t * ) skb - > cb ) =
pci_map_single ( rtlpci - > pdev , skb_tail_pointer ( skb ) ,
rtlpci - > rxbuffersize ,
PCI_DMA_FROMDEVICE ) ;
2011-04-25 13:23:20 -05:00
bufferaddress = ( * ( ( dma_addr_t * ) skb - > cb ) ) ;
2010-12-08 11:12:31 -06:00
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) entry , false ,
HW_DESC_RXBUFF_ADDR ,
( u8 * ) & bufferaddress ) ;
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) entry , false ,
HW_DESC_RXPKT_LEN ,
( u8 * ) & rtlpci - >
rxbuffersize ) ;
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) entry , false ,
HW_DESC_RXOWN ,
2012-06-04 12:44:17 +00:00
& tmp_one ) ;
2010-12-08 11:12:31 -06:00
}
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) entry , false ,
2012-06-04 12:44:17 +00:00
HW_DESC_RXERO , & tmp_one ) ;
2010-12-08 11:12:31 -06:00
}
return 0 ;
}
static void _rtl_pci_free_tx_ring ( struct ieee80211_hw * hw ,
unsigned int prio )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl8192_tx_ring * ring = & rtlpci - > tx_ring [ prio ] ;
while ( skb_queue_len ( & ring - > queue ) ) {
struct rtl_tx_desc * entry = & ring - > desc [ ring - > idx ] ;
struct sk_buff * skb = __skb_dequeue ( & ring - > queue ) ;
pci_unmap_single ( rtlpci - > pdev ,
2011-04-25 13:23:20 -05:00
rtlpriv - > cfg - >
2010-12-08 11:12:31 -06:00
ops - > get_desc ( ( u8 * ) entry , true ,
2011-04-25 13:23:20 -05:00
HW_DESC_TXBUFF_ADDR ) ,
2010-12-08 11:12:31 -06:00
skb - > len , PCI_DMA_TODEVICE ) ;
kfree_skb ( skb ) ;
ring - > idx = ( ring - > idx + 1 ) % ring - > entries ;
}
2012-02-07 18:07:38 -06:00
if ( ring - > desc ) {
pci_free_consistent ( rtlpci - > pdev ,
sizeof ( * ring - > desc ) * ring - > entries ,
ring - > desc , ring - > dma ) ;
ring - > desc = NULL ;
}
2010-12-08 11:12:31 -06:00
}
static void _rtl_pci_free_rx_ring ( struct rtl_pci * rtlpci )
{
int i , rx_queue_idx ;
/*rx_queue_idx 0:RX_MPDU_QUEUE */
/*rx_queue_idx 1:RX_CMD_QUEUE */
for ( rx_queue_idx = 0 ; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE ;
rx_queue_idx + + ) {
for ( i = 0 ; i < rtlpci - > rxringcount ; i + + ) {
struct sk_buff * skb =
rtlpci - > rx_ring [ rx_queue_idx ] . rx_buf [ i ] ;
if ( ! skb )
continue ;
pci_unmap_single ( rtlpci - > pdev ,
* ( ( dma_addr_t * ) skb - > cb ) ,
rtlpci - > rxbuffersize ,
PCI_DMA_FROMDEVICE ) ;
kfree_skb ( skb ) ;
}
2012-02-07 18:07:38 -06:00
if ( rtlpci - > rx_ring [ rx_queue_idx ] . desc ) {
pci_free_consistent ( rtlpci - > pdev ,
2010-12-08 11:12:31 -06:00
sizeof ( * rtlpci - > rx_ring [ rx_queue_idx ] .
desc ) * rtlpci - > rxringcount ,
rtlpci - > rx_ring [ rx_queue_idx ] . desc ,
rtlpci - > rx_ring [ rx_queue_idx ] . dma ) ;
2012-02-07 18:07:38 -06:00
rtlpci - > rx_ring [ rx_queue_idx ] . desc = NULL ;
}
2010-12-08 11:12:31 -06:00
}
}
static int _rtl_pci_init_trx_ring ( struct ieee80211_hw * hw )
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
int ret ;
int i ;
ret = _rtl_pci_init_rx_ring ( hw ) ;
if ( ret )
return ret ;
for ( i = 0 ; i < RTL_PCI_MAX_TX_QUEUE_COUNT ; i + + ) {
ret = _rtl_pci_init_tx_ring ( hw , i ,
rtlpci - > txringcount [ i ] ) ;
if ( ret )
goto err_free_rings ;
}
return 0 ;
err_free_rings :
_rtl_pci_free_rx_ring ( rtlpci ) ;
for ( i = 0 ; i < RTL_PCI_MAX_TX_QUEUE_COUNT ; i + + )
if ( rtlpci - > tx_ring [ i ] . desc )
_rtl_pci_free_tx_ring ( hw , i ) ;
return 1 ;
}
static int _rtl_pci_deinit_trx_ring ( struct ieee80211_hw * hw )
{
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
u32 i ;
/*free rx rings */
_rtl_pci_free_rx_ring ( rtlpci ) ;
/*free tx rings */
for ( i = 0 ; i < RTL_PCI_MAX_TX_QUEUE_COUNT ; i + + )
_rtl_pci_free_tx_ring ( hw , i ) ;
return 0 ;
}
int rtl_pci_reset_trx_ring ( struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
int i , rx_queue_idx ;
unsigned long flags ;
u8 tmp_one = 1 ;
/*rx_queue_idx 0:RX_MPDU_QUEUE */
/*rx_queue_idx 1:RX_CMD_QUEUE */
for ( rx_queue_idx = 0 ; rx_queue_idx < RTL_PCI_MAX_RX_QUEUE ;
rx_queue_idx + + ) {
/*
* force the rx_ring [ RX_MPDU_QUEUE /
* RX_CMD_QUEUE ] . idx to the first one
*/
if ( rtlpci - > rx_ring [ rx_queue_idx ] . desc ) {
struct rtl_rx_desc * entry = NULL ;
for ( i = 0 ; i < rtlpci - > rxringcount ; i + + ) {
entry = & rtlpci - > rx_ring [ rx_queue_idx ] . desc [ i ] ;
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) entry ,
false ,
HW_DESC_RXOWN ,
2012-06-04 12:44:17 +00:00
& tmp_one ) ;
2010-12-08 11:12:31 -06:00
}
rtlpci - > rx_ring [ rx_queue_idx ] . idx = 0 ;
}
}
/*
* after reset , release previous pending packet ,
* and force the tx idx to the first one
*/
for ( i = 0 ; i < RTL_PCI_MAX_TX_QUEUE_COUNT ; i + + ) {
if ( rtlpci - > tx_ring [ i ] . desc ) {
struct rtl8192_tx_ring * ring = & rtlpci - > tx_ring [ i ] ;
while ( skb_queue_len ( & ring - > queue ) ) {
2012-06-24 11:06:29 -05:00
struct rtl_tx_desc * entry ;
struct sk_buff * skb ;
2010-12-08 11:12:31 -06:00
2012-06-24 11:06:29 -05:00
spin_lock_irqsave ( & rtlpriv - > locks . irq_th_lock ,
flags ) ;
entry = & ring - > desc [ ring - > idx ] ;
skb = __skb_dequeue ( & ring - > queue ) ;
2010-12-08 11:12:31 -06:00
pci_unmap_single ( rtlpci - > pdev ,
2011-04-25 13:23:20 -05:00
rtlpriv - > cfg - > ops - >
2010-12-08 11:12:31 -06:00
get_desc ( ( u8 * )
entry ,
true ,
2011-04-25 13:23:20 -05:00
HW_DESC_TXBUFF_ADDR ) ,
2010-12-08 11:12:31 -06:00
skb - > len , PCI_DMA_TODEVICE ) ;
ring - > idx = ( ring - > idx + 1 ) % ring - > entries ;
2012-06-24 11:06:29 -05:00
spin_unlock_irqrestore ( & rtlpriv - > locks . irq_th_lock ,
flags ) ;
kfree_skb ( skb ) ;
2010-12-08 11:12:31 -06:00
}
ring - > idx = 0 ;
}
}
return 0 ;
}
2011-04-25 13:23:15 -05:00
static bool rtl_pci_tx_chk_waitq_insert ( struct ieee80211_hw * hw ,
2012-07-23 21:33:42 +02:00
struct ieee80211_sta * sta ,
2011-04-25 13:23:15 -05:00
struct sk_buff * skb )
2010-12-08 11:12:31 -06:00
{
2011-04-25 13:23:15 -05:00
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_sta_info * sta_entry = NULL ;
u8 tid = rtl_get_tid ( skb ) ;
2012-10-25 13:46:46 -05:00
__le16 fc = rtl_get_fc ( skb ) ;
2011-04-25 13:23:15 -05:00
if ( ! sta )
return false ;
sta_entry = ( struct rtl_sta_info * ) sta - > drv_priv ;
if ( ! rtlpriv - > rtlhal . earlymode_enable )
return false ;
2012-10-25 13:46:46 -05:00
if ( ieee80211_is_nullfunc ( fc ) )
return false ;
if ( ieee80211_is_qos_nullfunc ( fc ) )
return false ;
if ( ieee80211_is_pspoll ( fc ) )
return false ;
2011-04-25 13:23:15 -05:00
if ( sta_entry - > tids [ tid ] . agg . agg_state ! = RTL_AGG_OPERATIONAL )
return false ;
if ( _rtl_mac_to_hwqueue ( hw , skb ) > VO_QUEUE )
return false ;
if ( tid > 7 )
return false ;
/* maybe every tid should be checked */
if ( ! rtlpriv - > link_info . higher_busytxtraffic [ tid ] )
return false ;
spin_lock_bh ( & rtlpriv - > locks . waitq_lock ) ;
skb_queue_tail ( & rtlpriv - > mac80211 . skb_waitq [ tid ] , skb ) ;
spin_unlock_bh ( & rtlpriv - > locks . waitq_lock ) ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
return true ;
2010-12-08 11:12:31 -06:00
}
2012-07-23 21:33:42 +02:00
static int rtl_pci_tx ( struct ieee80211_hw * hw ,
struct ieee80211_sta * sta ,
struct sk_buff * skb ,
struct rtl_tcb_desc * ptcb_desc )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
2011-04-25 13:23:15 -05:00
struct rtl_sta_info * sta_entry = NULL ;
2010-12-08 11:12:31 -06:00
struct ieee80211_tx_info * info = IEEE80211_SKB_CB ( skb ) ;
struct rtl8192_tx_ring * ring ;
struct rtl_tx_desc * pdesc ;
u8 idx ;
2011-04-25 13:23:15 -05:00
u8 hw_queue = _rtl_mac_to_hwqueue ( hw , skb ) ;
2010-12-08 11:12:31 -06:00
unsigned long flags ;
2011-04-25 13:23:15 -05:00
struct ieee80211_hdr * hdr = rtl_get_hdr ( skb ) ;
__le16 fc = rtl_get_fc ( skb ) ;
2010-12-08 11:12:31 -06:00
u8 * pda_addr = hdr - > addr1 ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
/*ssn */
u8 tid = 0 ;
u16 seq_number = 0 ;
u8 own ;
u8 temp_one = 1 ;
2012-10-25 13:46:46 -05:00
if ( ieee80211_is_mgmt ( fc ) )
rtl_tx_mgmt_proc ( hw , skb ) ;
2011-04-25 13:23:15 -05:00
if ( rtlpriv - > psc . sw_ps_enabled ) {
if ( ieee80211_is_data ( fc ) & & ! ieee80211_is_nullfunc ( fc ) & &
! ieee80211_has_pm ( fc ) )
hdr - > frame_control | = cpu_to_le16 ( IEEE80211_FCTL_PM ) ;
}
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
rtl_action_proc ( hw , skb , true ) ;
2010-12-08 11:12:31 -06:00
if ( is_multicast_ether_addr ( pda_addr ) )
rtlpriv - > stats . txbytesmulticast + = skb - > len ;
else if ( is_broadcast_ether_addr ( pda_addr ) )
rtlpriv - > stats . txbytesbroadcast + = skb - > len ;
else
rtlpriv - > stats . txbytesunicast + = skb - > len ;
spin_lock_irqsave ( & rtlpriv - > locks . irq_th_lock , flags ) ;
ring = & rtlpci - > tx_ring [ hw_queue ] ;
if ( hw_queue ! = BEACON_QUEUE )
idx = ( ring - > idx + skb_queue_len ( & ring - > queue ) ) %
ring - > entries ;
else
idx = 0 ;
pdesc = & ring - > desc [ idx ] ;
own = ( u8 ) rtlpriv - > cfg - > ops - > get_desc ( ( u8 * ) pdesc ,
true , HW_DESC_OWN ) ;
if ( ( own = = 1 ) & & ( hw_queue ! = BEACON_QUEUE ) ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING ,
2012-01-04 19:40:41 -08:00
" No more TX desc@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%d \n " ,
hw_queue , ring - > idx , idx ,
skb_queue_len ( & ring - > queue ) ) ;
2010-12-08 11:12:31 -06:00
spin_unlock_irqrestore ( & rtlpriv - > locks . irq_th_lock , flags ) ;
return skb - > len ;
}
if ( ieee80211_is_data_qos ( fc ) ) {
2011-04-25 13:23:15 -05:00
tid = rtl_get_tid ( skb ) ;
if ( sta ) {
sta_entry = ( struct rtl_sta_info * ) sta - > drv_priv ;
seq_number = ( le16_to_cpu ( hdr - > seq_ctrl ) &
IEEE80211_SCTL_SEQ ) > > 4 ;
seq_number + = 1 ;
if ( ! ieee80211_has_morefrags ( hdr - > frame_control ) )
sta_entry - > tids [ tid ] . seq_number = seq_number ;
}
2010-12-08 11:12:31 -06:00
}
if ( ieee80211_is_data ( fc ) )
rtlpriv - > cfg - > ops - > led_control ( hw , LED_CTL_TX ) ;
2011-04-25 13:23:15 -05:00
rtlpriv - > cfg - > ops - > fill_tx_desc ( hw , hdr , ( u8 * ) pdesc ,
2012-07-23 21:33:42 +02:00
info , sta , skb , hw_queue , ptcb_desc ) ;
2010-12-08 11:12:31 -06:00
__skb_queue_tail ( & ring - > queue , skb ) ;
2011-04-25 13:23:15 -05:00
rtlpriv - > cfg - > ops - > set_desc ( ( u8 * ) pdesc , true ,
2012-06-04 12:44:17 +00:00
HW_DESC_OWN , & temp_one ) ;
2010-12-08 11:12:31 -06:00
if ( ( ring - > entries - skb_queue_len ( & ring - > queue ) ) < 2 & &
hw_queue ! = BEACON_QUEUE ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" less desc left, stop skb_queue@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%d \n " ,
hw_queue , ring - > idx , idx ,
skb_queue_len ( & ring - > queue ) ) ;
2010-12-08 11:12:31 -06:00
ieee80211_stop_queue ( hw , skb_get_queue_mapping ( skb ) ) ;
}
spin_unlock_irqrestore ( & rtlpriv - > locks . irq_th_lock , flags ) ;
rtlpriv - > cfg - > ops - > tx_polling ( hw , hw_queue ) ;
return 0 ;
}
2011-04-25 13:23:15 -05:00
static void rtl_pci_flush ( struct ieee80211_hw * hw , bool drop )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
u16 i = 0 ;
int queue_id ;
struct rtl8192_tx_ring * ring ;
for ( queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1 ; queue_id > = 0 ; ) {
u32 queue_len ;
ring = & pcipriv - > dev . tx_ring [ queue_id ] ;
queue_len = skb_queue_len ( & ring - > queue ) ;
if ( queue_len = = 0 | | queue_id = = BEACON_QUEUE | |
queue_id = = TXCMD_QUEUE ) {
queue_id - - ;
continue ;
} else {
msleep ( 20 ) ;
i + + ;
}
/* we just wait 1s for all queues */
if ( rtlpriv - > psc . rfpwr_state = = ERFOFF | |
is_hal_stop ( rtlhal ) | | i > = 200 )
return ;
}
}
2011-04-25 13:23:20 -05:00
static void rtl_pci_deinit ( struct ieee80211_hw * hw )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
_rtl_pci_deinit_trx_ring ( hw ) ;
synchronize_irq ( rtlpci - > pdev - > irq ) ;
tasklet_kill ( & rtlpriv - > works . irq_tasklet ) ;
2011-12-12 12:43:23 +01:00
cancel_work_sync ( & rtlpriv - > works . lps_leave_work ) ;
2010-12-08 11:12:31 -06:00
flush_workqueue ( rtlpriv - > works . rtl_wq ) ;
destroy_workqueue ( rtlpriv - > works . rtl_wq ) ;
}
2011-04-25 13:23:20 -05:00
static int rtl_pci_init ( struct ieee80211_hw * hw , struct pci_dev * pdev )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
int err ;
_rtl_pci_init_struct ( hw , pdev ) ;
err = _rtl_pci_init_trx_ring ( hw ) ;
if ( err ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" tx ring initialization failed \n " ) ;
2012-02-09 14:48:25 -05:00
return err ;
2010-12-08 11:12:31 -06:00
}
2012-02-09 14:48:25 -05:00
return 0 ;
2010-12-08 11:12:31 -06:00
}
2011-04-25 13:23:20 -05:00
static int rtl_pci_start ( struct ieee80211_hw * hw )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
int err ;
rtl_pci_reset_trx_ring ( hw ) ;
rtlpci - > driver_is_goingto_unload = false ;
err = rtlpriv - > cfg - > ops - > hw_init ( hw ) ;
if ( err ) {
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" Failed to config hardware! \n " ) ;
2010-12-08 11:12:31 -06:00
return err ;
}
rtlpriv - > cfg - > ops - > enable_interrupt ( hw ) ;
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_LOUD , " enable_interrupt OK \n " ) ;
2010-12-08 11:12:31 -06:00
rtl_init_rx_config ( hw ) ;
2011-06-23 20:01:55 +03:00
/*should be after adapter start and interrupt enable. */
2010-12-08 11:12:31 -06:00
set_hal_start ( rtlhal ) ;
RT_CLEAR_PS_LEVEL ( ppsc , RT_RF_OFF_LEVL_HALT_NIC ) ;
rtlpci - > up_first_time = false ;
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG , " OK \n " ) ;
2010-12-08 11:12:31 -06:00
return 0 ;
}
2011-04-25 13:23:20 -05:00
static void rtl_pci_stop ( struct ieee80211_hw * hw )
2010-12-08 11:12:31 -06:00
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( rtl_pcipriv ( hw ) ) ;
struct rtl_ps_ctl * ppsc = rtl_psc ( rtl_priv ( hw ) ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
unsigned long flags ;
u8 RFInProgressTimeOut = 0 ;
/*
2011-06-23 20:01:55 +03:00
* should be before disable interrupt & adapter
2010-12-08 11:12:31 -06:00
* and will do it immediately .
*/
set_hal_stop ( rtlhal ) ;
rtlpriv - > cfg - > ops - > disable_interrupt ( hw ) ;
2011-12-12 12:43:23 +01:00
cancel_work_sync ( & rtlpriv - > works . lps_leave_work ) ;
2010-12-08 11:12:31 -06:00
spin_lock_irqsave ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
while ( ppsc - > rfchange_inprogress ) {
spin_unlock_irqrestore ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
if ( RFInProgressTimeOut > 100 ) {
spin_lock_irqsave ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
break ;
}
mdelay ( 1 ) ;
RFInProgressTimeOut + + ;
spin_lock_irqsave ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
}
ppsc - > rfchange_inprogress = true ;
spin_unlock_irqrestore ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
rtlpci - > driver_is_goingto_unload = true ;
rtlpriv - > cfg - > ops - > hw_disable ( hw ) ;
2012-01-30 09:54:49 -06:00
/* some things are not needed if firmware not available */
if ( ! rtlpriv - > max_fw_size )
return ;
2010-12-08 11:12:31 -06:00
rtlpriv - > cfg - > ops - > led_control ( hw , LED_CTL_POWER_OFF ) ;
spin_lock_irqsave ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
ppsc - > rfchange_inprogress = false ;
spin_unlock_irqrestore ( & rtlpriv - > locks . rf_ps_lock , flags ) ;
rtl_pci_enable_aspm ( hw ) ;
}
static bool _rtl_pci_find_adapter ( struct pci_dev * pdev ,
struct ieee80211_hw * hw )
{
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
struct rtl_hal * rtlhal = rtl_hal ( rtl_priv ( hw ) ) ;
struct pci_dev * bridge_pdev = pdev - > bus - > self ;
u16 venderid ;
u16 deviceid ;
2011-04-25 13:23:15 -05:00
u8 revisionid ;
2010-12-08 11:12:31 -06:00
u16 irqline ;
u8 tmp ;
2011-05-06 15:32:02 -05:00
pcipriv - > ndis_adapter . pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN ;
2010-12-08 11:12:31 -06:00
venderid = pdev - > vendor ;
deviceid = pdev - > device ;
2011-04-25 13:23:15 -05:00
pci_read_config_byte ( pdev , 0x8 , & revisionid ) ;
2010-12-08 11:12:31 -06:00
pci_read_config_word ( pdev , 0x3C , & irqline ) ;
2011-06-18 22:49:53 -05:00
/* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses
* r8192e_pci , and RTL8192SE , which uses this driver . If the
* revision ID is RTL_PCI_REVISION_ID_8192PCIE ( 0x01 ) , then
* the correct driver is r8192e_pci , thus this routine should
* return false .
*/
if ( deviceid = = RTL_PCI_8192SE_DID & &
revisionid = = RTL_PCI_REVISION_ID_8192PCIE )
return false ;
2010-12-08 11:12:31 -06:00
if ( deviceid = = RTL_PCI_8192_DID | |
deviceid = = RTL_PCI_0044_DID | |
deviceid = = RTL_PCI_0047_DID | |
deviceid = = RTL_PCI_8192SE_DID | |
deviceid = = RTL_PCI_8174_DID | |
deviceid = = RTL_PCI_8173_DID | |
deviceid = = RTL_PCI_8172_DID | |
deviceid = = RTL_PCI_8171_DID ) {
2011-04-25 13:23:15 -05:00
switch ( revisionid ) {
2010-12-08 11:12:31 -06:00
case RTL_PCI_REVISION_ID_8192PCIE :
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" 8192 PCI-E is found - vid/did=%x/%x \n " ,
venderid , deviceid ) ;
2010-12-08 11:12:31 -06:00
rtlhal - > hw_type = HARDWARE_TYPE_RTL8192E ;
2012-10-25 13:46:46 -05:00
return false ;
2010-12-08 11:12:31 -06:00
case RTL_PCI_REVISION_ID_8192SE :
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" 8192SE is found - vid/did=%x/%x \n " ,
venderid , deviceid ) ;
2010-12-08 11:12:31 -06:00
rtlhal - > hw_type = HARDWARE_TYPE_RTL8192SE ;
break ;
default :
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING ,
2012-01-04 19:40:41 -08:00
" Err: Unknown device - vid/did=%x/%x \n " ,
venderid , deviceid ) ;
2010-12-08 11:12:31 -06:00
rtlhal - > hw_type = HARDWARE_TYPE_RTL8192SE ;
break ;
}
2012-10-25 13:46:46 -05:00
} else if ( deviceid = = RTL_PCI_8723AE_DID ) {
rtlhal - > hw_type = HARDWARE_TYPE_RTL8723AE ;
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
" 8723AE PCI-E is found - "
" vid/did=%x/%x \n " , venderid , deviceid ) ;
2010-12-08 11:12:31 -06:00
} else if ( deviceid = = RTL_PCI_8192CET_DID | |
deviceid = = RTL_PCI_8192CE_DID | |
deviceid = = RTL_PCI_8191CE_DID | |
deviceid = = RTL_PCI_8188CE_DID ) {
rtlhal - > hw_type = HARDWARE_TYPE_RTL8192CE ;
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" 8192C PCI-E is found - vid/did=%x/%x \n " ,
venderid , deviceid ) ;
2011-04-25 13:23:15 -05:00
} else if ( deviceid = = RTL_PCI_8192DE_DID | |
deviceid = = RTL_PCI_8192DE_DID2 ) {
rtlhal - > hw_type = HARDWARE_TYPE_RTL8192DE ;
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" 8192D PCI-E is found - vid/did=%x/%x \n " ,
venderid , deviceid ) ;
2010-12-08 11:12:31 -06:00
} else {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_WARNING ,
2012-01-04 19:40:41 -08:00
" Err: Unknown device - vid/did=%x/%x \n " ,
venderid , deviceid ) ;
2010-12-08 11:12:31 -06:00
rtlhal - > hw_type = RTL_DEFAULT_HARDWARE_TYPE ;
}
2011-04-25 13:23:15 -05:00
if ( rtlhal - > hw_type = = HARDWARE_TYPE_RTL8192DE ) {
if ( revisionid = = 0 | | revisionid = = 1 ) {
if ( revisionid = = 0 ) {
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_LOUD ,
" Find 92DE MAC0 \n " ) ;
2011-04-25 13:23:15 -05:00
rtlhal - > interfaceindex = 0 ;
} else if ( revisionid = = 1 ) {
RT_TRACE ( rtlpriv , COMP_INIT , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" Find 92DE MAC1 \n " ) ;
2011-04-25 13:23:15 -05:00
rtlhal - > interfaceindex = 1 ;
}
} else {
RT_TRACE ( rtlpriv , COMP_INIT , DBG_LOUD ,
2012-01-04 19:40:41 -08:00
" Unknown device - VendorID/DeviceID=%x/%x, Revision=%x \n " ,
venderid , deviceid , revisionid ) ;
2011-04-25 13:23:15 -05:00
rtlhal - > interfaceindex = 0 ;
}
}
2010-12-08 11:12:31 -06:00
/*find bus info */
pcipriv - > ndis_adapter . busnumber = pdev - > bus - > number ;
pcipriv - > ndis_adapter . devnumber = PCI_SLOT ( pdev - > devfn ) ;
pcipriv - > ndis_adapter . funcnumber = PCI_FUNC ( pdev - > devfn ) ;
2011-07-29 10:53:12 -05:00
if ( bridge_pdev ) {
/*find bridge info if available */
pcipriv - > ndis_adapter . pcibridge_vendorid = bridge_pdev - > vendor ;
for ( tmp = 0 ; tmp < PCI_BRIDGE_VENDOR_MAX ; tmp + + ) {
if ( bridge_pdev - > vendor = = pcibridge_vendors [ tmp ] ) {
pcipriv - > ndis_adapter . pcibridge_vendor = tmp ;
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" Pci Bridge Vendor is found index: %d \n " ,
tmp ) ;
2011-07-29 10:53:12 -05:00
break ;
}
2010-12-08 11:12:31 -06:00
}
}
if ( pcipriv - > ndis_adapter . pcibridge_vendor ! =
PCI_BRIDGE_VENDOR_UNKNOWN ) {
pcipriv - > ndis_adapter . pcibridge_busnum =
bridge_pdev - > bus - > number ;
pcipriv - > ndis_adapter . pcibridge_devnum =
PCI_SLOT ( bridge_pdev - > devfn ) ;
pcipriv - > ndis_adapter . pcibridge_funcnum =
PCI_FUNC ( bridge_pdev - > devfn ) ;
2011-04-25 13:23:15 -05:00
pcipriv - > ndis_adapter . pcibridge_pciehdr_offset =
pci_pcie_cap ( bridge_pdev ) ;
2010-12-08 11:12:31 -06:00
pcipriv - > ndis_adapter . num4bytes =
( pcipriv - > ndis_adapter . pcibridge_pciehdr_offset + 0x10 ) / 4 ;
rtl_pci_get_linkcontrol_field ( hw ) ;
if ( pcipriv - > ndis_adapter . pcibridge_vendor = =
PCI_BRIDGE_VENDOR_AMD ) {
pcipriv - > ndis_adapter . amd_l1_patch =
rtl_pci_get_amd_l1_patch ( hw ) ;
}
}
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" pcidev busnumber:devnumber:funcnumber:vendor:link_ctl %d:%d:%d:%x:%x \n " ,
pcipriv - > ndis_adapter . busnumber ,
pcipriv - > ndis_adapter . devnumber ,
pcipriv - > ndis_adapter . funcnumber ,
pdev - > vendor , pcipriv - > ndis_adapter . linkctrl_reg ) ;
2010-12-08 11:12:31 -06:00
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" pci_bridge busnumber:devnumber:funcnumber:vendor:pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x \n " ,
pcipriv - > ndis_adapter . pcibridge_busnum ,
pcipriv - > ndis_adapter . pcibridge_devnum ,
pcipriv - > ndis_adapter . pcibridge_funcnum ,
pcibridge_vendors [ pcipriv - > ndis_adapter . pcibridge_vendor ] ,
pcipriv - > ndis_adapter . pcibridge_pciehdr_offset ,
pcipriv - > ndis_adapter . pcibridge_linkctrlreg ,
pcipriv - > ndis_adapter . amd_l1_patch ) ;
2010-12-08 11:12:31 -06:00
rtl_pci_parse_configuration ( pdev , hw ) ;
return true ;
}
2012-12-03 09:56:43 -05:00
int rtl_pci_probe ( struct pci_dev * pdev ,
2010-12-08 11:12:31 -06:00
const struct pci_device_id * id )
{
struct ieee80211_hw * hw = NULL ;
struct rtl_priv * rtlpriv = NULL ;
struct rtl_pci_priv * pcipriv = NULL ;
struct rtl_pci * rtlpci ;
unsigned long pmem_start , pmem_len , pmem_flags ;
int err ;
err = pci_enable_device ( pdev ) ;
if ( err ) {
2012-01-04 19:40:43 -08:00
RT_ASSERT ( false , " %s : Cannot enable new PCI device \n " ,
pci_name ( pdev ) ) ;
2010-12-08 11:12:31 -06:00
return err ;
}
if ( ! pci_set_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ) {
if ( pci_set_consistent_dma_mask ( pdev , DMA_BIT_MASK ( 32 ) ) ) {
2012-01-04 19:40:43 -08:00
RT_ASSERT ( false ,
" Unable to obtain 32bit DMA for consistent allocations \n " ) ;
2012-02-02 13:48:06 -07:00
err = - ENOMEM ;
goto fail1 ;
2010-12-08 11:12:31 -06:00
}
}
pci_set_master ( pdev ) ;
hw = ieee80211_alloc_hw ( sizeof ( struct rtl_pci_priv ) +
sizeof ( struct rtl_priv ) , & rtl_ops ) ;
if ( ! hw ) {
RT_ASSERT ( false ,
2012-01-04 19:40:43 -08:00
" %s : ieee80211 alloc failed \n " , pci_name ( pdev ) ) ;
2010-12-08 11:12:31 -06:00
err = - ENOMEM ;
goto fail1 ;
}
SET_IEEE80211_DEV ( hw , & pdev - > dev ) ;
pci_set_drvdata ( pdev , hw ) ;
rtlpriv = hw - > priv ;
pcipriv = ( void * ) rtlpriv - > priv ;
pcipriv - > dev . pdev = pdev ;
2012-01-30 09:54:49 -06:00
init_completion ( & rtlpriv - > firmware_loading_complete ) ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
/* init cfg & intf_ops */
rtlpriv - > rtlhal . interface = INTF_PCI ;
rtlpriv - > cfg = ( struct rtl_hal_cfg * ) ( id - > driver_data ) ;
rtlpriv - > intf_ops = & rtl_pci_ops ;
2010-12-08 11:12:31 -06:00
/*
* init dbgp flags before all
* other functions , because we will
* use it in other funtions like
* RT_TRACE / RT_PRINT / RTL_PRINT_DATA
* you can not use these macro
* before this
*/
rtl_dbgp_flag_init ( hw ) ;
/* MEM map */
err = pci_request_regions ( pdev , KBUILD_MODNAME ) ;
if ( err ) {
2012-01-04 19:40:43 -08:00
RT_ASSERT ( false , " Can't obtain PCI resources \n " ) ;
2012-02-02 13:48:06 -07:00
goto fail1 ;
2010-12-08 11:12:31 -06:00
}
2011-04-25 13:23:15 -05:00
pmem_start = pci_resource_start ( pdev , rtlpriv - > cfg - > bar_id ) ;
pmem_len = pci_resource_len ( pdev , rtlpriv - > cfg - > bar_id ) ;
pmem_flags = pci_resource_flags ( pdev , rtlpriv - > cfg - > bar_id ) ;
2010-12-08 11:12:31 -06:00
/*shared mem start */
rtlpriv - > io . pci_mem_start =
2011-04-25 13:23:15 -05:00
( unsigned long ) pci_iomap ( pdev ,
rtlpriv - > cfg - > bar_id , pmem_len ) ;
2010-12-08 11:12:31 -06:00
if ( rtlpriv - > io . pci_mem_start = = 0 ) {
2012-01-04 19:40:43 -08:00
RT_ASSERT ( false , " Can't map PCI mem \n " ) ;
2012-02-02 13:48:06 -07:00
err = - ENOMEM ;
2010-12-08 11:12:31 -06:00
goto fail2 ;
}
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" mem mapped space: start: 0x%08lx len:%08lx flags:%08lx, after map:0x%08lx \n " ,
pmem_start , pmem_len , pmem_flags ,
rtlpriv - > io . pci_mem_start ) ;
2010-12-08 11:12:31 -06:00
/* Disable Clk Request */
pci_write_config_byte ( pdev , 0x81 , 0 ) ;
/* leave D3 mode */
pci_write_config_byte ( pdev , 0x44 , 0 ) ;
pci_write_config_byte ( pdev , 0x04 , 0x06 ) ;
pci_write_config_byte ( pdev , 0x04 , 0x07 ) ;
/* find adapter */
2012-02-02 13:48:06 -07:00
if ( ! _rtl_pci_find_adapter ( pdev , hw ) ) {
err = - ENODEV ;
2011-06-18 22:49:53 -05:00
goto fail3 ;
2012-02-02 13:48:06 -07:00
}
2010-12-08 11:12:31 -06:00
/* Init IO handler */
_rtl_pci_io_handler_init ( & pdev - > dev , hw ) ;
/*like read eeprom and so on */
rtlpriv - > cfg - > ops - > read_eeprom_info ( hw ) ;
/*aspm */
rtl_pci_init_aspm ( hw ) ;
/* Init mac80211 sw */
err = rtl_init_core ( hw ) ;
if ( err ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" Can't allocate sw for mac80211 \n " ) ;
2010-12-08 11:12:31 -06:00
goto fail3 ;
}
/* Init PCI sw */
2012-02-09 14:48:25 -05:00
err = rtl_pci_init ( hw , pdev ) ;
2010-12-08 11:12:31 -06:00
if ( err ) {
2012-01-04 19:40:41 -08:00
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG , " Failed to init PCI \n " ) ;
2010-12-08 11:12:31 -06:00
goto fail3 ;
}
2012-05-04 08:27:43 -05:00
if ( rtlpriv - > cfg - > ops - > init_sw_vars ( hw ) ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG , " Can't init_sw_vars \n " ) ;
err = - ENODEV ;
goto fail3 ;
}
rtlpriv - > cfg - > ops - > init_sw_leds ( hw ) ;
2010-12-08 11:12:31 -06:00
err = sysfs_create_group ( & pdev - > dev . kobj , & rtl_attribute_group ) ;
if ( err ) {
RT_TRACE ( rtlpriv , COMP_ERR , DBG_EMERG ,
2012-01-04 19:40:41 -08:00
" failed to create sysfs device attributes \n " ) ;
2010-12-08 11:12:31 -06:00
goto fail3 ;
}
rtlpci = rtl_pcidev ( pcipriv ) ;
err = request_irq ( rtlpci - > pdev - > irq , & _rtl_pci_interrupt ,
IRQF_SHARED , KBUILD_MODNAME , hw ) ;
if ( err ) {
RT_TRACE ( rtlpriv , COMP_INIT , DBG_DMESG ,
2012-01-04 19:40:41 -08:00
" %s: failed to register IRQ handler \n " ,
wiphy_name ( hw - > wiphy ) ) ;
2010-12-08 11:12:31 -06:00
goto fail3 ;
}
2012-01-30 09:54:49 -06:00
rtlpci - > irq_alloc = 1 ;
2010-12-08 11:12:31 -06:00
return 0 ;
fail3 :
rtl_deinit_core ( hw ) ;
_rtl_pci_io_handler_release ( hw ) ;
if ( rtlpriv - > io . pci_mem_start ! = 0 )
2011-02-11 14:27:46 -06:00
pci_iounmap ( pdev , ( void __iomem * ) rtlpriv - > io . pci_mem_start ) ;
2010-12-08 11:12:31 -06:00
fail2 :
pci_release_regions ( pdev ) ;
2012-01-30 09:54:49 -06:00
complete ( & rtlpriv - > firmware_loading_complete ) ;
2010-12-08 11:12:31 -06:00
fail1 :
2012-02-02 13:48:06 -07:00
if ( hw )
ieee80211_free_hw ( hw ) ;
pci_set_drvdata ( pdev , NULL ) ;
2010-12-08 11:12:31 -06:00
pci_disable_device ( pdev ) ;
2012-02-02 13:48:06 -07:00
return err ;
2010-12-08 11:12:31 -06:00
}
EXPORT_SYMBOL ( rtl_pci_probe ) ;
void rtl_pci_disconnect ( struct pci_dev * pdev )
{
struct ieee80211_hw * hw = pci_get_drvdata ( pdev ) ;
struct rtl_pci_priv * pcipriv = rtl_pcipriv ( hw ) ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
struct rtl_pci * rtlpci = rtl_pcidev ( pcipriv ) ;
struct rtl_mac * rtlmac = rtl_mac ( rtlpriv ) ;
2012-01-30 09:54:49 -06:00
/* just in case driver is removed before firmware callback */
wait_for_completion ( & rtlpriv - > firmware_loading_complete ) ;
2010-12-08 11:12:31 -06:00
clear_bit ( RTL_STATUS_INTERFACE_START , & rtlpriv - > status ) ;
sysfs_remove_group ( & pdev - > dev . kobj , & rtl_attribute_group ) ;
/*ieee80211_unregister_hw will call ops_stop */
if ( rtlmac - > mac80211_registered = = 1 ) {
ieee80211_unregister_hw ( hw ) ;
rtlmac - > mac80211_registered = 0 ;
} else {
rtl_deinit_deferred_work ( hw ) ;
rtlpriv - > intf_ops - > adapter_stop ( hw ) ;
}
2012-04-19 21:39:06 -05:00
rtlpriv - > cfg - > ops - > disable_interrupt ( hw ) ;
2010-12-08 11:12:31 -06:00
/*deinit rfkill */
rtl_deinit_rfkill ( hw ) ;
rtl_pci_deinit ( hw ) ;
rtl_deinit_core ( hw ) ;
_rtl_pci_io_handler_release ( hw ) ;
rtlpriv - > cfg - > ops - > deinit_sw_vars ( hw ) ;
if ( rtlpci - > irq_alloc ) {
free_irq ( rtlpci - > pdev - > irq , hw ) ;
rtlpci - > irq_alloc = 0 ;
}
if ( rtlpriv - > io . pci_mem_start ! = 0 ) {
2011-02-11 14:27:46 -06:00
pci_iounmap ( pdev , ( void __iomem * ) rtlpriv - > io . pci_mem_start ) ;
2010-12-08 11:12:31 -06:00
pci_release_regions ( pdev ) ;
}
pci_disable_device ( pdev ) ;
2011-04-25 13:23:15 -05:00
rtl_pci_disable_aspm ( hw ) ;
2010-12-08 11:12:31 -06:00
pci_set_drvdata ( pdev , NULL ) ;
ieee80211_free_hw ( hw ) ;
}
EXPORT_SYMBOL ( rtl_pci_disconnect ) ;
2012-11-29 23:27:17 +01:00
# ifdef CONFIG_PM_SLEEP
2010-12-08 11:12:31 -06:00
/***************************************
kernel pci power state define :
PCI_D0 ( ( pci_power_t __force ) 0 )
PCI_D1 ( ( pci_power_t __force ) 1 )
PCI_D2 ( ( pci_power_t __force ) 2 )
PCI_D3hot ( ( pci_power_t __force ) 3 )
PCI_D3cold ( ( pci_power_t __force ) 4 )
PCI_UNKNOWN ( ( pci_power_t __force ) 5 )
This function is called when system
goes into suspend state mac80211 will
call rtl_mac_stop ( ) from the mac80211
suspend function first , So there is
no need to call hw_disable here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-10-11 21:28:47 -05:00
int rtl_pci_suspend ( struct device * dev )
2010-12-08 11:12:31 -06:00
{
2011-10-11 21:28:47 -05:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2011-04-25 13:23:15 -05:00
struct ieee80211_hw * hw = pci_get_drvdata ( pdev ) ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
rtlpriv - > cfg - > ops - > hw_suspend ( hw ) ;
rtl_deinit_rfkill ( hw ) ;
2010-12-08 11:12:31 -06:00
return 0 ;
}
EXPORT_SYMBOL ( rtl_pci_suspend ) ;
2011-10-11 21:28:47 -05:00
int rtl_pci_resume ( struct device * dev )
2010-12-08 11:12:31 -06:00
{
2011-10-11 21:28:47 -05:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2011-04-25 13:23:15 -05:00
struct ieee80211_hw * hw = pci_get_drvdata ( pdev ) ;
struct rtl_priv * rtlpriv = rtl_priv ( hw ) ;
2010-12-08 11:12:31 -06:00
2011-04-25 13:23:15 -05:00
rtlpriv - > cfg - > ops - > hw_resume ( hw ) ;
rtl_init_rfkill ( hw ) ;
2010-12-08 11:12:31 -06:00
return 0 ;
}
EXPORT_SYMBOL ( rtl_pci_resume ) ;
2012-11-29 23:27:17 +01:00
# endif /* CONFIG_PM_SLEEP */
2010-12-08 11:12:31 -06:00
struct rtl_intf_ops rtl_pci_ops = {
2011-04-25 13:23:15 -05:00
. read_efuse_byte = read_efuse_byte ,
2010-12-08 11:12:31 -06:00
. adapter_start = rtl_pci_start ,
. adapter_stop = rtl_pci_stop ,
. adapter_tx = rtl_pci_tx ,
2011-04-25 13:23:15 -05:00
. flush = rtl_pci_flush ,
2010-12-08 11:12:31 -06:00
. reset_trx_ring = rtl_pci_reset_trx_ring ,
2011-04-25 13:23:15 -05:00
. waitq_insert = rtl_pci_tx_chk_waitq_insert ,
2010-12-08 11:12:31 -06:00
. disable_aspm = rtl_pci_disable_aspm ,
. enable_aspm = rtl_pci_enable_aspm ,
} ;