Root/package/mac80211/patches/530-ath9k_locking_fix.patch

1--- a/drivers/net/wireless/ath/ath9k/ath9k.h
2+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3@@ -309,7 +309,6 @@ struct ath_rx {
4     u8 rxotherant;
5     u32 *rxlink;
6     unsigned int rxfilter;
7- spinlock_t rxflushlock;
8     spinlock_t rxbuflock;
9     struct list_head rxbuf;
10     struct ath_descdma rxdma;
11@@ -600,9 +599,9 @@ struct ath_softc {
12     struct ath_hw *sc_ah;
13     void __iomem *mem;
14     int irq;
15- spinlock_t sc_resetlock;
16     spinlock_t sc_serial_rw;
17     spinlock_t sc_pm_lock;
18+ spinlock_t sc_pcu_lock;
19     struct mutex mutex;
20     struct work_struct paprd_work;
21     struct work_struct hw_check_work;
22--- a/drivers/net/wireless/ath/ath9k/main.c
23+++ b/drivers/net/wireless/ath/ath9k/main.c
24@@ -228,6 +228,8 @@ int ath_set_channel(struct ath_softc *sc
25 
26     ath9k_ps_wakeup(sc);
27 
28+ spin_lock_bh(&sc->sc_pcu_lock);
29+
30     /*
31      * This is only performed if the channel settings have
32      * actually changed.
33@@ -239,6 +241,7 @@ int ath_set_channel(struct ath_softc *sc
34      */
35     ath9k_hw_disable_interrupts(ah);
36     ath_drain_all_txq(sc, false);
37+
38     stopped = ath_stoprecv(sc);
39 
40     /* XXX: do not flush receive queue here. We don't want
41@@ -257,18 +260,14 @@ int ath_set_channel(struct ath_softc *sc
42           channel->center_freq, conf_is_ht40(conf),
43           fastcc);
44 
45- spin_lock_bh(&sc->sc_resetlock);
46-
47     r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
48     if (r) {
49         ath_print(common, ATH_DBG_FATAL,
50               "Unable to reset channel (%u MHz), "
51               "reset status %d\n",
52               channel->center_freq, r);
53- spin_unlock_bh(&sc->sc_resetlock);
54         goto ps_restore;
55     }
56- spin_unlock_bh(&sc->sc_resetlock);
57 
58     if (ath_startrecv(sc) != 0) {
59         ath_print(common, ATH_DBG_FATAL,
60@@ -287,6 +286,8 @@ int ath_set_channel(struct ath_softc *sc
61     }
62 
63  ps_restore:
64+ spin_unlock_bh(&sc->sc_pcu_lock);
65+
66     ath9k_ps_restore(sc);
67     return r;
68 }
69@@ -600,6 +601,8 @@ void ath9k_tasklet(unsigned long data)
70         return;
71     }
72 
73+ spin_lock_bh(&sc->sc_pcu_lock);
74+
75     if (!ath9k_hw_check_alive(ah))
76         ieee80211_queue_work(sc->hw, &sc->hw_check_work);
77 
78@@ -610,15 +613,12 @@ void ath9k_tasklet(unsigned long data)
79         rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
80 
81     if (status & rxmask) {
82- spin_lock_bh(&sc->rx.rxflushlock);
83-
84         /* Check for high priority Rx first */
85         if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
86             (status & ATH9K_INT_RXHP))
87             ath_rx_tasklet(sc, 0, true);
88 
89         ath_rx_tasklet(sc, 0, false);
90- spin_unlock_bh(&sc->rx.rxflushlock);
91     }
92 
93     if (status & ATH9K_INT_TX) {
94@@ -644,6 +644,8 @@ void ath9k_tasklet(unsigned long data)
95 
96     /* re-enable hardware interrupt */
97     ath9k_hw_enable_interrupts(ah);
98+
99+ spin_unlock_bh(&sc->sc_pcu_lock);
100     ath9k_ps_restore(sc);
101 }
102 
103@@ -871,12 +873,13 @@ void ath_radio_enable(struct ath_softc *
104     int r;
105 
106     ath9k_ps_wakeup(sc);
107+ spin_lock_bh(&sc->sc_pcu_lock);
108+
109     ath9k_hw_configpcipowersave(ah, 0, 0);
110 
111     if (!ah->curchan)
112         ah->curchan = ath_get_curchannel(sc, sc->hw);
113 
114- spin_lock_bh(&sc->sc_resetlock);
115     r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
116     if (r) {
117         ath_print(common, ATH_DBG_FATAL,
118@@ -884,15 +887,14 @@ void ath_radio_enable(struct ath_softc *
119               "reset status %d\n",
120               channel->center_freq, r);
121     }
122- spin_unlock_bh(&sc->sc_resetlock);
123 
124     ath_update_txpow(sc);
125     if (ath_startrecv(sc) != 0) {
126         ath_print(common, ATH_DBG_FATAL,
127               "Unable to restart recv logic\n");
128+ spin_unlock_bh(&sc->sc_pcu_lock);
129         return;
130     }
131-
132     if (sc->sc_flags & SC_OP_BEACONS)
133         ath_beacon_config(sc, NULL); /* restart beacons */
134 
135@@ -905,6 +907,8 @@ void ath_radio_enable(struct ath_softc *
136     ath9k_hw_set_gpio(ah, ah->led_pin, 0);
137 
138     ieee80211_wake_queues(hw);
139+ spin_unlock_bh(&sc->sc_pcu_lock);
140+
141     ath9k_ps_restore(sc);
142 }
143 
144@@ -915,6 +919,8 @@ void ath_radio_disable(struct ath_softc
145     int r;
146 
147     ath9k_ps_wakeup(sc);
148+ spin_lock_bh(&sc->sc_pcu_lock);
149+
150     ieee80211_stop_queues(hw);
151 
152     /*
153@@ -930,13 +936,13 @@ void ath_radio_disable(struct ath_softc
154     ath9k_hw_disable_interrupts(ah);
155 
156     ath_drain_all_txq(sc, false); /* clear pending tx frames */
157+
158     ath_stoprecv(sc); /* turn off frame recv */
159     ath_flushrecv(sc); /* flush recv queue */
160 
161     if (!ah->curchan)
162         ah->curchan = ath_get_curchannel(sc, hw);
163 
164- spin_lock_bh(&sc->sc_resetlock);
165     r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
166     if (r) {
167         ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
168@@ -944,11 +950,14 @@ void ath_radio_disable(struct ath_softc
169               "reset status %d\n",
170               channel->center_freq, r);
171     }
172- spin_unlock_bh(&sc->sc_resetlock);
173 
174     ath9k_hw_phy_disable(ah);
175+
176     ath9k_hw_configpcipowersave(ah, 1, 1);
177+
178+ spin_unlock_bh(&sc->sc_pcu_lock);
179     ath9k_ps_restore(sc);
180+
181     ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
182 }
183 
184@@ -962,19 +971,20 @@ int ath_reset(struct ath_softc *sc, bool
185     /* Stop ANI */
186     del_timer_sync(&common->ani.timer);
187 
188+ spin_lock_bh(&sc->sc_pcu_lock);
189+
190     ieee80211_stop_queues(hw);
191 
192     ath9k_hw_disable_interrupts(ah);
193     ath_drain_all_txq(sc, retry_tx);
194+
195     ath_stoprecv(sc);
196     ath_flushrecv(sc);
197 
198- spin_lock_bh(&sc->sc_resetlock);
199     r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
200     if (r)
201         ath_print(common, ATH_DBG_FATAL,
202               "Unable to reset hardware; reset status %d\n", r);
203- spin_unlock_bh(&sc->sc_resetlock);
204 
205     if (ath_startrecv(sc) != 0)
206         ath_print(common, ATH_DBG_FATAL,
207@@ -1004,6 +1014,7 @@ int ath_reset(struct ath_softc *sc, bool
208     }
209 
210     ieee80211_wake_queues(hw);
211+ spin_unlock_bh(&sc->sc_pcu_lock);
212 
213     /* Start ANI */
214     ath_start_ani(common);
215@@ -1142,17 +1153,16 @@ static int ath9k_start(struct ieee80211_
216      * be followed by initialization of the appropriate bits
217      * and then setup of the interrupt mask.
218      */
219- spin_lock_bh(&sc->sc_resetlock);
220+ spin_lock_bh(&sc->sc_pcu_lock);
221     r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
222     if (r) {
223         ath_print(common, ATH_DBG_FATAL,
224               "Unable to reset hardware; reset status %d "
225               "(freq %u MHz)\n", r,
226               curchan->center_freq);
227- spin_unlock_bh(&sc->sc_resetlock);
228+ spin_unlock_bh(&sc->sc_pcu_lock);
229         goto mutex_unlock;
230     }
231- spin_unlock_bh(&sc->sc_resetlock);
232 
233     /*
234      * This is needed only to setup initial state
235@@ -1171,8 +1181,10 @@ static int ath9k_start(struct ieee80211_
236         ath_print(common, ATH_DBG_FATAL,
237               "Unable to start recv logic\n");
238         r = -EIO;
239+ spin_unlock_bh(&sc->sc_pcu_lock);
240         goto mutex_unlock;
241     }
242+ spin_unlock_bh(&sc->sc_pcu_lock);
243 
244     /* Setup our intr mask. */
245     ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
246@@ -1367,6 +1379,8 @@ static void ath9k_stop(struct ieee80211_
247             ath9k_btcoex_timer_pause(sc);
248     }
249 
250+ spin_lock_bh(&sc->sc_pcu_lock);
251+
252     /* make sure h/w will not generate any interrupt
253      * before setting the invalid flag. */
254     ath9k_hw_disable_interrupts(ah);
255@@ -1381,6 +1395,9 @@ static void ath9k_stop(struct ieee80211_
256     /* disable HAL and put h/w to sleep */
257     ath9k_hw_disable(ah);
258     ath9k_hw_configpcipowersave(ah, 1, 1);
259+
260+ spin_unlock_bh(&sc->sc_pcu_lock);
261+
262     ath9k_ps_restore(sc);
263 
264     /* Finally, put the chip in FULL SLEEP mode */
265--- a/drivers/net/wireless/ath/ath9k/recv.c
266+++ b/drivers/net/wireless/ath/ath9k/recv.c
267@@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct a
268     ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
269                   sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
270 
271- spin_unlock_bh(&sc->rx.rxbuflock);
272-
273     ath_opmode_init(sc);
274 
275     ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
276+
277+ spin_unlock_bh(&sc->rx.rxbuflock);
278 }
279 
280 static void ath_edma_stop_recv(struct ath_softc *sc)
281 {
282- spin_lock_bh(&sc->rx.rxbuflock);
283     ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
284     ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
285- spin_unlock_bh(&sc->rx.rxbuflock);
286 }
287 
288 int ath_rx_init(struct ath_softc *sc, int nbufs)
289@@ -319,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, in
290     struct ath_buf *bf;
291     int error = 0;
292 
293- spin_lock_init(&sc->rx.rxflushlock);
294+ spin_lock_init(&sc->sc_pcu_lock);
295     sc->sc_flags &= ~SC_OP_RXFLUSH;
296     spin_lock_init(&sc->rx.rxbuflock);
297 
298@@ -506,9 +504,9 @@ int ath_startrecv(struct ath_softc *sc)
299     ath9k_hw_rxena(ah);
300 
301 start_recv:
302- spin_unlock_bh(&sc->rx.rxbuflock);
303     ath_opmode_init(sc);
304     ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
305+ spin_unlock_bh(&sc->rx.rxbuflock);
306 
307     return 0;
308 }
309@@ -518,6 +516,7 @@ bool ath_stoprecv(struct ath_softc *sc)
310     struct ath_hw *ah = sc->sc_ah;
311     bool stopped;
312 
313+ spin_lock_bh(&sc->rx.rxbuflock);
314     ath9k_hw_stoppcurecv(ah);
315     ath9k_hw_setrxfilter(ah, 0);
316     stopped = ath9k_hw_stopdmarecv(ah);
317@@ -526,19 +525,18 @@ bool ath_stoprecv(struct ath_softc *sc)
318         ath_edma_stop_recv(sc);
319     else
320         sc->rx.rxlink = NULL;
321+ spin_unlock_bh(&sc->rx.rxbuflock);
322 
323     return stopped;
324 }
325 
326 void ath_flushrecv(struct ath_softc *sc)
327 {
328- spin_lock_bh(&sc->rx.rxflushlock);
329     sc->sc_flags |= SC_OP_RXFLUSH;
330     if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
331         ath_rx_tasklet(sc, 1, true);
332     ath_rx_tasklet(sc, 1, false);
333     sc->sc_flags &= ~SC_OP_RXFLUSH;
334- spin_unlock_bh(&sc->rx.rxflushlock);
335 }
336 
337 static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
338--- a/drivers/net/wireless/ath/ath9k/init.c
339+++ b/drivers/net/wireless/ath/ath9k/init.c
340@@ -588,7 +588,6 @@ static int ath9k_init_softc(u16 devid, s
341     spin_lock_init(&common->cc_lock);
342 
343     spin_lock_init(&sc->wiphy_lock);
344- spin_lock_init(&sc->sc_resetlock);
345     spin_lock_init(&sc->sc_serial_rw);
346     spin_lock_init(&sc->sc_pm_lock);
347     mutex_init(&sc->mutex);
348--- a/drivers/net/wireless/ath/ath9k/xmit.c
349+++ b/drivers/net/wireless/ath/ath9k/xmit.c
350@@ -1142,13 +1142,11 @@ void ath_drain_all_txq(struct ath_softc
351         ath_print(common, ATH_DBG_FATAL,
352               "Failed to stop TX DMA. Resetting hardware!\n");
353 
354- spin_lock_bh(&sc->sc_resetlock);
355         r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
356         if (r)
357             ath_print(common, ATH_DBG_FATAL,
358                   "Unable to reset hardware; reset status %d\n",
359                   r);
360- spin_unlock_bh(&sc->sc_resetlock);
361     }
362 
363     for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
364

Archive Download this file



interactive