diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 137 |
1 files changed, 69 insertions, 68 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e944eadd677d..9ff73e007d34 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -596,74 +596,6 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
596 | ath_tx_node_cleanup(sc, an); | 596 | ath_tx_node_cleanup(sc, an); |
597 | } | 597 | } |
598 | 598 | ||
599 | void ath_hw_check(struct work_struct *work) | ||
600 | { | ||
601 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | ||
602 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
603 | unsigned long flags; | ||
604 | int busy; | ||
605 | |||
606 | ath9k_ps_wakeup(sc); | ||
607 | if (ath9k_hw_check_alive(sc->sc_ah)) | ||
608 | goto out; | ||
609 | |||
610 | spin_lock_irqsave(&common->cc_lock, flags); | ||
611 | busy = ath_update_survey_stats(sc); | ||
612 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
613 | |||
614 | ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " | ||
615 | "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); | ||
616 | if (busy >= 99) { | ||
617 | if (++sc->hw_busy_count >= 3) { | ||
618 | spin_lock_bh(&sc->sc_pcu_lock); | ||
619 | ath_reset(sc, true); | ||
620 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
621 | } | ||
622 | } else if (busy >= 0) | ||
623 | sc->hw_busy_count = 0; | ||
624 | |||
625 | out: | ||
626 | ath9k_ps_restore(sc); | ||
627 | } | ||
628 | |||
629 | static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) | ||
630 | { | ||
631 | static int count; | ||
632 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
633 | |||
634 | if (pll_sqsum >= 0x40000) { | ||
635 | count++; | ||
636 | if (count == 3) { | ||
637 | /* Rx is hung for more than 500ms. Reset it */ | ||
638 | ath_dbg(common, ATH_DBG_RESET, | ||
639 | "Possible RX hang, resetting"); | ||
640 | spin_lock_bh(&sc->sc_pcu_lock); | ||
641 | ath_reset(sc, true); | ||
642 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
643 | count = 0; | ||
644 | } | ||
645 | } else | ||
646 | count = 0; | ||
647 | } | ||
648 | |||
649 | void ath_hw_pll_work(struct work_struct *work) | ||
650 | { | ||
651 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
652 | hw_pll_work.work); | ||
653 | u32 pll_sqsum; | ||
654 | |||
655 | if (AR_SREV_9485(sc->sc_ah)) { | ||
656 | |||
657 | ath9k_ps_wakeup(sc); | ||
658 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | ||
659 | ath9k_ps_restore(sc); | ||
660 | |||
661 | ath_hw_pll_rx_hang_check(sc, pll_sqsum); | ||
662 | |||
663 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); | ||
664 | } | ||
665 | } | ||
666 | |||
667 | 599 | ||
668 | void ath9k_tasklet(unsigned long data) | 600 | void ath9k_tasklet(unsigned long data) |
669 | { | 601 | { |
@@ -1037,6 +969,75 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
1037 | return r; | 969 | return r; |
1038 | } | 970 | } |
1039 | 971 | ||
972 | void ath_hw_check(struct work_struct *work) | ||
973 | { | ||
974 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | ||
975 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
976 | unsigned long flags; | ||
977 | int busy; | ||
978 | |||
979 | ath9k_ps_wakeup(sc); | ||
980 | if (ath9k_hw_check_alive(sc->sc_ah)) | ||
981 | goto out; | ||
982 | |||
983 | spin_lock_irqsave(&common->cc_lock, flags); | ||
984 | busy = ath_update_survey_stats(sc); | ||
985 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
986 | |||
987 | ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " | ||
988 | "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); | ||
989 | if (busy >= 99) { | ||
990 | if (++sc->hw_busy_count >= 3) { | ||
991 | spin_lock_bh(&sc->sc_pcu_lock); | ||
992 | ath_reset(sc, true); | ||
993 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
994 | } | ||
995 | |||
996 | } else if (busy >= 0) | ||
997 | sc->hw_busy_count = 0; | ||
998 | |||
999 | out: | ||
1000 | ath9k_ps_restore(sc); | ||
1001 | } | ||
1002 | |||
1003 | static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) | ||
1004 | { | ||
1005 | static int count; | ||
1006 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1007 | |||
1008 | if (pll_sqsum >= 0x40000) { | ||
1009 | count++; | ||
1010 | if (count == 3) { | ||
1011 | /* Rx is hung for more than 500ms. Reset it */ | ||
1012 | ath_dbg(common, ATH_DBG_RESET, | ||
1013 | "Possible RX hang, resetting"); | ||
1014 | spin_lock_bh(&sc->sc_pcu_lock); | ||
1015 | ath_reset(sc, true); | ||
1016 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1017 | count = 0; | ||
1018 | } | ||
1019 | } else | ||
1020 | count = 0; | ||
1021 | } | ||
1022 | |||
1023 | void ath_hw_pll_work(struct work_struct *work) | ||
1024 | { | ||
1025 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
1026 | hw_pll_work.work); | ||
1027 | u32 pll_sqsum; | ||
1028 | |||
1029 | if (AR_SREV_9485(sc->sc_ah)) { | ||
1030 | |||
1031 | ath9k_ps_wakeup(sc); | ||
1032 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | ||
1033 | ath9k_ps_restore(sc); | ||
1034 | |||
1035 | ath_hw_pll_rx_hang_check(sc, pll_sqsum); | ||
1036 | |||
1037 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1040 | /**********************/ | 1041 | /**********************/ |
1041 | /* mac80211 callbacks */ | 1042 | /* mac80211 callbacks */ |
1042 | /**********************/ | 1043 | /**********************/ |