aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2012-07-17 07:46:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-17 15:11:39 -0400
commitda0d45f7b1dd08ab1ea4f542db797a0c51724281 (patch)
tree8e2c4a4eac44c4650a09b51d04d7148052dfff1a
parentfb6e252f8d262d05da3ae023b4a6f83d0eec17d9 (diff)
ath9k: Fix ANI management
Currently, there are problems with how ANI is handled in multi-VIF scenarios. This patch addresses them by unifying the start/stop logic. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c60
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c29
4 files changed, 70 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 41219a5e7f53..c8af0db97c4f 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -447,7 +447,9 @@ void ath_rx_poll(unsigned long data);
447void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon); 447void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon);
448void ath_paprd_calibrate(struct work_struct *work); 448void ath_paprd_calibrate(struct work_struct *work);
449void ath_ani_calibrate(unsigned long data); 449void ath_ani_calibrate(unsigned long data);
450void ath_start_ani(struct ath_common *common); 450void ath_start_ani(struct ath_softc *sc);
451void ath_stop_ani(struct ath_softc *sc);
452void ath_check_ani(struct ath_softc *sc);
451int ath_update_survey_stats(struct ath_softc *sc); 453int ath_update_survey_stats(struct ath_softc *sc);
452void ath_update_survey_nf(struct ath_softc *sc, int channel); 454void ath_update_survey_nf(struct ath_softc *sc, int channel);
453 455
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index b9ea067a7bb5..68b643c8943c 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -206,10 +206,9 @@ static ssize_t write_file_disable_ani(struct file *file,
206 206
207 if (disable_ani) { 207 if (disable_ani) {
208 clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); 208 clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
209 del_timer_sync(&common->ani.timer); 209 ath_stop_ani(sc);
210 } else { 210 } else {
211 set_bit(SC_OP_ANI_RUN, &sc->sc_flags); 211 ath_check_ani(sc);
212 ath_start_ani(common);
213 } 212 }
214 213
215 return count; 214 return count;
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 91650fe50461..42fc0a374c61 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -432,26 +432,72 @@ set_timer:
432 } 432 }
433} 433}
434 434
435void ath_start_ani(struct ath_common *common) 435void ath_start_ani(struct ath_softc *sc)
436{ 436{
437 struct ath_hw *ah = common->ah; 437 struct ath_hw *ah = sc->sc_ah;
438 struct ath_common *common = ath9k_hw_common(ah);
438 unsigned long timestamp = jiffies_to_msecs(jiffies); 439 unsigned long timestamp = jiffies_to_msecs(jiffies);
439 struct ath_softc *sc = (struct ath_softc *) common->priv;
440
441 if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags))
442 return;
443 440
444 if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) 441 if (common->disable_ani ||
442 !test_bit(SC_OP_ANI_RUN, &sc->sc_flags) ||
443 (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
445 return; 444 return;
446 445
447 common->ani.longcal_timer = timestamp; 446 common->ani.longcal_timer = timestamp;
448 common->ani.shortcal_timer = timestamp; 447 common->ani.shortcal_timer = timestamp;
449 common->ani.checkani_timer = timestamp; 448 common->ani.checkani_timer = timestamp;
450 449
450 ath_dbg(common, ANI, "Starting ANI\n");
451 mod_timer(&common->ani.timer, 451 mod_timer(&common->ani.timer,
452 jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); 452 jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));
453} 453}
454 454
455void ath_stop_ani(struct ath_softc *sc)
456{
457 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
458
459 ath_dbg(common, ANI, "Stopping ANI\n");
460 del_timer_sync(&common->ani.timer);
461}
462
463void ath_check_ani(struct ath_softc *sc)
464{
465 struct ath_hw *ah = sc->sc_ah;
466 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
467
468 /*
469 * Check for the various conditions in which ANI has to
470 * be stopped.
471 */
472 if (ah->opmode == NL80211_IFTYPE_ADHOC) {
473 if (!cur_conf->enable_beacon)
474 goto stop_ani;
475 } else if (ah->opmode == NL80211_IFTYPE_AP) {
476 if (!cur_conf->enable_beacon) {
477 /*
478 * Disable ANI only when there are no
479 * associated stations.
480 */
481 if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
482 goto stop_ani;
483 }
484 } else if (ah->opmode == NL80211_IFTYPE_STATION) {
485 if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
486 goto stop_ani;
487 }
488
489 if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) {
490 set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
491 ath_start_ani(sc);
492 }
493
494 return;
495
496stop_ani:
497 clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
498 ath_stop_ani(sc);
499}
500
455void ath_update_survey_nf(struct ath_softc *sc, int channel) 501void ath_update_survey_nf(struct ath_softc *sc, int channel)
456{ 502{
457 struct ath_hw *ah = sc->sc_ah; 503 struct ath_hw *ah = sc->sc_ah;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 915bd4881b3f..d80d5be2ccb7 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -167,8 +167,6 @@ static void ath_cancel_work(struct ath_softc *sc)
167 167
168static void ath_restart_work(struct ath_softc *sc) 168static void ath_restart_work(struct ath_softc *sc)
169{ 169{
170 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
171
172 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); 170 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
173 171
174 if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) || 172 if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||
@@ -177,21 +175,18 @@ static void ath_restart_work(struct ath_softc *sc)
177 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); 175 msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
178 176
179 ath_start_rx_poll(sc, 3); 177 ath_start_rx_poll(sc, 3);
180 178 ath_start_ani(sc);
181 if (!common->disable_ani)
182 ath_start_ani(common);
183} 179}
184 180
185static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) 181static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
186{ 182{
187 struct ath_hw *ah = sc->sc_ah; 183 struct ath_hw *ah = sc->sc_ah;
188 struct ath_common *common = ath9k_hw_common(ah);
189 bool ret = true; 184 bool ret = true;
190 185
191 ieee80211_stop_queues(sc->hw); 186 ieee80211_stop_queues(sc->hw);
192 187
193 sc->hw_busy_count = 0; 188 sc->hw_busy_count = 0;
194 del_timer_sync(&common->ani.timer); 189 ath_stop_ani(sc);
195 del_timer_sync(&sc->rx_poll_timer); 190 del_timer_sync(&sc->rx_poll_timer);
196 191
197 ath9k_debug_samp_bb_mac(sc); 192 ath9k_debug_samp_bb_mac(sc);
@@ -1481,6 +1476,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1481 struct ieee80211_bss_conf *bss_conf, 1476 struct ieee80211_bss_conf *bss_conf,
1482 u32 changed) 1477 u32 changed)
1483{ 1478{
1479#define CHECK_ANI \
1480 (BSS_CHANGED_ASSOC | \
1481 BSS_CHANGED_IBSS | \
1482 BSS_CHANGED_BEACON_ENABLED)
1483
1484 struct ath_softc *sc = hw->priv; 1484 struct ath_softc *sc = hw->priv;
1485 struct ath_hw *ah = sc->sc_ah; 1485 struct ath_hw *ah = sc->sc_ah;
1486 struct ath_common *common = ath9k_hw_common(ah); 1486 struct ath_common *common = ath9k_hw_common(ah);
@@ -1517,16 +1517,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1517 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); 1517 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
1518 common->curaid = bss_conf->aid; 1518 common->curaid = bss_conf->aid;
1519 ath9k_hw_write_associd(sc->sc_ah); 1519 ath9k_hw_write_associd(sc->sc_ah);
1520
1521 if (bss_conf->ibss_joined) {
1522 if (!common->disable_ani) {
1523 set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
1524 ath_start_ani(common);
1525 }
1526 } else {
1527 clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
1528 del_timer_sync(&common->ani.timer);
1529 }
1530 } 1520 }
1531 1521
1532 if ((changed & BSS_CHANGED_BEACON_ENABLED) || 1522 if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
@@ -1557,8 +1547,13 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1557 } 1547 }
1558 } 1548 }
1559 1549
1550 if (changed & CHECK_ANI)
1551 ath_check_ani(sc);
1552
1560 mutex_unlock(&sc->mutex); 1553 mutex_unlock(&sc->mutex);
1561 ath9k_ps_restore(sc); 1554 ath9k_ps_restore(sc);
1555
1556#undef CHECK_ANI
1562} 1557}
1563 1558
1564static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 1559static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)