mirror of
https://github.com/amazingfate/rtl8723ds.git
synced 2026-06-19 02:37:22 +01:00
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:
@@ -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
@@ -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
@@ -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
@@ -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(¶m, 1);
|
||||
} else {
|
||||
RTW_INFO("%s: disable case\n", __func__);
|
||||
ATOMIC_SET(&plps_poff_info->bSetPOFFParm, _FALSE);
|
||||
SET_H2CCMD_LPS_POFF_CTRL_EN(¶m, 0);
|
||||
}
|
||||
rtw_hal_fill_h2c_cmd(padapter, H2C_LPS_POFF_CTRL,
|
||||
H2C_LPS_POFF_CTRL_LEN, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
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
@@ -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 */
|
||||
@@ -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); */
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user