aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c137
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
599void 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
625out:
626 ath9k_ps_restore(sc);
627}
628
629static 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
649void 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
668void ath9k_tasklet(unsigned long data) 600void 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
972void 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
999out:
1000 ath9k_ps_restore(sc);
1001}
1002
1003static 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
1023void 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/**********************/