lkml.org 
[lkml]   [2015]   [Mar]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.18 026/151] rtlwifi: rtl8192ee: Fix DMA stalls
    Date
    3.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Troy Tan <troy_tan@realsil.com.cn>

    commit 21b39ddb5bb2294fe64fbd29045591fe0707825f upstream.

    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>
    Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | 140 +++++++++++++++++++++++++++
    drivers/net/wireless/rtlwifi/rtl8192ee/reg.h | 2
    2 files changed, 142 insertions(+)

    --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
    +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
    @@ -1137,6 +1137,139 @@ void rtl92ee_enable_hw_security_config(s
    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
    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);
    --- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
    +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
    @@ -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



    \
     
     \ /
      Last update: 2015-03-04 09:21    [W:2.770 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site