rtl8723ds: Initial commit of files

This repository contains the Realtek driver V5.1.1.5_20523.20161209_BTCOEX20161208-1212.

At inclusion, the only changes from the Realtek version were to fix any compile
warnings or errors. With these changes, the driver builds on kernels through
4.11.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
This commit is contained in:
Larry Finger
2017-04-25 09:56:34 -05:00
parent 76ab2438bb
commit e87533e664
469 changed files with 410449 additions and 1 deletions
+91
View File
@@ -0,0 +1,91 @@
/*++
Copyright (c) Realtek Semiconductor Corp. All rights reserved.
Module Name:
Hal8821PwrSeq.c
Abstract:
This file includes all kinds of Power Action event for RTL8821A and corresponding hardware configurtions which are released from HW SD.
Major Change History:
When Who What
---------- --------------- -------------------------------
2011-08-08 Roger Create.
--*/
#include "Mp_Precomp.h"
#if WPP_SOFTWARE_TRACE
#include "Hal8723DPwrSeq.tmh"
#endif
#include "Hal8723DPwrSeq.h"
/*
drivers should parse below arrays and do the corresponding actions
*/
/* 3 Power on Array */
WLAN_PWR_CFG rtl8723D_power_on_flow[RTL8723D_TRANS_CARDEMU_TO_ACT_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_CARDEMU_TO_ACT
RTL8723D_TRANS_END
};
/* 3Radio off GPIO Array */
WLAN_PWR_CFG rtl8723D_radio_off_flow[RTL8723D_TRANS_ACT_TO_CARDEMU_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_ACT_TO_CARDEMU
RTL8723D_TRANS_END
};
/* 3Card Disable Array */
WLAN_PWR_CFG rtl8723D_card_disable_flow[RTL8723D_TRANS_ACT_TO_CARDEMU_STEPS + RTL8723D_TRANS_CARDEMU_TO_CARDDIS_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_ACT_TO_CARDEMU
RTL8723D_TRANS_CARDEMU_TO_CARDDIS
RTL8723D_TRANS_END
};
/* 3 Card Enable Array */
WLAN_PWR_CFG rtl8723D_card_enable_flow[RTL8723D_TRANS_CARDDIS_TO_CARDEMU_STEPS + RTL8723D_TRANS_CARDEMU_TO_ACT_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_CARDDIS_TO_CARDEMU
RTL8723D_TRANS_CARDEMU_TO_ACT
RTL8723D_TRANS_END
};
/* 3Suspend Array */
WLAN_PWR_CFG rtl8723D_suspend_flow[RTL8723D_TRANS_ACT_TO_CARDEMU_STEPS + RTL8723D_TRANS_CARDEMU_TO_SUS_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_ACT_TO_CARDEMU
RTL8723D_TRANS_CARDEMU_TO_SUS
RTL8723D_TRANS_END
};
/* 3 Resume Array */
WLAN_PWR_CFG rtl8723D_resume_flow[RTL8723D_TRANS_SUS_TO_CARDEMU_STEPS + RTL8723D_TRANS_CARDEMU_TO_ACT_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_SUS_TO_CARDEMU
RTL8723D_TRANS_CARDEMU_TO_ACT
RTL8723D_TRANS_END
};
/* 3HWPDN Array */
WLAN_PWR_CFG rtl8723D_hwpdn_flow[RTL8723D_TRANS_ACT_TO_CARDEMU_STEPS + RTL8723D_TRANS_CARDEMU_TO_PDN_STEPS + RTL8723D_TRANS_END_STEPS] = {
RTL8723D_TRANS_ACT_TO_CARDEMU
RTL8723D_TRANS_CARDEMU_TO_PDN
RTL8723D_TRANS_END
};
/* 3 Enter LPS */
WLAN_PWR_CFG rtl8723D_enter_lps_flow[RTL8723D_TRANS_ACT_TO_LPS_STEPS + RTL8723D_TRANS_END_STEPS] = {
/* FW behavior */
RTL8723D_TRANS_ACT_TO_LPS
RTL8723D_TRANS_END
};
/* 3 Leave LPS */
WLAN_PWR_CFG rtl8723D_leave_lps_flow[RTL8723D_TRANS_LPS_TO_ACT_STEPS + RTL8723D_TRANS_END_STEPS] = {
/* FW behavior */
RTL8723D_TRANS_LPS_TO_ACT
RTL8723D_TRANS_END
};
File diff suppressed because it is too large Load Diff
+43
View File
@@ -0,0 +1,43 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2016 Realtek Corporation. All rights reserved.
*
* 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
*
*
******************************************************************************/
#ifdef CONFIG_RTL8723D
#ifndef _FW_HEADER_8723D_H
#define _FW_HEADER_8723D_H
#ifdef LOAD_FW_HEADER_FROM_DRIVER
#if (defined(CONFIG_AP_WOWLAN) || (DM_ODM_SUPPORT_TYPE & (ODM_AP)))
extern u8 array_mp_8723d_fw_ap[23862];
extern u32 array_length_mp_8723d_fw_ap;
#endif
#if (DM_ODM_SUPPORT_TYPE & (ODM_WIN)) || (DM_ODM_SUPPORT_TYPE & (ODM_CE))
extern u8 array_mp_8723d_fw_nic[27506];
extern u32 array_length_mp_8723d_fw_nic;
extern u8 array_mp_8723d_fw_wowlan[32334];
extern u32 array_length_mp_8723d_fw_wowlan;
#endif
#endif /* end of LOAD_FW_HEADER_FROM_DRIVER */
#endif
#endif
File diff suppressed because it is too large Load Diff
+536
View File
@@ -0,0 +1,536 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* 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
*
*
******************************************************************************/
/* ************************************************************
* Description:
*
* This file is for 92CE/92CU dynamic mechanism only
*
*
* ************************************************************ */
#define _RTL8723D_DM_C_
/* ************************************************************
* include files
* ************************************************************ */
#include <rtl8723d_hal.h>
/* ************************************************************
* Global var
* ************************************************************ */
static VOID
dm_CheckProtection(
IN PADAPTER Adapter
)
{
#if 0
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
u1Byte CurRate, RateThreshold;
if (pMgntInfo->pHTInfo->bCurBW40MHz)
RateThreshold = MGN_MCS1;
else
RateThreshold = MGN_MCS3;
if (Adapter->TxStats.CurrentInitTxRate <= RateThreshold) {
pMgntInfo->bDmDisableProtect = TRUE;
DbgPrint("Forced disable protect: %x\n", Adapter->TxStats.CurrentInitTxRate);
} else {
pMgntInfo->bDmDisableProtect = FALSE;
DbgPrint("Enable protect: %x\n", Adapter->TxStats.CurrentInitTxRate);
}
#endif
}
static VOID
dm_CheckStatistics(
IN PADAPTER Adapter
)
{
#if 0
if (!Adapter->MgntInfo.bMediaConnect)
return;
/* 2008.12.10 tynli Add for getting Current_Tx_Rate_Reg flexibly. */
rtw_hal_get_hwreg(Adapter, HW_VAR_INIT_TX_RATE, (pu1Byte)(&Adapter->TxStats.CurrentInitTxRate));
/* Calculate current Tx Rate(Successful transmited!!) */
/* Calculate current Rx Rate(Successful received!!) */
/* for tx tx retry count */
rtw_hal_get_hwreg(Adapter, HW_VAR_RETRY_COUNT, (pu1Byte)(&Adapter->TxStats.NumTxRetryCount));
#endif
}
#ifdef CONFIG_SUPPORT_HW_WPS_PBC
static void dm_CheckPbcGPIO(_adapter *padapter)
{
u8 tmp1byte;
u8 bPbcPressed = _FALSE;
if (!padapter->registrypriv.hw_wps_pbc)
return;
#ifdef CONFIG_USB_HCI
tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */
tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */
tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */
tmp1byte = rtw_read8(padapter, GPIO_IN);
if (tmp1byte == 0xff)
return;
if (tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT)
bPbcPressed = _TRUE;
#else
tmp1byte = rtw_read8(padapter, GPIO_IN);
if (tmp1byte == 0xff || padapter->init_adpt_in_progress)
return;
if ((tmp1byte & HAL_8192C_HW_GPIO_WPS_BIT) == 0)
bPbcPressed = _TRUE;
#endif
if (_TRUE == bPbcPressed) {
/* Here we only set bPbcPressed to true */
/* After trigger PBC, the variable will be set to false */
RTW_INFO("CheckPbcGPIO - PBC is pressed\n");
rtw_request_wps_pbc_event(padapter);
}
}
#endif /* #ifdef CONFIG_SUPPORT_HW_WPS_PBC */
#ifdef CONFIG_PCI_HCI
/*
* Description:
* Perform interrupt migration dynamically to reduce CPU utilization.
*
* Assumption:
* 1. Do not enable migration under WIFI test.
*
* Created by Roger, 2010.03.05.
* */
VOID
dm_InterruptMigration(
IN PADAPTER Adapter
)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
BOOLEAN bCurrentIntMt, bCurrentACIntDisable;
BOOLEAN IntMtToSet = _FALSE;
BOOLEAN ACIntToSet = _FALSE;
/* Retrieve current interrupt migration and Tx four ACs IMR settings first. */
bCurrentIntMt = pHalData->bInterruptMigration;
bCurrentACIntDisable = pHalData->bDisableTxInt;
/* */
/* <Roger_Notes> Currently we use busy traffic for reference instead of RxIntOK counts to prevent non-linear Rx statistics */
/* when interrupt migration is set before. 2010.03.05. */
/* */
if (!Adapter->registrypriv.wifi_spec &&
(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) &&
pmlmepriv->LinkDetectInfo.bHigherBusyTraffic) {
IntMtToSet = _TRUE;
/* To check whether we should disable Tx interrupt or not. */
if (pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic)
ACIntToSet = _TRUE;
}
/* Update current settings. */
if (bCurrentIntMt != IntMtToSet) {
RTW_INFO("%s(): Update interrupt migration(%d)\n", __FUNCTION__, IntMtToSet);
if (IntMtToSet) {
/* */
/* <Roger_Notes> Set interrupt migration timer and corresponging Tx/Rx counter. */
/* timer 25ns*0xfa0=100us for 0xf packets. */
/* 2010.03.05. */
/* */
rtw_write32(Adapter, REG_INT_MIG_8723D, 0xff000fa0);/* 0x306:Rx, 0x307:Tx */
pHalData->bInterruptMigration = IntMtToSet;
} else {
/* Reset all interrupt migration settings. */
rtw_write32(Adapter, REG_INT_MIG_8723D, 0);
pHalData->bInterruptMigration = IntMtToSet;
}
}
/*if( bCurrentACIntDisable != ACIntToSet ){
RTW_INFO("%s(): Update AC interrupt(%d)\n",__FUNCTION__,ACIntToSet);
if(ACIntToSet)
{
UpdateInterruptMask8192CE( Adapter, 0, RT_AC_INT_MASKS );
pHalData->bDisableTxInt = ACIntToSet;
}
else
{
UpdateInterruptMask8192CE( Adapter, RT_AC_INT_MASKS, 0 );
pHalData->bDisableTxInt = ACIntToSet;
}
}*/
}
#endif
/*
* Initialize GPIO setting registers
* */
static void
dm_InitGPIOSetting(
IN PADAPTER Adapter
)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
u8 tmp1byte;
tmp1byte = rtw_read8(Adapter, REG_GPIO_MUXCFG);
tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
rtw_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
}
/* ************************************************************
* functions
* ************************************************************ */
static void Init_ODM_ComInfo_8723d(PADAPTER Adapter)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
PDM_ODM_T pDM_Odm = &(pHalData->odmpriv);
u32 SupportAbility = 0;
u8 cut_ver, fab_ver;
Init_ODM_ComInfo(Adapter);
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_PACKAGE_TYPE, pHalData->PackageType);
fab_ver = ODM_TSMC;
cut_ver = GET_CVID_CUT_VERSION(pHalData->VersionID);
RTW_INFO("%s(): fab_ver=%d cut_ver=%d\n", __func__, fab_ver, cut_ver);
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
#ifdef CONFIG_DISABLE_ODM
SupportAbility = 0;
#else
SupportAbility =
#if 1
ODM_RF_CALIBRATION |
ODM_RF_TX_PWR_TRACK
#else
0
#endif
;
if (pHalData->AntDivCfg)
SupportAbility |= ODM_BB_ANT_DIV;
#endif
ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility);
}
static void Update_ODM_ComInfo_8723d(PADAPTER Adapter)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
PDM_ODM_T pDM_Odm = &(pHalData->odmpriv);
u32 SupportAbility = 0;
SupportAbility = 0
| ODM_BB_DIG /* For BB */
| ODM_BB_RA_MASK
| ODM_BB_FA_CNT
| ODM_BB_RSSI_MONITOR
| ODM_BB_CCK_PD
| ODM_BB_CFO_TRACKING
/* | ODM_BB_PWR_TRAIN */
| ODM_BB_NHM_CNT
| ODM_RF_TX_PWR_TRACK /* For RF */
| ODM_RF_CALIBRATION
| ODM_MAC_EDCA_TURBO /* For MAC */
;
if (rtw_odm_adaptivity_needed(Adapter) == _TRUE) {
rtw_odm_adaptivity_config_msg(RTW_DBGDUMP, Adapter);
SupportAbility |= ODM_BB_ADAPTIVITY;
}
#ifdef CONFIG_ANTENNA_DIVERSITY
if (pHalData->AntDivCfg)
SupportAbility |= ODM_BB_ANT_DIV;
#endif
#if (MP_DRIVER == 1)
if (Adapter->registrypriv.mp_mode == 1) {
SupportAbility = 0
| ODM_RF_CALIBRATION
| ODM_RF_TX_PWR_TRACK
;
}
#endif/* (MP_DRIVER==1) */
#ifdef CONFIG_DISABLE_ODM
SupportAbility = 0;
#endif/* CONFIG_DISABLE_ODM */
ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, SupportAbility);
ODM_CmnInfoInit(pDM_Odm, ODM_CMNINFO_RF_ANTENNA_TYPE,
pHalData->TRxAntDivType);
}
void
rtl8723d_InitHalDm(
IN PADAPTER Adapter
)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
PDM_ODM_T pDM_Odm = &(pHalData->odmpriv);
u8 i;
#ifdef CONFIG_USB_HCI
dm_InitGPIOSetting(Adapter);
#endif
pHalData->DM_Type = DM_Type_ByDriver;
Update_ODM_ComInfo_8723d(Adapter);
ODM_DMInit(pDM_Odm);
}
VOID
rtl8723d_HalDmWatchDog(
IN PADAPTER Adapter
)
{
BOOLEAN bFwCurrentInPSMode = _FALSE;
BOOLEAN bFwPSAwake = _TRUE;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
#ifdef CONFIG_MP_INCLUDED
/* #if MP_DRIVER */
if (Adapter->registrypriv.mp_mode == 1 && Adapter->mppriv.mp_dm == 0) /* for MP power tracking */
return;
/* #endif */
#endif
if (!rtw_is_hw_init_completed(Adapter))
goto skip_dm;
#ifdef CONFIG_LPS
bFwCurrentInPSMode = adapter_to_pwrctl(Adapter)->bFwCurrentInPSMode;
rtw_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
#endif
#ifdef CONFIG_P2P
/* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
/* modifed by thomas. 2011.06.11. */
if (Adapter->wdinfo.p2p_ps_mode)
bFwPSAwake = _FALSE;
#endif /* CONFIG_P2P */
if ((rtw_is_hw_init_completed(Adapter))
&& ((!bFwCurrentInPSMode) && bFwPSAwake)) {
/* */
/* Calculate Tx/Rx statistics. */
/* */
dm_CheckStatistics(Adapter);
rtw_hal_check_rxfifo_full(Adapter);
/* */
/* Dynamically switch RTS/CTS protection. */
/* */
/* dm_CheckProtection(Adapter); */
#ifdef CONFIG_PCI_HCI
/* 20100630 Joseph: Disable Interrupt Migration mechanism temporarily because it degrades Rx throughput. */
/* Tx Migration settings. */
/* dm_InterruptMigration(Adapter); */
/* if(Adapter->HalFunc.TxCheckStuckHandler(Adapter)) */
/* PlatformScheduleWorkItem(&(GET_HAL_DATA(Adapter)->HalResetWorkItem)); */
#endif
}
/* ODM */
if (rtw_is_hw_init_completed(Adapter)) {
u8 bLinked = _FALSE;
u8 bsta_state = _FALSE;
u8 bBtDisabled = _TRUE;
if (rtw_mi_check_status(Adapter, MI_ASSOC)) {
bLinked = _TRUE;
if (rtw_mi_check_status(Adapter, MI_STA_LINKED))
bsta_state = _TRUE;
}
ODM_CmnInfoUpdate(&pHalData->odmpriv , ODM_CMNINFO_LINK, bLinked);
ODM_CmnInfoUpdate(&pHalData->odmpriv , ODM_CMNINFO_STATION_STATE, bsta_state);
/* ODM_CmnInfoUpdate(&pHalData->odmpriv ,ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM); */
#ifdef CONFIG_BT_COEXIST
bBtDisabled = rtw_btcoex_IsBtDisabled(Adapter);
#endif /* CONFIG_BT_COEXIST */
ODM_CmnInfoUpdate(&pHalData->odmpriv, ODM_CMNINFO_BT_ENABLED, ((bBtDisabled == _TRUE) ? _FALSE : _TRUE));
ODM_DMWatchdog(&pHalData->odmpriv);
}
skip_dm:
/* Check GPIO to determine current RF on/off and Pbc status. */
/* Check Hardware Radio ON/OFF or not */
/* if(Adapter->MgntInfo.PowerSaveControl.bGpioRfSw) */
/* { */
/* RTPRINT(FPWR, PWRHW, ("dm_CheckRfCtrlGPIO\n")); */
/* dm_CheckRfCtrlGPIO(Adapter); */
/* } */
#ifdef CONFIG_SUPPORT_HW_WPS_PBC
dm_CheckPbcGPIO(Adapter);
#endif
return;
}
void rtl8723d_hal_dm_in_lps(PADAPTER padapter)
{
u32 PWDB_rssi = 0;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *psta = NULL;
RTW_INFO("%s, RSSI_Min=%d\n", __func__, pDM_Odm->RSSI_Min);
/* update IGI */
ODM_Write_DIG(pDM_Odm, pDM_Odm->RSSI_Min);
/* set rssi to fw */
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
if (psta && (psta->rssi_stat.UndecoratedSmoothedPWDB > 0)) {
PWDB_rssi = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB << 16));
rtl8723d_set_rssi_cmd(padapter, (u8 *)&PWDB_rssi);
}
}
void rtl8723d_HalDmWatchDog_in_LPS(IN PADAPTER Adapter)
{
u8 bLinked = _FALSE;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable;
struct sta_priv *pstapriv = &Adapter->stapriv;
struct sta_info *psta = NULL;
if (!rtw_is_hw_init_completed(Adapter))
goto skip_lps_dm;
if (rtw_mi_check_status(Adapter, MI_ASSOC))
bLinked = _TRUE;
ODM_CmnInfoUpdate(&pHalData->odmpriv , ODM_CMNINFO_LINK, bLinked);
if (bLinked == _FALSE)
goto skip_lps_dm;
if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
goto skip_lps_dm;
/* ODM_DMWatchdog(&pHalData->odmpriv); */
/* Do DIG by RSSI In LPS-32K */
/* .1 Find MIN-RSSI */
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
if (psta == NULL)
goto skip_lps_dm;
pHalData->EntryMinUndecoratedSmoothedPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
RTW_INFO("CurIGValue=%d, EntryMinUndecoratedSmoothedPWDB = %d\n", pDM_DigTable->CurIGValue, pHalData->EntryMinUndecoratedSmoothedPWDB);
if (pHalData->EntryMinUndecoratedSmoothedPWDB <= 0)
goto skip_lps_dm;
pHalData->MinUndecoratedPWDBForDM = pHalData->EntryMinUndecoratedSmoothedPWDB;
pDM_Odm->RSSI_Min = pHalData->MinUndecoratedPWDBForDM;
/* if(pDM_DigTable->CurIGValue != pDM_Odm->RSSI_Min) */
if ((pDM_DigTable->CurIGValue > pDM_Odm->RSSI_Min + 5) ||
(pDM_DigTable->CurIGValue < pDM_Odm->RSSI_Min - 5))
{
#ifdef CONFIG_LPS
rtw_dm_in_lps_wk_cmd(Adapter);
#endif /* CONFIG_LPS */
}
skip_lps_dm:
return;
}
void rtl8723d_init_dm_priv(IN PADAPTER Adapter)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
PDM_ODM_T podmpriv = &pHalData->odmpriv;
Init_ODM_ComInfo_8723d(Adapter);
ODM_InitAllTimers(podmpriv);
}
void rtl8723d_deinit_dm_priv(IN PADAPTER Adapter)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
PDM_ODM_T podmpriv = &pHalData->odmpriv;
ODM_CancelAllTimers(podmpriv);
}
File diff suppressed because it is too large Load Diff
+877
View File
@@ -0,0 +1,877 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* 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
*
*
******************************************************************************/
#include <rtl8723d_hal.h>
#ifdef CONFIG_LPS_POFF
/****************************************************************************
* Function: constuct Register Setting for HW to Backup Before LPS
* page 2/4/6/7/8~F and page 0x24(for NAN)
*****************************************************************************/
static bool hal_construct_poff_static_file(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *lps_poff_info = NULL;
u8 *staticFile = NULL;
u8 *start_at = NULL;
u8 page_count = 0, page_offset = 0, round = 0;
/*There are 256 bytes in each register bank, and 64 dwords*/
u8 total = 256 / 4;
u16 offset = 0, addr_value = 0;
if (pwrpriv->plps_poff_info == NULL) {
RTW_INFO("%s: please alloc plps_poff_info first!!\n", __func__);
return _FALSE;
}
lps_poff_info = pwrpriv->plps_poff_info;
if (lps_poff_info->pStaticFile == NULL) {
RTW_INFO("%s: please alloc static configure file first!!\n",
__func__);
return _FALSE;
}
staticFile = lps_poff_info->pStaticFile + TXDESC_SIZE;
for (page_count = 2 ; page_count < 16 ; page_count++) {
page_offset = 0;
if (page_count == 3 || page_count == 5)
continue;
offset = (round << 9);
for (page_offset = 0 ; page_offset < total ; page_offset++) {
start_at = staticFile + offset + (page_offset << 3);
addr_value =
((page_count << 8) + (page_offset << 2)) >> 2;
SET_HOIE_ENTRY_LOW_DATA(start_at, 0);
SET_HOIE_ENTRY_HIGH_DATA(start_at, 0);
SET_HOIE_ENTRY_MODE_SELECT(start_at, 0);
SET_HOIE_ENTRY_ADDRESS(start_at, addr_value);
SET_HOIE_ENTRY_BYTE_MASK(start_at, 0xF);
SET_HOIE_ENTRY_IO_LOCK(start_at, 0);
SET_HOIE_ENTRY_WR_EN(start_at, 1);
SET_HOIE_ENTRY_RD_EN(start_at, 1);
SET_HOIE_ENTRY_RAW_RW(start_at, 0);
SET_HOIE_ENTRY_RAW(start_at, 0);
SET_HOIE_ENTRY_IO_DELAY(start_at, 0);
}
round++;
}
/*construct page 24*/
offset = (round << 9);
for (page_offset = 0 ; page_offset < total ; page_offset++) {
start_at = staticFile + offset + (page_offset << 3);
addr_value = ((0x24 << 8) + (page_offset << 2)) >> 2;
SET_HOIE_ENTRY_LOW_DATA(start_at, 0);
SET_HOIE_ENTRY_HIGH_DATA(start_at, 0);
SET_HOIE_ENTRY_MODE_SELECT(start_at, 0);
SET_HOIE_ENTRY_ADDRESS(start_at, addr_value);
SET_HOIE_ENTRY_BYTE_MASK(start_at, 0xF);
SET_HOIE_ENTRY_IO_LOCK(start_at, 0);
SET_HOIE_ENTRY_WR_EN(start_at, 1);
SET_HOIE_ENTRY_RD_EN(start_at, 1);
SET_HOIE_ENTRY_RAW_RW(start_at, 0);
SET_HOIE_ENTRY_RAW(start_at, 0);
SET_HOIE_ENTRY_IO_DELAY(start_at, 0);
}
RTW_INFO("%s: (round << 9) + (PageOffset << 3) = %#08x\n",
__func__, offset + (page_offset << 3));
start_at = staticFile + offset + (page_offset << 3);
/* add last command: 00 00 00 00 00 40 30 00,suggested by DD */
*(start_at) = 0;
*(start_at + 1) = 0;
*(start_at + 2) = 0;
*(start_at + 3) = 0;
*(start_at + 4) = 0;
*(start_at + 5) = 0x40;
*(start_at + 6) = 0x30;
*(start_at + 7) = 0;
return _TRUE;
}
/****************************************************************************
Function: send Location of configuration file and other info for FW
*****************************************************************************/
static void rtl8723d_lps_poff_h2c_param(PADAPTER padapter, u8 tx_bndy, u16 len,
bool isDynamic)
{
u8 lps_poff_param[H2C_LPS_POFF_PARAM_LEN] = {0};
u8 start_addr_l = 0, start_addr_h = 0;
u8 end_addr_l = 0, end_addr_h = 0;
u16 start_addr = 0, end_addr = 0;
if (len < 8)
return;
/*
set start address, The parameter is entrys. every page has 16 entrys
The Tx Descriptor is 40Byte which locate 5 entries
*/
start_addr = (tx_bndy << 4) + 5;
end_addr = start_addr + (len >> 3) - 1;
RTW_INFO("%s: start_addr = %#02X, end_addr= %#02X\n",
__func__, start_addr, end_addr);
start_addr_l = (u8)start_addr;
start_addr_h = (u8)(start_addr >> 8);
end_addr_l = (u8)end_addr;
end_addr_h = (u8)(end_addr >> 8);
/*construct H2C Cmd*/
if (isDynamic)
SET_H2CCMD_LPS_POFF_PARAM_RDVLD(lps_poff_param, 0);
else
SET_H2CCMD_LPS_POFF_PARAM_RDVLD(lps_poff_param, 1);
SET_H2CCMD_LPS_POFF_PARAM_WRVLD(lps_poff_param, 1);
SET_H2CCMD_LPS_POFF_PARAM_STARTADDL(lps_poff_param, start_addr_l);
SET_H2CCMD_LPS_POFF_PARAM_STARTADDH(lps_poff_param, start_addr_h);
SET_H2CCMD_LPS_POFF_PARAM_ENDADDL(lps_poff_param, end_addr_l);
SET_H2CCMD_LPS_POFF_PARAM_ENDADDH(lps_poff_param, end_addr_h);
rtw_hal_fill_h2c_cmd(padapter, H2C_LPS_POFF_PARAM,
H2C_LPS_POFF_PARAM_LEN, lps_poff_param);
}
/*************************************************************************
Function: SET Location of Configuration File to FW
**************************************************************************/
static void rtl8723d_lps_poff_set_param(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
u8 static_tx_bndy = 0;
u8 dynamic_tx_bndy = 0;
u16 static_len = 0, dynamic_len = 0;
static_tx_bndy = plps_poff_info->tx_bndy_static;
dynamic_tx_bndy = plps_poff_info->tx_bndy_dynamic;
dynamic_len = plps_poff_info->ConfLenForPTK +
plps_poff_info->ConfLenForGTK;
if (ATOMIC_READ(&plps_poff_info->bSetPOFFParm) == _TRUE)
return;
/* download static configuration */
static_len = LPS_POFF_STATIC_FILE_LEN - TXDESC_SIZE;
rtl8723d_lps_poff_h2c_param(padapter, static_tx_bndy,
static_len, _FALSE);
/* download dynamic configuration */
/* the length must be add more 8 Byte due to hard bug */
if (dynamic_len != 0) {
dynamic_len += 8;
rtl8723d_lps_poff_h2c_param(padapter, dynamic_tx_bndy,
dynamic_len, _TRUE);
}
ATOMIC_SET(&plps_poff_info->bSetPOFFParm, _TRUE);
}
/****************************************************************************
Function: change tx boundary
*****************************************************************************/
static void rtl8723d_lps_poff_set_tx_bndy(PADAPTER padapter, u8 tx_bndy)
{
u32 numHQ = 0x10;
u32 numLQ = 0x10;
u32 numPubQ = 0;
u8 numNQ = 0;
u32 val32 = 0;
u8 val8 = 0;
#if (DEV_BUS_TYPE == RT_PCI_INTERFACE)
numHQ = 0x8;
numLQ = 0x8;
#endif
numPubQ = tx_bndy - numHQ - numLQ - numNQ - 1;
val8 = _NPQ(numNQ);
val32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
rtw_write8(padapter, REG_RQPN_NPQ, val8);
rtw_write32(padapter, REG_RQPN, val32);
}
/****************************************************************************
Function: change tx boundary flow
*****************************************************************************/
static bool rtl8723d_lps_poff_tx_bndy_flow(PADAPTER padapter, bool enable)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
struct xmit_priv *pxmitpriv;
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
u8 tx_bndy = 0, tx_bndy_new = 0, count = 0, queue_pending = _FALSE;
u8 val8 = 0;
u16 val16 = 0;
u32 val32 = 0;
pxmitpriv = &padapter->xmitpriv;
rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&tx_bndy);
RTW_INFO("%s: tx_bndy: %#X, tx_bndy_static: %#X\n",
__func__, tx_bndy, plps_poff_info->tx_bndy_static);
if (enable)
tx_bndy_new = plps_poff_info->tx_bndy_static + 1;
else
tx_bndy_new = tx_bndy;
ATOMIC_SET(&plps_poff_info->bTxBoundInProgress, _TRUE);
/* stop os layer TX*/
rtw_mi_netif_stop_queue(padapter, _FALSE);
val16 = rtw_read16(padapter, REG_TXPKT_EMPTY);
/* stop tx process and wait tx empty */
while ((val16 & 0x05FF) != 0x05FF) {
rtw_mdelay_os(10);
val16 = rtw_read16(padapter, REG_TXPKT_EMPTY);
count++;
if (count >= 100) {
val16 = rtw_read16(padapter, REG_TXPKT_EMPTY);
RTW_INFO("%s, txpkt_empty: %#04x\n", __func__, val16);
val8 = rtw_read8(padapter, REG_CPU_MGQ_INFORMATION);
RTW_INFO("%s, REG_CPU_MGQ_INFORMATION: %#02x\n",
__func__, val8);
RTW_INFO("%s, wait for tx empty timeout!!\n", __func__);
ATOMIC_SET(&plps_poff_info->bTxBoundInProgress, _FALSE);
rtw_mi_netif_wake_queue(padapter);
return _FALSE;
}
}
/* change tx boundary*/
rtl8723d_lps_poff_set_tx_bndy(padapter, tx_bndy_new);
/* set free tail */
val32 = rtw_read32(padapter, REG_FWHW_TXQ_CTRL);
val32 |= BIT20;
rtw_write32(padapter, REG_FWHW_TXQ_CTRL, val32);
rtw_write8(padapter, REG_BCNQ_BDNY, tx_bndy_new);
RTW_INFO("%s: free tail = %#x after\n", __func__,
rtw_read8(padapter, REG_FW_FREE_TAIL_8723D));
/* set bcn head */
val32 = rtw_read32(padapter, REG_FWHW_TXQ_CTRL);
val32 &= ~BIT20;
rtw_write32(padapter, REG_FWHW_TXQ_CTRL, val32);
rtw_write8(padapter, REG_BCNQ_BDNY, tx_bndy);
/* reinit LLT */
rtl8723d_InitLLTTable(padapter);
/* clear 0x210 ??*/
val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
if (val32 != 0) {
RTW_INFO("%s: REG_TXDMA_STATUS: %#08x\n", __func__, val32);
rtw_write32(padapter, REG_TXDMA_STATUS, val32);
}
ATOMIC_SET(&plps_poff_info->bTxBoundInProgress, _FALSE);
/* restart tx */
rtw_mi_netif_wake_queue(padapter);
return _TRUE;
}
/****************************************************************************
Function: Append extra bytes for dynamic confiure file
Add one entry to fix hw bug,
list command: 00 00 00 00 00 40 30 00, suggested by DD
*****************************************************************************/
static u8 rtl8723d_lps_poff_append_extra_info(PADAPTER padapter, u32 len)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
u32 data_offset = len + plps_poff_info->ConfFileOffset;
*(plps_poff_info->pDynamicFile + (data_offset)) = 0x00;
*(plps_poff_info->pDynamicFile + (data_offset + 1)) = 0x00;
*(plps_poff_info->pDynamicFile + (data_offset + 2)) = 0x00;
*(plps_poff_info->pDynamicFile + (data_offset + 3)) = 0x00;
*(plps_poff_info->pDynamicFile + (data_offset + 4)) = 0x00;
*(plps_poff_info->pDynamicFile + (data_offset + 5)) = 0x40;
*(plps_poff_info->pDynamicFile + (data_offset + 6)) = 0x30;
*(plps_poff_info->pDynamicFile + (data_offset + 7)) = 0x00;
return 8;
}
/****************************************************************************
Function: xmit config file to write port.
*****************************************************************************/
static void rtl8723d_lps_poff_send_config_frame(PADAPTER padapter,
u8 *pFile, u32 len)
{
struct xmit_frame *pcmdframe = NULL;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
int i = 0;
pxmitpriv = &padapter->xmitpriv;
pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
if (pcmdframe == NULL)
RTW_INFO("%s: alloc cmdframe fail\n", __func__);
_rtw_memcpy(pcmdframe->buf_addr, pFile, len);
pattrib = &pcmdframe->attrib;
update_mgntframe_attrib(padapter, pattrib);
pattrib->qsel = QSLT_BEACON;
pattrib->pktlen = len - TXDESC_OFFSET;
pattrib->last_txcmdsz = len - TXDESC_OFFSET;
RTW_INFO("%s, len: %d, MAX_CMDBUF_SZ: %d\n", __func__, len,
MAX_CMDBUF_SZ);
#ifdef CONFIG_PCI_HCI
dump_mgntframe(padapter, pcmdframe);
#else
dump_mgntframe_and_wait(padapter, pcmdframe, 100);
#endif
}
/****************************************************************************
Function: download config file flow
*****************************************************************************/
static void rtl8723d_lps_poff_send_config_file(PADAPTER padapter,
u8 *pFile, u8 loc, u32 len)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
bool bRecover = _FALSE, bcn_valid = _FALSE;
u8 DLBcnCount = 0, val8 = 0, tx_bndy = 0;
u32 poll = 0;
rtw_hal_get_def_var(padapter,
HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&tx_bndy);
/* set 0x100[8]=1 for SW beacon */
val8 = rtw_read8(padapter, REG_CR + 1);
val8 |= BIT(0);
rtw_write8(padapter, REG_CR + 1, val8);
/*set 0x422[6]=0 to disable beacon DMA pass to MACTx*/
if (pHalData->RegFwHwTxQCtrl & BIT(6))
bRecover = _TRUE;
rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
pHalData->RegFwHwTxQCtrl & ~BIT(6));
pHalData->RegFwHwTxQCtrl &= ~BIT(6);
/* Clear beacon valid check bit. */
rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
/* set 0x209[7:0] beacon queue head page to start download location */
rtw_write8(padapter, REG_TDECTRL_8723D + 1, loc);
DLBcnCount = 0;
poll = 0;
do {
rtl8723d_lps_poff_send_config_frame(padapter, pFile, len);
DLBcnCount++;
do {
rtw_mdelay_os(10);
/*check rsvd page download OK.*/
rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID,
(u8 *)(&bcn_valid));
poll++;
} while (!bcn_valid && (poll % 10) != 0
&& !RTW_CANNOT_RUN(padapter));
} while (!bcn_valid && DLBcnCount <= 100 && !RTW_CANNOT_RUN(padapter));
if (!bcn_valid)
RTW_INFO(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n",
ADPT_ARG(padapter), DLBcnCount, poll);
else
RTW_INFO(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n",
ADPT_ARG(padapter), DLBcnCount, poll);
/*restore bcn operation*/
rtw_write8(padapter, REG_TDECTRL_8723D + 1, tx_bndy);
/*restore 0x422[6]=1 for normal bcn*/
if (bRecover) {
rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
pHalData->RegFwHwTxQCtrl | BIT(6));
pHalData->RegFwHwTxQCtrl |= BIT(6);
}
/*restore 0x100[8]=0 for SW beacon*/
/* Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/
#ifndef CONFIG_PCI_HCI
val8 = rtw_read8(padapter, REG_CR + 1);
val8 &= ~BIT(0);
rtw_write8(padapter, REG_CR + 1, val8);
#endif
}
/****************************************************************************
Function: Prepare Confiure File
*****************************************************************************/
static void rtl8723d_lps_poff_dl_config_file(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
u8 count = 0, append_len = 0;
u32 offset = 0, static_file_len = 0, dynamic_file_len = 0;
int i = 0, j = 0;
offset = plps_poff_info->ConfFileOffset;
static_file_len = LPS_POFF_STATIC_FILE_LEN - offset;
dynamic_file_len =
plps_poff_info->ConfLenForPTK + plps_poff_info->ConfLenForGTK;
RTW_INFO("%s: static_file_len: %d dynamic_file_len: %d, offset: %d\n",
__func__, static_file_len, dynamic_file_len, offset);
/*static file*/
rtl8723d_lps_poff_send_config_file(padapter,
plps_poff_info->pStaticFile + offset,
plps_poff_info->tx_bndy_static,
static_file_len);
/*dynamic file*/
if (dynamic_file_len != 0) {
dynamic_file_len += TXDESC_SIZE - offset;
append_len =
rtl8723d_lps_poff_append_extra_info(padapter,
dynamic_file_len);
dynamic_file_len += append_len;
rtl8723d_lps_poff_send_config_file(padapter,
plps_poff_info->pDynamicFile + offset,
plps_poff_info->tx_bndy_dynamic,
dynamic_file_len);
}
}
static u8 rtl8723d_lps_poff_set_dynamic_file(u8 *pFile, u32 type, u32 wdata)
{
SET_HOIE_ENTRY_LOW_DATA(pFile, (u16)wdata);
SET_HOIE_ENTRY_HIGH_DATA(pFile, (u16)(wdata >> 16));
SET_HOIE_ENTRY_MODE_SELECT(pFile, 0);
SET_HOIE_ENTRY_ADDRESS(pFile, (type >> 2));
SET_HOIE_ENTRY_BYTE_MASK(pFile, 0xF);
SET_HOIE_ENTRY_IO_LOCK(pFile, 0);
SET_HOIE_ENTRY_WR_EN(pFile, 1);
SET_HOIE_ENTRY_RD_EN(pFile, 0);
SET_HOIE_ENTRY_RAW_RW(pFile, 0);
SET_HOIE_ENTRY_RAW(pFile, 0);
SET_HOIE_ENTRY_IO_DELAY(pFile, 0);
return 8;
}
static void rtl8723d_lps_poff_dynamic_file(PADAPTER padapter, u8 index, u8 isGK)
{
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
u8 *ptkfile = NULL;
u8 ret = 0;
u32 tgt_cmd = 0, tgt_wdata = 0;
int i = 0, j = 0;
for (i = 0 ; i < CAM_CONTENT_COUNT; i++) {
if (!isGK)
ptkfile = plps_poff_info->pDynamicFile +
plps_poff_info->ConfLenForPTK + TXDESC_SIZE;
else
ptkfile = plps_poff_info->pDynamicFile +
plps_poff_info->ConfLenForPTK +
plps_poff_info->ConfLenForGTK + TXDESC_SIZE;
tgt_cmd = i + (CAM_CONTENT_COUNT * index);
tgt_cmd = tgt_cmd | CAM_POLLINIG | CAM_WRITE;
switch (i) {
case 0:
tgt_wdata = dvobj->cam_cache[index].ctrl |
dvobj->cam_cache[index].mac[0] << 16 |
dvobj->cam_cache[index].mac[1] << 24;
break;
case 1:
tgt_wdata = dvobj->cam_cache[index].mac[2] |
dvobj->cam_cache[index].mac[3] << 8 |
dvobj->cam_cache[index].mac[4] << 16 |
dvobj->cam_cache[index].mac[5] << 24;
break;
default:
j = (i - 2) << 2;
tgt_wdata =
dvobj->cam_cache[index].key[j + 3] << 24 |
dvobj->cam_cache[index].key[j + 2] << 16 |
dvobj->cam_cache[index].key[j + 1] << 8 |
dvobj->cam_cache[index].key[j];
break;
}
ret = rtl8723d_lps_poff_set_dynamic_file(ptkfile,
WCAMI, tgt_wdata);
if (!isGK) {
plps_poff_info->ConfLenForPTK += ret;
ptkfile = plps_poff_info->pDynamicFile +
plps_poff_info->ConfLenForPTK + TXDESC_SIZE;
} else {
plps_poff_info->ConfLenForGTK += ret;
ptkfile = plps_poff_info->pDynamicFile +
plps_poff_info->ConfLenForPTK +
plps_poff_info->ConfLenForGTK + TXDESC_SIZE;
}
ret = rtl8723d_lps_poff_set_dynamic_file(ptkfile,
RWCAM, tgt_cmd);
if (!isGK)
plps_poff_info->ConfLenForPTK += ret;
else
plps_poff_info->ConfLenForGTK += ret;
#if 0
RTW_INFO("%s: tgt_wdata: %#08x\n", __func__, tgt_wdata);
#endif
}
}
static void rtl8723d_lps_poff_sec_cam_opt(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
int i = 0;
u8 isValid = 0, isGK = 0, index = 0, key_id = 0xff, gk_start = 0xff;
u16 val16 = 0, len = 0;
/*Using cam cache to create config file for FW use.*/
/*1- deail with pairwise key*/
for (i = 0 ; i < cam_ctl->num ; i++) {
val16 = dvobj->cam_cache[i].ctrl;
isValid = (val16 >> 15) & 0x01;
isGK = (val16 >> 6) & 0x01;
if (isValid && !isGK) {
rtl8723d_lps_poff_dynamic_file(padapter, i, _FALSE);
RTW_INFO("%s: id: %2u, kid: %3u, ctrl: %#04x, "MAC_FMT""KEY_FMT"\n",
__func__, i, (dvobj->cam_cache[i].ctrl) & 0x03,
dvobj->cam_cache[i].ctrl,
MAC_ARG(dvobj->cam_cache[i].mac),
KEY_ARG(dvobj->cam_cache[i].key));
} else if (isGK) {
key_id = dvobj->cam_cache[i].ctrl & 0x03;
if (key_id == pmlmeinfo->key_index)
gk_start = i;
RTW_INFO("%s: GK_start at %d\n", __func__, gk_start);
RTW_INFO("%s: id: %2u, kid: %3u, ctrl: %#04x, "MAC_FMT""KEY_FMT"\n",
__func__, i, key_id, dvobj->cam_cache[i].ctrl,
MAC_ARG(dvobj->cam_cache[i].mac),
KEY_ARG(dvobj->cam_cache[i].key));
}
}
/*2- deail with group key*/
rtl8723d_lps_poff_dynamic_file(padapter, gk_start, _TRUE);
RTW_INFO("%s: ConfLenForPTK: %d, ConfLenForGTK: %d\n", __func__,
plps_poff_info->ConfLenForPTK, plps_poff_info->ConfLenForGTK);
}
/****************************************************************************
Function: Prepare enter LPS partial off status.
change tx boundary, download configuration file if necessary and send info to FW
*****************************************************************************/
static bool rtl8723d_prepare_for_enter_poff(PADAPTER padapter, bool bEnterLPS)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
bool ret = _FALSE;
u8 i = 0, cam_cache_num = 0;
for (i = 0 ; i < cam_ctl->num; i++) {
if (dvobj->cam_cache[i].ctrl != 0)
cam_cache_num++;
}
ret = rtl8723d_lps_poff_tx_bndy_flow(padapter, bEnterLPS);
if (ret == _TRUE) {
if (cam_cache_num > 0) {
rtl8723d_lps_poff_sec_cam_opt(padapter);
} else {
plps_poff_info->ConfLenForPTK = 0;
plps_poff_info->ConfLenForGTK = 0;
}
rtl8723d_lps_poff_dl_config_file(padapter);
rtl8723d_lps_poff_set_param(padapter);
}
return ret;
}
/*************************************************************************
Function: SET H2C To Enable Partial Off
**************************************************************************/
void rtl8723d_lps_poff_h2c_ctrl(PADAPTER padapter, u8 en)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
u8 param = 0;
if (pregistrypriv->wifi_spec == 1)
return;
if (plps_poff_info->bEn == _FALSE)
return;
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
if (en) {
RTW_INFO("%s: enable case\n", __func__);
SET_H2CCMD_LPS_POFF_CTRL_EN(&param, 1);
} else {
RTW_INFO("%s: disable case\n", __func__);
ATOMIC_SET(&plps_poff_info->bSetPOFFParm, _FALSE);
SET_H2CCMD_LPS_POFF_CTRL_EN(&param, 0);
}
rtw_hal_fill_h2c_cmd(padapter, H2C_LPS_POFF_CTRL,
H2C_LPS_POFF_CTRL_LEN, &param);
}
}
/*************************************************************************
Function: The operation to Enter or Leave FWLPS 32K when partial off enable
**************************************************************************/
void rtl8723d_lps_poff_set_ps_mode(PADAPTER padapter, bool bEnterLPS)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
bool res = _FALSE;
if (pregistrypriv->wifi_spec == 1)
return;
if (plps_poff_info->bEn) {
plps_poff_info->ConfLenForPTK = 0;
plps_poff_info->ConfLenForGTK = 0;
if (bEnterLPS) {
res = rtl8723d_prepare_for_enter_poff(padapter,
bEnterLPS);
ATOMIC_SET(&plps_poff_info->bEnterPOFF, res);
} else
rtl8723d_lps_poff_tx_bndy_flow(padapter, bEnterLPS);
}
}
/*************************************************************************
Function: Get LPS-POFF Enter Status
**************************************************************************/
bool rtl8723d_lps_poff_get_status(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
if (pregistrypriv->wifi_spec == 1) {
RTW_INFO("%s: wifi_spec is enable\n", __func__);
return _FALSE;
}
if (plps_poff_info->bEn == _FALSE) {
RTW_INFO("%s: POFF is disable\n", __func__);
return _FALSE;
}
return ATOMIC_READ(&plps_poff_info->bEnterPOFF);
}
/*************************************************************************
Function: Get LPS-POFF change tx bndy status
**************************************************************************/
bool rtl8723d_lps_poff_get_txbndy_status(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
return ATOMIC_READ(&plps_poff_info->bTxBoundInProgress);
}
/*************************************************************************
Function: Get LPS-POFF initial
**************************************************************************/
void rtl8723d_lps_poff_init(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
struct registry_priv *pregistrypriv = &padapter->registrypriv;
lps_poff_info_t *lps_poff_info;
u8 tx_bndy = 0, page_size = 0, total_page = 0, page_num = 0;
u8 val = 0;
if (pregistrypriv->wifi_spec == 1)
return;
if (is_primary_adapter(padapter)) {
rtw_hal_get_def_var(padapter,
HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&val);
tx_bndy = val;
rtw_hal_get_def_var(padapter,
HAL_DEF_TX_PAGE_SIZE, (u8 *)&val);
page_size = val;
total_page = PageNum(LPS_POFF_STATIC_FILE_LEN, page_size) +
PageNum(LPS_POFF_DYNAMIC_FILE_LEN, page_size);
lps_poff_info =
(lps_poff_info_t *)rtw_zmalloc(sizeof(lps_poff_info_t));
if (lps_poff_info != NULL) {
pwrpriv->plps_poff_info = lps_poff_info;
lps_poff_info->pStaticFile =
(u8 *)rtw_zmalloc(LPS_POFF_STATIC_FILE_LEN);
if (lps_poff_info->pStaticFile == NULL) {
RTW_INFO("%s: alloc pStaticFile fail\n",
__func__);
goto alloc_static_conf_file_fail;
} else {
pwrpriv->plps_poff_info->pStaticFile =
lps_poff_info->pStaticFile;
}
lps_poff_info->pDynamicFile =
(u8 *)rtw_zmalloc(LPS_POFF_DYNAMIC_FILE_LEN);
if (lps_poff_info->pDynamicFile == NULL) {
RTW_INFO("%s: alloc pDynamicFile fail\n",
__func__);
goto alloc_dynamic_conf_file_fail;
} else {
pwrpriv->plps_poff_info->pDynamicFile =
lps_poff_info->pDynamicFile;
}
pwrpriv->plps_poff_info->bEn = _TRUE;
ATOMIC_SET(&pwrpriv->plps_poff_info->bEnterPOFF,
_FALSE);
ATOMIC_SET(&pwrpriv->plps_poff_info->bSetPOFFParm,
_FALSE);
ATOMIC_SET(&pwrpriv->plps_poff_info->bTxBoundInProgress,
_FALSE);
#ifdef CONFIG_PCI_HCI
pwrpriv->plps_poff_info->ConfFileOffset = 40;
#else
pwrpriv->plps_poff_info->ConfFileOffset = 0;
#endif
pwrpriv->plps_poff_info->tx_bndy_static =
tx_bndy - total_page;
page_num = PageNum(LPS_POFF_DYNAMIC_FILE_LEN,
page_size);
pwrpriv->plps_poff_info->tx_bndy_dynamic =
tx_bndy - page_num;
/*
construct static DLConfiguration File
*/
hal_construct_poff_static_file(padapter);
goto exit;
} else {
RTW_INFO("%s: alloc lps_poff_info fail\n", __func__);
goto exit;
}
}
alloc_dynamic_conf_file_fail:
rtw_mfree((u8 *)pwrpriv->plps_poff_info->pStaticFile,
LPS_POFF_STATIC_FILE_LEN);
pwrpriv->plps_poff_info->pStaticFile = NULL;
alloc_static_conf_file_fail:
rtw_mfree((u8 *)pwrpriv->plps_poff_info, sizeof(lps_poff_info_t));
pwrpriv->plps_poff_info = NULL;
exit:
return;
}
/*************************************************************************
Function: Get LPS-POFF de-initial
**************************************************************************/
void rtl8723d_lps_poff_deinit(PADAPTER padapter)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
lps_poff_info_t *plps_poff_info = pwrpriv->plps_poff_info;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
if (pregistrypriv->wifi_spec == 1)
return;
if (is_primary_adapter(padapter)) {
if (plps_poff_info->pDynamicFile != NULL) {
rtw_mfree((u8 *)plps_poff_info->pDynamicFile,
LPS_POFF_DYNAMIC_FILE_LEN);
plps_poff_info->pDynamicFile = NULL;
}
if (plps_poff_info->pStaticFile != NULL) {
rtw_mfree((u8 *)plps_poff_info->pStaticFile,
LPS_POFF_STATIC_FILE_LEN);
plps_poff_info->pStaticFile = NULL;
}
if (plps_poff_info != NULL) {
rtw_mfree((u8 *)plps_poff_info,
sizeof(lps_poff_info_t));
plps_poff_info = NULL;
}
}
}
#endif
File diff suppressed because it is too large Load Diff
+253
View File
@@ -0,0 +1,253 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* 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
*
*
******************************************************************************/
/******************************************************************************
*
*
* Module: rtl8192c_rf6052.c ( Source C File)
*
* Note: Provide RF 6052 series relative API.
*
* Function:
*
* Export:
*
* Abbrev:
*
* History:
* Data Who Remark
*
* 09/25/2008 MHC Create initial version.
* 11/05/2008 MHC Add API for tw power setting.
*
*
******************************************************************************/
#include <rtl8723d_hal.h>
/*---------------------------Define Local Constant---------------------------*/
/*---------------------------Define Local Constant---------------------------*/
/*------------------------Define global variable-----------------------------*/
/*------------------------Define global variable-----------------------------*/
/*------------------------Define local variable------------------------------*/
/* 2008/11/20 MH For Debug only, RF
* static RF_SHADOW_T RF_Shadow[RF6052_MAX_PATH][RF6052_MAX_REG] = {0}; */
static RF_SHADOW_T RF_Shadow[RF6052_MAX_PATH][RF6052_MAX_REG];
/*------------------------Define local variable------------------------------*/
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetBandwidth()
*
* Overview: This function is called by SetBWModeCallback8190Pci() only
*
* Input: PADAPTER Adapter
* WIRELESS_BANDWIDTH_E Bandwidth
*
* Output: NONE
*
* Return: NONE
*
* Note: For RF type 0222D
*---------------------------------------------------------------------------*/
VOID
PHY_RF6052SetBandwidth8723D(
IN PADAPTER padapter,
IN CHANNEL_WIDTH Bandwidth) /* 20M or 40M */
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
switch (Bandwidth) {
case CHANNEL_WIDTH_20:
/*
RF_A_reg 0x18[11:10]=2'b11
RF_A_reg 0x18[9:0]
*/
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10) | BIT(11));
PHY_SetRFReg(padapter, ODM_RF_PATH_A, 0x18, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]); /* RF TRX_BW */
break;
case CHANNEL_WIDTH_40:
/*
RF_A_reg 0x18[11:10]=2'b01
RF_A_reg 0x18[9:0]
*/
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | BIT(10));
PHY_SetRFReg(padapter, ODM_RF_PATH_A, 0x18, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]); /* RF TRX_BW */
break;
default:
break;
}
}
static VOID
phy_RF6052_Config_HardCode(
IN PADAPTER Adapter
)
{
/* Set Default Bandwidth to 20M */
/* Adapter->HalFunc .SetBWModeHandler(Adapter, CHANNEL_WIDTH_20); */
/* TODO: Set Default Channel to channel one for RTL8225 */
}
static int
phy_RF6052_Config_ParaFile(
IN PADAPTER Adapter
)
{
u32 u4RegValue = 0;
u8 eRFPath;
BB_REGISTER_DEFINITION_T *pPhyReg;
int rtStatus = _SUCCESS;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
/* 3//----------------------------------------------------------------- */
/* 3// <2> Initialize RF */
/* 3//----------------------------------------------------------------- */
/* for(eRFPath = RF_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++) */
for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
pPhyReg = &pHalData->PHYRegDef[eRFPath];
/*----Store original RFENV control type----*/
switch (eRFPath) {
case RF_PATH_A:
case RF_PATH_C:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
break;
case RF_PATH_B:
case RF_PATH_D:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16);
break;
}
/*----Set RF_ENV enable----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1);
rtw_udelay_os(1);/* PlatformStallExecution(1); */
/*----Set RF_ENV output high----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
rtw_udelay_os(1);/* PlatformStallExecution(1); */
/* Set bit number of Address and Data for RF register */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
rtw_udelay_os(1);/* PlatformStallExecution(1); */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
rtw_udelay_os(1);/* PlatformStallExecution(1); */
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF_PATH_A:
#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
if (PHY_ConfigRFWithParaFile(Adapter, PHY_FILE_RADIO_A, eRFPath) == _FAIL)
#endif
{
#ifdef CONFIG_EMBEDDED_FWIMG
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_RADIO, (ODM_RF_RADIO_PATH_E)eRFPath))
rtStatus = _FAIL;
#endif
}
break;
case RF_PATH_B:
#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
if (PHY_ConfigRFWithParaFile(Adapter, PHY_FILE_RADIO_B, eRFPath) == _FAIL)
#endif
{
#ifdef CONFIG_EMBEDDED_FWIMG
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile(&pHalData->odmpriv, CONFIG_RF_RADIO, (ODM_RF_RADIO_PATH_E)eRFPath))
rtStatus = _FAIL;
#endif
}
break;
case RF_PATH_C:
break;
case RF_PATH_D:
break;
}
/*----Restore RFENV control type----*/;
switch (eRFPath) {
case RF_PATH_A:
case RF_PATH_C:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
break;
case RF_PATH_B:
case RF_PATH_D:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue);
break;
}
if (rtStatus != _SUCCESS) {
goto phy_RF6052_Config_ParaFile_Fail;
}
}
/* 3 ----------------------------------------------------------------- */
/* 3 Configuration of Tx Power Tracking */
/* 3 ----------------------------------------------------------------- */
#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
if (PHY_ConfigRFWithTxPwrTrackParaFile(Adapter, PHY_FILE_TXPWR_TRACK) == _FAIL)
#endif
{
#ifdef CONFIG_EMBEDDED_FWIMG
ODM_ConfigRFWithTxPwrTrackHeaderFile(&pHalData->odmpriv);
#endif
}
return rtStatus;
phy_RF6052_Config_ParaFile_Fail:
return rtStatus;
}
int
PHY_RF6052_Config8723D(
IN PADAPTER Adapter)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
int rtStatus = _SUCCESS;
/* */
/* Initialize general global value */
/* */
/* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
if (pHalData->rf_type == RF_1T1R)
pHalData->NumTotalRFPath = 1;
else
pHalData->NumTotalRFPath = 2;
/* */
/* Config BB and RF */
/* */
rtStatus = phy_RF6052_Config_ParaFile(Adapter);
return rtStatus;
}
/* End of HalRf6052.c */
+62
View File
@@ -0,0 +1,62 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* 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 _RTL8723D_REDESC_C_
#include <rtl8723d_hal.h>
void rtl8723d_query_rx_desc_status(union recv_frame *precvframe, u8 *pdesc)
{
struct rx_pkt_attrib *pattrib;
pattrib = &precvframe->u.hdr.attrib;
_rtw_memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
pattrib->pkt_len = (u16)GET_RX_STATUS_DESC_PKT_LEN_8723D(pdesc);
pattrib->pkt_rpt_type = GET_RX_STATUS_DESC_RPT_SEL_8723D(pdesc) ? C2H_PACKET : NORMAL_RX;
if (pattrib->pkt_rpt_type == NORMAL_RX) {
/* Offset 0 */
pattrib->crc_err = (u8)GET_RX_STATUS_DESC_CRC32_8723D(pdesc);
pattrib->icv_err = (u8)GET_RX_STATUS_DESC_ICV_8723D(pdesc);
pattrib->drvinfo_sz = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE_8723D(pdesc) << 3;
pattrib->encrypt = (u8)GET_RX_STATUS_DESC_SECURITY_8723D(pdesc);
pattrib->qos = (u8)GET_RX_STATUS_DESC_QOS_8723D(pdesc);
pattrib->shift_sz = (u8)GET_RX_STATUS_DESC_SHIFT_8723D(pdesc);
pattrib->physt = (u8)GET_RX_STATUS_DESC_PHY_STATUS_8723D(pdesc);
pattrib->bdecrypted = (u8)GET_RX_STATUS_DESC_SWDEC_8723D(pdesc) ? 0 : 1;
/* Offset 4 */
pattrib->priority = (u8)GET_RX_STATUS_DESC_TID_8723D(pdesc);
pattrib->amsdu = (u8)GET_RX_STATUS_DESC_AMSDU_8723D(pdesc);
pattrib->mdata = (u8)GET_RX_STATUS_DESC_MORE_DATA_8723D(pdesc);
pattrib->mfrag = (u8)GET_RX_STATUS_DESC_MORE_FRAG_8723D(pdesc);
/* Offset 8 */
pattrib->seq_num = (u16)GET_RX_STATUS_DESC_SEQ_8723D(pdesc);
pattrib->frag_num = (u8)GET_RX_STATUS_DESC_FRAG_8723D(pdesc);
/* Offset 12 */
pattrib->data_rate = (u8)GET_RX_STATUS_DESC_RX_RATE_8723D(pdesc);
/* Offset 20 */
/* pattrib->tsfl=(u8)GET_RX_STATUS_DESC_TSFL_8723D(pdesc); */
}
}
+109
View File
@@ -0,0 +1,109 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* 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 _RTL8723D_SRESET_C_
#include <rtl8723d_hal.h>
#ifdef DBG_CONFIG_ERROR_DETECT
void rtl8723d_sreset_xmit_status_check(_adapter *padapter)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
unsigned long current_time;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
unsigned int diff_time;
u32 txdma_status;
txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
if (txdma_status != 0x00 && txdma_status != 0xeaeaeaea) {
RTW_INFO("%s REG_TXDMA_STATUS:0x%08x\n", __FUNCTION__, txdma_status);
rtw_hal_sreset_reset(padapter);
}
#ifdef CONFIG_USB_HCI
/* total xmit irp = 4 */
/* DBG_8192C("==>%s free_xmitbuf_cnt(%d),txirp_cnt(%d)\n",__FUNCTION__,pxmitpriv->free_xmitbuf_cnt,pxmitpriv->txirp_cnt); */
/* if(pxmitpriv->txirp_cnt == NR_XMITBUFF+1) */
current_time = rtw_get_current_time();
if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) {
diff_time = rtw_get_passing_time_ms(psrtpriv->last_tx_time);
if (diff_time > 2000) {
if (psrtpriv->last_tx_complete_time == 0)
psrtpriv->last_tx_complete_time = current_time;
else {
diff_time = rtw_get_passing_time_ms(psrtpriv->last_tx_complete_time);
if (diff_time > 4000) {
u32 ability = 0;
/* padapter->Wifi_Error_Status = WIFI_TX_HANG; */
ability = rtw_phydm_ability_get(padapter);
RTW_INFO("%s tx hang %s\n", __FUNCTION__,
(ability & ODM_BB_ADAPTIVITY) ? "ODM_BB_ADAPTIVITY" : "");
if (!(ability & ODM_BB_ADAPTIVITY))
rtw_hal_sreset_reset(padapter);
}
}
}
}
#endif /* #ifdef CONFIG_USB_HCI */
if (psrtpriv->dbg_trigger_point == SRESET_TGP_XMIT_STATUS) {
psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
rtw_hal_sreset_reset(padapter);
return;
}
}
void rtl8723d_sreset_linked_status_check(_adapter *padapter)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
#if 0
u32 regc50, regc58, reg824, reg800;
regc50 = rtw_read32(padapter, 0xc50);
regc58 = rtw_read32(padapter, 0xc58);
reg824 = rtw_read32(padapter, 0x824);
reg800 = rtw_read32(padapter, 0x800);
if (((regc50 & 0xFFFFFF00) != 0x69543400) ||
((regc58 & 0xFFFFFF00) != 0x69543400) ||
(((reg824 & 0xFFFFFF00) != 0x00390000) && (((reg824 & 0xFFFFFF00) != 0x80390000))) ||
(((reg800 & 0xFFFFFF00) != 0x03040000) && ((reg800 & 0xFFFFFF00) != 0x83040000))) {
DBG_8192C("%s regc50:0x%08x, regc58:0x%08x, reg824:0x%08x, reg800:0x%08x,\n", __FUNCTION__,
regc50, regc58, reg824, reg800);
rtw_hal_sreset_reset(padapter);
}
#endif
if (psrtpriv->dbg_trigger_point == SRESET_TGP_LINK_STATUS) {
psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
rtw_hal_sreset_reset(padapter);
return;
}
}
#endif
+126
View File
@@ -0,0 +1,126 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* 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 _RTL8723DS_LED_C_
#include "rtl8723d_hal.h"
/* ********************************************************************************
* LED object.
* ******************************************************************************** */
/* ********************************************************************************
* Prototype of protected function.
* ******************************************************************************** */
/* ********************************************************************************
* LED_819xUsb routines.
* ******************************************************************************** */
/*
* Description:
* Turn on LED according to LedPin specified.
* */
void
SwLedOn_8723DS(
_adapter *padapter,
PLED_SDIO pLed
)
{
u8 LedCfg;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
if (RTW_CANNOT_RUN(padapter))
return;
pLed->bLedOn = _TRUE;
}
/*
* Description:
* Turn off LED according to LedPin specified.
* */
void
SwLedOff_8723DS(
_adapter *padapter,
PLED_SDIO pLed
)
{
u8 LedCfg;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
if (RTW_CANNOT_RUN(padapter))
goto exit;
exit:
pLed->bLedOn = _FALSE;
}
/* ********************************************************************************
* Interface to manipulate LED objects.
* ******************************************************************************** */
/* ********************************************************************************
* Default LED behavior.
* ******************************************************************************** */
/*
* Description:
* Initialize all LED_871x objects.
* */
void
rtl8723ds_InitSwLeds(
_adapter *padapter
)
{
#if 0
struct led_priv *pledpriv = &(padapter->ledpriv);
pledpriv->LedControlHandler = LedControlSDIO;
pledpriv->SwLedOn = SwLedOn_8723DS;
pledpriv->SwLedOff = SwLedOff_8723DS;
InitLed871x(padapter, &(pledpriv->SwLed0), LED_PIN_LED0);
InitLed871x(padapter, &(pledpriv->SwLed1), LED_PIN_LED1);
#endif
}
/*
* Description:
* DeInitialize all LED_819xUsb objects.
* */
void
rtl8723ds_DeInitSwLeds(
_adapter *padapter
)
{
#if 0
struct led_priv *ledpriv = &(padapter->ledpriv);
DeInitLed871x(&(ledpriv->SwLed0));
DeInitLed871x(&(ledpriv->SwLed1));
#endif
}
+500
View File
@@ -0,0 +1,500 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* 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 _RTL8723DS_RECV_C_
#include <rtl8723d_hal.h>
static s32 initrecvbuf(struct recv_buf *precvbuf, PADAPTER padapter)
{
_rtw_init_listhead(&precvbuf->list);
_rtw_spinlock_init(&precvbuf->recvbuf_lock);
precvbuf->adapter = padapter;
return _SUCCESS;
}
static void freerecvbuf(struct recv_buf *precvbuf)
{
_rtw_spinlock_free(&precvbuf->recvbuf_lock);
}
#ifdef CONFIG_SDIO_RX_COPY
static void rtl8723ds_recv_tasklet(void *priv)
{
PADAPTER padapter;
PHAL_DATA_TYPE pHalData;
struct recv_priv *precvpriv;
struct recv_buf *precvbuf;
union recv_frame *precvframe;
struct recv_frame_hdr *phdr;
struct rx_pkt_attrib *pattrib;
u8 *ptr;
u32 pkt_len, pkt_offset;
u8 rx_report_sz = 0;
padapter = (PADAPTER)priv;
pHalData = GET_HAL_DATA(padapter);
precvpriv = &padapter->recvpriv;
do {
precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
if (NULL == precvbuf)
break;
ptr = precvbuf->pdata;
while (ptr < precvbuf->ptail) {
precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
if (precvframe == NULL) {
RTW_INFO("%s: no enough recv frame!\n", __FUNCTION__);
rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
/* The case of can't allocate recvframe should be temporary, */
/* schedule again and hope recvframe is available next time. */
#ifdef PLATFORM_LINUX
tasklet_schedule(&precvpriv->recv_tasklet);
#endif
return;
}
/* rx desc parsing */
rtl8723d_query_rx_desc_status(precvframe, ptr);
pattrib = &precvframe->u.hdr.attrib;
/* fix Hardware RX data error, drop whole recv_buffer */
if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) {
#if !(MP_DRIVER == 1)
RTW_INFO("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
#endif
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
break;
}
rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz;
pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len;
if ((ptr + pkt_offset) > precvbuf->ptail) {
RTW_INFO("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __FUNCTION__, __LINE__, ptr, pkt_offset, precvbuf->ptail);
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
break;
}
if ((pattrib->crc_err) || (pattrib->icv_err)) {
#ifdef CONFIG_MP_INCLUDED
if (padapter->registrypriv.mp_mode == 1) {
if (check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE) { /* &&(padapter->mppriv.check_mp_pkt == 0)) */
if (pattrib->crc_err == 1)
padapter->mppriv.rx_crcerrpktcount++;
}
} else
#endif
{
RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
}
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
} else {
#ifdef CONFIG_RX_PACKET_APPEND_FCS
if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == _FALSE)
if ((pattrib->pkt_rpt_type == NORMAL_RX) && (pHalData->ReceiveConfig & RCR_APPFCS))
pattrib->pkt_len -= IEEE80211_FCS_LEN;
#endif
if (rtw_os_alloc_recvframe(padapter, precvframe,
(ptr + rx_report_sz + pattrib->shift_sz), precvbuf->pskb) == _FAIL) {
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
break;
}
recvframe_put(precvframe, pattrib->pkt_len);
/* move to drv info position */
ptr += RXDESC_SIZE;
/* update drv info */
if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
/* rtl8723s_update_bassn(padapter, pdrvinfo); */
ptr += 4;
}
if (pattrib->pkt_rpt_type == NORMAL_RX) {
/* skip the rx packet with abnormal length */
if (pattrib->pkt_len < 14 || pattrib->pkt_len > 8192) {
RTW_INFO("skip abnormal rx packet(%d)\n", pattrib->pkt_len);
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
break;
}
#ifdef CONFIG_CONCURRENT_MODE
pre_recv_entry(precvframe, ptr);
#endif
if (pattrib->physt)
rx_query_phy_status(precvframe, ptr);
rtw_recv_entry(precvframe);
} else {
#ifdef CONFIG_FW_C2H_PKT
if (pattrib->pkt_rpt_type == C2H_PACKET)
rtw_hal_c2h_pkt_pre_hdl(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
else {
RTW_INFO("%s: [WARNNING] RX type(%d) not be handled!\n",
__FUNCTION__, pattrib->pkt_rpt_type);
}
#endif
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
}
}
pkt_offset = _RND8(pkt_offset);
precvbuf->pdata += pkt_offset;
ptr = precvbuf->pdata;
precvframe = NULL;
}
rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
} while (1);
}
#else
static void rtl8723ds_recv_tasklet(void *priv)
{
PADAPTER padapter;
PHAL_DATA_TYPE pHalData;
struct recv_priv *precvpriv;
struct recv_buf *precvbuf;
union recv_frame *precvframe;
struct recv_frame_hdr *phdr;
struct rx_pkt_attrib *pattrib;
u8 *ptr;
_pkt *ppkt;
u32 pkt_offset;
padapter = (PADAPTER)priv;
pHalData = GET_HAL_DATA(padapter);
precvpriv = &padapter->recvpriv;
do {
precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue);
if (NULL == precvbuf)
break;
ptr = precvbuf->pdata;
while (ptr < precvbuf->ptail) {
precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue);
if (precvframe == NULL) {
rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
/* The case of can't allocate recvframe should be temporary, */
/* schedule again and hope recvframe is available next time. */
#ifdef PLATFORM_LINUX
tasklet_schedule(&precvpriv->recv_tasklet);
#endif
return;
}
phdr = &precvframe->u.hdr;
pattrib = &phdr->attrib;
rtl8723d_query_rx_desc_status(precvframe, ptr);
#if 0
{
int i, len = 64;
u8 *pptr = ptr;
if ((*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x80) && (*(pptr + RXDESC_SIZE + pattrib->drvinfo_sz) != 0x40)) {
RTW_INFO("##############RxDESC###############\n");
for (i = 0; i < 32; i = i + 16)
RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr + i),
*(pptr + i + 1), *(pptr + i + 2) , *(pptr + i + 3) , *(pptr + i + 4), *(pptr + i + 5), *(pptr + i + 6), *(pptr + i + 7), *(pptr + i + 8),
*(pptr + i + 9), *(pptr + i + 10),
*(pptr + i + 11), *(pptr + i + 12), *(pptr + i + 13), *(pptr + i + 14), *(pptr + i + 15));
if (pattrib->pkt_len < 100)
len = pattrib->pkt_len;
pptr = ptr + RXDESC_SIZE + pattrib->drvinfo_sz;
RTW_INFO("##############Len=%d###############\n", pattrib->pkt_len);
for (i = 0; i < len; i = i + 16)
RTW_INFO("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(pptr + i),
*(pptr + i + 1), *(pptr + i + 2) , *(pptr + i + 3) , *(pptr + i + 4), *(pptr + i + 5), *(pptr + i + 6), *(pptr + i + 7), *(pptr + i + 8),
*(pptr + i + 9), *(pptr + i + 10),
*(pptr + i + 11), *(pptr + i + 12), *(pptr + i + 13), *(pptr + i + 14), *(pptr + i + 15));
RTW_INFO("#############################\n");
}
}
#endif
/* fix Hardware RX data error, drop whole recv_buffer */
if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) {
RTW_INFO("%s()-%d: RX Warning! rx CRC ERROR !!\n", __FUNCTION__, __LINE__);
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
break;
}
pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->pkt_len;
#if 0 /* reduce check to speed up */
if ((ptr + pkt_offset) > precvbuf->ptail) {
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
break;
}
#endif
if ((pattrib->crc_err) || (pattrib->icv_err)) {
#ifdef CONFIG_MP_INCLUDED
if (padapter->registrypriv.mp_mode == 1) {
if (check_fwstate(&padapter->mlmepriv, WIFI_MP_STATE) == _TRUE) { /* &&(padapter->mppriv.check_mp_pkt == 0)) */
if (pattrib->crc_err == 1)
padapter->mppriv.rx_crcerrpktcount++;
}
} else
#endif
{
RTW_INFO("%s: crc_err=%d icv_err=%d, skip!\n", __FUNCTION__, pattrib->crc_err, pattrib->icv_err);
}
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
} else {
ppkt = rtw_skb_clone(precvbuf->pskb);
if (ppkt == NULL) {
RTW_INFO("%s: no enough memory to allocate SKB!\n", __FUNCTION__);
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue);
/* The case of can't allocate skb is serious and may never be recovered, */
/* once bDriverStopped is enable, this task should be stopped. */
if (!rtw_is_drv_stopped(padapter)) {
#ifdef PLATFORM_LINUX
tasklet_schedule(&precvpriv->recv_tasklet);
#endif
}
return;
}
phdr->pkt = ppkt;
phdr->len = 0;
phdr->rx_head = precvbuf->phead;
phdr->rx_data = phdr->rx_tail = precvbuf->pdata;
phdr->rx_end = precvbuf->pend;
recvframe_put(precvframe, pkt_offset);
recvframe_pull(precvframe, RXDESC_SIZE + pattrib->drvinfo_sz);
skb_pull(ppkt, RXDESC_SIZE + pattrib->drvinfo_sz);
#ifdef CONFIG_RX_PACKET_APPEND_FCS
if (check_fwstate(&padapter->mlmepriv, WIFI_MONITOR_STATE) == _FALSE) {
if ((pattrib->pkt_rpt_type == NORMAL_RX) && (pHalData->ReceiveConfig & RCR_APPFCS)) {
recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN);
pattrib->pkt_len -= IEEE80211_FCS_LEN;
ppkt->len = pattrib->pkt_len;
}
}
#endif
/* move to drv info position */
ptr += RXDESC_SIZE;
/* update drv info */
if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) {
/* rtl8723s_update_bassn(padapter, pdrvinfo); */
ptr += 4;
}
if (pattrib->pkt_rpt_type == NORMAL_RX) {
#ifdef CONFIG_CONCURRENT_MODE
pre_recv_entry(precvframe, ptr);
#endif /*CONFIG_CONCURRENT_MODE*/
if (pattrib->physt)
rx_query_phy_status(precvframe, ptr);
rtw_recv_entry(precvframe);
} else {
#ifdef CONFIG_FW_C2H_PKT
if (pattrib->pkt_rpt_type == C2H_PACKET)
rtw_hal_c2h_pkt_pre_hdl(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len);
else {
RTW_INFO("%s: [WARNNING] RX type(%d) not be handled!\n",
__FUNCTION__, pattrib->pkt_rpt_type);
}
#endif
rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue);
}
}
pkt_offset = _RND8(pkt_offset);
precvbuf->pdata += pkt_offset;
ptr = precvbuf->pdata;
}
rtw_skb_free(precvbuf->pskb);
precvbuf->pskb = NULL;
rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue);
} while (1);
}
#endif
/*
* Initialize recv private variable for hardware dependent
* 1. recv buf
* 2. recv tasklet
*
*/
s32 rtl8723ds_init_recv_priv(PADAPTER padapter)
{
s32 res;
u32 i, n;
struct recv_priv *precvpriv;
struct recv_buf *precvbuf;
res = _SUCCESS;
precvpriv = &padapter->recvpriv;
/* 3 1. init recv buffer */
_rtw_init_queue(&precvpriv->free_recv_buf_queue);
_rtw_init_queue(&precvpriv->recv_buf_pending_queue);
n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
precvpriv->pallocated_recv_buf = rtw_zmalloc(n);
if (precvpriv->pallocated_recv_buf == NULL) {
res = _FAIL;
goto exit;
}
precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
/* init each recv buffer */
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
res = initrecvbuf(precvbuf, padapter);
if (res == _FAIL)
break;
res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
if (res == _FAIL) {
freerecvbuf(precvbuf);
break;
}
#ifdef CONFIG_SDIO_RX_COPY
if (precvbuf->pskb == NULL) {
SIZE_PTR tmpaddr = 0;
SIZE_PTR alignment = 0;
precvbuf->pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
if (precvbuf->pskb) {
precvbuf->pskb->dev = padapter->pnetdev;
tmpaddr = (SIZE_PTR)precvbuf->pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
}
if (precvbuf->pskb == NULL)
RTW_INFO("%s: alloc_skb fail!\n", __FUNCTION__);
}
#endif
rtw_list_insert_tail(&precvbuf->list, &precvpriv->free_recv_buf_queue.queue);
precvbuf++;
}
precvpriv->free_recv_buf_queue_cnt = i;
if (res == _FAIL)
goto initbuferror;
/* 3 2. init tasklet */
#ifdef PLATFORM_LINUX
tasklet_init(&precvpriv->recv_tasklet,
(void(*)(unsigned long))rtl8723ds_recv_tasklet,
(unsigned long)padapter);
#endif
goto exit;
initbuferror:
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
if (precvbuf) {
n = precvpriv->free_recv_buf_queue_cnt;
precvpriv->free_recv_buf_queue_cnt = 0;
for (i = 0; i < n ; i++) {
rtw_list_delete(&precvbuf->list);
rtw_os_recvbuf_resource_free(padapter, precvbuf);
freerecvbuf(precvbuf);
precvbuf++;
}
precvpriv->precv_buf = NULL;
}
if (precvpriv->pallocated_recv_buf) {
n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
rtw_mfree(precvpriv->pallocated_recv_buf, n);
precvpriv->pallocated_recv_buf = NULL;
}
exit:
return res;
}
/*
* Free recv private variable of hardware dependent
* 1. recv buf
* 2. recv tasklet
*
*/
void rtl8723ds_free_recv_priv(PADAPTER padapter)
{
u32 i, n;
struct recv_priv *precvpriv;
struct recv_buf *precvbuf;
precvpriv = &padapter->recvpriv;
/* 3 1. kill tasklet */
#ifdef PLATFORM_LINUX
tasklet_kill(&precvpriv->recv_tasklet);
#endif
/* 3 2. free all recv buffers */
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
if (precvbuf) {
n = NR_RECVBUFF;
precvpriv->free_recv_buf_queue_cnt = 0;
for (i = 0; i < n ; i++) {
rtw_list_delete(&precvbuf->list);
rtw_os_recvbuf_resource_free(padapter, precvbuf);
freerecvbuf(precvbuf);
precvbuf++;
}
precvpriv->precv_buf = NULL;
}
if (precvpriv->pallocated_recv_buf) {
n = NR_RECVBUFF * sizeof(struct recv_buf) + 4;
rtw_mfree(precvpriv->pallocated_recv_buf, n);
precvpriv->pallocated_recv_buf = NULL;
}
}
+723
View File
@@ -0,0 +1,723 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* 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 _RTL8723DS_XMIT_C_
#include <rtl8723d_hal.h>
static u8 rtw_sdio_wait_enough_TxOQT_space(PADAPTER padapter, u8 agg_num)
{
u32 n = 0;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
while (pHalData->SdioTxOQTFreeSpace < agg_num) {
if (RTW_CANNOT_RUN(padapter)) {
RTW_INFO("%s: bSurpriseRemoved or bDriverStopped (wait TxOQT)\n", __func__);
return _FALSE;
}
HalQueryTxOQTBufferStatus8723DSdio(padapter);
if ((++n % 60) == 0) {
if ((n % 300) == 0) {
RTW_INFO("%s(%d): QOT free space(%d), agg_num: %d\n",
__func__, n, pHalData->SdioTxOQTFreeSpace, agg_num);
}
rtw_msleep_os(1);
/* yield(); */
}
}
pHalData->SdioTxOQTFreeSpace -= agg_num;
/* if (n > 1) */
/* ++priv->pshare->nr_out_of_txoqt_space; */
return _TRUE;
}
s32 _dequeue_writeport(PADAPTER padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct xmit_buf *pxmitbuf;
u8 PageIdx = 0;
u32 deviceId;
#ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
u8 bUpdatePageNum = _FALSE;
#else
u32 polling_num = 0;
#endif
pxmitbuf = select_and_dequeue_pending_xmitbuf(padapter);
if (pxmitbuf == NULL)
return _TRUE;
deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
/* translate fifo addr to queue index */
switch (deviceId) {
case WLAN_TX_HIQ_DEVICE_ID:
PageIdx = HI_QUEUE_IDX;
break;
case WLAN_TX_MIQ_DEVICE_ID:
PageIdx = MID_QUEUE_IDX;
break;
case WLAN_TX_LOQ_DEVICE_ID:
PageIdx = LOW_QUEUE_IDX;
break;
}
query_free_page:
/* check if hardware tx fifo page is enough */
if (_FALSE == rtw_hal_sdio_query_tx_freepage(padapter, PageIdx, pxmitbuf->pg_num)) {
if (RTW_CANNOT_RUN(padapter))
goto free_xmitbuf;
#ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
if (!bUpdatePageNum) {
/* Total number of page is NOT available, so update current FIFO status */
HalQueryTxBufferStatus8723DSdio(padapter);
bUpdatePageNum = _TRUE;
goto query_free_page;
} else {
bUpdatePageNum = _FALSE;
enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
return _TRUE;
}
#else /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
polling_num++;
if ((polling_num % 0x10) == 0) {
/* RTW_INFO("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n", */
/* __func__, polling_num, pxmitbuf->len, pxmitbuf->agg_num, pframe->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]); */
enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
rtw_usleep_os(50);
return _FALSE;
}
/* Total number of page is NOT available, so update current FIFO status */
HalQueryTxBufferStatus8723DSdio(padapter);
goto query_free_page;
#endif /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
}
#ifdef CONFIG_LPS_POFF
if (rtl8723d_lps_poff_get_txbndy_status(padapter) == _TRUE) {
RTW_INFO("%s: enqueue xmitbuf to pending queue head~~~\n",
__func__);
enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
return _TRUE;
}
#endif
if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == _FALSE)
goto free_xmitbuf;
#ifdef CONFIG_CHECK_LEAVE_LPS
traffic_check_for_leave_lps(padapter, _TRUE, pxmitbuf->agg_num);
#endif
rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
rtw_hal_sdio_update_tx_freepage(padapter, PageIdx, pxmitbuf->pg_num);
free_xmitbuf:
/* rtw_free_xmitframe(pxmitpriv, pframe); */
/* pxmitbuf->priv_data = NULL; */
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
#if 0 /* improve TX/RX throughput balance */
{
PSDIO_DATA psdio;
struct sdio_func *func;
static u8 i = 0;
u32 sdio_hisr;
u8 j;
psdio = &adapter_to_dvobj(padapter)->intf_data;
func = psdio->func;
if (i == 2) {
j = 0;
while (j < 10) {
sdio_hisr = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR);
sdio_hisr &= GET_HAL_DATA(padapter)->sdio_himr;
if (sdio_hisr & SDIO_HISR_RX_REQUEST) {
sdio_claim_host(func);
sd_int_hdl(GET_PRIMARY_ADAPTER(padapter));
sdio_release_host(func);
} else
break;
j++;
}
i = 0;
} else
i++;
}
#endif
#ifdef CONFIG_SDIO_TX_TASKLET
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
#endif
return _FALSE;
}
/*
* Description
* Transmit xmitbuf to hardware tx fifo
*
* Return
* _SUCCESS ok
* _FAIL something error
*/
s32 rtl8723ds_xmit_buf_handler(PADAPTER padapter)
{
struct xmit_priv *pxmitpriv;
u8 queue_empty;
s32 ret;
pxmitpriv = &padapter->xmitpriv;
ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
if (_FAIL == ret) {
RTW_ERR("%s: down SdioXmitBufSema fail!\n", __func__);
return _FAIL;
}
if (RTW_CANNOT_RUN(padapter)) {
return _FAIL;
}
if (rtw_mi_check_pending_xmitbuf(padapter) == 0)
return _SUCCESS;
#ifdef CONFIG_LPS_LCLK
ret = rtw_register_tx_alive(padapter);
if (ret != _SUCCESS)
return _SUCCESS;
#endif
do {
queue_empty = rtw_mi_dequeue_writeport(padapter);
} while (!queue_empty);
#ifdef CONFIG_LPS_LCLK
rtw_unregister_tx_alive(padapter);
#endif
return _SUCCESS;
}
/*
* Description:
* Aggregation packets and send to hardware
*
* Return:
* 0 Success
* -1 Hardware resource(TX FIFO) not ready
* -2 Software resource(xmitbuf) not ready
*/
static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv)
{
s32 err, ret;
u32 k = 0;
struct hw_xmit *hwxmits, *phwxmit;
u8 no_res, idx, hwentry;
_irqL irql;
struct tx_servq *ptxservq;
_list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
struct xmit_frame *pxmitframe;
_queue *pframe_queue;
struct xmit_buf *pxmitbuf;
u32 txlen, max_xmit_len, page_size;
u8 txdesc_size = TXDESC_SIZE;
int inx[4];
u8 pre_qsel = 0xFF, next_qsel = 0xFF;
u8 single_sta_in_queue = _FALSE;
err = 0;
no_res = _FALSE;
hwxmits = pxmitpriv->hwxmits;
hwentry = pxmitpriv->hwxmit_entry;
ptxservq = NULL;
pxmitframe = NULL;
pframe_queue = NULL;
pxmitbuf = NULL;
rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
if (padapter->registrypriv.wifi_spec == 1) {
for (idx = 0; idx < 4; idx++)
inx[idx] = pxmitpriv->wmm_para_seq[idx];
} else {
inx[0] = 0;
inx[1] = 1;
inx[2] = 2;
inx[3] = 3;
}
/* 0(VO), 1(VI), 2(BE), 3(BK) */
for (idx = 0; idx < hwentry; idx++) {
phwxmit = hwxmits + inx[idx];
if ((check_pending_xmitbuf(pxmitpriv) == _TRUE) && (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) {
if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
err = -2;
break;
}
}
max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
_enter_critical_bh(&pxmitpriv->lock, &irql);
sta_phead = get_list_head(phwxmit->sta_queue);
sta_plist = get_next(sta_phead);
/* because stop_sta_xmit may delete sta_plist at any time */
/* so we should add lock here, or while loop can not exit */
single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist));
while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE) {
ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
sta_plist = get_next(sta_plist);
#ifdef DBG_XMIT_BUF
RTW_INFO("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __func__, idx, phwxmit->accnt, ptxservq->qcnt);
RTW_INFO("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d\n",
__func__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt,
pxmitpriv->free_xmitframe_cnt);
#endif
pframe_queue = &ptxservq->sta_pending;
frame_phead = get_list_head(pframe_queue);
while (rtw_is_list_empty(frame_phead) == _FALSE) {
frame_plist = get_next(frame_phead);
pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
/* check xmit_buf size enough or not */
txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
next_qsel = pxmitframe->attrib.qsel;
if ((NULL == pxmitbuf) ||
(pxmitbuf->pg_num + PageNum(txlen, page_size) > PageNum(max_xmit_len, page_size))
|| (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
|| ((k != 0) && (_FAIL == rtw_hal_busagg_qsel_check(padapter, pre_qsel, next_qsel)))
) {
if (pxmitbuf) {
/* pxmitbuf->priv_data will be NULL, and will crash here */
if (pxmitbuf->len > 0 && pxmitbuf->priv_data) {
struct xmit_frame *pframe;
pframe = (struct xmit_frame *)pxmitbuf->priv_data;
pframe->agg_num = k;
pxmitbuf->agg_num = k;
rtl8723d_update_txdesc(pframe, pframe->buf_addr);
rtw_free_xmitframe(pxmitpriv, pframe);
pxmitbuf->priv_data = NULL;
enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
/* can not yield under lock */
/* rtw_yield_os(); */
if (single_sta_in_queue == _FALSE) {
/* break the loop in case there is more than one sta in this ac queue */
pxmitbuf = NULL;
err = -3;
break;
}
} else
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
}
pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
if (pxmitbuf == NULL) {
#ifdef DBG_XMIT_BUF
RTW_ERR("%s: xmit_buf is not enough!\n", __func__);
#endif
err = -2;
#ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
_rtw_up_sema(&(GET_PRIMARY_ADAPTER(padapter)->xmitpriv.xmit_sema));
#endif
break;
}
k = 0;
}
/* ok to send, remove frame from queue */
#ifdef CONFIG_AP_MODE
if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) {
if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
(pxmitframe->attrib.triggered == 0)) {
RTW_INFO("%s: one not triggered pkt in queue when this STA sleep, break and goto next sta\n", __func__);
break;
}
}
#endif
rtw_list_delete(&pxmitframe->list);
ptxservq->qcnt--;
phwxmit->accnt--;
if (k == 0) {
pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
pxmitbuf->priv_data = (u8 *)pxmitframe;
}
/* coalesce the xmitframe to xmitbuf */
pxmitframe->pxmitbuf = pxmitbuf;
pxmitframe->buf_addr = pxmitbuf->ptail;
ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
if (ret == _FAIL) {
RTW_ERR("%s: coalesce FAIL!", __func__);
/* Todo: error handler */
} else {
k++;
if (k != 1)
rtl8723d_update_txdesc(pxmitframe, pxmitframe->buf_addr);
rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
pre_qsel = pxmitframe->attrib.qsel;
txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
pxmitframe->pg_num = (txlen + 127) / 128;
pxmitbuf->pg_num += (txlen + 127) / 128;
/* if (k != 1) */
/* ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
}
if (k != 1)
rtw_free_xmitframe(pxmitpriv, pxmitframe);
pxmitframe = NULL;
}
if (_rtw_queue_empty(pframe_queue) == _TRUE)
rtw_list_delete(&ptxservq->tx_pending);
else if (err == -3) {
/* Re-arrange the order of stations in this ac queue to balance the service for these stations */
rtw_list_delete(&ptxservq->tx_pending);
rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue));
}
if (err)
break;
}
_exit_critical_bh(&pxmitpriv->lock, &irql);
/* dump xmit_buf to hw tx fifo */
if (pxmitbuf) {
if (pxmitbuf->len > 0) {
struct xmit_frame *pframe;
pframe = (struct xmit_frame *)pxmitbuf->priv_data;
pframe->agg_num = k;
pxmitbuf->agg_num = k;
rtl8723d_update_txdesc(pframe, pframe->buf_addr);
rtw_free_xmitframe(pxmitpriv, pframe);
pxmitbuf->priv_data = NULL;
enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
rtw_yield_os();
} else
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
pxmitbuf = NULL;
}
if (err == -2)
break;
}
return err;
}
/*
* Description
* Transmit xmitframe from queue
*
* Return
* _SUCCESS ok
* _FAIL something error
*/
s32 rtl8723ds_xmit_handler(PADAPTER padapter)
{
struct xmit_priv *pxmitpriv;
s32 ret;
_irqL irql;
pxmitpriv = &padapter->xmitpriv;
wait:
ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
if (_FAIL == ret) {
RTW_ERR("%s: down sema fail!\n", __func__);
return _FAIL;
}
next:
if (RTW_CANNOT_RUN(padapter)) {
return _FAIL;
}
_enter_critical_bh(&pxmitpriv->lock, &irql);
ret = rtw_txframes_pending(padapter);
_exit_critical_bh(&pxmitpriv->lock, &irql);
if (ret == 0)
return _SUCCESS;
/* dequeue frame and write to hardware */
ret = xmit_xmitframes(padapter, pxmitpriv);
if (ret == -2) {
/* here sleep 1ms will cause big TP loss of TX */
/* from 50+ to 40+ */
if (padapter->registrypriv.wifi_spec)
rtw_msleep_os(1);
else
#ifdef CONFIG_REDUCE_TX_CPU_LOADING
rtw_msleep_os(1);
#else
rtw_yield_os();
#endif
goto next;
}
_enter_critical_bh(&pxmitpriv->lock, &irql);
ret = rtw_txframes_pending(padapter);
_exit_critical_bh(&pxmitpriv->lock, &irql);
if (ret == 1) {
#ifdef CONFIG_REDUCE_TX_CPU_LOADING
rtw_msleep_os(1);
#endif
goto next;
}
return _SUCCESS;
}
thread_return rtl8723ds_xmit_thread(thread_context context)
{
s32 ret;
PADAPTER padapter;
struct xmit_priv *pxmitpriv;
u8 thread_name[20] = "RTWHALXT";
ret = _SUCCESS;
padapter = (PADAPTER)context;
pxmitpriv = &padapter->xmitpriv;
rtw_sprintf(thread_name, 20, "%s-"ADPT_FMT, thread_name, ADPT_ARG(padapter));
thread_enter(thread_name);
RTW_INFO("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
/* For now, no one would down sema to check thread is running, */
/* so mark this temporary, Lucas@20130820
* _rtw_up_sema(&pxmitpriv->SdioXmitTerminateSema); */
do {
ret = rtl8723ds_xmit_handler(padapter);
if (signal_pending(current))
flush_signals(current);
} while (_SUCCESS == ret);
_rtw_up_sema(&pxmitpriv->SdioXmitTerminateSema);
thread_exit();
}
s32 rtl8723ds_mgnt_xmit(PADAPTER padapter, struct xmit_frame *pmgntframe)
{
s32 ret = _SUCCESS;
struct pkt_attrib *pattrib;
struct xmit_buf *pxmitbuf;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
u8 txdesc_size = TXDESC_SIZE;
pattrib = &pmgntframe->attrib;
pxmitbuf = pmgntframe->pxmitbuf;
rtl8723d_update_txdesc(pmgntframe, pmgntframe->buf_addr);
pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
/* pmgntframe->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size */
pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
rtw_free_xmitframe(pxmitpriv, pmgntframe);
pxmitbuf->priv_data = NULL;
if (GetFrameSubType(pframe) == WIFI_BEACON ||
pxmitbuf->buf_tag == XMITBUF_CMD) {
#ifdef CONFIG_LPS_POFF
if (rtl8723d_lps_poff_get_txbndy_status(padapter) == _TRUE) {
RTW_INFO("%s: enqueue xmitbuf to pending queue ~~~\n",
__func__);
enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
return ret;
}
#endif
ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
if (ret != _SUCCESS)
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
} else
enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
return ret;
}
/*
* Description:
* Handle xmitframe(packet) come from rtw_xmit()
*
* Return:
* _TRUE dump packet directly ok
* _FALSE enqueue, temporary can't transmit packets to hardware
*/
s32 rtl8723ds_hal_xmit(PADAPTER padapter, struct xmit_frame *pxmitframe)
{
struct xmit_priv *pxmitpriv;
_irqL irql;
s32 err;
pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
pxmitpriv = &padapter->xmitpriv;
#ifdef CONFIG_80211N_HT
if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
(pxmitframe->attrib.ether_type != 0x0806) &&
(pxmitframe->attrib.ether_type != 0x888e) &&
(pxmitframe->attrib.dhcp_pkt != 1)) {
if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
rtw_issue_addbareq_cmd(padapter, pxmitframe);
}
#endif
_enter_critical_bh(&pxmitpriv->lock, &irql);
err = rtw_xmitframe_enqueue(padapter, pxmitframe);
_exit_critical_bh(&pxmitpriv->lock, &irql);
if (err != _SUCCESS) {
rtw_free_xmitframe(pxmitpriv, pxmitframe);
pxmitpriv->tx_drop++;
return _TRUE;
}
_rtw_up_sema(&pxmitpriv->SdioXmitSema);
return _FALSE;
}
s32 rtl8723ds_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
s32 err;
err = rtw_xmitframe_enqueue(padapter, pxmitframe);
if (err != _SUCCESS) {
rtw_free_xmitframe(pxmitpriv, pxmitframe);
pxmitpriv->tx_drop++;
} else {
#ifdef CONFIG_SDIO_TX_TASKLET
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
#else
_rtw_up_sema(&pxmitpriv->SdioXmitSema);
#endif
}
return err;
}
/*
* Return
* _SUCCESS start thread ok
* _FAIL start thread fail
*
*/
s32 rtl8723ds_init_xmit_priv(PADAPTER padapter)
{
struct xmit_priv *xmitpriv = &padapter->xmitpriv;
PHAL_DATA_TYPE phal;
phal = GET_HAL_DATA(padapter);
_rtw_spinlock_init(&phal->SdioTxFIFOFreePageLock);
_rtw_init_sema(&xmitpriv->SdioXmitSema, 0);
_rtw_init_sema(&xmitpriv->SdioXmitTerminateSema, 0);
return _SUCCESS;
}
void rtl8723ds_free_xmit_priv(PADAPTER padapter)
{
PHAL_DATA_TYPE phal;
struct xmit_priv *pxmitpriv;
struct xmit_buf *pxmitbuf;
_queue *pqueue;
_list *plist, *phead;
_list tmplist;
_irqL irql;
phal = GET_HAL_DATA(padapter);
pxmitpriv = &padapter->xmitpriv;
pqueue = &pxmitpriv->pending_xmitbuf_queue;
phead = get_list_head(pqueue);
_rtw_init_listhead(&tmplist);
_enter_critical_bh(&pqueue->lock, &irql);
if (_rtw_queue_empty(pqueue) == _FALSE) {
/* Insert tmplist to end of queue, and delete phead */
/* then tmplist become head of queue. */
rtw_list_insert_tail(&tmplist, phead);
rtw_list_delete(phead);
}
_exit_critical_bh(&pqueue->lock, &irql);
phead = &tmplist;
while (rtw_is_list_empty(phead) == _FALSE) {
plist = get_next(phead);
rtw_list_delete(plist);
pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
pxmitbuf->priv_data = NULL;
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
}
_rtw_spinlock_free(&phal->SdioTxFIFOFreePageLock);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff