ath9k_hw: Speedup register ops for HTC driver
authorRajkumar Manoharan <rmanoharan@atheros.com>
Tue, 15 Mar 2011 17:41:35 +0000 (23:11 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 30 Mar 2011 18:15:12 +0000 (14:15 -0400)
Fine-tuning register write operation and avoid unnecessay
delays for ath9k_htc driver, saves hw reset time which
improves scanning time and also solves one of the following
scenario.

Sometimes the ACK is sent by STA for assoc response is not
seen at AP side. So the AP continues to send retry assoc
responses. At the STA side, since the assoc response was
already forwarded to mac80211, it proceeded to channel change
which in turns does chip reset.

In most of the cases the chip reset was completed before
max retries are reached at AP side. Hence STA can able to ACK
the retried frames again. But in clear environment these retries
are completed within shortspan of time.

Since ath9k_htc consumes more time for hw reset, this latency
is causing dissociation by AP due to max reties are reached.
This issue was originally reported with Cisco Aironet 1250 AP
in HT40 mode in noise free environment.

Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/phy.h

index ffcf44a4058b7777a21c865095b4331c628e690b..94acce59f51d59293e51488d1ef631746cbcff4a 100644 (file)
@@ -729,6 +729,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
                                 struct ath9k_channel *chan)
 {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_common *common = ath9k_hw_common(ah);
        int i, regWrites = 0;
        struct ieee80211_channel *channel = chan->chan;
        u32 modesIndex, freqIndex;
@@ -805,7 +806,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
                REG_WRITE(ah, reg, val);
 
                if (reg >= 0x7800 && reg < 0x78a0
-                   && ah->config.analog_shiftreg) {
+                   && ah->config.analog_shiftreg
+                   && (common->bus_ops->ath_bus_type != ATH_USB)) {
                        udelay(100);
                }
 
@@ -835,7 +837,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
                REG_WRITE(ah, reg, val);
 
                if (reg >= 0x7800 && reg < 0x78a0
-                   && ah->config.analog_shiftreg) {
+                   && ah->config.analog_shiftreg
+                   && (common->bus_ops->ath_bus_type != ATH_USB)) {
                        udelay(100);
                }
 
index 8cd8333cc0865f71556e163f2ae9c3e4c4c3333a..2f0712ea49a69c97287888ecc53dc84e7d8b51f4 100644 (file)
@@ -392,6 +392,8 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
                                                           numXpdGain);
                        }
 
+                       ENABLE_REGWRITE_BUFFER(ah);
+
                        if (i == 0) {
                                if (!ath9k_hw_ar9287_get_eeprom(ah,
                                                        EEP_OL_PWRCTRL)) {
@@ -442,6 +444,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
                                        regOffset += 4;
                                }
                        }
+                       REGWRITE_BUFFER_FLUSH(ah);
                }
        }
 
@@ -757,6 +760,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
                        ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
        }
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        /* OFDM power per rate */
        REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
                  ATH9K_POW_SM(ratesArray[rate18mb], 24)
@@ -840,6 +845,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
                          | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
                          | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
        }
+       REGWRITE_BUFFER_FLUSH(ah);
 }
 
 static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
index fccd87df7300b27a91ed896325af85a134e8a9b0..995949ddd63e4d707aa79c5b0c1734dc9731276e 100644 (file)
@@ -799,6 +799,8 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
                                                           pwr_table_offset,
                                                           &diff);
 
+                       ENABLE_REGWRITE_BUFFER(ah);
+
                        if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
                                if (OLC_FOR_AR9280_20_LATER) {
                                        REG_WRITE(ah,
@@ -847,6 +849,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
 
                                regOffset += 4;
                        }
+                       REGWRITE_BUFFER_FLUSH(ah);
                }
        }
 
@@ -1205,6 +1208,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
                }
        }
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
                  ATH9K_POW_SM(ratesArray[rate18mb], 24)
                  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
@@ -1291,6 +1296,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
        REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
                  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
                  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+       REGWRITE_BUFFER_FLUSH(ah);
 }
 
 static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
index 6650fd48415cb6f0cb2c558521aca3fc6b15f72f..c86eea28a88fa1fbcd4014343bf8a12aafcd0e73 100644 (file)
 #define REG_CLR_BIT(_a, _r, _f) \
        REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
 
-#define DO_DELAY(x) do {                       \
-               if ((++(x) % 64) == 0)          \
-                       udelay(1);              \
+#define DO_DELAY(x) do {                                       \
+               if (((++(x) % 64) == 0) &&                      \
+                   (ath9k_hw_common(ah)->bus_ops->ath_bus_type \
+                       != ATH_USB))                            \
+                       udelay(1);                              \
        } while (0)
 
 #define REG_WRITE_ARRAY(iniarray, column, regWr) do {                   \
                int r;                                                  \
+               ENABLE_REGWRITE_BUFFER(ah);                             \
                for (r = 0; r < ((iniarray)->ia_rows); r++) {           \
                        REG_WRITE(ah, INI_RA((iniarray), (r), 0),       \
                                  INI_RA((iniarray), r, (column)));     \
                        DO_DELAY(regWr);                                \
                }                                                       \
+               REGWRITE_BUFFER_FLUSH(ah);                              \
        } while (0)
 
 #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
index 5e3d7496986e77656912ab5b7c7745d9f3f36cee..e4029325c787abfbb2d2630e8f4b9dc705ccccdf 100644 (file)
 
 #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do {               \
                int r;                                                  \
+               ENABLE_REGWRITE_BUFFER(ah);                             \
                for (r = 0; r < ((iniarray)->ia_rows); r++) {           \
                        REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
                        DO_DELAY(regWr);                                \
                }                                                       \
+               REGWRITE_BUFFER_FLUSH(ah);                              \
        } while (0)
 
 #define ANTSWAP_AB 0x0001