Root/package/mac80211/patches/570-ath9k_bb_hang_check_fix.patch

1--- a/drivers/net/wireless/ath/ath9k/main.c
2+++ b/drivers/net/wireless/ath/ath9k/main.c
3@@ -177,7 +177,12 @@ static void ath_update_survey_nf(struct
4     }
5 }
6 
7-static void ath_update_survey_stats(struct ath_softc *sc)
8+/*
9+ * Updates the survey statistics and returns the busy time since last
10+ * update in %, if the measurement duration was long enough for the
11+ * result to be useful, -1 otherwise.
12+ */
13+static int ath_update_survey_stats(struct ath_softc *sc)
14 {
15     struct ath_hw *ah = sc->sc_ah;
16     struct ath_common *common = ath9k_hw_common(ah);
17@@ -185,9 +190,10 @@ static void ath_update_survey_stats(stru
18     struct survey_info *survey = &sc->survey[pos];
19     struct ath_cycle_counters *cc = &common->cc_survey;
20     unsigned int div = common->clockrate * 1000;
21+ int ret = 0;
22 
23     if (!ah->curchan)
24- return;
25+ return -1;
26 
27     if (ah->power_mode == ATH9K_PM_AWAKE)
28         ath_hw_cycle_counters_update(common);
29@@ -202,9 +208,18 @@ static void ath_update_survey_stats(stru
30         survey->channel_time_rx += cc->rx_frame / div;
31         survey->channel_time_tx += cc->tx_frame / div;
32     }
33+
34+ if (cc->cycles < div)
35+ return -1;
36+
37+ if (cc->cycles > 0)
38+ ret = cc->rx_busy * 100 / cc->cycles;
39+
40     memset(cc, 0, sizeof(*cc));
41 
42     ath_update_survey_nf(sc, pos);
43+
44+ return ret;
45 }
46 
47 /*
48@@ -226,6 +241,8 @@ int ath_set_channel(struct ath_softc *sc
49     if (sc->sc_flags & SC_OP_INVALID)
50         return -EIO;
51 
52+ sc->hw_busy_count = 0;
53+
54     del_timer_sync(&common->ani.timer);
55     cancel_work_sync(&sc->paprd_work);
56     cancel_work_sync(&sc->hw_check_work);
57@@ -584,17 +601,25 @@ static void ath_node_detach(struct ath_s
58 void ath_hw_check(struct work_struct *work)
59 {
60     struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
61- int i;
62+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
63+ unsigned long flags;
64+ int busy;
65 
66     ath9k_ps_wakeup(sc);
67+ if (ath9k_hw_check_alive(sc->sc_ah))
68+ goto out;
69 
70- for (i = 0; i < 3; i++) {
71- if (ath9k_hw_check_alive(sc->sc_ah))
72- goto out;
73+ spin_lock_irqsave(&common->cc_lock, flags);
74+ busy = ath_update_survey_stats(sc);
75+ spin_unlock_irqrestore(&common->cc_lock, flags);
76 
77- msleep(1);
78- }
79- ath_reset(sc, true);
80+ ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
81+ "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
82+ if (busy >= 99) {
83+ if (++sc->hw_busy_count >= 3)
84+ ath_reset(sc, true);
85+ } else if (busy >= 0)
86+ sc->hw_busy_count = 0;
87 
88 out:
89     ath9k_ps_restore(sc);
90@@ -988,6 +1013,8 @@ int ath_reset(struct ath_softc *sc, bool
91     struct ieee80211_hw *hw = sc->hw;
92     int r;
93 
94+ sc->hw_busy_count = 0;
95+
96     /* Stop ANI */
97     del_timer_sync(&common->ani.timer);
98 
99--- a/drivers/net/wireless/ath/ath9k/ath9k.h
100+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
101@@ -598,6 +598,8 @@ struct ath_softc {
102     struct completion paprd_complete;
103     bool paprd_pending;
104 
105+ unsigned int hw_busy_count;
106+
107     u32 intrstatus;
108     u32 sc_flags; /* SC_OP_* */
109     u16 ps_flags; /* PS_* */
110

Archive Download this file



interactive