mac80211: update to wireless-testing 2011-05-27
authorFelix Fietkau <nbd@openwrt.org>
Tue, 31 May 2011 23:07:29 +0000 (23:07 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 31 May 2011 23:07:29 +0000 (23:07 +0000)
SVN-Revision: 27071

26 files changed:
package/mac80211/Makefile
package/mac80211/patches/002-disable_rfkill.patch
package/mac80211/patches/005-disable_ssb_build.patch
package/mac80211/patches/007-remove_misc_drivers.patch
package/mac80211/patches/011-no_sdio.patch
package/mac80211/patches/015-remove-rt2x00-options.patch
package/mac80211/patches/110-disable_usb_compat.patch
package/mac80211/patches/300-pending_work.patch
package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
package/mac80211/patches/511-ath9k_increase_bcbuf.patch
package/mac80211/patches/521-mac80211_ht_change_rate_update.patch [new file with mode: 0644]
package/mac80211/patches/530-ath9k_noise_dbm_fixup.patch [new file with mode: 0644]
package/mac80211/patches/530-mac80211_remove_wds_sta_flag.patch [deleted file]
package/mac80211/patches/531-mac80211_fix_iftype_wds.patch [deleted file]
package/mac80211/patches/532-mac80211_enable_iftype_wds_aggregation.patch [deleted file]
package/mac80211/patches/540-ath9k_debugfs_show_xretry.patch [deleted file]
package/mac80211/patches/550-mac80211_ht_change_rate_update.patch [deleted file]
package/mac80211/patches/560-ath9k_noise_dbm_fixup.patch [deleted file]
package/mac80211/patches/570-ath9k_fix_adhoc_beacons.patch [deleted file]
package/mac80211/patches/571-ath9k_fix_adhoc_nexttbtt.patch [deleted file]
package/mac80211/patches/572-ath9k_tx_last_beacon.patch [deleted file]
package/mac80211/patches/580-ath9k_tx_fifo_cleanup.patch [deleted file]
package/mac80211/patches/581-ath9k_remove_get_desc_link.patch [deleted file]
package/mac80211/patches/800-b43-gpio-mask-module-option.patch
package/mac80211/patches/810-b43_no_pio.patch

index d531ecd..492fc97 100644 (file)
@@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2011-05-13
+PKG_VERSION:=2011-05-27
 PKG_RELEASE:=1
 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_MD5SUM:=8670d18633dbd28b19168abe3ecd0357
+PKG_MD5SUM:=3a382b03333aff304dbe8ee94fce6b5a
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
index 6105af9..f6350a6 100644 (file)
@@ -9,7 +9,7 @@
  
  ifeq ($(CONFIG_MAC80211),y)
  $(error "ERROR: you have MAC80211 compiled into the kernel, CONFIG_MAC80211=y, as such you cannot replace its mac80211 driver. You need this set to CONFIG_MAC80211=m. If you are using Fedora upgrade your kernel as later version should this set as modular. For further information on Fedora see https://bugzilla.redhat.com/show_bug.cgi?id=470143. If you are using your own kernel recompile it and make mac80211 modular")
-@@ -617,10 +617,10 @@ endif #CONFIG_COMPAT_KERNEL_27
+@@ -622,10 +622,10 @@ endif #CONFIG_COMPAT_KERNEL_27
  # We need the backported rfkill module on kernel < 2.6.31.
  # In more recent kernel versions use the in kernel rfkill module.
  ifdef CONFIG_COMPAT_KERNEL_31
index 401b20f..3a92f36 100644 (file)
@@ -51,7 +51,7 @@
  
  CONFIG_P54_PCI=m
  
-@@ -507,7 +505,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -511,7 +509,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
  
  ifdef CONFIG_MMC
  
index d2cb2dc..46081e2 100644 (file)
@@ -4,8 +4,8 @@
  endif #CONFIG_WIRELESS_EXT
  
  ifdef CONFIG_STAGING
--CONFIG_COMPAT_STAGING=y
-+# CONFIG_COMPAT_STAGING=y
+-CONFIG_COMPAT_STAGING=m
++# CONFIG_COMPAT_STAGING=m
  endif #CONFIG_STAGING
  
  # mac80211 test driver
@@ -28,7 +28,7 @@
  endif #CONFIG_COMPAT_KERNEL_27
  
  ifdef CONFIG_WIRELESS_EXT
-@@ -402,21 +402,21 @@ endif #CONFIG_COMPAT_KERNEL_29
+@@ -406,21 +406,21 @@ endif #CONFIG_COMPAT_KERNEL_29
  # Note: this depends on CONFIG_USB_NET_RNDIS_HOST and CONFIG_USB_NET_CDCETHER
  # it also requires new RNDIS_HOST and CDC_ETHER modules which we add
  ifdef CONFIG_COMPAT_KERNEL_29
index 984039e..e61d25e 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -488,7 +488,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -492,7 +492,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
  
  ifdef CONFIG_MMC
  
index db9126d..4ba8b76 100644 (file)
@@ -9,7 +9,7 @@
  CONFIG_RT2400PCI=m
  CONFIG_RT2500PCI=m
  ifdef CONFIG_CRC_CCITT
-@@ -437,7 +437,7 @@ CONFIG_RT2800USB_RT33XX=y
+@@ -441,7 +441,7 @@ CONFIG_RT2800USB_RT33XX=y
  # CONFIG_RT2800USB_RT53XX=y
  CONFIG_RT2800USB_UNKNOWN=y
  endif #CONFIG_CRC_CCITT
index 86467eb..7068315 100644 (file)
@@ -33,7 +33,7 @@
  #endif
 --- a/config.mk
 +++ b/config.mk
-@@ -423,7 +423,7 @@ endif #CONFIG_COMPAT_KERNEL_29
+@@ -427,7 +427,7 @@ endif #CONFIG_COMPAT_KERNEL_29
  # This activates a threading fix for usb urb.
  # this is mainline commit: b3e670443b7fb8a2d29831b62b44a039c283e351
  # This fix will be included in some stable releases.
index 15e6bd0..782f7d7 100644 (file)
---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
-@@ -829,7 +829,7 @@ static bool ar9002_hw_init_cal(struct at
-       if (AR_SREV_9271(ah)) {
-               if (!ar9285_hw_cl_cal(ah, chan))
-                       return false;
--      } else if (AR_SREV_9285_12_OR_LATER(ah)) {
-+      } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
-               if (!ar9285_hw_clc(ah, chan))
-                       return false;
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -603,7 +603,6 @@ struct ath_hw_ops {
+                                    int power_off);
+       void (*rx_enable)(struct ath_hw *ah);
+       void (*set_desc_link)(void *ds, u32 link);
+-      void (*get_desc_link)(void *ds, u32 **link);
+       bool (*calibrate)(struct ath_hw *ah,
+                         struct ath9k_channel *chan,
+                         u8 rxchainmask,
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -62,8 +62,6 @@ static bool ath9k_has_pending_frames(str
+       if (txq->axq_depth || !list_empty(&txq->axq_acq))
+               pending = true;
+-      else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+-              pending = !list_empty(&txq->txq_fifo_pending);
+       spin_unlock_bh(&txq->axq_lock);
+       return pending;
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -28,11 +28,6 @@ static void ar9002_hw_set_desc_link(void
+       ((struct ath_desc*) ds)->ds_link = ds_link;
+ }
+-static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
+-{
+-      *ds_link = &((struct ath_desc *)ds)->ds_link;
+-}
+-
+ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+ {
+       u32 isr = 0;
+@@ -437,7 +432,6 @@ void ar9002_hw_attach_mac_ops(struct ath
+       ops->rx_enable = ar9002_hw_rx_enable;
+       ops->set_desc_link = ar9002_hw_set_desc_link;
+-      ops->get_desc_link = ar9002_hw_get_desc_link;
+       ops->get_isr = ar9002_hw_get_isr;
+       ops->fill_txdesc = ar9002_hw_fill_txdesc;
+       ops->proc_txdesc = ar9002_hw_proc_txdesc;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -43,13 +43,6 @@ static void ar9003_hw_set_desc_link(void
+       ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
+ }
+-static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
+-{
+-      struct ar9003_txc *ads = ds;
+-
+-      *ds_link = &ads->link;
+-}
+-
+ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
+ {
+       u32 isr = 0;
+@@ -498,7 +491,6 @@ void ar9003_hw_attach_mac_ops(struct ath
+       ops->rx_enable = ar9003_hw_rx_enable;
+       ops->set_desc_link = ar9003_hw_set_desc_link;
+-      ops->get_desc_link = ar9003_hw_get_desc_link;
+       ops->get_isr = ar9003_hw_get_isr;
+       ops->fill_txdesc = ar9003_hw_fill_txdesc;
+       ops->proc_txdesc = ar9003_hw_proc_txdesc;
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -179,7 +179,7 @@ enum ATH_AGGR_STATUS {
+ struct ath_txq {
+       int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
+       u32 axq_qnum; /* ath9k hardware queue number */
+-      u32 *axq_link;
++      void *axq_link;
+       struct list_head axq_q;
+       spinlock_t axq_lock;
+       u32 axq_depth;
+@@ -188,7 +188,6 @@ struct ath_txq {
+       bool axq_tx_inprogress;
+       struct list_head axq_acq;
+       struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
+-      struct list_head txq_fifo_pending;
+       u8 txq_headidx;
+       u8 txq_tailidx;
+       int pending_frames;
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -550,6 +550,7 @@ static ssize_t read_file_xmit(struct fil
+       PR("MPDUs Queued:    ", queued);
+       PR("MPDUs Completed: ", completed);
++      PR("MPDUs XRetried:  ", xretries);
+       PR("Aggregates:      ", a_aggr);
+       PR("AMPDUs Queued HW:", a_queued_hw);
+       PR("AMPDUs Queued SW:", a_queued_sw);
+@@ -587,7 +588,6 @@ static ssize_t read_file_xmit(struct fil
+       PRQLE("axq_q empty:       ", axq_q);
+       PRQLE("axq_acq empty:     ", axq_acq);
+-      PRQLE("txq_fifo_pending:  ", txq_fifo_pending);
+       for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
+               snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
+               PRQLE(tmp, txq_fifo[i]);
+@@ -807,7 +807,10 @@ void ath_debug_stat_tx(struct ath_softc 
+               else
+                       TX_STAT_INC(qnum, a_completed);
        } else {
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -1381,3 +1381,25 @@ void ar9003_hw_bb_watchdog_dbg_info(stru
-               "==== BB update: done ====\n\n");
+-              TX_STAT_INC(qnum, completed);
++              if (bf_isxretried(bf))
++                      TX_STAT_INC(qnum, xretries);
++              else
++                      TX_STAT_INC(qnum, completed);
+       }
+       if (ts->ts_status & ATH9K_TXERR_FIFO)
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -39,11 +39,6 @@ static inline void ath9k_hw_set_desc_lin
+       ath9k_hw_ops(ah)->set_desc_link(ds, link);
+ }
+-static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
+-                                        u32 **link)
+-{
+-      ath9k_hw_ops(ah)->get_desc_link(ds, link);
+-}
+ static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
+                                     struct ath9k_channel *chan,
+                                     u8 rxchainmask,
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -53,7 +53,7 @@ static void ath_tx_complete_buf(struct a
+                               struct ath_txq *txq, struct list_head *bf_q,
+                               struct ath_tx_status *ts, int txok, int sendbar);
+ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+-                           struct list_head *head);
++                           struct list_head *head, bool internal);
+ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
+ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+                            struct ath_tx_status *ts, int nframes, int nbad,
+@@ -377,8 +377,7 @@ static void ath_tx_complete_aggr(struct 
+                       bf_next = bf->bf_next;
+                       bf->bf_state.bf_type |= BUF_XRETRY;
+-                      if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
+-                          !bf->bf_stale || bf_next != NULL)
++                      if (!bf->bf_stale || bf_next != NULL)
+                               list_move_tail(&bf->list, &bf_head);
+                       ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
+@@ -463,20 +462,14 @@ static void ath_tx_complete_aggr(struct 
+                       }
+               }
+-              if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+-                  bf_next == NULL) {
+-                      /*
+-                       * Make sure the last desc is reclaimed if it
+-                       * not a holding desc.
+-                       */
+-                      if (!bf_last->bf_stale)
+-                              list_move_tail(&bf->list, &bf_head);
+-                      else
+-                              INIT_LIST_HEAD(&bf_head);
+-              } else {
+-                      BUG_ON(list_empty(bf_q));
++              /*
++               * Make sure the last desc is reclaimed if it
++               * not a holding desc.
++               */
++              if (!bf_last->bf_stale || bf_next != NULL)
+                       list_move_tail(&bf->list, &bf_head);
+-              }
++              else
++                      INIT_LIST_HEAD(&bf_head);
+               if (!txpending || (tid->state & AGGR_CLEANUP)) {
+                       /*
+@@ -837,7 +830,7 @@ static void ath_tx_sched_aggr(struct ath
+                       bf->bf_state.bf_type &= ~BUF_AGGR;
+                       ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
+                       ath_buf_set_rate(sc, bf, fi->framelen);
+-                      ath_tx_txqaddbuf(sc, txq, &bf_q);
++                      ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+                       continue;
+               }
+@@ -849,7 +842,7 @@ static void ath_tx_sched_aggr(struct ath
+               /* anchor last desc of aggregate */
+               ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
+-              ath_tx_txqaddbuf(sc, txq, &bf_q);
++              ath_tx_txqaddbuf(sc, txq, &bf_q, false);
+               TX_STAT_INC(txq->axq_qnum, a_aggr);
+       } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
+@@ -1085,7 +1078,6 @@ struct ath_txq *ath_txq_setup(struct ath
+               txq->txq_headidx = txq->txq_tailidx = 0;
+               for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
+                       INIT_LIST_HEAD(&txq->txq_fifo[i]);
+-              INIT_LIST_HEAD(&txq->txq_fifo_pending);
+       }
+       return &sc->tx.txq[axq_qnum];
+ }
+@@ -1155,13 +1147,8 @@ static bool bf_is_ampdu_not_probing(stru
+     return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+ }
+-/*
+- * Drain a given TX queue (could be Beacon or Data)
+- *
+- * This assumes output has been stopped and
+- * we do not need to block ath_tx_tasklet.
+- */
+-void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
++static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
++                             struct list_head *list, bool retry_tx)
+ {
+       struct ath_buf *bf, *lastbf;
+       struct list_head bf_head;
+@@ -1170,93 +1157,63 @@ void ath_draintxq(struct ath_softc *sc, 
+       memset(&ts, 0, sizeof(ts));
+       INIT_LIST_HEAD(&bf_head);
+-      for (;;) {
+-              spin_lock_bh(&txq->axq_lock);
++      while (!list_empty(list)) {
++              bf = list_first_entry(list, struct ath_buf, list);
+-              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+-                      if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+-                              txq->txq_headidx = txq->txq_tailidx = 0;
+-                              spin_unlock_bh(&txq->axq_lock);
+-                              break;
+-                      } else {
+-                              bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
+-                                                    struct ath_buf, list);
+-                      }
+-              } else {
+-                      if (list_empty(&txq->axq_q)) {
+-                              txq->axq_link = NULL;
+-                              spin_unlock_bh(&txq->axq_lock);
+-                              break;
+-                      }
+-                      bf = list_first_entry(&txq->axq_q, struct ath_buf,
+-                                            list);
+-
+-                      if (bf->bf_stale) {
+-                              list_del(&bf->list);
+-                              spin_unlock_bh(&txq->axq_lock);
++              if (bf->bf_stale) {
++                      list_del(&bf->list);
+-                              ath_tx_return_buffer(sc, bf);
+-                              continue;
+-                      }
++                      ath_tx_return_buffer(sc, bf);
++                      continue;
+               }
+               lastbf = bf->bf_lastbf;
+-
+-              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+-                      list_cut_position(&bf_head,
+-                                        &txq->txq_fifo[txq->txq_tailidx],
+-                                        &lastbf->list);
+-                      INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
+-              } else {
+-                      /* remove ath_buf's of the same mpdu from txq */
+-                      list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
+-              }
++              list_cut_position(&bf_head, list, &lastbf->list);
+               txq->axq_depth--;
+               if (bf_is_ampdu_not_probing(bf))
+                       txq->axq_ampdu_depth--;
+-              spin_unlock_bh(&txq->axq_lock);
++              spin_unlock_bh(&txq->axq_lock);
+               if (bf_isampdu(bf))
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+                                            retry_tx);
+               else
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++              spin_lock_bh(&txq->axq_lock);
+       }
++}
++/*
++ * Drain a given TX queue (could be Beacon or Data)
++ *
++ * This assumes output has been stopped and
++ * we do not need to block ath_tx_tasklet.
++ */
++void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
++{
+       spin_lock_bh(&txq->axq_lock);
+-      txq->axq_tx_inprogress = false;
+-      spin_unlock_bh(&txq->axq_lock);
+-
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+-              spin_lock_bh(&txq->axq_lock);
+-              while (!list_empty(&txq->txq_fifo_pending)) {
+-                      bf = list_first_entry(&txq->txq_fifo_pending,
+-                                            struct ath_buf, list);
+-                      list_cut_position(&bf_head,
+-                                        &txq->txq_fifo_pending,
+-                                        &bf->bf_lastbf->list);
+-                      spin_unlock_bh(&txq->axq_lock);
++              int idx = txq->txq_tailidx;
+-                      if (bf_isampdu(bf))
+-                              ath_tx_complete_aggr(sc, txq, bf, &bf_head,
+-                                                   &ts, 0, retry_tx);
+-                      else
+-                              ath_tx_complete_buf(sc, bf, txq, &bf_head,
+-                                                  &ts, 0, 0);
+-                      spin_lock_bh(&txq->axq_lock);
++              while (!list_empty(&txq->txq_fifo[idx])) {
++                      ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
++                                         retry_tx);
++
++                      INCR(idx, ATH_TXFIFO_DEPTH);
+               }
+-              spin_unlock_bh(&txq->axq_lock);
++              txq->txq_tailidx = idx;
+       }
++      txq->axq_link = NULL;
++      txq->axq_tx_inprogress = false;
++      ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
++
+       /* flush any pending frames if aggregation is enabled */
+-      if (sc->sc_flags & SC_OP_TXAGGR) {
+-              if (!retry_tx) {
+-                      spin_lock_bh(&txq->axq_lock);
+-                      ath_txq_drain_pending_buffers(sc, txq);
+-                      spin_unlock_bh(&txq->axq_lock);
+-              }
+-      }
++      if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
++              ath_txq_drain_pending_buffers(sc, txq);
++
++      spin_unlock_bh(&txq->axq_lock);
  }
- EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info);
+ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+@@ -1370,11 +1327,13 @@ void ath_txq_schedule(struct ath_softc *
+  * assume the descriptors are already chained together by caller.
+  */
+ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+-                           struct list_head *head)
++                           struct list_head *head, bool internal)
+ {
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+-      struct ath_buf *bf;
++      struct ath_buf *bf, *bf_last;
++      bool puttxbuf = false;
++      bool edma;
+       /*
+        * Insert the frame on the outbound list and
+@@ -1384,51 +1343,49 @@ static void ath_tx_txqaddbuf(struct ath_
+       if (list_empty(head))
+               return;
++      edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       bf = list_first_entry(head, struct ath_buf, list);
++      bf_last = list_entry(head->prev, struct ath_buf, list);
+       ath_dbg(common, ATH_DBG_QUEUE,
+               "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
+-      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+-              if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
+-                      list_splice_tail_init(head, &txq->txq_fifo_pending);
+-                      return;
+-              }
+-              if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
+-                      ath_dbg(common, ATH_DBG_XMIT,
+-                              "Initializing tx fifo %d which is non-empty\n",
+-                              txq->txq_headidx);
+-              INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
+-              list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
++      if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
++              list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
+               INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
+-              TX_STAT_INC(txq->axq_qnum, puttxbuf);
+-              ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+-              ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+-                      txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
++              puttxbuf = true;
+       } else {
+               list_splice_tail_init(head, &txq->axq_q);
+-              if (txq->axq_link == NULL) {
+-                      TX_STAT_INC(txq->axq_qnum, puttxbuf);
+-                      ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
+-                      ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
+-                              txq->axq_qnum, ito64(bf->bf_daddr),
+-                              bf->bf_desc);
+-              } else {
+-                      *txq->axq_link = bf->bf_daddr;
++              if (txq->axq_link) {
++                      ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
+                       ath_dbg(common, ATH_DBG_XMIT,
+                               "link[%u] (%p)=%llx (%p)\n",
+                               txq->axq_qnum, txq->axq_link,
+                               ito64(bf->bf_daddr), bf->bf_desc);
+-              }
+-              ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
+-                                     &txq->axq_link);
++              } else if (!edma)
++                      puttxbuf = true;
++
++              txq->axq_link = bf_last->bf_desc;
++      }
++
++      if (puttxbuf) {
++              TX_STAT_INC(txq->axq_qnum, puttxbuf);
++              ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
++              ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
++                      txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
++      }
 +
-+void ar9003_hw_disable_phy_restart(struct ath_hw *ah)
++      if (!edma) {
+               TX_STAT_INC(txq->axq_qnum, txstart);
+               ath9k_hw_txstart(ah, txq->axq_qnum);
+       }
+-      txq->axq_depth++;
+-      if (bf_is_ampdu_not_probing(bf))
+-              txq->axq_ampdu_depth++;
++
++      if (!internal) {
++              txq->axq_depth++;
++              if (bf_is_ampdu_not_probing(bf))
++                      txq->axq_ampdu_depth++;
++      }
+ }
+ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
+@@ -1470,7 +1427,7 @@ static void ath_tx_send_ampdu(struct ath
+       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+       bf->bf_lastbf = bf;
+       ath_buf_set_rate(sc, bf, fi->framelen);
+-      ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
++      ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
+ }
+ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+@@ -1490,7 +1447,7 @@ static void ath_tx_send_normal(struct at
+       bf->bf_lastbf = bf;
+       fi = get_frame_info(bf->bf_mpdu);
+       ath_buf_set_rate(sc, bf, fi->framelen);
+-      ath_tx_txqaddbuf(sc, txq, bf_head);
++      ath_tx_txqaddbuf(sc, txq, bf_head, false);
+       TX_STAT_INC(txq->axq_qnum, queued);
+ }
+@@ -2077,6 +2034,38 @@ static void ath_tx_rc_status(struct ath_
+       tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
+ }
++static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
++                                struct ath_tx_status *ts, struct ath_buf *bf,
++                                struct list_head *bf_head)
 +{
-+      u32 val;
-+
-+      /* While receiving unsupported rate frame rx state machine
-+       * gets into a state 0xb and if phy_restart happens in that
-+       * state, BB would go hang. If RXSM is in 0xb state after
-+       * first bb panic, ensure to disable the phy_restart.
-+       */
-+      if (!((MS(ah->bb_watchdog_last_status,
-+                AR_PHY_WATCHDOG_RX_OFDM_SM) == 0xb) ||
-+          ah->bb_hang_rx_ofdm))
-+              return;
++      int txok;
++
++      txq->axq_depth--;
++      txok = !(ts->ts_status & ATH9K_TXERR_MASK);
++      txq->axq_tx_inprogress = false;
++      if (bf_is_ampdu_not_probing(bf))
++              txq->axq_ampdu_depth--;
 +
-+      ah->bb_hang_rx_ofdm = true;
-+      val = REG_READ(ah, AR_PHY_RESTART);
-+      val &= ~AR_PHY_RESTART_ENA;
++      spin_unlock_bh(&txq->axq_lock);
 +
-+      REG_WRITE(ah, AR_PHY_RESTART, val);
++      if (!bf_isampdu(bf)) {
++              /*
++               * This frame is sent out as a single frame.
++               * Use hardware retry status for this frame.
++               */
++              if (ts->ts_status & ATH9K_TXERR_XRETRY)
++                      bf->bf_state.bf_type |= BUF_XRETRY;
++              ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
++              ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
++      } else
++              ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
++
++      spin_lock_bh(&txq->axq_lock);
++
++      if (sc->sc_flags & SC_OP_TXAGGR)
++              ath_txq_schedule(sc, txq);
 +}
-+EXPORT_SYMBOL(ar9003_hw_disable_phy_restart);
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1555,9 +1555,12 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       if (ah->btcoex_hw.enabled)
-               ath9k_hw_btcoex_enable(ah);
--      if (AR_SREV_9300_20_OR_LATER(ah))
-+      if (AR_SREV_9300_20_OR_LATER(ah)) {
-               ar9003_hw_bb_watchdog_config(ah);
-+              ar9003_hw_disable_phy_restart(ah);
-+      }
 +
-       ath9k_hw_apply_gpio_override(ah);
+ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+ {
+       struct ath_hw *ah = sc->sc_ah;
+@@ -2085,20 +2074,18 @@ static void ath_tx_processq(struct ath_s
+       struct list_head bf_head;
+       struct ath_desc *ds;
+       struct ath_tx_status ts;
+-      int txok;
+       int status;
  
-       return 0;
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -842,6 +842,7 @@ struct ath_hw {
-       u32 bb_watchdog_last_status;
-       u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
-+      u8 bb_hang_rx_ofdm; /* true if bb hang due to rx_ofdm */
-       unsigned int paprd_target_power;
-       unsigned int paprd_training_power;
-@@ -990,6 +991,7 @@ void ar9002_hw_enable_wep_aggregation(st
- void ar9003_hw_bb_watchdog_config(struct ath_hw *ah);
- void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
- void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
-+void ar9003_hw_disable_phy_restart(struct ath_hw *ah);
- void ar9003_paprd_enable(struct ath_hw *ah, bool val);
- void ar9003_paprd_populate_single_table(struct ath_hw *ah,
-                                       struct ath9k_hw_cal_data *caldata,
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -670,7 +670,8 @@ void ath9k_tasklet(unsigned long data)
-       u32 status = sc->intrstatus;
-       u32 rxmask;
--      if (status & ATH9K_INT_FATAL) {
-+      if ((status & ATH9K_INT_FATAL) ||
-+          (status & ATH9K_INT_BB_WATCHDOG)) {
-               ath_reset(sc, true);
-               return;
+       ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
+               txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
+               txq->axq_link);
++      spin_lock_bh(&txq->axq_lock);
+       for (;;) {
+-              spin_lock_bh(&txq->axq_lock);
+               if (list_empty(&txq->axq_q)) {
+                       txq->axq_link = NULL;
+                       if (sc->sc_flags & SC_OP_TXAGGR)
+                               ath_txq_schedule(sc, txq);
+-                      spin_unlock_bh(&txq->axq_lock);
+                       break;
+               }
+               bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
+@@ -2114,13 +2101,11 @@ static void ath_tx_processq(struct ath_s
+               bf_held = NULL;
+               if (bf->bf_stale) {
+                       bf_held = bf;
+-                      if (list_is_last(&bf_held->list, &txq->axq_q)) {
+-                              spin_unlock_bh(&txq->axq_lock);
++                      if (list_is_last(&bf_held->list, &txq->axq_q))
+                               break;
+-                      } else {
+-                              bf = list_entry(bf_held->list.next,
+-                                              struct ath_buf, list);
+-                      }
++
++                      bf = list_entry(bf_held->list.next, struct ath_buf,
++                                      list);
+               }
+               lastbf = bf->bf_lastbf;
+@@ -2128,10 +2113,9 @@ static void ath_tx_processq(struct ath_s
+               memset(&ts, 0, sizeof(ts));
+               status = ath9k_hw_txprocdesc(ah, ds, &ts);
+-              if (status == -EINPROGRESS) {
+-                      spin_unlock_bh(&txq->axq_lock);
++              if (status == -EINPROGRESS)
+                       break;
+-              }
++
+               TX_STAT_INC(txq->axq_qnum, txprocdesc);
+               /*
+@@ -2145,42 +2129,14 @@ static void ath_tx_processq(struct ath_s
+                       list_cut_position(&bf_head,
+                               &txq->axq_q, lastbf->list.prev);
+-              txq->axq_depth--;
+-              txok = !(ts.ts_status & ATH9K_TXERR_MASK);
+-              txq->axq_tx_inprogress = false;
+-              if (bf_held)
++              if (bf_held) {
+                       list_del(&bf_held->list);
+-
+-              if (bf_is_ampdu_not_probing(bf))
+-                      txq->axq_ampdu_depth--;
+-
+-              spin_unlock_bh(&txq->axq_lock);
+-
+-              if (bf_held)
+                       ath_tx_return_buffer(sc, bf_held);
+-
+-              if (!bf_isampdu(bf)) {
+-                      /*
+-                       * This frame is sent out as a single frame.
+-                       * Use hardware retry status for this frame.
+-                       */
+-                      if (ts.ts_status & ATH9K_TXERR_XRETRY)
+-                              bf->bf_state.bf_type |= BUF_XRETRY;
+-                      ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
+               }
+-              if (bf_isampdu(bf))
+-                      ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
+-                                           true);
+-              else
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
+-
+-              spin_lock_bh(&txq->axq_lock);
+-
+-              if (sc->sc_flags & SC_OP_TXAGGR)
+-                      ath_txq_schedule(sc, txq);
+-              spin_unlock_bh(&txq->axq_lock);
++              ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
        }
-@@ -737,6 +738,7 @@ irqreturn_t ath_isr(int irq, void *dev)
++      spin_unlock_bh(&txq->axq_lock);
+ }
+ static void ath_tx_complete_poll_work(struct work_struct *work)
+@@ -2237,17 +2193,16 @@ void ath_tx_tasklet(struct ath_softc *sc
+ void ath_tx_edma_tasklet(struct ath_softc *sc)
+ {
+-      struct ath_tx_status txs;
++      struct ath_tx_status ts;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_txq *txq;
+       struct ath_buf *bf, *lastbf;
+       struct list_head bf_head;
+       int status;
+-      int txok;
+       for (;;) {
+-              status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
++              status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
+               if (status == -EINPROGRESS)
+                       break;
+               if (status == -EIO) {
+@@ -2257,12 +2212,13 @@ void ath_tx_edma_tasklet(struct ath_soft
+               }
+               /* Skip beacon completions */
+-              if (txs.qid == sc->beacon.beaconq)
++              if (ts.qid == sc->beacon.beaconq)
+                       continue;
+-              txq = &sc->tx.txq[txs.qid];
++              txq = &sc->tx.txq[ts.qid];
+               spin_lock_bh(&txq->axq_lock);
++
+               if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+                       spin_unlock_bh(&txq->axq_lock);
+                       return;
+@@ -2275,41 +2231,21 @@ void ath_tx_edma_tasklet(struct ath_soft
+               INIT_LIST_HEAD(&bf_head);
+               list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
+                                 &lastbf->list);
+-              INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
+-              txq->axq_depth--;
+-              txq->axq_tx_inprogress = false;
+-              if (bf_is_ampdu_not_probing(bf))
+-                      txq->axq_ampdu_depth--;
+-              spin_unlock_bh(&txq->axq_lock);
+-              txok = !(txs.ts_status & ATH9K_TXERR_MASK);
+-
+-              if (!bf_isampdu(bf)) {
+-                      if (txs.ts_status & ATH9K_TXERR_XRETRY)
+-                              bf->bf_state.bf_type |= BUF_XRETRY;
+-                      ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
+-              }
+-
+-              if (bf_isampdu(bf))
+-                      ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
+-                                           txok, true);
+-              else
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head,
+-                                          &txs, txok, 0);
++              if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
++                      INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
+-              spin_lock_bh(&txq->axq_lock);
++                      if (!list_empty(&txq->axq_q)) {
++                              struct list_head bf_q;
+-              if (!list_empty(&txq->txq_fifo_pending)) {
+-                      INIT_LIST_HEAD(&bf_head);
+-                      bf = list_first_entry(&txq->txq_fifo_pending,
+-                                            struct ath_buf, list);
+-                      list_cut_position(&bf_head,
+-                                        &txq->txq_fifo_pending,
+-                                        &bf->bf_lastbf->list);
+-                      ath_tx_txqaddbuf(sc, txq, &bf_head);
+-              } else if (sc->sc_flags & SC_OP_TXAGGR)
+-                      ath_txq_schedule(sc, txq);
++                              INIT_LIST_HEAD(&bf_q);
++                              txq->axq_link = NULL;
++                              list_splice_tail_init(&txq->axq_q, &bf_q);
++                              ath_tx_txqaddbuf(sc, txq, &bf_q, true);
++                      }
++              }
++              ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
+               spin_unlock_bh(&txq->axq_lock);
+       }
+ }
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -161,6 +161,8 @@ static void ieee80211_send_addba_resp(st
+               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
++      else if (sdata->vif.type == NL80211_IFTYPE_WDS)
++              memcpy(mgmt->bssid, da, ETH_ALEN);
+       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                         IEEE80211_STYPE_ACTION);
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
+       memcpy(mgmt->da, da, ETH_ALEN);
+       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+       if (sdata->vif.type == NL80211_IFTYPE_AP ||
+-          sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++          sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
++          sdata->vif.type == NL80211_IFTYPE_WDS)
+               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+@@ -388,7 +389,8 @@ int ieee80211_start_tx_ba_session(struct
+        */
+       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+-          sdata->vif.type != NL80211_IFTYPE_AP)
++          sdata->vif.type != NL80211_IFTYPE_AP &&
++          sdata->vif.type != NL80211_IFTYPE_WDS)
+               return -EINVAL;
+       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
+--- a/net/mac80211/debugfs_sta.c
++++ b/net/mac80211/debugfs_sta.c
+@@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
+       char buf[100];
+       struct sta_info *sta = file->private_data;
+       u32 staflags = get_sta_flags(sta);
+-      int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
++      int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
+               staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
+               staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+               staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
+@@ -67,7 +67,6 @@ static ssize_t sta_flags_read(struct fil
+               staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+               staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
+               staflags & WLAN_STA_WME ? "WME\n" : "",
+-              staflags & WLAN_STA_WDS ? "WDS\n" : "",
+               staflags & WLAN_STA_MFP ? "MFP\n" : "");
+       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+ }
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
  {
- #define SCHED_INTR (                          \
-               ATH9K_INT_FATAL |               \
-+              ATH9K_INT_BB_WATCHDOG |         \
-               ATH9K_INT_RXORN |               \
-               ATH9K_INT_RXEOL |               \
-               ATH9K_INT_RX |                  \
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+-      struct sta_info *sta;
+       u32 changed = 0;
+       int res;
+       u32 hw_reconf_flags = 0;
+@@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_
+       set_bit(SDATA_STATE_RUNNING, &sdata->state);
+-      if (sdata->vif.type == NL80211_IFTYPE_WDS) {
+-              /* Create STA entry for the WDS peer */
+-              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
+-                                   GFP_KERNEL);
+-              if (!sta) {
+-                      res = -ENOMEM;
+-                      goto err_del_interface;
+-              }
+-
+-              /* no locking required since STA is not live yet */
+-              sta->flags |= WLAN_STA_AUTHORIZED;
+-
+-              res = sta_info_insert(sta);
+-              if (res) {
+-                      /* STA has been freed */
+-                      goto err_del_interface;
+-              }
+-
+-              rate_control_rate_init(sta);
+-      }
+-
+       /*
+        * set_multicast_list will be invoked by the networking core
+        * which will check whether any increments here were done in
+@@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_
+       netif_tx_start_all_queues(dev);
+       return 0;
+- err_del_interface:
+-      drv_remove_interface(local, &sdata->vif);
++
+  err_stop:
+       if (!local->open_count)
+               drv_stop(local);
+@@ -718,6 +695,70 @@ static void ieee80211_if_setup(struct ne
+       dev->destructor = free_netdev;
+ }
++static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
++                                       struct sk_buff *skb)
++{
++      struct ieee80211_local *local = sdata->local;
++      struct ieee80211_rx_status *rx_status;
++      struct ieee802_11_elems elems;
++      struct ieee80211_mgmt *mgmt;
++      struct sta_info *sta;
++      size_t baselen;
++      u32 rates = 0;
++      u16 stype;
++      bool new = false;
++      enum ieee80211_band band = local->hw.conf.channel->band;
++      struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
++
++      rx_status = IEEE80211_SKB_RXCB(skb);
++      mgmt = (struct ieee80211_mgmt *) skb->data;
++      stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
++
++      if (stype != IEEE80211_STYPE_BEACON)
++              return;
++
++      baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
++      if (baselen > skb->len)
++              return;
++
++      ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
++                             skb->len - baselen, &elems);
++
++      rates = ieee80211_sta_get_rates(local, &elems, band);
++
++      rcu_read_lock();
++
++      sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
++
++      if (!sta) {
++              rcu_read_unlock();
++              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
++                                   GFP_KERNEL);
++              if (!sta)
++                      return;
++
++              new = true;
++      }
++
++      sta->last_rx = jiffies;
++      sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
++
++      if (elems.ht_cap_elem)
++              ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
++                              elems.ht_cap_elem, &sta->sta.ht_cap);
++
++      if (elems.wmm_param)
++              set_sta_flags(sta, WLAN_STA_WME);
++
++      if (new) {
++              sta->flags = WLAN_STA_AUTHORIZED;
++              rate_control_rate_init(sta);
++              sta_info_insert_rcu(sta);
++      }
++
++      rcu_read_unlock();
++}
++
+ static void ieee80211_iface_work(struct work_struct *work)
+ {
+       struct ieee80211_sub_if_data *sdata =
+@@ -822,6 +863,9 @@ static void ieee80211_iface_work(struct 
+                               break;
+                       ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+                       break;
++              case NL80211_IFTYPE_WDS:
++                      ieee80211_wds_rx_queued_mgmt(sdata, skb);
++                      break;
+               default:
+                       WARN(1, "frame for unexpected interface type");
+                       break;
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+                */
+               if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+                   sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+-                  sdata->vif.type != NL80211_IFTYPE_AP)
++                  sdata->vif.type != NL80211_IFTYPE_AP &&
++                  sdata->vif.type != NL80211_IFTYPE_WDS)
+                       break;
+               /* verify action_code is present */
+@@ -2335,13 +2336,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+       if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+           sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+-          sdata->vif.type != NL80211_IFTYPE_STATION)
++          sdata->vif.type != NL80211_IFTYPE_STATION &&
++          sdata->vif.type != NL80211_IFTYPE_WDS)
+               return RX_DROP_MONITOR;
+       switch (stype) {
+       case cpu_to_le16(IEEE80211_STYPE_BEACON):
+       case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+-              /* process for all: mesh, mlme, ibss */
++              /* process for all: mesh, mlme, ibss, wds */
+               break;
+       case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+       case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+@@ -2680,10 +2682,16 @@ static int prepare_for_handlers(struct i
+               }
+               break;
+       case NL80211_IFTYPE_WDS:
+-              if (bssid || !ieee80211_is_data(hdr->frame_control))
+-                      return 0;
+               if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
+                       return 0;
++
++              if (ieee80211_is_data(hdr->frame_control) ||
++                  ieee80211_is_action(hdr->frame_control)) {
++                      if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
++                              return 0;
++              } else if (!ieee80211_is_beacon(hdr->frame_control))
++                      return 0;
++
+               break;
+       default:
+               /* should never get here */
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -31,7 +31,6 @@
+  *    frames.
+  * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
+  * @WLAN_STA_WME: Station is a QoS-STA.
+- * @WLAN_STA_WDS: Station is one of our WDS peers.
+  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
+  *    IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
+  *    frame to this station is transmitted.
+@@ -54,7 +53,6 @@ enum ieee80211_sta_info_flags {
+       WLAN_STA_SHORT_PREAMBLE = 1<<4,
+       WLAN_STA_ASSOC_AP       = 1<<5,
+       WLAN_STA_WME            = 1<<6,
+-      WLAN_STA_WDS            = 1<<7,
+       WLAN_STA_CLEAR_PS_FILT  = 1<<9,
+       WLAN_STA_MFP            = 1<<10,
+       WLAN_STA_BLOCK_BA       = 1<<11,
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -116,6 +116,7 @@ struct ath_tx_stats {
+       u32 tx_bytes_all;
+       u32 queued;
+       u32 completed;
++      u32 xretries;
+       u32 a_aggr;
+       u32 a_queued_hw;
+       u32 a_queued_sw;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -4645,10 +4645,16 @@ static void ar9003_hw_set_power_per_rate
+       case 1:
+               break;
+       case 2:
+-              scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++              if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
++                      scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++              else
++                      scaledPower = 0;
+               break;
+       case 3:
+-              scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++              if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
++                      scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++              else
++                      scaledPower = 0;
+               break;
+       }
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -524,10 +524,16 @@ static void ath9k_hw_set_ar9287_power_pe
+       case 1:
+               break;
+       case 2:
+-              scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++              if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
++                      scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++              else
++                      scaledPower = 0;
+               break;
+       case 3:
+-              scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++              if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
++                      scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++              else
++                      scaledPower = 0;
+               break;
+       }
+       scaledPower = max((u16)0, scaledPower);
index 6d872e9..6982671 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1482,15 +1482,6 @@ static int ath9k_add_interface(struct ie
+@@ -1480,15 +1480,6 @@ static int ath9k_add_interface(struct ie
                }
        }
  
@@ -16,7 +16,7 @@
        ath_dbg(common, ATH_DBG_CONFIG,
                "Attach a VIF of type: %d\n", vif->type);
  
-@@ -1516,15 +1507,6 @@ static int ath9k_change_interface(struct
+@@ -1514,15 +1505,6 @@ static int ath9k_change_interface(struct
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
  
index fa330d0..4aa83c7 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1120,6 +1120,53 @@ static const struct file_operations fops
+@@ -1131,6 +1131,53 @@ static const struct file_operations fops
        .llseek = default_llseek,/* read accesses f_pos */
  };
  
@@ -54,7 +54,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1168,6 +1215,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1179,6 +1226,9 @@ int ath9k_init_debug(struct ath_hw *ah)
        debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
                           sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
  
index 3052c41..951e31d 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -366,7 +366,7 @@ struct ath_vif {
+@@ -365,7 +365,7 @@ struct ath_vif {
   * number of beacon intervals, the game's up.
   */
  #define BSTUCK_THRESH                 9
diff --git a/package/mac80211/patches/521-mac80211_ht_change_rate_update.patch b/package/mac80211/patches/521-mac80211_ht_change_rate_update.patch
new file mode 100644 (file)
index 0000000..d2f1982
--- /dev/null
@@ -0,0 +1,35 @@
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -239,7 +239,9 @@ void ieee80211_bss_info_change_notify(st
+                                     u32 changed)
+ {
+       struct ieee80211_local *local = sdata->local;
++      struct ieee80211_supported_band *sband;
+       static const u8 zero[ETH_ALEN] = { 0 };
++      struct sta_info *sta;
+       if (!changed)
+               return;
+@@ -269,6 +271,22 @@ void ieee80211_bss_info_change_notify(st
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_AP:
++              if (!(changed & BSS_CHANGED_HT))
++                      break;
++
++              sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
++              rcu_read_lock();
++              list_for_each_entry(sta, &local->sta_list, list) {
++                      if (sta->sdata != sdata &&
++                          (!sdata->bss || sta->sdata->bss != sdata->bss))
++                              continue;
++
++                      rate_control_rate_update(local, sband, sta,
++                              IEEE80211_RC_HT_CHANGED,
++                              local->_oper_channel_type);
++              }
++              rcu_read_unlock();
++              break;
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_WDS:
+       case NL80211_IFTYPE_MESH_POINT:
diff --git a/package/mac80211/patches/530-ath9k_noise_dbm_fixup.patch b/package/mac80211/patches/530-ath9k_noise_dbm_fixup.patch
new file mode 100644 (file)
index 0000000..8f72207
--- /dev/null
@@ -0,0 +1,99 @@
+--- a/drivers/net/wireless/ath/ath9k/calib.c
++++ b/drivers/net/wireless/ath/ath9k/calib.c
+@@ -63,6 +63,19 @@ static s16 ath9k_hw_get_default_nf(struc
+       return ath9k_hw_get_nf_limits(ah, chan)->nominal;
+ }
++s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
++{
++      s8 noise = ATH_DEFAULT_NOISE_FLOOR;
++
++      if (chan && chan->noisefloor) {
++              s8 delta = chan->noisefloor -
++                         ath9k_hw_get_default_nf(ah, chan);
++              if (delta > 0)
++                      noise += delta;
++      }
++      return noise;
++}
++EXPORT_SYMBOL(ath9k_hw_getchan_noise);
+ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
+                                             struct ath9k_hw_cal_data *cal,
+@@ -378,6 +391,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
+       if (!caldata) {
+               chan->noisefloor = nf;
++              ah->noise = ath9k_hw_getchan_noise(ah, chan);
+               return false;
+       }
+@@ -385,6 +399,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
+       caldata->nfcal_pending = false;
+       ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
+       chan->noisefloor = h[0].privNF;
++      ah->noise = ath9k_hw_getchan_noise(ah, chan);
+       return true;
+ }
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1344,6 +1344,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+               memset(caldata, 0, sizeof(*caldata));
+               ath9k_init_nfcal_hist_buffer(ah, chan);
+       }
++      ah->noise = ath9k_hw_getchan_noise(ah, chan);
+       if (bChannelChange &&
+           (ah->chip_fullsleep != true) &&
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -687,6 +687,7 @@ struct ath_hw {
+       enum nl80211_iftype opmode;
+       enum ath9k_power_mode power_mode;
++      s8 noise;
+       struct ath9k_hw_cal_data *caldata;
+       struct ath9k_pacal_info pacal_info;
+       struct ar5416Stats stats;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -163,7 +163,7 @@ static void ath_update_survey_nf(struct 
+       if (chan->noisefloor) {
+               survey->filled |= SURVEY_INFO_NOISE_DBM;
+-              survey->noise = chan->noisefloor;
++              survey->noise = ath9k_hw_getchan_noise(ah, chan);
+       }
+ }
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -985,6 +985,8 @@ static int ath9k_rx_skb_preprocess(struc
+                                  struct ieee80211_rx_status *rx_status,
+                                  bool *decrypt_error)
+ {
++      struct ath_hw *ah = common->ah;
++
+       memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+       /*
+@@ -1005,7 +1007,7 @@ static int ath9k_rx_skb_preprocess(struc
+       rx_status->band = hw->conf.channel->band;
+       rx_status->freq = hw->conf.channel->center_freq;
+-      rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
++      rx_status->signal = ah->noise + rx_stats->rs_rssi;
+       rx_status->antenna = rx_stats->rs_antenna;
+       rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+--- a/drivers/net/wireless/ath/ath9k/calib.h
++++ b/drivers/net/wireless/ath/ath9k/calib.h
+@@ -108,6 +108,7 @@ void ath9k_init_nfcal_hist_buffer(struct
+ void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
+ void ath9k_hw_reset_calibration(struct ath_hw *ah,
+                               struct ath9k_cal_list *currCal);
++s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
+ #endif /* CALIB_H */
diff --git a/package/mac80211/patches/530-mac80211_remove_wds_sta_flag.patch b/package/mac80211/patches/530-mac80211_remove_wds_sta_flag.patch
deleted file mode 100644 (file)
index 29c2fd7..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -31,7 +31,6 @@
-  *    frames.
-  * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
-  * @WLAN_STA_WME: Station is a QoS-STA.
-- * @WLAN_STA_WDS: Station is one of our WDS peers.
-  * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
-  *    IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
-  *    frame to this station is transmitted.
-@@ -54,7 +53,6 @@ enum ieee80211_sta_info_flags {
-       WLAN_STA_SHORT_PREAMBLE = 1<<4,
-       WLAN_STA_ASSOC_AP       = 1<<5,
-       WLAN_STA_WME            = 1<<6,
--      WLAN_STA_WDS            = 1<<7,
-       WLAN_STA_CLEAR_PS_FILT  = 1<<9,
-       WLAN_STA_MFP            = 1<<10,
-       WLAN_STA_BLOCK_BA       = 1<<11,
---- a/net/mac80211/debugfs_sta.c
-+++ b/net/mac80211/debugfs_sta.c
-@@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
-       char buf[100];
-       struct sta_info *sta = file->private_data;
-       u32 staflags = get_sta_flags(sta);
--      int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
-+      int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
-               staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
-               staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
-               staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
-@@ -67,7 +67,6 @@ static ssize_t sta_flags_read(struct fil
-               staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
-               staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
-               staflags & WLAN_STA_WME ? "WME\n" : "",
--              staflags & WLAN_STA_WDS ? "WDS\n" : "",
-               staflags & WLAN_STA_MFP ? "MFP\n" : "");
-       return simple_read_from_buffer(userbuf, count, ppos, buf, res);
- }
diff --git a/package/mac80211/patches/531-mac80211_fix_iftype_wds.patch b/package/mac80211/patches/531-mac80211_fix_iftype_wds.patch
deleted file mode 100644 (file)
index 98a8993..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2335,13 +2335,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
-       if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-           sdata->vif.type != NL80211_IFTYPE_ADHOC &&
--          sdata->vif.type != NL80211_IFTYPE_STATION)
-+          sdata->vif.type != NL80211_IFTYPE_STATION &&
-+          sdata->vif.type != NL80211_IFTYPE_WDS)
-               return RX_DROP_MONITOR;
-       switch (stype) {
-       case cpu_to_le16(IEEE80211_STYPE_BEACON):
-       case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
--              /* process for all: mesh, mlme, ibss */
-+              /* process for all: mesh, mlme, ibss, wds */
-               break;
-       case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-       case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
-@@ -2680,7 +2681,10 @@ static int prepare_for_handlers(struct i
-               }
-               break;
-       case NL80211_IFTYPE_WDS:
--              if (bssid || !ieee80211_is_data(hdr->frame_control))
-+              if (bssid) {
-+                      if (!ieee80211_is_beacon(hdr->frame_control))
-+                              return 0;
-+              } else if (!ieee80211_is_data(hdr->frame_control))
-                       return 0;
-               if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
-                       return 0;
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
- {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = sdata->local;
--      struct sta_info *sta;
-       u32 changed = 0;
-       int res;
-       u32 hw_reconf_flags = 0;
-@@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_
-       set_bit(SDATA_STATE_RUNNING, &sdata->state);
--      if (sdata->vif.type == NL80211_IFTYPE_WDS) {
--              /* Create STA entry for the WDS peer */
--              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
--                                   GFP_KERNEL);
--              if (!sta) {
--                      res = -ENOMEM;
--                      goto err_del_interface;
--              }
--
--              /* no locking required since STA is not live yet */
--              sta->flags |= WLAN_STA_AUTHORIZED;
--
--              res = sta_info_insert(sta);
--              if (res) {
--                      /* STA has been freed */
--                      goto err_del_interface;
--              }
--
--              rate_control_rate_init(sta);
--      }
--
-       /*
-        * set_multicast_list will be invoked by the networking core
-        * which will check whether any increments here were done in
-@@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_
-       netif_tx_start_all_queues(dev);
-       return 0;
-- err_del_interface:
--      drv_remove_interface(local, &sdata->vif);
-+
-  err_stop:
-       if (!local->open_count)
-               drv_stop(local);
-@@ -718,6 +695,70 @@ static void ieee80211_if_setup(struct ne
-       dev->destructor = free_netdev;
- }
-+static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
-+                                       struct sk_buff *skb)
-+{
-+      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_rx_status *rx_status;
-+      struct ieee802_11_elems elems;
-+      struct ieee80211_mgmt *mgmt;
-+      struct sta_info *sta;
-+      size_t baselen;
-+      u32 rates = 0;
-+      u16 stype;
-+      bool new = false;
-+      enum ieee80211_band band = local->hw.conf.channel->band;
-+      struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
-+
-+      rx_status = IEEE80211_SKB_RXCB(skb);
-+      mgmt = (struct ieee80211_mgmt *) skb->data;
-+      stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
-+
-+      if (stype != IEEE80211_STYPE_BEACON)
-+              return;
-+
-+      baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
-+      if (baselen > skb->len)
-+              return;
-+
-+      ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
-+                             skb->len - baselen, &elems);
-+
-+      rates = ieee80211_sta_get_rates(local, &elems, band);
-+
-+      rcu_read_lock();
-+
-+      sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
-+
-+      if (!sta) {
-+              rcu_read_unlock();
-+              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
-+                                   GFP_KERNEL);
-+              if (!sta)
-+                      return;
-+
-+              new = true;
-+      }
-+
-+      sta->last_rx = jiffies;
-+      sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
-+
-+      if (elems.ht_cap_elem)
-+              ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
-+                              elems.ht_cap_elem, &sta->sta.ht_cap);
-+
-+      if (elems.wmm_param)
-+              set_sta_flags(sta, WLAN_STA_WME);
-+
-+      if (new) {
-+              sta->flags = WLAN_STA_AUTHORIZED;
-+              rate_control_rate_init(sta);
-+              sta_info_insert_rcu(sta);
-+      }
-+
-+      rcu_read_unlock();
-+}
-+
- static void ieee80211_iface_work(struct work_struct *work)
- {
-       struct ieee80211_sub_if_data *sdata =
-@@ -822,6 +863,9 @@ static void ieee80211_iface_work(struct 
-                               break;
-                       ieee80211_mesh_rx_queued_mgmt(sdata, skb);
-                       break;
-+              case NL80211_IFTYPE_WDS:
-+                      ieee80211_wds_rx_queued_mgmt(sdata, skb);
-+                      break;
-               default:
-                       WARN(1, "frame for unexpected interface type");
-                       break;
diff --git a/package/mac80211/patches/532-mac80211_enable_iftype_wds_aggregation.patch b/package/mac80211/patches/532-mac80211_enable_iftype_wds_aggregation.patch
deleted file mode 100644 (file)
index f981be4..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
-       memcpy(mgmt->da, da, ETH_ALEN);
-       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
-       if (sdata->vif.type == NL80211_IFTYPE_AP ||
--          sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+          sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-+              sdata->vif.type == NL80211_IFTYPE_WDS)
-               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
-       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-@@ -388,7 +389,8 @@ int ieee80211_start_tx_ba_session(struct
-        */
-       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-           sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
--          sdata->vif.type != NL80211_IFTYPE_AP)
-+          sdata->vif.type != NL80211_IFTYPE_AP &&
-+          sdata->vif.type != NL80211_IFTYPE_WDS)
-               return -EINVAL;
-       if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -161,6 +161,8 @@ static void ieee80211_send_addba_resp(st
-               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
-       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-+      else if (sdata->vif.type == NL80211_IFTYPE_WDS)
-+              memcpy(mgmt->bssid, da, ETH_ALEN);
-       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-                                         IEEE80211_STYPE_ACTION);
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
-                */
-               if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-                   sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
--                  sdata->vif.type != NL80211_IFTYPE_AP)
-+                  sdata->vif.type != NL80211_IFTYPE_AP &&
-+                  sdata->vif.type != NL80211_IFTYPE_WDS)
-                       break;
-               /* verify action_code is present */
-@@ -2681,13 +2682,16 @@ static int prepare_for_handlers(struct i
-               }
-               break;
-       case NL80211_IFTYPE_WDS:
--              if (bssid) {
--                      if (!ieee80211_is_beacon(hdr->frame_control))
--                              return 0;
--              } else if (!ieee80211_is_data(hdr->frame_control))
--                      return 0;
-               if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
-                       return 0;
-+
-+              if (ieee80211_is_data(hdr->frame_control) ||
-+                  ieee80211_is_action(hdr->frame_control)) {
-+                      if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
-+                              return 0;
-+              } else if (!ieee80211_is_beacon(hdr->frame_control))
-+                      return 0;
-+
-               break;
-       default:
-               /* should never get here */
diff --git a/package/mac80211/patches/540-ath9k_debugfs_show_xretry.patch b/package/mac80211/patches/540-ath9k_debugfs_show_xretry.patch
deleted file mode 100644 (file)
index ca6ef3b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -548,6 +548,7 @@ static ssize_t read_file_xmit(struct fil
-       PR("MPDUs Queued:    ", queued);
-       PR("MPDUs Completed: ", completed);
-+      PR("MPDUs XRetried:  ", xretries);
-       PR("Aggregates:      ", a_aggr);
-       PR("AMPDUs Queued HW:", a_queued_hw);
-       PR("AMPDUs Queued SW:", a_queued_sw);
-@@ -803,7 +804,10 @@ void ath_debug_stat_tx(struct ath_softc 
-               else
-                       TX_STAT_INC(qnum, a_completed);
-       } else {
--              TX_STAT_INC(qnum, completed);
-+              if (bf_isxretried(bf))
-+                      TX_STAT_INC(qnum, xretries);
-+              else
-+                      TX_STAT_INC(qnum, completed);
-       }
-       if (ts->ts_status & ATH9K_TXERR_FIFO)
---- a/drivers/net/wireless/ath/ath9k/debug.h
-+++ b/drivers/net/wireless/ath/ath9k/debug.h
-@@ -116,6 +116,7 @@ struct ath_tx_stats {
-       u32 tx_bytes_all;
-       u32 queued;
-       u32 completed;
-+      u32 xretries;
-       u32 a_aggr;
-       u32 a_queued_hw;
-       u32 a_queued_sw;
diff --git a/package/mac80211/patches/550-mac80211_ht_change_rate_update.patch b/package/mac80211/patches/550-mac80211_ht_change_rate_update.patch
deleted file mode 100644 (file)
index d2f1982..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -239,7 +239,9 @@ void ieee80211_bss_info_change_notify(st
-                                     u32 changed)
- {
-       struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_supported_band *sband;
-       static const u8 zero[ETH_ALEN] = { 0 };
-+      struct sta_info *sta;
-       if (!changed)
-               return;
-@@ -269,6 +271,22 @@ void ieee80211_bss_info_change_notify(st
-       switch (sdata->vif.type) {
-       case NL80211_IFTYPE_AP:
-+              if (!(changed & BSS_CHANGED_HT))
-+                      break;
-+
-+              sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+              rcu_read_lock();
-+              list_for_each_entry(sta, &local->sta_list, list) {
-+                      if (sta->sdata != sdata &&
-+                          (!sdata->bss || sta->sdata->bss != sdata->bss))
-+                              continue;
-+
-+                      rate_control_rate_update(local, sband, sta,
-+                              IEEE80211_RC_HT_CHANGED,
-+                              local->_oper_channel_type);
-+              }
-+              rcu_read_unlock();
-+              break;
-       case NL80211_IFTYPE_ADHOC:
-       case NL80211_IFTYPE_WDS:
-       case NL80211_IFTYPE_MESH_POINT:
diff --git a/package/mac80211/patches/560-ath9k_noise_dbm_fixup.patch b/package/mac80211/patches/560-ath9k_noise_dbm_fixup.patch
deleted file mode 100644 (file)
index 486e5d1..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/calib.c
-+++ b/drivers/net/wireless/ath/ath9k/calib.c
-@@ -63,6 +63,19 @@ static s16 ath9k_hw_get_default_nf(struc
-       return ath9k_hw_get_nf_limits(ah, chan)->nominal;
- }
-+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
-+{
-+      s8 noise = ATH_DEFAULT_NOISE_FLOOR;
-+
-+      if (chan && chan->noisefloor) {
-+              s8 delta = chan->noisefloor -
-+                         ath9k_hw_get_default_nf(ah, chan);
-+              if (delta > 0)
-+                      noise += delta;
-+      }
-+      return noise;
-+}
-+EXPORT_SYMBOL(ath9k_hw_getchan_noise);
- static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
-                                             struct ath9k_hw_cal_data *cal,
-@@ -378,6 +391,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
-       if (!caldata) {
-               chan->noisefloor = nf;
-+              ah->noise = ath9k_hw_getchan_noise(ah, chan);
-               return false;
-       }
-@@ -385,6 +399,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
-       caldata->nfcal_pending = false;
-       ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
-       chan->noisefloor = h[0].privNF;
-+      ah->noise = ath9k_hw_getchan_noise(ah, chan);
-       return true;
- }
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1344,6 +1344,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-               memset(caldata, 0, sizeof(*caldata));
-               ath9k_init_nfcal_hist_buffer(ah, chan);
-       }
-+      ah->noise = ath9k_hw_getchan_noise(ah, chan);
-       if (bChannelChange &&
-           (ah->chip_fullsleep != true) &&
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -688,6 +688,7 @@ struct ath_hw {
-       enum nl80211_iftype opmode;
-       enum ath9k_power_mode power_mode;
-+      s8 noise;
-       struct ath9k_hw_cal_data *caldata;
-       struct ath9k_pacal_info pacal_info;
-       struct ar5416Stats stats;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -165,7 +165,7 @@ static void ath_update_survey_nf(struct 
-       if (chan->noisefloor) {
-               survey->filled |= SURVEY_INFO_NOISE_DBM;
--              survey->noise = chan->noisefloor;
-+              survey->noise = ath9k_hw_getchan_noise(ah, chan);
-       }
- }
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -985,6 +985,8 @@ static int ath9k_rx_skb_preprocess(struc
-                                  struct ieee80211_rx_status *rx_status,
-                                  bool *decrypt_error)
- {
-+      struct ath_hw *ah = common->ah;
-+
-       memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-       /*
-@@ -1005,7 +1007,7 @@ static int ath9k_rx_skb_preprocess(struc
-       rx_status->band = hw->conf.channel->band;
-       rx_status->freq = hw->conf.channel->center_freq;
--      rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
-+      rx_status->signal = ah->noise + rx_stats->rs_rssi;
-       rx_status->antenna = rx_stats->rs_antenna;
-       rx_status->flag |= RX_FLAG_MACTIME_MPDU;
---- a/drivers/net/wireless/ath/ath9k/calib.h
-+++ b/drivers/net/wireless/ath/ath9k/calib.h
-@@ -108,6 +108,7 @@ void ath9k_init_nfcal_hist_buffer(struct
- void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
- void ath9k_hw_reset_calibration(struct ath_hw *ah,
-                               struct ath9k_cal_list *currCal);
-+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
- #endif /* CALIB_H */
diff --git a/package/mac80211/patches/570-ath9k_fix_adhoc_beacons.patch b/package/mac80211/patches/570-ath9k_fix_adhoc_beacons.patch
deleted file mode 100644 (file)
index d3eb764..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -351,9 +351,7 @@ void ath_beacon_tasklet(unsigned long da
-       struct ath_buf *bf = NULL;
-       struct ieee80211_vif *vif;
-       int slot;
--      u32 bfaddr, bc = 0, tsftu;
--      u64 tsf;
--      u16 intval;
-+      u32 bfaddr, bc = 0;
-       /*
-        * Check if the previous beacon has gone out.  If
-@@ -388,17 +386,27 @@ void ath_beacon_tasklet(unsigned long da
-        * on the tsf to safeguard against missing an swba.
-        */
--      intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
--      tsf = ath9k_hw_gettsf64(ah);
--      tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
--      tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
--      slot = (tsftu % (intval * ATH_BCBUF)) / intval;
--      vif = sc->beacon.bslot[slot];
-+      if (ah->opmode == NL80211_IFTYPE_AP) {
-+              u16 intval;
-+              u32 tsftu;
-+              u64 tsf;
-+
-+              intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
-+              tsf = ath9k_hw_gettsf64(ah);
-+              tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
-+              tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
-+              slot = (tsftu % (intval * ATH_BCBUF)) / intval;
-+              vif = sc->beacon.bslot[slot];
-+
-+              ath_dbg(common, ATH_DBG_BEACON,
-+                      "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
-+                      slot, tsf, tsftu / ATH_BCBUF, intval, vif);
-+      } else {
-+              slot = 0;
-+              vif = sc->beacon.bslot[slot];
-+      }
--      ath_dbg(common, ATH_DBG_BEACON,
--              "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
--              slot, tsf, tsftu / ATH_BCBUF, intval, vif);
-       bfaddr = 0;
-       if (vif) {
diff --git a/package/mac80211/patches/571-ath9k_fix_adhoc_nexttbtt.patch b/package/mac80211/patches/571-ath9k_fix_adhoc_nexttbtt.patch
deleted file mode 100644 (file)
index 544c7a9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -654,7 +654,7 @@ static void ath_beacon_config_adhoc(stru
-                       delta = (tsf - sc->beacon.bc_tstamp);
-               else
-                       delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
--              nexttbtt = tsf + roundup(delta, intval);
-+              nexttbtt = tsf + intval - (delta % intval);
-       }
-       ath_dbg(common, ATH_DBG_BEACON,
diff --git a/package/mac80211/patches/572-ath9k_tx_last_beacon.patch b/package/mac80211/patches/572-ath9k_tx_last_beacon.patch
deleted file mode 100644 (file)
index 8b2950d..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -397,6 +397,9 @@ struct ath_beacon {
-       struct ath_descdma bdma;
-       struct ath_txq *cabq;
-       struct list_head bbuf;
-+
-+      bool tx_processed;
-+      bool tx_last;
- };
- void ath_beacon_tasklet(unsigned long data);
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -18,6 +18,12 @@
- #define FUDGE 2
-+static void ath9k_reset_beacon_status(struct ath_softc *sc)
-+{
-+      sc->beacon.tx_processed = false;
-+      sc->beacon.tx_last = false;
-+}
-+
- /*
-  *  This function will modify certain transmit queue properties depending on
-  *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
-@@ -72,6 +78,8 @@ static void ath_beacon_setup(struct ath_
-       struct ieee80211_supported_band *sband;
-       u8 rate = 0;
-+      ath9k_reset_beacon_status(sc);
-+
-       ds = bf->bf_desc;
-       flags = ATH9K_TXDESC_NOACK;
-@@ -134,6 +142,8 @@ static struct ath_buf *ath_beacon_genera
-       struct ieee80211_tx_info *info;
-       int cabq_depth;
-+      ath9k_reset_beacon_status(sc);
-+
-       avp = (void *)vif->drv_priv;
-       cabq = sc->beacon.cabq;
-@@ -644,6 +654,8 @@ static void ath_beacon_config_adhoc(stru
-       struct ath_common *common = ath9k_hw_common(ah);
-       u32 tsf, delta, intval, nexttbtt;
-+      ath9k_reset_beacon_status(sc);
-+
-       tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
-       intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -2316,6 +2316,48 @@ static bool ath9k_tx_frames_pending(stru
-       return false;
- }
-+int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
-+{
-+      struct ath_softc *sc = hw->priv;
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ieee80211_vif *vif;
-+      struct ath_vif *avp;
-+      struct ath_buf *bf;
-+      struct ath_tx_status ts;
-+      int status;
-+
-+      if (ah->opmode != NL80211_IFTYPE_ADHOC)
-+              return 0;
-+
-+      vif = sc->beacon.bslot[0];
-+      if (!vif)
-+              return 0;
-+
-+      avp = (void *)vif->drv_priv;
-+      if (!avp->is_bslot_active)
-+              return 0;
-+
-+      if (!sc->beacon.tx_processed) {
-+              tasklet_disable(&sc->bcon_tasklet);
-+
-+              bf = avp->av_bcbuf;
-+              if (!bf || !bf->bf_mpdu)
-+                      goto skip;
-+
-+              status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts);
-+              if (status == -EINPROGRESS)
-+                      goto skip;
-+
-+              sc->beacon.tx_processed = true;
-+              sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
-+
-+skip:
-+              tasklet_enable(&sc->bcon_tasklet);
-+      }
-+
-+      return sc->beacon.tx_last;
-+}
-+
- struct ieee80211_ops ath9k_ops = {
-       .tx                 = ath9k_tx,
-       .start              = ath9k_start,
-@@ -2340,4 +2382,5 @@ struct ieee80211_ops ath9k_ops = {
-       .set_coverage_class = ath9k_set_coverage_class,
-       .flush              = ath9k_flush,
-       .tx_frames_pending  = ath9k_tx_frames_pending,
-+      .tx_last_beacon = ath9k_tx_last_beacon,
- };
diff --git a/package/mac80211/patches/580-ath9k_tx_fifo_cleanup.patch b/package/mac80211/patches/580-ath9k_tx_fifo_cleanup.patch
deleted file mode 100644 (file)
index b334bf1..0000000
+++ /dev/null
@@ -1,598 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -53,7 +53,7 @@ static void ath_tx_complete_buf(struct a
-                               struct ath_txq *txq, struct list_head *bf_q,
-                               struct ath_tx_status *ts, int txok, int sendbar);
- static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
--                           struct list_head *head);
-+                           struct list_head *head, bool internal);
- static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
- static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
-                            struct ath_tx_status *ts, int nframes, int nbad,
-@@ -377,8 +377,7 @@ static void ath_tx_complete_aggr(struct 
-                       bf_next = bf->bf_next;
-                       bf->bf_state.bf_type |= BUF_XRETRY;
--                      if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
--                          !bf->bf_stale || bf_next != NULL)
-+                      if (!bf->bf_stale || bf_next != NULL)
-                               list_move_tail(&bf->list, &bf_head);
-                       ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
-@@ -463,20 +462,14 @@ static void ath_tx_complete_aggr(struct 
-                       }
-               }
--              if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
--                  bf_next == NULL) {
--                      /*
--                       * Make sure the last desc is reclaimed if it
--                       * not a holding desc.
--                       */
--                      if (!bf_last->bf_stale)
--                              list_move_tail(&bf->list, &bf_head);
--                      else
--                              INIT_LIST_HEAD(&bf_head);
--              } else {
--                      BUG_ON(list_empty(bf_q));
-+              /*
-+               * Make sure the last desc is reclaimed if it
-+               * not a holding desc.
-+               */
-+              if (!bf_last->bf_stale || bf_next != NULL)
-                       list_move_tail(&bf->list, &bf_head);
--              }
-+              else
-+                      INIT_LIST_HEAD(&bf_head);
-               if (!txpending || (tid->state & AGGR_CLEANUP)) {
-                       /*
-@@ -837,7 +830,7 @@ static void ath_tx_sched_aggr(struct ath
-                       bf->bf_state.bf_type &= ~BUF_AGGR;
-                       ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
-                       ath_buf_set_rate(sc, bf, fi->framelen);
--                      ath_tx_txqaddbuf(sc, txq, &bf_q);
-+                      ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-                       continue;
-               }
-@@ -849,7 +842,7 @@ static void ath_tx_sched_aggr(struct ath
-               /* anchor last desc of aggregate */
-               ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
--              ath_tx_txqaddbuf(sc, txq, &bf_q);
-+              ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-               TX_STAT_INC(txq->axq_qnum, a_aggr);
-       } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
-@@ -1085,7 +1078,6 @@ struct ath_txq *ath_txq_setup(struct ath
-               txq->txq_headidx = txq->txq_tailidx = 0;
-               for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
-                       INIT_LIST_HEAD(&txq->txq_fifo[i]);
--              INIT_LIST_HEAD(&txq->txq_fifo_pending);
-       }
-       return &sc->tx.txq[axq_qnum];
- }
-@@ -1155,13 +1147,8 @@ static bool bf_is_ampdu_not_probing(stru
-     return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
- }
--/*
-- * Drain a given TX queue (could be Beacon or Data)
-- *
-- * This assumes output has been stopped and
-- * we do not need to block ath_tx_tasklet.
-- */
--void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
-+static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
-+                             struct list_head *list, bool retry_tx)
- {
-       struct ath_buf *bf, *lastbf;
-       struct list_head bf_head;
-@@ -1170,93 +1157,63 @@ void ath_draintxq(struct ath_softc *sc, 
-       memset(&ts, 0, sizeof(ts));
-       INIT_LIST_HEAD(&bf_head);
--      for (;;) {
--              spin_lock_bh(&txq->axq_lock);
-+      while (!list_empty(list)) {
-+              bf = list_first_entry(list, struct ath_buf, list);
--              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
--                      if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
--                              txq->txq_headidx = txq->txq_tailidx = 0;
--                              spin_unlock_bh(&txq->axq_lock);
--                              break;
--                      } else {
--                              bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
--                                                    struct ath_buf, list);
--                      }
--              } else {
--                      if (list_empty(&txq->axq_q)) {
--                              txq->axq_link = NULL;
--                              spin_unlock_bh(&txq->axq_lock);
--                              break;
--                      }
--                      bf = list_first_entry(&txq->axq_q, struct ath_buf,
--                                            list);
--
--                      if (bf->bf_stale) {
--                              list_del(&bf->list);
--                              spin_unlock_bh(&txq->axq_lock);
-+              if (bf->bf_stale) {
-+                      list_del(&bf->list);
--                              ath_tx_return_buffer(sc, bf);
--                              continue;
--                      }
-+                      ath_tx_return_buffer(sc, bf);
-+                      continue;
-               }
-               lastbf = bf->bf_lastbf;
--
--              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
--                      list_cut_position(&bf_head,
--                                        &txq->txq_fifo[txq->txq_tailidx],
--                                        &lastbf->list);
--                      INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
--              } else {
--                      /* remove ath_buf's of the same mpdu from txq */
--                      list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
--              }
-+              list_cut_position(&bf_head, list, &lastbf->list);
-               txq->axq_depth--;
-               if (bf_is_ampdu_not_probing(bf))
-                       txq->axq_ampdu_depth--;
--              spin_unlock_bh(&txq->axq_lock);
-+              spin_unlock_bh(&txq->axq_lock);
-               if (bf_isampdu(bf))
-                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
-                                            retry_tx);
-               else
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-+              spin_lock_bh(&txq->axq_lock);
-       }
-+}
-+/*
-+ * Drain a given TX queue (could be Beacon or Data)
-+ *
-+ * This assumes output has been stopped and
-+ * we do not need to block ath_tx_tasklet.
-+ */
-+void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
-+{
-       spin_lock_bh(&txq->axq_lock);
--      txq->axq_tx_inprogress = false;
--      spin_unlock_bh(&txq->axq_lock);
--
-       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
--              spin_lock_bh(&txq->axq_lock);
--              while (!list_empty(&txq->txq_fifo_pending)) {
--                      bf = list_first_entry(&txq->txq_fifo_pending,
--                                            struct ath_buf, list);
--                      list_cut_position(&bf_head,
--                                        &txq->txq_fifo_pending,
--                                        &bf->bf_lastbf->list);
--                      spin_unlock_bh(&txq->axq_lock);
-+              int idx = txq->txq_tailidx;
--                      if (bf_isampdu(bf))
--                              ath_tx_complete_aggr(sc, txq, bf, &bf_head,
--                                                   &ts, 0, retry_tx);
--                      else
--                              ath_tx_complete_buf(sc, bf, txq, &bf_head,
--                                                  &ts, 0, 0);
--                      spin_lock_bh(&txq->axq_lock);
-+              while (!list_empty(&txq->txq_fifo[idx])) {
-+                      ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
-+                                         retry_tx);
-+
-+                      INCR(idx, ATH_TXFIFO_DEPTH);
-               }
--              spin_unlock_bh(&txq->axq_lock);
-+              txq->txq_tailidx = idx;
-       }
-+      txq->axq_link = NULL;
-+      txq->axq_tx_inprogress = false;
-+      ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
-+
-       /* flush any pending frames if aggregation is enabled */
--      if (sc->sc_flags & SC_OP_TXAGGR) {
--              if (!retry_tx) {
--                      spin_lock_bh(&txq->axq_lock);
--                      ath_txq_drain_pending_buffers(sc, txq);
--                      spin_unlock_bh(&txq->axq_lock);
--              }
--      }
-+      if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
-+              ath_txq_drain_pending_buffers(sc, txq);
-+
-+      spin_unlock_bh(&txq->axq_lock);
- }
- bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
-@@ -1370,11 +1327,13 @@ void ath_txq_schedule(struct ath_softc *
-  * assume the descriptors are already chained together by caller.
-  */
- static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
--                           struct list_head *head)
-+                           struct list_head *head, bool internal)
- {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
--      struct ath_buf *bf;
-+      struct ath_buf *bf, *bf_last;
-+      bool puttxbuf = false;
-+      bool edma;
-       /*
-        * Insert the frame on the outbound list and
-@@ -1384,51 +1343,49 @@ static void ath_tx_txqaddbuf(struct ath_
-       if (list_empty(head))
-               return;
-+      edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
-       bf = list_first_entry(head, struct ath_buf, list);
-+      bf_last = list_entry(head->prev, struct ath_buf, list);
-       ath_dbg(common, ATH_DBG_QUEUE,
-               "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
--      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
--              if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
--                      list_splice_tail_init(head, &txq->txq_fifo_pending);
--                      return;
--              }
--              if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
--                      ath_dbg(common, ATH_DBG_XMIT,
--                              "Initializing tx fifo %d which is non-empty\n",
--                              txq->txq_headidx);
--              INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
--              list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
-+      if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) {
-+              list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);
-               INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
--              TX_STAT_INC(txq->axq_qnum, puttxbuf);
--              ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
--              ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
--                      txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
-+              puttxbuf = true;
-       } else {
-               list_splice_tail_init(head, &txq->axq_q);
--              if (txq->axq_link == NULL) {
--                      TX_STAT_INC(txq->axq_qnum, puttxbuf);
--                      ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
--                      ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
--                              txq->axq_qnum, ito64(bf->bf_daddr),
--                              bf->bf_desc);
--              } else {
--                      *txq->axq_link = bf->bf_daddr;
-+              if (txq->axq_link) {
-+                      ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);
-                       ath_dbg(common, ATH_DBG_XMIT,
-                               "link[%u] (%p)=%llx (%p)\n",
-                               txq->axq_qnum, txq->axq_link,
-                               ito64(bf->bf_daddr), bf->bf_desc);
--              }
--              ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
--                                     &txq->axq_link);
-+              } else if (!edma)
-+                      puttxbuf = true;
-+
-+              txq->axq_link = bf_last->bf_desc;
-+      }
-+
-+      if (puttxbuf) {
-+              TX_STAT_INC(txq->axq_qnum, puttxbuf);
-+              ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
-+              ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
-+                      txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
-+      }
-+
-+      if (!edma) {
-               TX_STAT_INC(txq->axq_qnum, txstart);
-               ath9k_hw_txstart(ah, txq->axq_qnum);
-       }
--      txq->axq_depth++;
--      if (bf_is_ampdu_not_probing(bf))
--              txq->axq_ampdu_depth++;
-+
-+      if (!internal) {
-+              txq->axq_depth++;
-+              if (bf_is_ampdu_not_probing(bf))
-+                      txq->axq_ampdu_depth++;
-+      }
- }
- static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
-@@ -1470,7 +1427,7 @@ static void ath_tx_send_ampdu(struct ath
-       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
-       bf->bf_lastbf = bf;
-       ath_buf_set_rate(sc, bf, fi->framelen);
--      ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
-+      ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
- }
- static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
-@@ -1490,7 +1447,7 @@ static void ath_tx_send_normal(struct at
-       bf->bf_lastbf = bf;
-       fi = get_frame_info(bf->bf_mpdu);
-       ath_buf_set_rate(sc, bf, fi->framelen);
--      ath_tx_txqaddbuf(sc, txq, bf_head);
-+      ath_tx_txqaddbuf(sc, txq, bf_head, false);
-       TX_STAT_INC(txq->axq_qnum, queued);
- }
-@@ -2077,6 +2034,38 @@ static void ath_tx_rc_status(struct ath_
-       tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
- }
-+static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
-+                                struct ath_tx_status *ts, struct ath_buf *bf,
-+                                struct list_head *bf_head)
-+{
-+      int txok;
-+
-+      txq->axq_depth--;
-+      txok = !(ts->ts_status & ATH9K_TXERR_MASK);
-+      txq->axq_tx_inprogress = false;
-+      if (bf_is_ampdu_not_probing(bf))
-+              txq->axq_ampdu_depth--;
-+
-+      spin_unlock_bh(&txq->axq_lock);
-+
-+      if (!bf_isampdu(bf)) {
-+              /*
-+               * This frame is sent out as a single frame.
-+               * Use hardware retry status for this frame.
-+               */
-+              if (ts->ts_status & ATH9K_TXERR_XRETRY)
-+                      bf->bf_state.bf_type |= BUF_XRETRY;
-+              ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
-+              ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
-+      } else
-+              ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
-+
-+      spin_lock_bh(&txq->axq_lock);
-+
-+      if (sc->sc_flags & SC_OP_TXAGGR)
-+              ath_txq_schedule(sc, txq);
-+}
-+
- static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
- {
-       struct ath_hw *ah = sc->sc_ah;
-@@ -2085,20 +2074,18 @@ static void ath_tx_processq(struct ath_s
-       struct list_head bf_head;
-       struct ath_desc *ds;
-       struct ath_tx_status ts;
--      int txok;
-       int status;
-       ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
-               txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
-               txq->axq_link);
-+      spin_lock_bh(&txq->axq_lock);
-       for (;;) {
--              spin_lock_bh(&txq->axq_lock);
-               if (list_empty(&txq->axq_q)) {
-                       txq->axq_link = NULL;
-                       if (sc->sc_flags & SC_OP_TXAGGR)
-                               ath_txq_schedule(sc, txq);
--                      spin_unlock_bh(&txq->axq_lock);
-                       break;
-               }
-               bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
-@@ -2114,13 +2101,11 @@ static void ath_tx_processq(struct ath_s
-               bf_held = NULL;
-               if (bf->bf_stale) {
-                       bf_held = bf;
--                      if (list_is_last(&bf_held->list, &txq->axq_q)) {
--                              spin_unlock_bh(&txq->axq_lock);
-+                      if (list_is_last(&bf_held->list, &txq->axq_q))
-                               break;
--                      } else {
--                              bf = list_entry(bf_held->list.next,
--                                              struct ath_buf, list);
--                      }
-+
-+                      bf = list_entry(bf_held->list.next, struct ath_buf,
-+                                      list);
-               }
-               lastbf = bf->bf_lastbf;
-@@ -2128,10 +2113,9 @@ static void ath_tx_processq(struct ath_s
-               memset(&ts, 0, sizeof(ts));
-               status = ath9k_hw_txprocdesc(ah, ds, &ts);
--              if (status == -EINPROGRESS) {
--                      spin_unlock_bh(&txq->axq_lock);
-+              if (status == -EINPROGRESS)
-                       break;
--              }
-+
-               TX_STAT_INC(txq->axq_qnum, txprocdesc);
-               /*
-@@ -2145,42 +2129,14 @@ static void ath_tx_processq(struct ath_s
-                       list_cut_position(&bf_head,
-                               &txq->axq_q, lastbf->list.prev);
--              txq->axq_depth--;
--              txok = !(ts.ts_status & ATH9K_TXERR_MASK);
--              txq->axq_tx_inprogress = false;
--              if (bf_held)
-+              if (bf_held) {
-                       list_del(&bf_held->list);
--
--              if (bf_is_ampdu_not_probing(bf))
--                      txq->axq_ampdu_depth--;
--
--              spin_unlock_bh(&txq->axq_lock);
--
--              if (bf_held)
-                       ath_tx_return_buffer(sc, bf_held);
--
--              if (!bf_isampdu(bf)) {
--                      /*
--                       * This frame is sent out as a single frame.
--                       * Use hardware retry status for this frame.
--                       */
--                      if (ts.ts_status & ATH9K_TXERR_XRETRY)
--                              bf->bf_state.bf_type |= BUF_XRETRY;
--                      ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
-               }
--              if (bf_isampdu(bf))
--                      ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
--                                           true);
--              else
--                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
--
--              spin_lock_bh(&txq->axq_lock);
--
--              if (sc->sc_flags & SC_OP_TXAGGR)
--                      ath_txq_schedule(sc, txq);
--              spin_unlock_bh(&txq->axq_lock);
-+              ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
-       }
-+      spin_unlock_bh(&txq->axq_lock);
- }
- static void ath_tx_complete_poll_work(struct work_struct *work)
-@@ -2237,17 +2193,16 @@ void ath_tx_tasklet(struct ath_softc *sc
- void ath_tx_edma_tasklet(struct ath_softc *sc)
- {
--      struct ath_tx_status txs;
-+      struct ath_tx_status ts;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_txq *txq;
-       struct ath_buf *bf, *lastbf;
-       struct list_head bf_head;
-       int status;
--      int txok;
-       for (;;) {
--              status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
-+              status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
-               if (status == -EINPROGRESS)
-                       break;
-               if (status == -EIO) {
-@@ -2257,12 +2212,13 @@ void ath_tx_edma_tasklet(struct ath_soft
-               }
-               /* Skip beacon completions */
--              if (txs.qid == sc->beacon.beaconq)
-+              if (ts.qid == sc->beacon.beaconq)
-                       continue;
--              txq = &sc->tx.txq[txs.qid];
-+              txq = &sc->tx.txq[ts.qid];
-               spin_lock_bh(&txq->axq_lock);
-+
-               if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
-                       spin_unlock_bh(&txq->axq_lock);
-                       return;
-@@ -2275,41 +2231,21 @@ void ath_tx_edma_tasklet(struct ath_soft
-               INIT_LIST_HEAD(&bf_head);
-               list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
-                                 &lastbf->list);
--              INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
--              txq->axq_depth--;
--              txq->axq_tx_inprogress = false;
--              if (bf_is_ampdu_not_probing(bf))
--                      txq->axq_ampdu_depth--;
--              spin_unlock_bh(&txq->axq_lock);
--              txok = !(txs.ts_status & ATH9K_TXERR_MASK);
--
--              if (!bf_isampdu(bf)) {
--                      if (txs.ts_status & ATH9K_TXERR_XRETRY)
--                              bf->bf_state.bf_type |= BUF_XRETRY;
--                      ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
--              }
--
--              if (bf_isampdu(bf))
--                      ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
--                                           txok, true);
--              else
--                      ath_tx_complete_buf(sc, bf, txq, &bf_head,
--                                          &txs, txok, 0);
-+              if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
-+                      INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
--              spin_lock_bh(&txq->axq_lock);
-+                      if (!list_empty(&txq->axq_q)) {
-+                              struct list_head bf_q;
--              if (!list_empty(&txq->txq_fifo_pending)) {
--                      INIT_LIST_HEAD(&bf_head);
--                      bf = list_first_entry(&txq->txq_fifo_pending,
--                                            struct ath_buf, list);
--                      list_cut_position(&bf_head,
--                                        &txq->txq_fifo_pending,
--                                        &bf->bf_lastbf->list);
--                      ath_tx_txqaddbuf(sc, txq, &bf_head);
--              } else if (sc->sc_flags & SC_OP_TXAGGR)
--                      ath_txq_schedule(sc, txq);
-+                              INIT_LIST_HEAD(&bf_q);
-+                              txq->axq_link = NULL;
-+                              list_splice_tail_init(&txq->axq_q, &bf_q);
-+                              ath_tx_txqaddbuf(sc, txq, &bf_q, true);
-+                      }
-+              }
-+              ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
-               spin_unlock_bh(&txq->axq_lock);
-       }
- }
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -179,7 +179,7 @@ enum ATH_AGGR_STATUS {
- struct ath_txq {
-       int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
-       u32 axq_qnum; /* ath9k hardware queue number */
--      u32 *axq_link;
-+      void *axq_link;
-       struct list_head axq_q;
-       spinlock_t axq_lock;
-       u32 axq_depth;
-@@ -188,7 +188,6 @@ struct ath_txq {
-       bool axq_tx_inprogress;
-       struct list_head axq_acq;
-       struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
--      struct list_head txq_fifo_pending;
-       u8 txq_headidx;
-       u8 txq_tailidx;
-       int pending_frames;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -62,8 +62,6 @@ static bool ath9k_has_pending_frames(str
-       if (txq->axq_depth || !list_empty(&txq->axq_acq))
-               pending = true;
--      else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
--              pending = !list_empty(&txq->txq_fifo_pending);
-       spin_unlock_bh(&txq->axq_lock);
-       return pending;
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -586,7 +586,6 @@ static ssize_t read_file_xmit(struct fil
-       PRQLE("axq_q empty:       ", axq_q);
-       PRQLE("axq_acq empty:     ", axq_acq);
--      PRQLE("txq_fifo_pending:  ", txq_fifo_pending);
-       for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
-               snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
-               PRQLE(tmp, txq_fifo[i]);
diff --git a/package/mac80211/patches/581-ath9k_remove_get_desc_link.patch b/package/mac80211/patches/581-ath9k_remove_get_desc_link.patch
deleted file mode 100644 (file)
index 5072842..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-@@ -28,11 +28,6 @@ static void ar9002_hw_set_desc_link(void
-       ((struct ath_desc*) ds)->ds_link = ds_link;
- }
--static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
--{
--      *ds_link = &((struct ath_desc *)ds)->ds_link;
--}
--
- static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
- {
-       u32 isr = 0;
-@@ -437,7 +432,6 @@ void ar9002_hw_attach_mac_ops(struct ath
-       ops->rx_enable = ar9002_hw_rx_enable;
-       ops->set_desc_link = ar9002_hw_set_desc_link;
--      ops->get_desc_link = ar9002_hw_get_desc_link;
-       ops->get_isr = ar9002_hw_get_isr;
-       ops->fill_txdesc = ar9002_hw_fill_txdesc;
-       ops->proc_txdesc = ar9002_hw_proc_txdesc;
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -43,13 +43,6 @@ static void ar9003_hw_set_desc_link(void
-       ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
- }
--static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
--{
--      struct ar9003_txc *ads = ds;
--
--      *ds_link = &ads->link;
--}
--
- static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
- {
-       u32 isr = 0;
-@@ -498,7 +491,6 @@ void ar9003_hw_attach_mac_ops(struct ath
-       ops->rx_enable = ar9003_hw_rx_enable;
-       ops->set_desc_link = ar9003_hw_set_desc_link;
--      ops->get_desc_link = ar9003_hw_get_desc_link;
-       ops->get_isr = ar9003_hw_get_isr;
-       ops->fill_txdesc = ar9003_hw_fill_txdesc;
-       ops->proc_txdesc = ar9003_hw_proc_txdesc;
---- a/drivers/net/wireless/ath/ath9k/hw-ops.h
-+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
-@@ -39,11 +39,6 @@ static inline void ath9k_hw_set_desc_lin
-       ath9k_hw_ops(ah)->set_desc_link(ds, link);
- }
--static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
--                                        u32 **link)
--{
--      ath9k_hw_ops(ah)->get_desc_link(ds, link);
--}
- static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
-                                     struct ath9k_channel *chan,
-                                     u8 rxchainmask,
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -603,7 +603,6 @@ struct ath_hw_ops {
-                                    int power_off);
-       void (*rx_enable)(struct ath_hw *ah);
-       void (*set_desc_link)(void *ds, u32 link);
--      void (*get_desc_link)(void *ds, u32 **link);
-       bool (*calibrate)(struct ath_hw *ah,
-                         struct ath9k_channel *chan,
-                         u8 rxchainmask,
index dcbf668..27a1ac1 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/b43.h
 +++ b/drivers/net/wireless/b43/b43.h
-@@ -718,6 +718,7 @@ struct b43_wldev {
+@@ -720,6 +720,7 @@ struct b43_wldev {
        bool qos_enabled;               /* TRUE, if QoS is used. */
        bool hwcrypto_enabled;          /* TRUE, if HW crypto acceleration is enabled. */
        bool use_pio;                   /* TRUE if next init should use PIO */
@@ -22,7 +22,7 @@
  static int modparam_bad_frames_preempt;
  module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
  MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2543,10 +2548,10 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2560,10 +2565,10 @@ static int b43_gpio_init(struct b43_wlde
                    & ~B43_MACCTL_GPOUTSMSK);
  
        b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)
        mask = 0x0000001F;
 -      set = 0x0000000F;
 +      set = modparam_gpiomask;
-       if (dev->dev->bus->chip_id == 0x4301) {
+       if (dev->sdev->bus->chip_id == 0x4301) {
                mask |= 0x0060;
                set |= 0x0060;
-@@ -5078,10 +5083,10 @@ static void b43_print_driverinfo(void)
+@@ -5084,10 +5089,10 @@ static void b43_print_driverinfo(void)
        feat_sdio = "S";
  #endif
        printk(KERN_INFO "Broadcom 43xx driver loaded "
index 5a48658..5e55f77 100644 (file)
@@ -11,7 +11,7 @@
  b43-$(CONFIG_B43_PCMCIA)      += pcmcia.o
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -1813,9 +1813,11 @@ static void b43_do_interrupt_thread(stru
+@@ -1819,9 +1819,11 @@ static void b43_do_interrupt_thread(stru
                               dma_reason[4], dma_reason[5]);
                        b43err(dev->wl, "This device does not support DMA "
                               "on your system. It will now be switched to PIO.\n");