diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/link.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/link.c | 73 |
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 | ||
104 | sched_reset: | 104 | sched_reset: |
105 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 105 | ath9k_queue_reset(sc, type); |
106 | out: | 106 | out: |
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 | ||
435 | void ath_start_ani(struct ath_common *common) | 434 | void 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 | ||
454 | void 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 | |||
462 | void 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 | |||
495 | stop_ani: | ||
496 | clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); | ||
497 | ath_stop_ani(sc); | ||
498 | } | ||
499 | |||
455 | void ath_update_survey_nf(struct ath_softc *sc, int channel) | 500 | void 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; |