rtlwifi: rtl8192ee: Fix DMA stalls
There are instances where the DMA engine stalls. The new code detects such stalls and restarts DMA without needing a power reset. Signed-off-by: Troy Tan <troy_tan@realsil.com.cn> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Stable <stable@vger.kernel.org> [3.18] Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
parent
92ff754240
commit
21b39ddb5b
|
@ -1137,6 +1137,139 @@ void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw)
|
|||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
|
||||
}
|
||||
|
||||
static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
/* write reg 0x350 Bit[26]=1. Enable debug port. */
|
||||
tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3);
|
||||
if (!(tmp & BIT(2))) {
|
||||
rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3,
|
||||
tmp | BIT(2));
|
||||
mdelay(100); /* Suggested by DD Justin_tsai. */
|
||||
}
|
||||
|
||||
/* read reg 0x350 Bit[25] if 1 : RX hang
|
||||
* read reg 0x350 Bit[24] if 1 : TX hang
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3);
|
||||
if ((tmp & BIT(0)) || (tmp & BIT(1))) {
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"CheckPcieDMAHang8192EE(): true!!\n");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv,
|
||||
bool mac_power_on)
|
||||
{
|
||||
u8 tmp;
|
||||
bool release_mac_rx_pause;
|
||||
u8 backup_pcie_dma_pause;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
|
||||
"ResetPcieInterfaceDMA8192EE()\n");
|
||||
|
||||
/* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03"
|
||||
* released by SD1 Alan.
|
||||
*/
|
||||
|
||||
/* 1. disable register write lock
|
||||
* write 0x1C bit[1:0] = 2'h0
|
||||
* write 0xCC bit[2] = 1'b1
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL);
|
||||
tmp &= ~(BIT(1) | BIT(0));
|
||||
rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp);
|
||||
tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
|
||||
tmp |= BIT(2);
|
||||
rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
|
||||
|
||||
/* 2. Check and pause TRX DMA
|
||||
* write 0x284 bit[18] = 1'b1
|
||||
* write 0x301 = 0xFF
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
|
||||
if (tmp & BIT(2)) {
|
||||
/* Already pause before the function for another reason. */
|
||||
release_mac_rx_pause = false;
|
||||
} else {
|
||||
rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2)));
|
||||
release_mac_rx_pause = true;
|
||||
}
|
||||
|
||||
backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1);
|
||||
if (backup_pcie_dma_pause != 0xFF)
|
||||
rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF);
|
||||
|
||||
if (mac_power_on) {
|
||||
/* 3. reset TRX function
|
||||
* write 0x100 = 0x00
|
||||
*/
|
||||
rtl_write_byte(rtlpriv, REG_CR, 0);
|
||||
}
|
||||
|
||||
/* 4. Reset PCIe DMA
|
||||
* write 0x003 bit[0] = 0
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
|
||||
tmp &= ~(BIT(0));
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
|
||||
|
||||
/* 5. Enable PCIe DMA
|
||||
* write 0x003 bit[0] = 1
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
|
||||
tmp |= BIT(0);
|
||||
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
|
||||
|
||||
if (mac_power_on) {
|
||||
/* 6. enable TRX function
|
||||
* write 0x100 = 0xFF
|
||||
*/
|
||||
rtl_write_byte(rtlpriv, REG_CR, 0xFF);
|
||||
|
||||
/* We should init LLT & RQPN and
|
||||
* prepare Tx/Rx descrptor address later
|
||||
* because MAC function is reset.
|
||||
*/
|
||||
}
|
||||
|
||||
/* 7. Restore PCIe autoload down bit
|
||||
* write 0xF8 bit[17] = 1'b1
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2);
|
||||
tmp |= BIT(1);
|
||||
rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp);
|
||||
|
||||
/* In MAC power on state, BB and RF maybe in ON state,
|
||||
* if we release TRx DMA here
|
||||
* it will cause packets to be started to Tx/Rx,
|
||||
* so we release Tx/Rx DMA later.
|
||||
*/
|
||||
if (!mac_power_on) {
|
||||
/* 8. release TRX DMA
|
||||
* write 0x284 bit[18] = 1'b0
|
||||
* write 0x301 = 0x00
|
||||
*/
|
||||
if (release_mac_rx_pause) {
|
||||
tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
|
||||
rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL,
|
||||
(tmp & (~BIT(2))));
|
||||
}
|
||||
rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1,
|
||||
backup_pcie_dma_pause);
|
||||
}
|
||||
|
||||
/* 9. lock system register
|
||||
* write 0xCC bit[2] = 1'b0
|
||||
*/
|
||||
tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
|
||||
tmp &= ~(BIT(2));
|
||||
rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
|
||||
}
|
||||
|
||||
int rtl92ee_hw_init(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
|
@ -1162,6 +1295,13 @@ int rtl92ee_hw_init(struct ieee80211_hw *hw)
|
|||
rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E;
|
||||
}
|
||||
|
||||
if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) {
|
||||
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n");
|
||||
_rtl8192ee_reset_pcie_interface_dma(rtlpriv,
|
||||
rtlhal->mac_func_enable);
|
||||
rtlhal->mac_func_enable = false;
|
||||
}
|
||||
|
||||
rtstatus = _rtl92ee_init_mac(hw);
|
||||
|
||||
rtl_write_byte(rtlpriv, 0x577, 0x03);
|
||||
|
|
|
@ -77,9 +77,11 @@
|
|||
#define REG_HIMRE 0x00B8
|
||||
#define REG_HISRE 0x00BC
|
||||
|
||||
#define REG_PMC_DBG_CTRL2 0x00CC
|
||||
#define REG_EFUSE_ACCESS 0x00CF
|
||||
#define REG_HPON_FSM 0x00EC
|
||||
#define REG_SYS_CFG1 0x00F0
|
||||
#define REG_MAC_PHY_CTRL_NORMAL 0x00F8
|
||||
#define REG_SYS_CFG2 0x00FC
|
||||
|
||||
#define REG_CR 0x0100
|
||||
|
|
Loading…
Reference in New Issue