aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/link.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c73
1 files changed, 59 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 91650fe50461..d4549e9aac5c 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -50,8 +50,7 @@ void ath_tx_complete_poll_work(struct work_struct *work)
50 if (needreset) { 50 if (needreset) {
51 ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, 51 ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
52 "tx hung, resetting the chip\n"); 52 "tx hung, resetting the chip\n");
53 RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); 53 ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
54 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
55 return; 54 return;
56 } 55 }
57 56
@@ -69,6 +68,7 @@ void ath_hw_check(struct work_struct *work)
69 unsigned long flags; 68 unsigned long flags;
70 int busy; 69 int busy;
71 u8 is_alive, nbeacon = 1; 70 u8 is_alive, nbeacon = 1;
71 enum ath_reset_type type;
72 72
73 ath9k_ps_wakeup(sc); 73 ath9k_ps_wakeup(sc);
74 is_alive = ath9k_hw_check_alive(sc->sc_ah); 74 is_alive = ath9k_hw_check_alive(sc->sc_ah);
@@ -78,7 +78,7 @@ void ath_hw_check(struct work_struct *work)
78 else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { 78 else if (!is_alive && AR_SREV_9300(sc->sc_ah)) {
79 ath_dbg(common, RESET, 79 ath_dbg(common, RESET,
80 "DCU stuck is detected. Schedule chip reset\n"); 80 "DCU stuck is detected. Schedule chip reset\n");
81 RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); 81 type = RESET_TYPE_MAC_HANG;
82 goto sched_reset; 82 goto sched_reset;
83 } 83 }
84 84
@@ -90,7 +90,7 @@ void ath_hw_check(struct work_struct *work)
90 busy, sc->hw_busy_count + 1); 90 busy, sc->hw_busy_count + 1);
91 if (busy >= 99) { 91 if (busy >= 99) {
92 if (++sc->hw_busy_count >= 3) { 92 if (++sc->hw_busy_count >= 3) {
93 RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); 93 type = RESET_TYPE_BB_HANG;
94 goto sched_reset; 94 goto sched_reset;
95 } 95 }
96 } else if (busy >= 0) { 96 } else if (busy >= 0) {
@@ -102,7 +102,7 @@ void ath_hw_check(struct work_struct *work)
102 goto out; 102 goto out;
103 103
104sched_reset: 104sched_reset:
105 ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 105 ath9k_queue_reset(sc, type);
106out: 106out:
107 ath9k_ps_restore(sc); 107 ath9k_ps_restore(sc);
108} 108}
@@ -119,8 +119,7 @@ static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
119 count++; 119 count++;
120 if (count == 3) { 120 if (count == 3) {
121 ath_dbg(common, RESET, "PLL WAR, resetting the chip\n"); 121 ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
122 RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); 122 ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);
123 ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
124 count = 0; 123 count = 0;
125 return true; 124 return true;
126 } 125 }
@@ -432,26 +431,72 @@ set_timer:
432 } 431 }
433} 432}
434 433
435void ath_start_ani(struct ath_common *common) 434void ath_start_ani(struct ath_softc *sc)
436{ 435{
437 struct ath_hw *ah = common->ah; 436 struct ath_hw *ah = sc->sc_ah;
437 struct ath_common *common = ath9k_hw_common(ah);
438 unsigned long timestamp = jiffies_to_msecs(jiffies); 438 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 439
444 if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) 440 if (common->disable_ani ||
441 !test_bit(SC_OP_ANI_RUN, &sc->sc_flags) ||
442 (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
445 return; 443 return;
446 444
447 common->ani.longcal_timer = timestamp; 445 common->ani.longcal_timer = timestamp;
448 common->ani.shortcal_timer = timestamp; 446 common->ani.shortcal_timer = timestamp;
449 common->ani.checkani_timer = timestamp; 447 common->ani.checkani_timer = timestamp;
450 448
449 ath_dbg(common, ANI, "Starting ANI\n");
451 mod_timer(&common->ani.timer, 450 mod_timer(&common->ani.timer,
452 jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); 451 jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));
453} 452}
454 453
454void ath_stop_ani(struct ath_softc *sc)
455{
456 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
457
458 ath_dbg(common, ANI, "Stopping ANI\n");
459 del_timer_sync(&common->ani.timer);
460}
461
462void ath_check_ani(struct ath_softc *sc)
463{
464 struct ath_hw *ah = sc->sc_ah;
465 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
466
467 /*
468 * Check for the various conditions in which ANI has to
469 * be stopped.
470 */
471 if (ah->opmode == NL80211_IFTYPE_ADHOC) {
472 if (!cur_conf->enable_beacon)
473 goto stop_ani;
474 } else if (ah->opmode == NL80211_IFTYPE_AP) {
475 if (!cur_conf->enable_beacon) {
476 /*
477 * Disable ANI only when there are no
478 * associated stations.
479 */
480 if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
481 goto stop_ani;
482 }
483 } else if (ah->opmode == NL80211_IFTYPE_STATION) {
484 if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
485 goto stop_ani;
486 }
487
488 if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) {
489 set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
490 ath_start_ani(sc);
491 }
492
493 return;
494
495stop_ani:
496 clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
497 ath_stop_ani(sc);
498}
499
455void ath_update_survey_nf(struct ath_softc *sc, int channel) 500void ath_update_survey_nf(struct ath_softc *sc, int channel)
456{ 501{
457 struct ath_hw *ah = sc->sc_ah; 502 struct ath_hw *ah = sc->sc_ah;