aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorTroy Tan <troy_tan@realsil.com.cn>2015-01-20 12:01:26 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-02-03 08:10:41 -0500
commit21b39ddb5bb2294fe64fbd29045591fe0707825f (patch)
treeb9859003ecb40f4c13ca6ec3fe210ae4eb4545d6 /drivers/net/wireless
parent92ff754240b892cbc16dee5aa080322f3db88b68 (diff)
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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ee/hw.c140
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ee/reg.h2
2 files changed, 142 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
index 3c27ec2c7b5a..b461b3128da5 100644
--- 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(struct ieee80211_hw *hw)
1137 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); 1137 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
1138} 1138}
1139 1139
1140static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv)
1141{
1142 u8 tmp;
1143
1144 /* write reg 0x350 Bit[26]=1. Enable debug port. */
1145 tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3);
1146 if (!(tmp & BIT(2))) {
1147 rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3,
1148 tmp | BIT(2));
1149 mdelay(100); /* Suggested by DD Justin_tsai. */
1150 }
1151
1152 /* read reg 0x350 Bit[25] if 1 : RX hang
1153 * read reg 0x350 Bit[24] if 1 : TX hang
1154 */
1155 tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3);
1156 if ((tmp & BIT(0)) || (tmp & BIT(1))) {
1157 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
1158 "CheckPcieDMAHang8192EE(): true!!\n");
1159 return true;
1160 }
1161 return false;
1162}
1163
1164static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv,
1165 bool mac_power_on)
1166{
1167 u8 tmp;
1168 bool release_mac_rx_pause;
1169 u8 backup_pcie_dma_pause;
1170
1171 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
1172 "ResetPcieInterfaceDMA8192EE()\n");
1173
1174 /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03"
1175 * released by SD1 Alan.
1176 */
1177
1178 /* 1. disable register write lock
1179 * write 0x1C bit[1:0] = 2'h0
1180 * write 0xCC bit[2] = 1'b1
1181 */
1182 tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL);
1183 tmp &= ~(BIT(1) | BIT(0));
1184 rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp);
1185 tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
1186 tmp |= BIT(2);
1187 rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
1188
1189 /* 2. Check and pause TRX DMA
1190 * write 0x284 bit[18] = 1'b1
1191 * write 0x301 = 0xFF
1192 */
1193 tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
1194 if (tmp & BIT(2)) {
1195 /* Already pause before the function for another reason. */
1196 release_mac_rx_pause = false;
1197 } else {
1198 rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2)));
1199 release_mac_rx_pause = true;
1200 }
1201
1202 backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1);
1203 if (backup_pcie_dma_pause != 0xFF)
1204 rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF);
1205
1206 if (mac_power_on) {
1207 /* 3. reset TRX function
1208 * write 0x100 = 0x00
1209 */
1210 rtl_write_byte(rtlpriv, REG_CR, 0);
1211 }
1212
1213 /* 4. Reset PCIe DMA
1214 * write 0x003 bit[0] = 0
1215 */
1216 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
1217 tmp &= ~(BIT(0));
1218 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
1219
1220 /* 5. Enable PCIe DMA
1221 * write 0x003 bit[0] = 1
1222 */
1223 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
1224 tmp |= BIT(0);
1225 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp);
1226
1227 if (mac_power_on) {
1228 /* 6. enable TRX function
1229 * write 0x100 = 0xFF
1230 */
1231 rtl_write_byte(rtlpriv, REG_CR, 0xFF);
1232
1233 /* We should init LLT & RQPN and
1234 * prepare Tx/Rx descrptor address later
1235 * because MAC function is reset.
1236 */
1237 }
1238
1239 /* 7. Restore PCIe autoload down bit
1240 * write 0xF8 bit[17] = 1'b1
1241 */
1242 tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2);
1243 tmp |= BIT(1);
1244 rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp);
1245
1246 /* In MAC power on state, BB and RF maybe in ON state,
1247 * if we release TRx DMA here
1248 * it will cause packets to be started to Tx/Rx,
1249 * so we release Tx/Rx DMA later.
1250 */
1251 if (!mac_power_on) {
1252 /* 8. release TRX DMA
1253 * write 0x284 bit[18] = 1'b0
1254 * write 0x301 = 0x00
1255 */
1256 if (release_mac_rx_pause) {
1257 tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
1258 rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL,
1259 (tmp & (~BIT(2))));
1260 }
1261 rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1,
1262 backup_pcie_dma_pause);
1263 }
1264
1265 /* 9. lock system register
1266 * write 0xCC bit[2] = 1'b0
1267 */
1268 tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2);
1269 tmp &= ~(BIT(2));
1270 rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp);
1271}
1272
1140int rtl92ee_hw_init(struct ieee80211_hw *hw) 1273int rtl92ee_hw_init(struct ieee80211_hw *hw)
1141{ 1274{
1142 struct rtl_priv *rtlpriv = rtl_priv(hw); 1275 struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1162,6 +1295,13 @@ int rtl92ee_hw_init(struct ieee80211_hw *hw)
1162 rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; 1295 rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E;
1163 } 1296 }
1164 1297
1298 if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) {
1299 RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n");
1300 _rtl8192ee_reset_pcie_interface_dma(rtlpriv,
1301 rtlhal->mac_func_enable);
1302 rtlhal->mac_func_enable = false;
1303 }
1304
1165 rtstatus = _rtl92ee_init_mac(hw); 1305 rtstatus = _rtl92ee_init_mac(hw);
1166 1306
1167 rtl_write_byte(rtlpriv, 0x577, 0x03); 1307 rtl_write_byte(rtlpriv, 0x577, 0x03);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
index 3f2a9596e7cd..1eaa1fab550d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h
@@ -77,9 +77,11 @@
77#define REG_HIMRE 0x00B8 77#define REG_HIMRE 0x00B8
78#define REG_HISRE 0x00BC 78#define REG_HISRE 0x00BC
79 79
80#define REG_PMC_DBG_CTRL2 0x00CC
80#define REG_EFUSE_ACCESS 0x00CF 81#define REG_EFUSE_ACCESS 0x00CF
81#define REG_HPON_FSM 0x00EC 82#define REG_HPON_FSM 0x00EC
82#define REG_SYS_CFG1 0x00F0 83#define REG_SYS_CFG1 0x00F0
84#define REG_MAC_PHY_CTRL_NORMAL 0x00F8
83#define REG_SYS_CFG2 0x00FC 85#define REG_SYS_CFG2 0x00FC
84 86
85#define REG_CR 0x0100 87#define REG_CR 0x0100