mac80211: update to wireless-testing 2011-05-27
[openwrt.git] / package / mac80211 / patches / 300-pending_work.patch
1 --- a/drivers/net/wireless/ath/ath9k/hw.h
2 +++ b/drivers/net/wireless/ath/ath9k/hw.h
3 @@ -603,7 +603,6 @@ struct ath_hw_ops {
4                                      int power_off);
5         void (*rx_enable)(struct ath_hw *ah);
6         void (*set_desc_link)(void *ds, u32 link);
7 -       void (*get_desc_link)(void *ds, u32 **link);
8         bool (*calibrate)(struct ath_hw *ah,
9                           struct ath9k_channel *chan,
10                           u8 rxchainmask,
11 --- a/drivers/net/wireless/ath/ath9k/main.c
12 +++ b/drivers/net/wireless/ath/ath9k/main.c
13 @@ -62,8 +62,6 @@ static bool ath9k_has_pending_frames(str
14  
15         if (txq->axq_depth || !list_empty(&txq->axq_acq))
16                 pending = true;
17 -       else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
18 -               pending = !list_empty(&txq->txq_fifo_pending);
19  
20         spin_unlock_bh(&txq->axq_lock);
21         return pending;
22 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
23 +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
24 @@ -28,11 +28,6 @@ static void ar9002_hw_set_desc_link(void
25         ((struct ath_desc*) ds)->ds_link = ds_link;
26  }
27  
28 -static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
29 -{
30 -       *ds_link = &((struct ath_desc *)ds)->ds_link;
31 -}
32 -
33  static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
34  {
35         u32 isr = 0;
36 @@ -437,7 +432,6 @@ void ar9002_hw_attach_mac_ops(struct ath
37  
38         ops->rx_enable = ar9002_hw_rx_enable;
39         ops->set_desc_link = ar9002_hw_set_desc_link;
40 -       ops->get_desc_link = ar9002_hw_get_desc_link;
41         ops->get_isr = ar9002_hw_get_isr;
42         ops->fill_txdesc = ar9002_hw_fill_txdesc;
43         ops->proc_txdesc = ar9002_hw_proc_txdesc;
44 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
45 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
46 @@ -43,13 +43,6 @@ static void ar9003_hw_set_desc_link(void
47         ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
48  }
49  
50 -static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
51 -{
52 -       struct ar9003_txc *ads = ds;
53 -
54 -       *ds_link = &ads->link;
55 -}
56 -
57  static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
58  {
59         u32 isr = 0;
60 @@ -498,7 +491,6 @@ void ar9003_hw_attach_mac_ops(struct ath
61  
62         ops->rx_enable = ar9003_hw_rx_enable;
63         ops->set_desc_link = ar9003_hw_set_desc_link;
64 -       ops->get_desc_link = ar9003_hw_get_desc_link;
65         ops->get_isr = ar9003_hw_get_isr;
66         ops->fill_txdesc = ar9003_hw_fill_txdesc;
67         ops->proc_txdesc = ar9003_hw_proc_txdesc;
68 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
69 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
70 @@ -179,7 +179,7 @@ enum ATH_AGGR_STATUS {
71  struct ath_txq {
72         int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
73         u32 axq_qnum; /* ath9k hardware queue number */
74 -       u32 *axq_link;
75 +       void *axq_link;
76         struct list_head axq_q;
77         spinlock_t axq_lock;
78         u32 axq_depth;
79 @@ -188,7 +188,6 @@ struct ath_txq {
80         bool axq_tx_inprogress;
81         struct list_head axq_acq;
82         struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
83 -       struct list_head txq_fifo_pending;
84         u8 txq_headidx;
85         u8 txq_tailidx;
86         int pending_frames;
87 --- a/drivers/net/wireless/ath/ath9k/debug.c
88 +++ b/drivers/net/wireless/ath/ath9k/debug.c
89 @@ -550,6 +550,7 @@ static ssize_t read_file_xmit(struct fil
90  
91         PR("MPDUs Queued:    ", queued);
92         PR("MPDUs Completed: ", completed);
93 +       PR("MPDUs XRetried:  ", xretries);
94         PR("Aggregates:      ", a_aggr);
95         PR("AMPDUs Queued HW:", a_queued_hw);
96         PR("AMPDUs Queued SW:", a_queued_sw);
97 @@ -587,7 +588,6 @@ static ssize_t read_file_xmit(struct fil
98  
99         PRQLE("axq_q empty:       ", axq_q);
100         PRQLE("axq_acq empty:     ", axq_acq);
101 -       PRQLE("txq_fifo_pending:  ", txq_fifo_pending);
102         for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
103                 snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
104                 PRQLE(tmp, txq_fifo[i]);
105 @@ -807,7 +807,10 @@ void ath_debug_stat_tx(struct ath_softc 
106                 else
107                         TX_STAT_INC(qnum, a_completed);
108         } else {
109 -               TX_STAT_INC(qnum, completed);
110 +               if (bf_isxretried(bf))
111 +                       TX_STAT_INC(qnum, xretries);
112 +               else
113 +                       TX_STAT_INC(qnum, completed);
114         }
115  
116         if (ts->ts_status & ATH9K_TXERR_FIFO)
117 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
118 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
119 @@ -39,11 +39,6 @@ static inline void ath9k_hw_set_desc_lin
120         ath9k_hw_ops(ah)->set_desc_link(ds, link);
121  }
122  
123 -static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
124 -                                         u32 **link)
125 -{
126 -       ath9k_hw_ops(ah)->get_desc_link(ds, link);
127 -}
128  static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
129                                       struct ath9k_channel *chan,
130                                       u8 rxchainmask,
131 --- a/drivers/net/wireless/ath/ath9k/xmit.c
132 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
133 @@ -53,7 +53,7 @@ static void ath_tx_complete_buf(struct a
134                                 struct ath_txq *txq, struct list_head *bf_q,
135                                 struct ath_tx_status *ts, int txok, int sendbar);
136  static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
137 -                            struct list_head *head);
138 +                            struct list_head *head, bool internal);
139  static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
140  static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
141                              struct ath_tx_status *ts, int nframes, int nbad,
142 @@ -377,8 +377,7 @@ static void ath_tx_complete_aggr(struct 
143                         bf_next = bf->bf_next;
144  
145                         bf->bf_state.bf_type |= BUF_XRETRY;
146 -                       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
147 -                           !bf->bf_stale || bf_next != NULL)
148 +                       if (!bf->bf_stale || bf_next != NULL)
149                                 list_move_tail(&bf->list, &bf_head);
150  
151                         ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
152 @@ -463,20 +462,14 @@ static void ath_tx_complete_aggr(struct 
153                         }
154                 }
155  
156 -               if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
157 -                   bf_next == NULL) {
158 -                       /*
159 -                        * Make sure the last desc is reclaimed if it
160 -                        * not a holding desc.
161 -                        */
162 -                       if (!bf_last->bf_stale)
163 -                               list_move_tail(&bf->list, &bf_head);
164 -                       else
165 -                               INIT_LIST_HEAD(&bf_head);
166 -               } else {
167 -                       BUG_ON(list_empty(bf_q));
168 +               /*
169 +                * Make sure the last desc is reclaimed if it
170 +                * not a holding desc.
171 +                */
172 +               if (!bf_last->bf_stale || bf_next != NULL)
173                         list_move_tail(&bf->list, &bf_head);
174 -               }
175 +               else
176 +                       INIT_LIST_HEAD(&bf_head);
177  
178                 if (!txpending || (tid->state & AGGR_CLEANUP)) {
179                         /*
180 @@ -837,7 +830,7 @@ static void ath_tx_sched_aggr(struct ath
181                         bf->bf_state.bf_type &= ~BUF_AGGR;
182                         ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
183                         ath_buf_set_rate(sc, bf, fi->framelen);
184 -                       ath_tx_txqaddbuf(sc, txq, &bf_q);
185 +                       ath_tx_txqaddbuf(sc, txq, &bf_q, false);
186                         continue;
187                 }
188  
189 @@ -849,7 +842,7 @@ static void ath_tx_sched_aggr(struct ath
190                 /* anchor last desc of aggregate */
191                 ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
192  
193 -               ath_tx_txqaddbuf(sc, txq, &bf_q);
194 +               ath_tx_txqaddbuf(sc, txq, &bf_q, false);
195                 TX_STAT_INC(txq->axq_qnum, a_aggr);
196  
197         } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
198 @@ -1085,7 +1078,6 @@ struct ath_txq *ath_txq_setup(struct ath
199                 txq->txq_headidx = txq->txq_tailidx = 0;
200                 for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
201                         INIT_LIST_HEAD(&txq->txq_fifo[i]);
202 -               INIT_LIST_HEAD(&txq->txq_fifo_pending);
203         }
204         return &sc->tx.txq[axq_qnum];
205  }
206 @@ -1155,13 +1147,8 @@ static bool bf_is_ampdu_not_probing(stru
207      return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
208  }
209  
210 -/*
211 - * Drain a given TX queue (could be Beacon or Data)
212 - *
213 - * This assumes output has been stopped and
214 - * we do not need to block ath_tx_tasklet.
215 - */
216 -void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
217 +static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
218 +                              struct list_head *list, bool retry_tx)
219  {
220         struct ath_buf *bf, *lastbf;
221         struct list_head bf_head;
222 @@ -1170,93 +1157,63 @@ void ath_draintxq(struct ath_softc *sc, 
223         memset(&ts, 0, sizeof(ts));
224         INIT_LIST_HEAD(&bf_head);
225  
226 -       for (;;) {
227 -               spin_lock_bh(&txq->axq_lock);
228 +       while (!list_empty(list)) {
229 +               bf = list_first_entry(list, struct ath_buf, list);
230  
231 -               if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
232 -                       if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
233 -                               txq->txq_headidx = txq->txq_tailidx = 0;
234 -                               spin_unlock_bh(&txq->axq_lock);
235 -                               break;
236 -                       } else {
237 -                               bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
238 -                                                     struct ath_buf, list);
239 -                       }
240 -               } else {
241 -                       if (list_empty(&txq->axq_q)) {
242 -                               txq->axq_link = NULL;
243 -                               spin_unlock_bh(&txq->axq_lock);
244 -                               break;
245 -                       }
246 -                       bf = list_first_entry(&txq->axq_q, struct ath_buf,
247 -                                             list);
248 -
249 -                       if (bf->bf_stale) {
250 -                               list_del(&bf->list);
251 -                               spin_unlock_bh(&txq->axq_lock);
252 +               if (bf->bf_stale) {
253 +                       list_del(&bf->list);
254  
255 -                               ath_tx_return_buffer(sc, bf);
256 -                               continue;
257 -                       }
258 +                       ath_tx_return_buffer(sc, bf);
259 +                       continue;
260                 }
261  
262                 lastbf = bf->bf_lastbf;
263 -
264 -               if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
265 -                       list_cut_position(&bf_head,
266 -                                         &txq->txq_fifo[txq->txq_tailidx],
267 -                                         &lastbf->list);
268 -                       INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
269 -               } else {
270 -                       /* remove ath_buf's of the same mpdu from txq */
271 -                       list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
272 -               }
273 +               list_cut_position(&bf_head, list, &lastbf->list);
274  
275                 txq->axq_depth--;
276                 if (bf_is_ampdu_not_probing(bf))
277                         txq->axq_ampdu_depth--;
278 -               spin_unlock_bh(&txq->axq_lock);
279  
280 +               spin_unlock_bh(&txq->axq_lock);
281                 if (bf_isampdu(bf))
282                         ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
283                                              retry_tx);
284                 else
285                         ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
286 +               spin_lock_bh(&txq->axq_lock);
287         }
288 +}
289  
290 +/*
291 + * Drain a given TX queue (could be Beacon or Data)
292 + *
293 + * This assumes output has been stopped and
294 + * we do not need to block ath_tx_tasklet.
295 + */
296 +void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
297 +{
298         spin_lock_bh(&txq->axq_lock);
299 -       txq->axq_tx_inprogress = false;
300 -       spin_unlock_bh(&txq->axq_lock);
301 -
302         if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
303 -               spin_lock_bh(&txq->axq_lock);
304 -               while (!list_empty(&txq->txq_fifo_pending)) {
305 -                       bf = list_first_entry(&txq->txq_fifo_pending,
306 -                                             struct ath_buf, list);
307 -                       list_cut_position(&bf_head,
308 -                                         &txq->txq_fifo_pending,
309 -                                         &bf->bf_lastbf->list);
310 -                       spin_unlock_bh(&txq->axq_lock);
311 +               int idx = txq->txq_tailidx;
312  
313 -                       if (bf_isampdu(bf))
314 -                               ath_tx_complete_aggr(sc, txq, bf, &bf_head,
315 -                                                    &ts, 0, retry_tx);
316 -                       else
317 -                               ath_tx_complete_buf(sc, bf, txq, &bf_head,
318 -                                                   &ts, 0, 0);
319 -                       spin_lock_bh(&txq->axq_lock);
320 +               while (!list_empty(&txq->txq_fifo[idx])) {
321 +                       ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
322 +                                          retry_tx);
323 +
324 +                       INCR(idx, ATH_TXFIFO_DEPTH);
325                 }
326 -               spin_unlock_bh(&txq->axq_lock);
327 +               txq->txq_tailidx = idx;
328         }
329  
330 +       txq->axq_link = NULL;
331 +       txq->axq_tx_inprogress = false;
332 +       ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
333 +
334         /* flush any pending frames if aggregation is enabled */
335 -       if (sc->sc_flags & SC_OP_TXAGGR) {
336 -               if (!retry_tx) {
337 -                       spin_lock_bh(&txq->axq_lock);
338 -                       ath_txq_drain_pending_buffers(sc, txq);
339 -                       spin_unlock_bh(&txq->axq_lock);
340 -               }
341 -       }
342 +       if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
343 +               ath_txq_drain_pending_buffers(sc, txq);
344 +
345 +       spin_unlock_bh(&txq->axq_lock);
346  }
347  
348  bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
349 @@ -1370,11 +1327,13 @@ void ath_txq_schedule(struct ath_softc *
350   * assume the descriptors are already chained together by caller.
351   */
352  static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
353 -                            struct list_head *head)
354 +                            struct list_head *head, bool internal)
355  {
356         struct ath_hw *ah = sc->sc_ah;
357         struct ath_common *common = ath9k_hw_common(ah);
358 -       struct ath_buf *bf;
359 +       struct ath_buf *bf, *bf_last;
360 +       bool puttxbuf = false;
361 +       bool edma;
362  
363         /*
364          * Insert the frame on the outbound list and
365 @@ -1384,51 +1343,49 @@ static void ath_tx_txqaddbuf(struct ath_
366         if (list_empty(head))
367                 return;
368  
369 +       edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
370         bf = list_first_entry(head, struct ath_buf, list);
371 +       bf_last = list_entry(head->prev, struct ath_buf, list);
372  
373         ath_dbg(common, ATH_DBG_QUEUE,
374                 "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
375  
376 -       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
377 -               if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
378 -                       list_splice_tail_init(head, &txq->txq_fifo_pending);
379 -                       return;
380 -               }
381 -               if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
382 -                       ath_dbg(common, ATH_DBG_XMIT,
383 -                               "Initializing tx fifo %d which is non-empty\n",
384 -                               txq->txq_headidx);
385 -               INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
386 -               list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
387 +       if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
388 +               list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
389                 INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
390 -               TX_STAT_INC(txq->axq_qnum, puttxbuf);
391 -               ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
392 -               ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
393 -                       txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
394 +               puttxbuf = true;
395         } else {
396                 list_splice_tail_init(head, &txq->axq_q);
397  
398 -               if (txq->axq_link == NULL) {
399 -                       TX_STAT_INC(txq->axq_qnum, puttxbuf);
400 -                       ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
401 -                       ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
402 -                               txq->axq_qnum, ito64(bf->bf_daddr),
403 -                               bf->bf_desc);
404 -               } else {
405 -                       *txq->axq_link = bf->bf_daddr;
406 +               if (txq->axq_link) {
407 +                       ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
408                         ath_dbg(common, ATH_DBG_XMIT,
409                                 "link[%u] (%p)=%llx (%p)\n",
410                                 txq->axq_qnum, txq->axq_link,
411                                 ito64(bf->bf_daddr), bf->bf_desc);
412 -               }
413 -               ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
414 -                                      &txq->axq_link);
415 +               } else if (!edma)
416 +                       puttxbuf = true;
417 +
418 +               txq->axq_link = bf_last->bf_desc;
419 +       }
420 +
421 +       if (puttxbuf) {
422 +               TX_STAT_INC(txq->axq_qnum, puttxbuf);
423 +               ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
424 +               ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
425 +                       txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
426 +       }
427 +
428 +       if (!edma) {
429                 TX_STAT_INC(txq->axq_qnum, txstart);
430                 ath9k_hw_txstart(ah, txq->axq_qnum);
431         }
432 -       txq->axq_depth++;
433 -       if (bf_is_ampdu_not_probing(bf))
434 -               txq->axq_ampdu_depth++;
435 +
436 +       if (!internal) {
437 +               txq->axq_depth++;
438 +               if (bf_is_ampdu_not_probing(bf))
439 +                       txq->axq_ampdu_depth++;
440 +       }
441  }
442  
443  static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
444 @@ -1470,7 +1427,7 @@ static void ath_tx_send_ampdu(struct ath
445         TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
446         bf->bf_lastbf = bf;
447         ath_buf_set_rate(sc, bf, fi->framelen);
448 -       ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
449 +       ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
450  }
451  
452  static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
453 @@ -1490,7 +1447,7 @@ static void ath_tx_send_normal(struct at
454         bf->bf_lastbf = bf;
455         fi = get_frame_info(bf->bf_mpdu);
456         ath_buf_set_rate(sc, bf, fi->framelen);
457 -       ath_tx_txqaddbuf(sc, txq, bf_head);
458 +       ath_tx_txqaddbuf(sc, txq, bf_head, false);
459         TX_STAT_INC(txq->axq_qnum, queued);
460  }
461  
462 @@ -2077,6 +2034,38 @@ static void ath_tx_rc_status(struct ath_
463         tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
464  }
465  
466 +static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
467 +                                 struct ath_tx_status *ts, struct ath_buf *bf,
468 +                                 struct list_head *bf_head)
469 +{
470 +       int txok;
471 +
472 +       txq->axq_depth--;
473 +       txok = !(ts->ts_status & ATH9K_TXERR_MASK);
474 +       txq->axq_tx_inprogress = false;
475 +       if (bf_is_ampdu_not_probing(bf))
476 +               txq->axq_ampdu_depth--;
477 +
478 +       spin_unlock_bh(&txq->axq_lock);
479 +
480 +       if (!bf_isampdu(bf)) {
481 +               /*
482 +                * This frame is sent out as a single frame.
483 +                * Use hardware retry status for this frame.
484 +                */
485 +               if (ts->ts_status & ATH9K_TXERR_XRETRY)
486 +                       bf->bf_state.bf_type |= BUF_XRETRY;
487 +               ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
488 +               ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
489 +       } else
490 +               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
491 +
492 +       spin_lock_bh(&txq->axq_lock);
493 +
494 +       if (sc->sc_flags & SC_OP_TXAGGR)
495 +               ath_txq_schedule(sc, txq);
496 +}
497 +
498  static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
499  {
500         struct ath_hw *ah = sc->sc_ah;
501 @@ -2085,20 +2074,18 @@ static void ath_tx_processq(struct ath_s
502         struct list_head bf_head;
503         struct ath_desc *ds;
504         struct ath_tx_status ts;
505 -       int txok;
506         int status;
507  
508         ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
509                 txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
510                 txq->axq_link);
511  
512 +       spin_lock_bh(&txq->axq_lock);
513         for (;;) {
514 -               spin_lock_bh(&txq->axq_lock);
515                 if (list_empty(&txq->axq_q)) {
516                         txq->axq_link = NULL;
517                         if (sc->sc_flags & SC_OP_TXAGGR)
518                                 ath_txq_schedule(sc, txq);
519 -                       spin_unlock_bh(&txq->axq_lock);
520                         break;
521                 }
522                 bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
523 @@ -2114,13 +2101,11 @@ static void ath_tx_processq(struct ath_s
524                 bf_held = NULL;
525                 if (bf->bf_stale) {
526                         bf_held = bf;
527 -                       if (list_is_last(&bf_held->list, &txq->axq_q)) {
528 -                               spin_unlock_bh(&txq->axq_lock);
529 +                       if (list_is_last(&bf_held->list, &txq->axq_q))
530                                 break;
531 -                       } else {
532 -                               bf = list_entry(bf_held->list.next,
533 -                                               struct ath_buf, list);
534 -                       }
535 +
536 +                       bf = list_entry(bf_held->list.next, struct ath_buf,
537 +                                       list);
538                 }
539  
540                 lastbf = bf->bf_lastbf;
541 @@ -2128,10 +2113,9 @@ static void ath_tx_processq(struct ath_s
542  
543                 memset(&ts, 0, sizeof(ts));
544                 status = ath9k_hw_txprocdesc(ah, ds, &ts);
545 -               if (status == -EINPROGRESS) {
546 -                       spin_unlock_bh(&txq->axq_lock);
547 +               if (status == -EINPROGRESS)
548                         break;
549 -               }
550 +
551                 TX_STAT_INC(txq->axq_qnum, txprocdesc);
552  
553                 /*
554 @@ -2145,42 +2129,14 @@ static void ath_tx_processq(struct ath_s
555                         list_cut_position(&bf_head,
556                                 &txq->axq_q, lastbf->list.prev);
557  
558 -               txq->axq_depth--;
559 -               txok = !(ts.ts_status & ATH9K_TXERR_MASK);
560 -               txq->axq_tx_inprogress = false;
561 -               if (bf_held)
562 +               if (bf_held) {
563                         list_del(&bf_held->list);
564 -
565 -               if (bf_is_ampdu_not_probing(bf))
566 -                       txq->axq_ampdu_depth--;
567 -
568 -               spin_unlock_bh(&txq->axq_lock);
569 -
570 -               if (bf_held)
571                         ath_tx_return_buffer(sc, bf_held);
572 -
573 -               if (!bf_isampdu(bf)) {
574 -                       /*
575 -                        * This frame is sent out as a single frame.
576 -                        * Use hardware retry status for this frame.
577 -                        */
578 -                       if (ts.ts_status & ATH9K_TXERR_XRETRY)
579 -                               bf->bf_state.bf_type |= BUF_XRETRY;
580 -                       ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
581                 }
582  
583 -               if (bf_isampdu(bf))
584 -                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
585 -                                            true);
586 -               else
587 -                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
588 -
589 -               spin_lock_bh(&txq->axq_lock);
590 -
591 -               if (sc->sc_flags & SC_OP_TXAGGR)
592 -                       ath_txq_schedule(sc, txq);
593 -               spin_unlock_bh(&txq->axq_lock);
594 +               ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
595         }
596 +       spin_unlock_bh(&txq->axq_lock);
597  }
598  
599  static void ath_tx_complete_poll_work(struct work_struct *work)
600 @@ -2237,17 +2193,16 @@ void ath_tx_tasklet(struct ath_softc *sc
601  
602  void ath_tx_edma_tasklet(struct ath_softc *sc)
603  {
604 -       struct ath_tx_status txs;
605 +       struct ath_tx_status ts;
606         struct ath_common *common = ath9k_hw_common(sc->sc_ah);
607         struct ath_hw *ah = sc->sc_ah;
608         struct ath_txq *txq;
609         struct ath_buf *bf, *lastbf;
610         struct list_head bf_head;
611         int status;
612 -       int txok;
613  
614         for (;;) {
615 -               status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
616 +               status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
617                 if (status == -EINPROGRESS)
618                         break;
619                 if (status == -EIO) {
620 @@ -2257,12 +2212,13 @@ void ath_tx_edma_tasklet(struct ath_soft
621                 }
622  
623                 /* Skip beacon completions */
624 -               if (txs.qid == sc->beacon.beaconq)
625 +               if (ts.qid == sc->beacon.beaconq)
626                         continue;
627  
628 -               txq = &sc->tx.txq[txs.qid];
629 +               txq = &sc->tx.txq[ts.qid];
630  
631                 spin_lock_bh(&txq->axq_lock);
632 +
633                 if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
634                         spin_unlock_bh(&txq->axq_lock);
635                         return;
636 @@ -2275,41 +2231,21 @@ void ath_tx_edma_tasklet(struct ath_soft
637                 INIT_LIST_HEAD(&bf_head);
638                 list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
639                                   &lastbf->list);
640 -               INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
641 -               txq->axq_depth--;
642 -               txq->axq_tx_inprogress = false;
643 -               if (bf_is_ampdu_not_probing(bf))
644 -                       txq->axq_ampdu_depth--;
645 -               spin_unlock_bh(&txq->axq_lock);
646  
647 -               txok = !(txs.ts_status & ATH9K_TXERR_MASK);
648 -
649 -               if (!bf_isampdu(bf)) {
650 -                       if (txs.ts_status & ATH9K_TXERR_XRETRY)
651 -                               bf->bf_state.bf_type |= BUF_XRETRY;
652 -                       ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
653 -               }
654 -
655 -               if (bf_isampdu(bf))
656 -                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
657 -                                            txok, true);
658 -               else
659 -                       ath_tx_complete_buf(sc, bf, txq, &bf_head,
660 -                                           &txs, txok, 0);
661 +               if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
662 +                       INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
663  
664 -               spin_lock_bh(&txq->axq_lock);
665 +                       if (!list_empty(&txq->axq_q)) {
666 +                               struct list_head bf_q;
667  
668 -               if (!list_empty(&txq->txq_fifo_pending)) {
669 -                       INIT_LIST_HEAD(&bf_head);
670 -                       bf = list_first_entry(&txq->txq_fifo_pending,
671 -                                             struct ath_buf, list);
672 -                       list_cut_position(&bf_head,
673 -                                         &txq->txq_fifo_pending,
674 -                                         &bf->bf_lastbf->list);
675 -                       ath_tx_txqaddbuf(sc, txq, &bf_head);
676 -               } else if (sc->sc_flags & SC_OP_TXAGGR)
677 -                       ath_txq_schedule(sc, txq);
678 +                               INIT_LIST_HEAD(&bf_q);
679 +                               txq->axq_link = NULL;
680 +                               list_splice_tail_init(&txq->axq_q, &bf_q);
681 +                               ath_tx_txqaddbuf(sc, txq, &bf_q, true);
682 +                       }
683 +               }
684  
685 +               ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
686                 spin_unlock_bh(&txq->axq_lock);
687         }
688  }
689 --- a/net/mac80211/agg-rx.c
690 +++ b/net/mac80211/agg-rx.c
691 @@ -161,6 +161,8 @@ static void ieee80211_send_addba_resp(st
692                 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
693         else if (sdata->vif.type == NL80211_IFTYPE_STATION)
694                 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
695 +       else if (sdata->vif.type == NL80211_IFTYPE_WDS)
696 +               memcpy(mgmt->bssid, da, ETH_ALEN);
697  
698         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
699                                           IEEE80211_STYPE_ACTION);
700 --- a/net/mac80211/agg-tx.c
701 +++ b/net/mac80211/agg-tx.c
702 @@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
703         memcpy(mgmt->da, da, ETH_ALEN);
704         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
705         if (sdata->vif.type == NL80211_IFTYPE_AP ||
706 -           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
707 +           sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
708 +           sdata->vif.type == NL80211_IFTYPE_WDS)
709                 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
710         else if (sdata->vif.type == NL80211_IFTYPE_STATION)
711                 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
712 @@ -388,7 +389,8 @@ int ieee80211_start_tx_ba_session(struct
713          */
714         if (sdata->vif.type != NL80211_IFTYPE_STATION &&
715             sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
716 -           sdata->vif.type != NL80211_IFTYPE_AP)
717 +           sdata->vif.type != NL80211_IFTYPE_AP &&
718 +           sdata->vif.type != NL80211_IFTYPE_WDS)
719                 return -EINVAL;
720  
721         if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
722 --- a/net/mac80211/debugfs_sta.c
723 +++ b/net/mac80211/debugfs_sta.c
724 @@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
725         char buf[100];
726         struct sta_info *sta = file->private_data;
727         u32 staflags = get_sta_flags(sta);
728 -       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
729 +       int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
730                 staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
731                 staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
732                 staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
733 @@ -67,7 +67,6 @@ static ssize_t sta_flags_read(struct fil
734                 staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
735                 staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
736                 staflags & WLAN_STA_WME ? "WME\n" : "",
737 -               staflags & WLAN_STA_WDS ? "WDS\n" : "",
738                 staflags & WLAN_STA_MFP ? "MFP\n" : "");
739         return simple_read_from_buffer(userbuf, count, ppos, buf, res);
740  }
741 --- a/net/mac80211/iface.c
742 +++ b/net/mac80211/iface.c
743 @@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
744  {
745         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
746         struct ieee80211_local *local = sdata->local;
747 -       struct sta_info *sta;
748         u32 changed = 0;
749         int res;
750         u32 hw_reconf_flags = 0;
751 @@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_
752  
753         set_bit(SDATA_STATE_RUNNING, &sdata->state);
754  
755 -       if (sdata->vif.type == NL80211_IFTYPE_WDS) {
756 -               /* Create STA entry for the WDS peer */
757 -               sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
758 -                                    GFP_KERNEL);
759 -               if (!sta) {
760 -                       res = -ENOMEM;
761 -                       goto err_del_interface;
762 -               }
763 -
764 -               /* no locking required since STA is not live yet */
765 -               sta->flags |= WLAN_STA_AUTHORIZED;
766 -
767 -               res = sta_info_insert(sta);
768 -               if (res) {
769 -                       /* STA has been freed */
770 -                       goto err_del_interface;
771 -               }
772 -
773 -               rate_control_rate_init(sta);
774 -       }
775 -
776         /*
777          * set_multicast_list will be invoked by the networking core
778          * which will check whether any increments here were done in
779 @@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_
780         netif_tx_start_all_queues(dev);
781  
782         return 0;
783 - err_del_interface:
784 -       drv_remove_interface(local, &sdata->vif);
785 +
786   err_stop:
787         if (!local->open_count)
788                 drv_stop(local);
789 @@ -718,6 +695,70 @@ static void ieee80211_if_setup(struct ne
790         dev->destructor = free_netdev;
791  }
792  
793 +static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
794 +                                        struct sk_buff *skb)
795 +{
796 +       struct ieee80211_local *local = sdata->local;
797 +       struct ieee80211_rx_status *rx_status;
798 +       struct ieee802_11_elems elems;
799 +       struct ieee80211_mgmt *mgmt;
800 +       struct sta_info *sta;
801 +       size_t baselen;
802 +       u32 rates = 0;
803 +       u16 stype;
804 +       bool new = false;
805 +       enum ieee80211_band band = local->hw.conf.channel->band;
806 +       struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
807 +
808 +       rx_status = IEEE80211_SKB_RXCB(skb);
809 +       mgmt = (struct ieee80211_mgmt *) skb->data;
810 +       stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
811 +
812 +       if (stype != IEEE80211_STYPE_BEACON)
813 +               return;
814 +
815 +       baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
816 +       if (baselen > skb->len)
817 +               return;
818 +
819 +       ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
820 +                              skb->len - baselen, &elems);
821 +
822 +       rates = ieee80211_sta_get_rates(local, &elems, band);
823 +
824 +       rcu_read_lock();
825 +
826 +       sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
827 +
828 +       if (!sta) {
829 +               rcu_read_unlock();
830 +               sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
831 +                                    GFP_KERNEL);
832 +               if (!sta)
833 +                       return;
834 +
835 +               new = true;
836 +       }
837 +
838 +       sta->last_rx = jiffies;
839 +       sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
840 +
841 +       if (elems.ht_cap_elem)
842 +               ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
843 +                               elems.ht_cap_elem, &sta->sta.ht_cap);
844 +
845 +       if (elems.wmm_param)
846 +               set_sta_flags(sta, WLAN_STA_WME);
847 +
848 +       if (new) {
849 +               sta->flags = WLAN_STA_AUTHORIZED;
850 +               rate_control_rate_init(sta);
851 +               sta_info_insert_rcu(sta);
852 +       }
853 +
854 +       rcu_read_unlock();
855 +}
856 +
857  static void ieee80211_iface_work(struct work_struct *work)
858  {
859         struct ieee80211_sub_if_data *sdata =
860 @@ -822,6 +863,9 @@ static void ieee80211_iface_work(struct 
861                                 break;
862                         ieee80211_mesh_rx_queued_mgmt(sdata, skb);
863                         break;
864 +               case NL80211_IFTYPE_WDS:
865 +                       ieee80211_wds_rx_queued_mgmt(sdata, skb);
866 +                       break;
867                 default:
868                         WARN(1, "frame for unexpected interface type");
869                         break;
870 --- a/net/mac80211/rx.c
871 +++ b/net/mac80211/rx.c
872 @@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
873                  */
874                 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
875                     sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
876 -                   sdata->vif.type != NL80211_IFTYPE_AP)
877 +                   sdata->vif.type != NL80211_IFTYPE_AP &&
878 +                   sdata->vif.type != NL80211_IFTYPE_WDS)
879                         break;
880  
881                 /* verify action_code is present */
882 @@ -2335,13 +2336,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
883  
884         if (!ieee80211_vif_is_mesh(&sdata->vif) &&
885             sdata->vif.type != NL80211_IFTYPE_ADHOC &&
886 -           sdata->vif.type != NL80211_IFTYPE_STATION)
887 +           sdata->vif.type != NL80211_IFTYPE_STATION &&
888 +           sdata->vif.type != NL80211_IFTYPE_WDS)
889                 return RX_DROP_MONITOR;
890  
891         switch (stype) {
892         case cpu_to_le16(IEEE80211_STYPE_BEACON):
893         case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
894 -               /* process for all: mesh, mlme, ibss */
895 +               /* process for all: mesh, mlme, ibss, wds */
896                 break;
897         case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
898         case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
899 @@ -2680,10 +2682,16 @@ static int prepare_for_handlers(struct i
900                 }
901                 break;
902         case NL80211_IFTYPE_WDS:
903 -               if (bssid || !ieee80211_is_data(hdr->frame_control))
904 -                       return 0;
905                 if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
906                         return 0;
907 +
908 +               if (ieee80211_is_data(hdr->frame_control) ||
909 +                   ieee80211_is_action(hdr->frame_control)) {
910 +                       if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
911 +                               return 0;
912 +               } else if (!ieee80211_is_beacon(hdr->frame_control))
913 +                       return 0;
914 +
915                 break;
916         default:
917                 /* should never get here */
918 --- a/net/mac80211/sta_info.h
919 +++ b/net/mac80211/sta_info.h
920 @@ -31,7 +31,6 @@
921   *     frames.
922   * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
923   * @WLAN_STA_WME: Station is a QoS-STA.
924 - * @WLAN_STA_WDS: Station is one of our WDS peers.
925   * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
926   *     IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
927   *     frame to this station is transmitted.
928 @@ -54,7 +53,6 @@ enum ieee80211_sta_info_flags {
929         WLAN_STA_SHORT_PREAMBLE = 1<<4,
930         WLAN_STA_ASSOC_AP       = 1<<5,
931         WLAN_STA_WME            = 1<<6,
932 -       WLAN_STA_WDS            = 1<<7,
933         WLAN_STA_CLEAR_PS_FILT  = 1<<9,
934         WLAN_STA_MFP            = 1<<10,
935         WLAN_STA_BLOCK_BA       = 1<<11,
936 --- a/drivers/net/wireless/ath/ath9k/debug.h
937 +++ b/drivers/net/wireless/ath/ath9k/debug.h
938 @@ -116,6 +116,7 @@ struct ath_tx_stats {
939         u32 tx_bytes_all;
940         u32 queued;
941         u32 completed;
942 +       u32 xretries;
943         u32 a_aggr;
944         u32 a_queued_hw;
945         u32 a_queued_sw;
946 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
947 +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
948 @@ -4645,10 +4645,16 @@ static void ar9003_hw_set_power_per_rate
949         case 1:
950                 break;
951         case 2:
952 -               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
953 +               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
954 +                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
955 +               else
956 +                       scaledPower = 0;
957                 break;
958         case 3:
959 -               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
960 +               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
961 +                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
962 +               else
963 +                       scaledPower = 0;
964                 break;
965         }
966  
967 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
968 +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
969 @@ -524,10 +524,16 @@ static void ath9k_hw_set_ar9287_power_pe
970         case 1:
971                 break;
972         case 2:
973 -               scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
974 +               if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
975 +                       scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
976 +               else
977 +                       scaledPower = 0;
978                 break;
979         case 3:
980 -               scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
981 +               if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
982 +                       scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
983 +               else
984 +                       scaledPower = 0;
985                 break;
986         }
987         scaledPower = max((u16)0, scaledPower);