ath9k: add a missing dma cache sync on aggregation software retry
[openwrt/staging/mkresin.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 @@ -595,74 +595,6 @@ static void ath_node_detach(struct ath_s
61 ath_tx_node_cleanup(sc, an);
62 }
63
64 -void ath_hw_check(struct work_struct *work)
65 -{
66 - struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
67 - struct ath_common *common = ath9k_hw_common(sc->sc_ah);
68 - unsigned long flags;
69 - int busy;
70 -
71 - ath9k_ps_wakeup(sc);
72 - if (ath9k_hw_check_alive(sc->sc_ah))
73 - goto out;
74 -
75 - spin_lock_irqsave(&common->cc_lock, flags);
76 - busy = ath_update_survey_stats(sc);
77 - spin_unlock_irqrestore(&common->cc_lock, flags);
78 -
79 - ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
80 - "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
81 - if (busy >= 99) {
82 - if (++sc->hw_busy_count >= 3) {
83 - spin_lock_bh(&sc->sc_pcu_lock);
84 - ath_reset(sc, true);
85 - spin_unlock_bh(&sc->sc_pcu_lock);
86 - }
87 - } else if (busy >= 0)
88 - sc->hw_busy_count = 0;
89 -
90 -out:
91 - ath9k_ps_restore(sc);
92 -}
93 -
94 -static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
95 -{
96 - static int count;
97 - struct ath_common *common = ath9k_hw_common(sc->sc_ah);
98 -
99 - if (pll_sqsum >= 0x40000) {
100 - count++;
101 - if (count == 3) {
102 - /* Rx is hung for more than 500ms. Reset it */
103 - ath_dbg(common, ATH_DBG_RESET,
104 - "Possible RX hang, resetting");
105 - spin_lock_bh(&sc->sc_pcu_lock);
106 - ath_reset(sc, true);
107 - spin_unlock_bh(&sc->sc_pcu_lock);
108 - count = 0;
109 - }
110 - } else
111 - count = 0;
112 -}
113 -
114 -void ath_hw_pll_work(struct work_struct *work)
115 -{
116 - struct ath_softc *sc = container_of(work, struct ath_softc,
117 - hw_pll_work.work);
118 - u32 pll_sqsum;
119 -
120 - if (AR_SREV_9485(sc->sc_ah)) {
121 -
122 - ath9k_ps_wakeup(sc);
123 - pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
124 - ath9k_ps_restore(sc);
125 -
126 - ath_hw_pll_rx_hang_check(sc, pll_sqsum);
127 -
128 - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
129 - }
130 -}
131 -
132
133 void ath9k_tasklet(unsigned long data)
134 {
135 @@ -675,9 +607,7 @@ void ath9k_tasklet(unsigned long data)
136
137 if ((status & ATH9K_INT_FATAL) ||
138 (status & ATH9K_INT_BB_WATCHDOG)) {
139 - spin_lock(&sc->sc_pcu_lock);
140 - ath_reset(sc, true);
141 - spin_unlock(&sc->sc_pcu_lock);
142 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
143 return;
144 }
145
146 @@ -968,13 +898,14 @@ void ath_radio_disable(struct ath_softc
147 ath9k_ps_restore(sc);
148 }
149
150 -int ath_reset(struct ath_softc *sc, bool retry_tx)
151 +static int ath_reset(struct ath_softc *sc, bool retry_tx)
152 {
153 struct ath_hw *ah = sc->sc_ah;
154 struct ath_common *common = ath9k_hw_common(ah);
155 struct ieee80211_hw *hw = sc->hw;
156 int r;
157
158 + sc->sc_flags &= ~SC_OP_HW_RESET;
159 sc->hw_busy_count = 0;
160
161 /* Stop ANI */
162 @@ -1035,6 +966,84 @@ int ath_reset(struct ath_softc *sc, bool
163 return r;
164 }
165
166 +void ath_reset_work(struct work_struct *work)
167 +{
168 + struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
169 +
170 + spin_lock_bh(&sc->sc_pcu_lock);
171 + ath_reset(sc, true);
172 + spin_unlock_bh(&sc->sc_pcu_lock);
173 +}
174 +
175 +void ath_hw_check(struct work_struct *work)
176 +{
177 + struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
178 + struct ath_common *common = ath9k_hw_common(sc->sc_ah);
179 + unsigned long flags;
180 + int busy;
181 +
182 + ath9k_ps_wakeup(sc);
183 + if (ath9k_hw_check_alive(sc->sc_ah))
184 + goto out;
185 +
186 + spin_lock_irqsave(&common->cc_lock, flags);
187 + busy = ath_update_survey_stats(sc);
188 + spin_unlock_irqrestore(&common->cc_lock, flags);
189 +
190 + ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
191 + "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
192 + if (busy >= 99) {
193 + if (++sc->hw_busy_count >= 3) {
194 + spin_lock_bh(&sc->sc_pcu_lock);
195 + ath_reset(sc, true);
196 + spin_unlock_bh(&sc->sc_pcu_lock);
197 + }
198 +
199 + } else if (busy >= 0)
200 + sc->hw_busy_count = 0;
201 +
202 +out:
203 + ath9k_ps_restore(sc);
204 +}
205 +
206 +static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
207 +{
208 + static int count;
209 + struct ath_common *common = ath9k_hw_common(sc->sc_ah);
210 +
211 + if (pll_sqsum >= 0x40000) {
212 + count++;
213 + if (count == 3) {
214 + /* Rx is hung for more than 500ms. Reset it */
215 + ath_dbg(common, ATH_DBG_RESET,
216 + "Possible RX hang, resetting");
217 + spin_lock_bh(&sc->sc_pcu_lock);
218 + ath_reset(sc, true);
219 + spin_unlock_bh(&sc->sc_pcu_lock);
220 + count = 0;
221 + }
222 + } else
223 + count = 0;
224 +}
225 +
226 +void ath_hw_pll_work(struct work_struct *work)
227 +{
228 + struct ath_softc *sc = container_of(work, struct ath_softc,
229 + hw_pll_work.work);
230 + u32 pll_sqsum;
231 +
232 + if (AR_SREV_9485(sc->sc_ah)) {
233 +
234 + ath9k_ps_wakeup(sc);
235 + pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
236 + ath9k_ps_restore(sc);
237 +
238 + ath_hw_pll_rx_hang_check(sc, pll_sqsum);
239 +
240 + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
241 + }
242 +}
243 +
244 /**********************/
245 /* mac80211 callbacks */
246 /**********************/
247 --- a/drivers/net/wireless/ath/ath9k/xmit.c
248 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
249 @@ -603,8 +603,10 @@ static void ath_tx_complete_aggr(struct
250
251 rcu_read_unlock();
252
253 - if (needreset)
254 - ath_reset(sc, false);
255 + if (needreset) {
256 + sc->sc_flags |= SC_OP_HW_RESET;
257 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
258 + }
259 }
260
261 static bool ath_lookup_legacy(struct ath_buf *bf)
262 @@ -2184,6 +2186,9 @@ static void ath_tx_processq(struct ath_s
263
264 spin_lock_bh(&txq->axq_lock);
265 for (;;) {
266 + if (sc->sc_flags & SC_OP_HW_RESET)
267 + break;
268 +
269 if (list_empty(&txq->axq_q)) {
270 txq->axq_link = NULL;
271 if (sc->sc_flags & SC_OP_TXAGGR)
272 @@ -2271,9 +2276,7 @@ static void ath_tx_complete_poll_work(st
273 if (needreset) {
274 ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
275 "tx hung, resetting the chip\n");
276 - spin_lock_bh(&sc->sc_pcu_lock);
277 - ath_reset(sc, true);
278 - spin_unlock_bh(&sc->sc_pcu_lock);
279 + ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
280 }
281
282 ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
283 @@ -2306,6 +2309,9 @@ void ath_tx_edma_tasklet(struct ath_soft
284 int status;
285
286 for (;;) {
287 + if (sc->sc_flags & SC_OP_HW_RESET)
288 + break;
289 +
290 status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
291 if (status == -EINPROGRESS)
292 break;