From: Luis R. Rodriguez Date: Wed Mar 11 10:24:17 2009 -0700 ath9k: Fix SMP hang on 11n PCI devices due to hw FIFO queue issue Some PCI 11n devices will see a hang on SMP systems due to an issue with the hardware where the FIFO will get filled too quick and the device goes into a loop. There are several ways to work around this issue but this particular approach doesn't penalize the performance for all devices. We simply do a udelay() after a lot of consecutive reads/writes. Signed-off-by: Luis R. Rodriguez --- diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c index a39eb76..7f3e411 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath9k/ani.c @@ -60,6 +60,7 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_LOW, ah->coarse_low[level]); + udelay(30); REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, AR_PHY_AGC_CTL1_COARSE_HIGH, ah->coarse_high[level]); @@ -92,6 +93,7 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); + udelay(30); REG_RMW_FIELD(ah, AR_PHY_SFCORR, AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); @@ -101,6 +103,7 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]); + udelay(30); REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, @@ -224,6 +227,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); + udelay(30); stats->rts_good += REG_READ(ah, AR_RTS_OK); stats->beacons += REG_READ(ah, AR_BEACON_CNT); } @@ -706,6 +710,7 @@ void ath9k_hw_procmibevent(struct ath_hw *ah, /* Reset these counters regardless */ REG_WRITE(ah, AR_FILT_OFDM, 0); REG_WRITE(ah, AR_FILT_CCK, 0); + udelay(10); if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);