7836718bbd7bcc523c402d7473f38d9f4df86eb8
[10.03/openwrt.git] / package / mac80211 / patches / 581-ath9k_use_reset_work.patch
1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -429,6 +429,7 @@ void ath9k_set_beaconing_status(struct a
4  
5  #define ATH_PAPRD_TIMEOUT      100 /* msecs */
6  
7 +void ath_reset_work(struct work_struct *work);
8  void ath_hw_check(struct work_struct *work);
9  void ath_hw_pll_work(struct work_struct *work);
10  void ath_paprd_calibrate(struct work_struct *work);
11 @@ -559,6 +560,7 @@ struct ath_ant_comb {
12  #define SC_OP_RXFLUSH                BIT(7)
13  #define SC_OP_LED_ASSOCIATED         BIT(8)
14  #define SC_OP_LED_ON                 BIT(9)
15 +#define SC_OP_HW_RESET               BIT(10)
16  #define SC_OP_TSF_RESET              BIT(11)
17  #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
18  #define SC_OP_BT_SCAN               BIT(13)
19 @@ -609,6 +611,7 @@ struct ath_softc {
20         struct mutex mutex;
21         struct work_struct paprd_work;
22         struct work_struct hw_check_work;
23 +       struct work_struct hw_reset_work;
24         struct completion paprd_complete;
25  
26         unsigned int hw_busy_count;
27 @@ -655,7 +658,6 @@ struct ath_softc {
28  };
29  
30  void ath9k_tasklet(unsigned long data);
31 -int ath_reset(struct ath_softc *sc, bool retry_tx);
32  int ath_cabq_update(struct ath_softc *);
33  
34  static inline void ath_read_cachesize(struct ath_common *common, int *csz)
35 --- a/drivers/net/wireless/ath/ath9k/beacon.c
36 +++ b/drivers/net/wireless/ath/ath9k/beacon.c
37 @@ -386,9 +386,7 @@ void ath_beacon_tasklet(unsigned long da
38                         ath_dbg(common, ATH_DBG_BSTUCK,
39                                 "beacon is officially stuck\n");
40                         sc->sc_flags |= SC_OP_TSF_RESET;
41 -                       spin_lock(&sc->sc_pcu_lock);
42 -                       ath_reset(sc, true);
43 -                       spin_unlock(&sc->sc_pcu_lock);
44 +                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
45                 }
46  
47                 return;
48 --- a/drivers/net/wireless/ath/ath9k/init.c
49 +++ b/drivers/net/wireless/ath/ath9k/init.c
50 @@ -776,6 +776,7 @@ int ath9k_init_device(u16 devid, struct 
51                         goto error_world;
52         }
53  
54 +       INIT_WORK(&sc->hw_reset_work, ath_reset_work);
55         INIT_WORK(&sc->hw_check_work, ath_hw_check);
56         INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
57         INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
58 --- a/drivers/net/wireless/ath/ath9k/main.c
59 +++ b/drivers/net/wireless/ath/ath9k/main.c
60 @@ -236,6 +236,7 @@ static int ath_set_channel(struct ath_so
61         del_timer_sync(&common->ani.timer);
62         cancel_work_sync(&sc->paprd_work);
63         cancel_work_sync(&sc->hw_check_work);
64 +       cancel_work_sync(&sc->hw_reset_work);
65         cancel_delayed_work_sync(&sc->tx_complete_work);
66         cancel_delayed_work_sync(&sc->hw_pll_work);
67  
68 @@ -595,74 +596,6 @@ static void ath_node_detach(struct ath_s
69                 ath_tx_node_cleanup(sc, an);
70  }
71  
72 -void ath_hw_check(struct work_struct *work)
73 -{
74 -       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
75 -       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
76 -       unsigned long flags;
77 -       int busy;
78 -
79 -       ath9k_ps_wakeup(sc);
80 -       if (ath9k_hw_check_alive(sc->sc_ah))
81 -               goto out;
82 -
83 -       spin_lock_irqsave(&common->cc_lock, flags);
84 -       busy = ath_update_survey_stats(sc);
85 -       spin_unlock_irqrestore(&common->cc_lock, flags);
86 -
87 -       ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
88 -               "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
89 -       if (busy >= 99) {
90 -               if (++sc->hw_busy_count >= 3) {
91 -                       spin_lock_bh(&sc->sc_pcu_lock);
92 -                       ath_reset(sc, true);
93 -                       spin_unlock_bh(&sc->sc_pcu_lock);
94 -               }
95 -       } else if (busy >= 0)
96 -               sc->hw_busy_count = 0;
97 -
98 -out:
99 -       ath9k_ps_restore(sc);
100 -}
101 -
102 -static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
103 -{
104 -       static int count;
105 -       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
106 -
107 -       if (pll_sqsum >= 0x40000) {
108 -               count++;
109 -               if (count == 3) {
110 -                       /* Rx is hung for more than 500ms. Reset it */
111 -                       ath_dbg(common, ATH_DBG_RESET,
112 -                               "Possible RX hang, resetting");
113 -                       spin_lock_bh(&sc->sc_pcu_lock);
114 -                       ath_reset(sc, true);
115 -                       spin_unlock_bh(&sc->sc_pcu_lock);
116 -                       count = 0;
117 -               }
118 -       } else
119 -               count = 0;
120 -}
121 -
122 -void ath_hw_pll_work(struct work_struct *work)
123 -{
124 -       struct ath_softc *sc = container_of(work, struct ath_softc,
125 -                                           hw_pll_work.work);
126 -       u32 pll_sqsum;
127 -
128 -       if (AR_SREV_9485(sc->sc_ah)) {
129 -
130 -               ath9k_ps_wakeup(sc);
131 -               pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
132 -               ath9k_ps_restore(sc);
133 -
134 -               ath_hw_pll_rx_hang_check(sc, pll_sqsum);
135 -
136 -               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
137 -       }
138 -}
139 -
140  
141  void ath9k_tasklet(unsigned long data)
142  {
143 @@ -675,9 +608,7 @@ void ath9k_tasklet(unsigned long data)
144  
145         if ((status & ATH9K_INT_FATAL) ||
146             (status & ATH9K_INT_BB_WATCHDOG)) {
147 -               spin_lock(&sc->sc_pcu_lock);
148 -               ath_reset(sc, true);
149 -               spin_unlock(&sc->sc_pcu_lock);
150 +               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
151                 return;
152         }
153  
154 @@ -968,13 +899,14 @@ void ath_radio_disable(struct ath_softc 
155         ath9k_ps_restore(sc);
156  }
157  
158 -int ath_reset(struct ath_softc *sc, bool retry_tx)
159 +static int ath_reset(struct ath_softc *sc, bool retry_tx)
160  {
161         struct ath_hw *ah = sc->sc_ah;
162         struct ath_common *common = ath9k_hw_common(ah);
163         struct ieee80211_hw *hw = sc->hw;
164         int r;
165  
166 +       sc->sc_flags &= ~SC_OP_HW_RESET;
167         sc->hw_busy_count = 0;
168  
169         /* Stop ANI */
170 @@ -1035,6 +967,84 @@ int ath_reset(struct ath_softc *sc, bool
171         return r;
172  }
173  
174 +void ath_reset_work(struct work_struct *work)
175 +{
176 +       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
177 +
178 +       spin_lock_bh(&sc->sc_pcu_lock);
179 +       ath_reset(sc, true);
180 +       spin_unlock_bh(&sc->sc_pcu_lock);
181 +}
182 +
183 +void ath_hw_check(struct work_struct *work)
184 +{
185 +       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
186 +       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
187 +       unsigned long flags;
188 +       int busy;
189 +
190 +       ath9k_ps_wakeup(sc);
191 +       if (ath9k_hw_check_alive(sc->sc_ah))
192 +               goto out;
193 +
194 +       spin_lock_irqsave(&common->cc_lock, flags);
195 +       busy = ath_update_survey_stats(sc);
196 +       spin_unlock_irqrestore(&common->cc_lock, flags);
197 +
198 +       ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
199 +               "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
200 +       if (busy >= 99) {
201 +               if (++sc->hw_busy_count >= 3) {
202 +                       spin_lock_bh(&sc->sc_pcu_lock);
203 +                       ath_reset(sc, true);
204 +                       spin_unlock_bh(&sc->sc_pcu_lock);
205 +               }
206 +
207 +       } else if (busy >= 0)
208 +               sc->hw_busy_count = 0;
209 +
210 +out:
211 +       ath9k_ps_restore(sc);
212 +}
213 +
214 +static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
215 +{
216 +       static int count;
217 +       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
218 +
219 +       if (pll_sqsum >= 0x40000) {
220 +               count++;
221 +               if (count == 3) {
222 +                       /* Rx is hung for more than 500ms. Reset it */
223 +                       ath_dbg(common, ATH_DBG_RESET,
224 +                               "Possible RX hang, resetting");
225 +                       spin_lock_bh(&sc->sc_pcu_lock);
226 +                       ath_reset(sc, true);
227 +                       spin_unlock_bh(&sc->sc_pcu_lock);
228 +                       count = 0;
229 +               }
230 +       } else
231 +               count = 0;
232 +}
233 +
234 +void ath_hw_pll_work(struct work_struct *work)
235 +{
236 +       struct ath_softc *sc = container_of(work, struct ath_softc,
237 +                                           hw_pll_work.work);
238 +       u32 pll_sqsum;
239 +
240 +       if (AR_SREV_9485(sc->sc_ah)) {
241 +
242 +               ath9k_ps_wakeup(sc);
243 +               pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
244 +               ath9k_ps_restore(sc);
245 +
246 +               ath_hw_pll_rx_hang_check(sc, pll_sqsum);
247 +
248 +               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
249 +       }
250 +}
251 +
252  /**********************/
253  /* mac80211 callbacks */
254  /**********************/
255 @@ -1227,6 +1237,7 @@ static void ath9k_stop(struct ieee80211_
256         cancel_delayed_work_sync(&sc->hw_pll_work);
257         cancel_work_sync(&sc->paprd_work);
258         cancel_work_sync(&sc->hw_check_work);
259 +       cancel_work_sync(&sc->hw_reset_work);
260  
261         if (sc->sc_flags & SC_OP_INVALID) {
262                 ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
263 --- a/drivers/net/wireless/ath/ath9k/xmit.c
264 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
265 @@ -603,8 +603,10 @@ static void ath_tx_complete_aggr(struct 
266  
267         rcu_read_unlock();
268  
269 -       if (needreset)
270 -               ath_reset(sc, false);
271 +       if (needreset) {
272 +               sc->sc_flags |= SC_OP_HW_RESET;
273 +               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
274 +       }
275  }
276  
277  static bool ath_lookup_legacy(struct ath_buf *bf)
278 @@ -1357,7 +1359,7 @@ void ath_txq_schedule(struct ath_softc *
279         struct ath_atx_ac *ac, *ac_tmp, *last_ac;
280         struct ath_atx_tid *tid, *last_tid;
281  
282 -       if (list_empty(&txq->axq_acq) ||
283 +       if ((sc->sc_flags & SC_OP_HW_RESET) || list_empty(&txq->axq_acq) ||
284             txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
285                 return;
286  
287 @@ -2184,6 +2186,9 @@ static void ath_tx_processq(struct ath_s
288  
289         spin_lock_bh(&txq->axq_lock);
290         for (;;) {
291 +               if (sc->sc_flags & SC_OP_HW_RESET)
292 +                       break;
293 +
294                 if (list_empty(&txq->axq_q)) {
295                         txq->axq_link = NULL;
296                         if (sc->sc_flags & SC_OP_TXAGGR)
297 @@ -2271,9 +2276,7 @@ static void ath_tx_complete_poll_work(st
298         if (needreset) {
299                 ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
300                         "tx hung, resetting the chip\n");
301 -               spin_lock_bh(&sc->sc_pcu_lock);
302 -               ath_reset(sc, true);
303 -               spin_unlock_bh(&sc->sc_pcu_lock);
304 +               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
305         }
306  
307         ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
308 @@ -2306,6 +2309,9 @@ void ath_tx_edma_tasklet(struct ath_soft
309         int status;
310  
311         for (;;) {
312 +               if (sc->sc_flags & SC_OP_HW_RESET)
313 +                       break;
314 +
315                 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
316                 if (status == -EINPROGRESS)
317                         break;