mac80211: improve minstrel_ht performance by ensuring that rates get sampled fast...
[oweals/openwrt.git] / 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,8 +309,8 @@ struct ath_rx {
4         u8 rxotherant;
5         u32 *rxlink;
6         unsigned int rxfilter;
7 -       spinlock_t rxflushlock;
8         spinlock_t rxbuflock;
9 +       spinlock_t pcu_lock;
10         struct list_head rxbuf;
11         struct ath_descdma rxdma;
12         struct ath_buf *rx_bufptr;
13 --- a/drivers/net/wireless/ath/ath9k/main.c
14 +++ b/drivers/net/wireless/ath/ath9k/main.c
15 @@ -239,6 +239,9 @@ int ath_set_channel(struct ath_softc *sc
16          */
17         ath9k_hw_disable_interrupts(ah);
18         ath_drain_all_txq(sc, false);
19 +
20 +       spin_lock_bh(&sc->rx.pcu_lock);
21 +
22         stopped = ath_stoprecv(sc);
23  
24         /* XXX: do not flush receive queue here. We don't want
25 @@ -266,6 +269,7 @@ int ath_set_channel(struct ath_softc *sc
26                           "reset status %d\n",
27                           channel->center_freq, r);
28                 spin_unlock_bh(&sc->sc_resetlock);
29 +               spin_unlock_bh(&sc->rx.pcu_lock);
30                 goto ps_restore;
31         }
32         spin_unlock_bh(&sc->sc_resetlock);
33 @@ -274,9 +278,12 @@ int ath_set_channel(struct ath_softc *sc
34                 ath_print(common, ATH_DBG_FATAL,
35                           "Unable to restart recv logic\n");
36                 r = -EIO;
37 +               spin_unlock_bh(&sc->rx.pcu_lock);
38                 goto ps_restore;
39         }
40  
41 +       spin_unlock_bh(&sc->rx.pcu_lock);
42 +
43         ath_update_txpow(sc);
44         ath9k_hw_set_interrupts(ah, ah->imask);
45  
46 @@ -610,7 +617,7 @@ void ath9k_tasklet(unsigned long data)
47                 rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
48  
49         if (status & rxmask) {
50 -               spin_lock_bh(&sc->rx.rxflushlock);
51 +               spin_lock_bh(&sc->rx.pcu_lock);
52  
53                 /* Check for high priority Rx first */
54                 if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
55 @@ -618,7 +625,7 @@ void ath9k_tasklet(unsigned long data)
56                         ath_rx_tasklet(sc, 0, true);
57  
58                 ath_rx_tasklet(sc, 0, false);
59 -               spin_unlock_bh(&sc->rx.rxflushlock);
60 +               spin_unlock_bh(&sc->rx.pcu_lock);
61         }
62  
63         if (status & ATH9K_INT_TX) {
64 @@ -876,6 +883,7 @@ void ath_radio_enable(struct ath_softc *
65         if (!ah->curchan)
66                 ah->curchan = ath_get_curchannel(sc, sc->hw);
67  
68 +       spin_lock_bh(&sc->rx.pcu_lock);
69         spin_lock_bh(&sc->sc_resetlock);
70         r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
71         if (r) {
72 @@ -890,8 +898,10 @@ void ath_radio_enable(struct ath_softc *
73         if (ath_startrecv(sc) != 0) {
74                 ath_print(common, ATH_DBG_FATAL,
75                           "Unable to restart recv logic\n");
76 +               spin_unlock_bh(&sc->rx.pcu_lock);
77                 return;
78         }
79 +       spin_unlock_bh(&sc->rx.pcu_lock);
80  
81         if (sc->sc_flags & SC_OP_BEACONS)
82                 ath_beacon_config(sc, NULL);    /* restart beacons */
83 @@ -930,6 +940,9 @@ void ath_radio_disable(struct ath_softc 
84         ath9k_hw_disable_interrupts(ah);
85  
86         ath_drain_all_txq(sc, false);   /* clear pending tx frames */
87 +
88 +       spin_lock_bh(&sc->rx.pcu_lock);
89 +
90         ath_stoprecv(sc);               /* turn off frame recv */
91         ath_flushrecv(sc);              /* flush recv queue */
92  
93 @@ -947,6 +960,9 @@ void ath_radio_disable(struct ath_softc 
94         spin_unlock_bh(&sc->sc_resetlock);
95  
96         ath9k_hw_phy_disable(ah);
97 +
98 +       spin_unlock_bh(&sc->rx.pcu_lock);
99 +
100         ath9k_hw_configpcipowersave(ah, 1, 1);
101         ath9k_ps_restore(sc);
102         ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
103 @@ -966,6 +982,9 @@ int ath_reset(struct ath_softc *sc, bool
104  
105         ath9k_hw_disable_interrupts(ah);
106         ath_drain_all_txq(sc, retry_tx);
107 +
108 +       spin_lock_bh(&sc->rx.pcu_lock);
109 +
110         ath_stoprecv(sc);
111         ath_flushrecv(sc);
112  
113 @@ -980,6 +999,8 @@ int ath_reset(struct ath_softc *sc, bool
114                 ath_print(common, ATH_DBG_FATAL,
115                           "Unable to start recv logic\n");
116  
117 +       spin_unlock_bh(&sc->rx.pcu_lock);
118 +
119         /*
120          * We may be doing a reset in response to a request
121          * that changes the channel so update any state that
122 @@ -1142,6 +1163,7 @@ static int ath9k_start(struct ieee80211_
123          * be followed by initialization of the appropriate bits
124          * and then setup of the interrupt mask.
125          */
126 +       spin_lock_bh(&sc->rx.pcu_lock);
127         spin_lock_bh(&sc->sc_resetlock);
128         r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
129         if (r) {
130 @@ -1150,6 +1172,7 @@ static int ath9k_start(struct ieee80211_
131                           "(freq %u MHz)\n", r,
132                           curchan->center_freq);
133                 spin_unlock_bh(&sc->sc_resetlock);
134 +               spin_unlock_bh(&sc->rx.pcu_lock);
135                 goto mutex_unlock;
136         }
137         spin_unlock_bh(&sc->sc_resetlock);
138 @@ -1171,8 +1194,10 @@ static int ath9k_start(struct ieee80211_
139                 ath_print(common, ATH_DBG_FATAL,
140                           "Unable to start recv logic\n");
141                 r = -EIO;
142 +               spin_unlock_bh(&sc->rx.pcu_lock);
143                 goto mutex_unlock;
144         }
145 +       spin_unlock_bh(&sc->rx.pcu_lock);
146  
147         /* Setup our intr mask. */
148         ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
149 @@ -1371,12 +1396,14 @@ static void ath9k_stop(struct ieee80211_
150          * before setting the invalid flag. */
151         ath9k_hw_disable_interrupts(ah);
152  
153 +       spin_lock_bh(&sc->rx.pcu_lock);
154         if (!(sc->sc_flags & SC_OP_INVALID)) {
155                 ath_drain_all_txq(sc, false);
156                 ath_stoprecv(sc);
157                 ath9k_hw_phy_disable(ah);
158         } else
159                 sc->rx.rxlink = NULL;
160 +       spin_unlock_bh(&sc->rx.pcu_lock);
161  
162         /* disable HAL and put h/w to sleep */
163         ath9k_hw_disable(ah);
164 --- a/drivers/net/wireless/ath/ath9k/recv.c
165 +++ b/drivers/net/wireless/ath/ath9k/recv.c
166 @@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct a
167         ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
168                               sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
169  
170 -       spin_unlock_bh(&sc->rx.rxbuflock);
171 -
172         ath_opmode_init(sc);
173  
174         ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
175 +
176 +       spin_unlock_bh(&sc->rx.rxbuflock);
177  }
178  
179  static void ath_edma_stop_recv(struct ath_softc *sc)
180  {
181 -       spin_lock_bh(&sc->rx.rxbuflock);
182         ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
183         ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
184 -       spin_unlock_bh(&sc->rx.rxbuflock);
185  }
186  
187  int ath_rx_init(struct ath_softc *sc, int nbufs)
188 @@ -319,8 +317,8 @@ int ath_rx_init(struct ath_softc *sc, in
189         struct ath_buf *bf;
190         int error = 0;
191  
192 -       spin_lock_init(&sc->rx.rxflushlock);
193         sc->sc_flags &= ~SC_OP_RXFLUSH;
194 +       spin_lock_init(&sc->rx.pcu_lock);
195         spin_lock_init(&sc->rx.rxbuflock);
196  
197         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
198 @@ -506,9 +504,9 @@ int ath_startrecv(struct ath_softc *sc)
199         ath9k_hw_rxena(ah);
200  
201  start_recv:
202 -       spin_unlock_bh(&sc->rx.rxbuflock);
203         ath_opmode_init(sc);
204         ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
205 +       spin_unlock_bh(&sc->rx.rxbuflock);
206  
207         return 0;
208  }
209 @@ -518,6 +516,7 @@ bool ath_stoprecv(struct ath_softc *sc)
210         struct ath_hw *ah = sc->sc_ah;
211         bool stopped;
212  
213 +       spin_lock_bh(&sc->rx.rxbuflock);
214         ath9k_hw_stoppcurecv(ah);
215         ath9k_hw_setrxfilter(ah, 0);
216         stopped = ath9k_hw_stopdmarecv(ah);
217 @@ -526,19 +525,18 @@ bool ath_stoprecv(struct ath_softc *sc)
218                 ath_edma_stop_recv(sc);
219         else
220                 sc->rx.rxlink = NULL;
221 +       spin_unlock_bh(&sc->rx.rxbuflock);
222  
223         return stopped;
224  }
225  
226  void ath_flushrecv(struct ath_softc *sc)
227  {
228 -       spin_lock_bh(&sc->rx.rxflushlock);
229         sc->sc_flags |= SC_OP_RXFLUSH;
230         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
231                 ath_rx_tasklet(sc, 1, true);
232         ath_rx_tasklet(sc, 1, false);
233         sc->sc_flags &= ~SC_OP_RXFLUSH;
234 -       spin_unlock_bh(&sc->rx.rxflushlock);
235  }
236  
237  static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)