aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-07-30 18:11:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-04 15:27:37 -0400
commit5ee0865615f65f84e6ee9174771a6716c29e08e1 (patch)
tree8afd490ee1b69dc1399500971428c92db680c42f /drivers/net/wireless
parentb2ccc507b70be2815a25e3c5dc23c636e128222c (diff)
ath9k: prevent calibration during off-channel activity
Previously the software scan callback was used to indicate to the hardware, when it was safe to calibrate. This didn't really work properly, because it depends on a specific order of software scan callbacks vs. channel changes. Also, software scans are not the only thing that triggers off-channel activity, so it's better to use the newly added indication from mac80211 for this and not use the software scan callback for anything calibration related. This fixes at least some of the invalid noise floor readings that I've seen in AP mode on AR9160 Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c73
2 files changed, 40 insertions, 35 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 998ae2c49ed2..11fc69bee58f 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -510,7 +510,7 @@ void ath_deinit_leds(struct ath_softc *sc);
510#define SC_OP_BEACONS BIT(1) 510#define SC_OP_BEACONS BIT(1)
511#define SC_OP_RXAGGR BIT(2) 511#define SC_OP_RXAGGR BIT(2)
512#define SC_OP_TXAGGR BIT(3) 512#define SC_OP_TXAGGR BIT(3)
513#define SC_OP_FULL_RESET BIT(4) 513#define SC_OP_OFFCHANNEL BIT(4)
514#define SC_OP_PREAMBLE_SHORT BIT(5) 514#define SC_OP_PREAMBLE_SHORT BIT(5)
515#define SC_OP_PROTECT_ENABLE BIT(6) 515#define SC_OP_PROTECT_ENABLE BIT(6)
516#define SC_OP_RXFLUSH BIT(7) 516#define SC_OP_RXFLUSH BIT(7)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6c1d9ef550de..8387ad5b4897 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -154,6 +154,27 @@ void ath9k_ps_restore(struct ath_softc *sc)
154 spin_unlock_irqrestore(&sc->sc_pm_lock, flags); 154 spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
155} 155}
156 156
157static void ath_start_ani(struct ath_common *common)
158{
159 struct ath_hw *ah = common->ah;
160 unsigned long timestamp = jiffies_to_msecs(jiffies);
161 struct ath_softc *sc = (struct ath_softc *) common->priv;
162
163 if (!(sc->sc_flags & SC_OP_ANI_RUN))
164 return;
165
166 if (sc->sc_flags & SC_OP_OFFCHANNEL)
167 return;
168
169 common->ani.longcal_timer = timestamp;
170 common->ani.shortcal_timer = timestamp;
171 common->ani.checkani_timer = timestamp;
172
173 mod_timer(&common->ani.timer,
174 jiffies +
175 msecs_to_jiffies((u32)ah->config.ani_poll_interval));
176}
177
157/* 178/*
158 * Set/change channels. If the channel is really being changed, it's done 179 * Set/change channels. If the channel is really being changed, it's done
159 * by reseting the chip. To accomplish this we must first cleanup any pending 180 * by reseting the chip. To accomplish this we must first cleanup any pending
@@ -172,6 +193,11 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
172 if (sc->sc_flags & SC_OP_INVALID) 193 if (sc->sc_flags & SC_OP_INVALID)
173 return -EIO; 194 return -EIO;
174 195
196 del_timer_sync(&common->ani.timer);
197 cancel_work_sync(&sc->paprd_work);
198 cancel_work_sync(&sc->hw_check_work);
199 cancel_delayed_work_sync(&sc->tx_complete_work);
200
175 ath9k_ps_wakeup(sc); 201 ath9k_ps_wakeup(sc);
176 202
177 /* 203 /*
@@ -191,7 +217,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
191 * to flush data frames already in queue because of 217 * to flush data frames already in queue because of
192 * changing channel. */ 218 * changing channel. */
193 219
194 if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) 220 if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
195 fastcc = false; 221 fastcc = false;
196 222
197 ath_print(common, ATH_DBG_CONFIG, 223 ath_print(common, ATH_DBG_CONFIG,
@@ -212,8 +238,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
212 } 238 }
213 spin_unlock_bh(&sc->sc_resetlock); 239 spin_unlock_bh(&sc->sc_resetlock);
214 240
215 sc->sc_flags &= ~SC_OP_FULL_RESET;
216
217 if (ath_startrecv(sc) != 0) { 241 if (ath_startrecv(sc) != 0) {
218 ath_print(common, ATH_DBG_FATAL, 242 ath_print(common, ATH_DBG_FATAL,
219 "Unable to restart recv logic\n"); 243 "Unable to restart recv logic\n");
@@ -225,6 +249,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
225 ath_update_txpow(sc); 249 ath_update_txpow(sc);
226 ath9k_hw_set_interrupts(ah, ah->imask); 250 ath9k_hw_set_interrupts(ah, ah->imask);
227 251
252 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) {
253 ath_start_ani(common);
254 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
255 ath_beacon_config(sc, NULL);
256 }
257
228 ps_restore: 258 ps_restore:
229 ath9k_ps_restore(sc); 259 ath9k_ps_restore(sc);
230 return r; 260 return r;
@@ -440,8 +470,7 @@ set_timer:
440 cal_interval = min(cal_interval, (u32)short_cal_interval); 470 cal_interval = min(cal_interval, (u32)short_cal_interval);
441 471
442 mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); 472 mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
443 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && 473 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) {
444 !(sc->sc_flags & SC_OP_SCANNING)) {
445 if (!sc->sc_ah->curchan->paprd_done) 474 if (!sc->sc_ah->curchan->paprd_done)
446 ieee80211_queue_work(sc->hw, &sc->paprd_work); 475 ieee80211_queue_work(sc->hw, &sc->paprd_work);
447 else 476 else
@@ -449,24 +478,6 @@ set_timer:
449 } 478 }
450} 479}
451 480
452static void ath_start_ani(struct ath_common *common)
453{
454 struct ath_hw *ah = common->ah;
455 unsigned long timestamp = jiffies_to_msecs(jiffies);
456 struct ath_softc *sc = (struct ath_softc *) common->priv;
457
458 if (!(sc->sc_flags & SC_OP_ANI_RUN))
459 return;
460
461 common->ani.longcal_timer = timestamp;
462 common->ani.shortcal_timer = timestamp;
463 common->ani.checkani_timer = timestamp;
464
465 mod_timer(&common->ani.timer,
466 jiffies +
467 msecs_to_jiffies((u32)ah->config.ani_poll_interval));
468}
469
470/* 481/*
471 * Update tx/rx chainmask. For legacy association, 482 * Update tx/rx chainmask. For legacy association,
472 * hard code chainmask to 1x1, for 11n association, use 483 * hard code chainmask to 1x1, for 11n association, use
@@ -478,7 +489,7 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht)
478 struct ath_hw *ah = sc->sc_ah; 489 struct ath_hw *ah = sc->sc_ah;
479 struct ath_common *common = ath9k_hw_common(ah); 490 struct ath_common *common = ath9k_hw_common(ah);
480 491
481 if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || 492 if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht ||
482 (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { 493 (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) {
483 common->tx_chainmask = ah->caps.tx_chainmask; 494 common->tx_chainmask = ah->caps.tx_chainmask;
484 common->rx_chainmask = ah->caps.rx_chainmask; 495 common->rx_chainmask = ah->caps.rx_chainmask;
@@ -1580,6 +1591,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1580 1591
1581 aphy->chan_idx = pos; 1592 aphy->chan_idx = pos;
1582 aphy->chan_is_ht = conf_is_ht(conf); 1593 aphy->chan_is_ht = conf_is_ht(conf);
1594 if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
1595 sc->sc_flags |= SC_OP_OFFCHANNEL;
1596 else
1597 sc->sc_flags &= ~SC_OP_OFFCHANNEL;
1583 1598
1584 if (aphy->state == ATH_WIPHY_SCAN || 1599 if (aphy->state == ATH_WIPHY_SCAN ||
1585 aphy->state == ATH_WIPHY_ACTIVE) 1600 aphy->state == ATH_WIPHY_ACTIVE)
@@ -1991,7 +2006,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
1991{ 2006{
1992 struct ath_wiphy *aphy = hw->priv; 2007 struct ath_wiphy *aphy = hw->priv;
1993 struct ath_softc *sc = aphy->sc; 2008 struct ath_softc *sc = aphy->sc;
1994 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1995 2009
1996 mutex_lock(&sc->mutex); 2010 mutex_lock(&sc->mutex);
1997 if (ath9k_wiphy_scanning(sc)) { 2011 if (ath9k_wiphy_scanning(sc)) {
@@ -2009,10 +2023,6 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
2009 aphy->state = ATH_WIPHY_SCAN; 2023 aphy->state = ATH_WIPHY_SCAN;
2010 ath9k_wiphy_pause_all_forced(sc, aphy); 2024 ath9k_wiphy_pause_all_forced(sc, aphy);
2011 sc->sc_flags |= SC_OP_SCANNING; 2025 sc->sc_flags |= SC_OP_SCANNING;
2012 del_timer_sync(&common->ani.timer);
2013 cancel_work_sync(&sc->paprd_work);
2014 cancel_work_sync(&sc->hw_check_work);
2015 cancel_delayed_work_sync(&sc->tx_complete_work);
2016 mutex_unlock(&sc->mutex); 2026 mutex_unlock(&sc->mutex);
2017} 2027}
2018 2028
@@ -2024,15 +2034,10 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
2024{ 2034{
2025 struct ath_wiphy *aphy = hw->priv; 2035 struct ath_wiphy *aphy = hw->priv;
2026 struct ath_softc *sc = aphy->sc; 2036 struct ath_softc *sc = aphy->sc;
2027 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2028 2037
2029 mutex_lock(&sc->mutex); 2038 mutex_lock(&sc->mutex);
2030 aphy->state = ATH_WIPHY_ACTIVE; 2039 aphy->state = ATH_WIPHY_ACTIVE;
2031 sc->sc_flags &= ~SC_OP_SCANNING; 2040 sc->sc_flags &= ~SC_OP_SCANNING;
2032 sc->sc_flags |= SC_OP_FULL_RESET;
2033 ath_start_ani(common);
2034 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
2035 ath_beacon_config(sc, NULL);
2036 mutex_unlock(&sc->mutex); 2041 mutex_unlock(&sc->mutex);
2037} 2042}
2038 2043