mac80211/ath9k: some more performance improvements
authorFelix Fietkau <nbd@openwrt.org>
Sat, 10 Mar 2012 12:59:40 +0000 (12:59 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 10 Mar 2012 12:59:40 +0000 (12:59 +0000)
SVN-Revision: 30866

package/mac80211/patches/560-ath9k_optimize_beacon_tx.patch [new file with mode: 0644]
package/mac80211/patches/561-ath9k_optimize_hw_check.patch [new file with mode: 0644]
package/mac80211/patches/562-mac80211_remove_code_duplication.patch [new file with mode: 0644]
package/mac80211/patches/563-mac80211_optimize_mcs_rate_mask.patch [new file with mode: 0644]
package/mac80211/patches/564-ath9k_optimize_interrupt_mitigation.patch [new file with mode: 0644]

diff --git a/package/mac80211/patches/560-ath9k_optimize_beacon_tx.patch b/package/mac80211/patches/560-ath9k_optimize_beacon_tx.patch
new file mode 100644 (file)
index 0000000..cfa1eb7
--- /dev/null
@@ -0,0 +1,129 @@
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -357,41 +357,12 @@ void ath_beacon_tasklet(unsigned long da
+       struct ieee80211_vif *vif;
+       bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
+       int slot;
+-      u32 bfaddr, bc = 0;
+-
+-      /*
+-       * Check if the previous beacon has gone out.  If
+-       * not don't try to post another, skip this period
+-       * and wait for the next.  Missed beacons indicate
+-       * a problem and should not occur.  If we miss too
+-       * many consecutive beacons reset the device.
+-       */
+-      if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
+-              sc->beacon.bmisscnt++;
+-
+-              if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
+-                      ath_dbg(common, BSTUCK,
+-                              "missed %u consecutive beacons\n",
+-                              sc->beacon.bmisscnt);
+-                      ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+-                      if (sc->beacon.bmisscnt > 3)
+-                              ath9k_hw_bstuck_nfcal(ah);
+-              } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
+-                      ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
+-                      sc->sc_flags |= SC_OP_TSF_RESET;
+-                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+-              }
+-
+-              return;
+-      }
+       /*
+        * Generate beacon frames. we are sending frames
+        * staggered so calculate the slot for this frame based
+        * on the tsf to safeguard against missing an swba.
+        */
+-
+-
+       if (ah->opmode == NL80211_IFTYPE_AP) {
+               u16 intval;
+               u32 tsftu;
+@@ -412,23 +383,6 @@ void ath_beacon_tasklet(unsigned long da
+               vif = sc->beacon.bslot[slot];
+       }
+-
+-      bfaddr = 0;
+-      if (vif) {
+-              bf = ath_beacon_generate(sc->hw, vif);
+-              if (bf != NULL) {
+-                      bfaddr = bf->bf_daddr;
+-                      bc = 1;
+-              }
+-
+-              if (sc->beacon.bmisscnt != 0) {
+-                      ath_dbg(common, BSTUCK,
+-                              "resume beacon xmit after %u misses\n",
+-                              sc->beacon.bmisscnt);
+-                      sc->beacon.bmisscnt = 0;
+-              }
+-      }
+-
+       /*
+        * Handle slot time change when a non-ERP station joins/leaves
+        * an 11g network.  The 802.11 layer notifies us via callback,
+@@ -453,15 +407,54 @@ void ath_beacon_tasklet(unsigned long da
+               ath9k_hw_init_global_settings(ah);
+               sc->beacon.updateslot = OK;
+       }
+-      if (bfaddr != 0) {
+-              /* NB: cabq traffic should already be queued and primed */
+-              ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
+-              if (!edma)
+-                      ath9k_hw_txstart(ah, sc->beacon.beaconq);
++      if (!vif)
++              return;
++
++      /*
++       * Check if the previous beacon has gone out.  If
++       * not don't try to post another, skip this period
++       * and wait for the next.  Missed beacons indicate
++       * a problem and should not occur.  If we miss too
++       * many consecutive beacons reset the device.
++       */
++      if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
++              sc->beacon.bmisscnt++;
++
++              if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
++                      ath_dbg(common, BSTUCK,
++                              "missed %u consecutive beacons\n",
++                              sc->beacon.bmisscnt);
++                      ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
++                      if (sc->beacon.bmisscnt > 3)
++                              ath9k_hw_bstuck_nfcal(ah);
++              } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
++                      ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
++                      sc->sc_flags |= SC_OP_TSF_RESET;
++                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++              }
++
++              return;
++      }
++
++      bf = ath_beacon_generate(sc->hw, vif);
++      if (!bf)
++              return;
+-              sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
++      if (sc->beacon.bmisscnt != 0) {
++              ath_dbg(common, BSTUCK,
++                      "resume beacon xmit after %u misses\n",
++                      sc->beacon.bmisscnt);
++              sc->beacon.bmisscnt = 0;
+       }
++
++      /* NB: cabq traffic should already be queued and primed */
++      ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
++
++      if (!edma)
++              ath9k_hw_txstart(ah, sc->beacon.beaconq);
++
++      sc->beacon.ast_be_xmit++;
+ }
+ static void ath9k_beacon_init(struct ath_softc *sc,
diff --git a/package/mac80211/patches/561-ath9k_optimize_hw_check.patch b/package/mac80211/patches/561-ath9k_optimize_hw_check.patch
new file mode 100644 (file)
index 0000000..d10fbed
--- /dev/null
@@ -0,0 +1,32 @@
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -421,6 +421,9 @@ void ath_beacon_tasklet(unsigned long da
+       if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
+               sc->beacon.bmisscnt++;
++              if (!ath9k_hw_check_alive(ah))
++                      ieee80211_queue_work(sc->hw, &sc->hw_check_work);
++
+               if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) {
+                       ath_dbg(common, BSTUCK,
+                               "missed %u consecutive beacons\n",
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -695,17 +695,6 @@ void ath9k_tasklet(unsigned long data)
+               goto out;
+       }
+-      /*
+-       * Only run the baseband hang check if beacons stop working in AP or
+-       * IBSS mode, because it has a high false positive rate. For station
+-       * mode it should not be necessary, since the upper layers will detect
+-       * this through a beacon miss automatically and the following channel
+-       * change will trigger a hardware reset anyway
+-       */
+-      if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 &&
+-          !ath9k_hw_check_alive(ah))
+-              ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+-
+       if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
+               /*
+                * TSF sync does not look correct; remain awake to sync with
diff --git a/package/mac80211/patches/562-mac80211_remove_code_duplication.patch b/package/mac80211/patches/562-mac80211_remove_code_duplication.patch
new file mode 100644 (file)
index 0000000..e411d76
--- /dev/null
@@ -0,0 +1,127 @@
+--- a/net/mac80211/debugfs_netdev.c
++++ b/net/mac80211/debugfs_netdev.c
+@@ -445,26 +445,23 @@ IEEE80211_IF_FILE(dot11MeshHWMPRannInter
+ IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
+ #endif
+-
+-#define DEBUGFS_ADD(name) \
+-      debugfs_create_file(#name, 0400, sdata->debugfs.dir, \
+-                          sdata, &name##_ops);
+-
+ #define DEBUGFS_ADD_MODE(name, mode) \
+       debugfs_create_file(#name, mode, sdata->debugfs.dir, \
+                           sdata, &name##_ops);
+-static void add_sta_files(struct ieee80211_sub_if_data *sdata)
++#define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
++
++static void add_common_files(struct ieee80211_sub_if_data *sdata)
+ {
+       DEBUGFS_ADD(drop_unencrypted);
+-      DEBUGFS_ADD(flags);
+-      DEBUGFS_ADD(state);
+-      DEBUGFS_ADD(channel_type);
+       DEBUGFS_ADD(rc_rateidx_mask_2ghz);
+       DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+       DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
+       DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
++}
++static void add_sta_files(struct ieee80211_sub_if_data *sdata)
++{
+       DEBUGFS_ADD(bssid);
+       DEBUGFS_ADD(aid);
+       DEBUGFS_ADD(last_beacon);
+@@ -475,15 +472,6 @@ static void add_sta_files(struct ieee802
+ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
+ {
+-      DEBUGFS_ADD(drop_unencrypted);
+-      DEBUGFS_ADD(flags);
+-      DEBUGFS_ADD(state);
+-      DEBUGFS_ADD(channel_type);
+-      DEBUGFS_ADD(rc_rateidx_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
+-
+       DEBUGFS_ADD(num_sta_authorized);
+       DEBUGFS_ADD(num_sta_ps);
+       DEBUGFS_ADD(dtim_count);
+@@ -493,48 +481,14 @@ static void add_ap_files(struct ieee8021
+ static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
+ {
+-      DEBUGFS_ADD(channel_type);
+-      DEBUGFS_ADD(rc_rateidx_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
+-
+       DEBUGFS_ADD_MODE(tsf, 0600);
+ }
+ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
+ {
+-      DEBUGFS_ADD(drop_unencrypted);
+-      DEBUGFS_ADD(flags);
+-      DEBUGFS_ADD(state);
+-      DEBUGFS_ADD(channel_type);
+-      DEBUGFS_ADD(rc_rateidx_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
+-
+       DEBUGFS_ADD(peer);
+ }
+-static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+-{
+-      DEBUGFS_ADD(drop_unencrypted);
+-      DEBUGFS_ADD(flags);
+-      DEBUGFS_ADD(state);
+-      DEBUGFS_ADD(channel_type);
+-      DEBUGFS_ADD(rc_rateidx_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mask_5ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
+-      DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
+-}
+-
+-static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
+-{
+-      DEBUGFS_ADD(flags);
+-      DEBUGFS_ADD(state);
+-      DEBUGFS_ADD(channel_type);
+-}
+-
+ #ifdef CONFIG_MAC80211_MESH
+ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
+@@ -590,6 +544,13 @@ static void add_files(struct ieee80211_s
+       if (!sdata->debugfs.dir)
+               return;
++      DEBUGFS_ADD(flags);
++      DEBUGFS_ADD(state);
++      DEBUGFS_ADD(channel_type);
++
++      if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
++              add_common_files(sdata);
++
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_MESH_POINT:
+ #ifdef CONFIG_MAC80211_MESH
+@@ -609,12 +570,6 @@ static void add_files(struct ieee80211_s
+       case NL80211_IFTYPE_WDS:
+               add_wds_files(sdata);
+               break;
+-      case NL80211_IFTYPE_MONITOR:
+-              add_monitor_files(sdata);
+-              break;
+-      case NL80211_IFTYPE_AP_VLAN:
+-              add_vlan_files(sdata);
+-              break;
+       default:
+               break;
+       }
diff --git a/package/mac80211/patches/563-mac80211_optimize_mcs_rate_mask.patch b/package/mac80211/patches/563-mac80211_optimize_mcs_rate_mask.patch
new file mode 100644 (file)
index 0000000..3166638
--- /dev/null
@@ -0,0 +1,97 @@
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -656,6 +656,8 @@ struct ieee80211_sub_if_data {
+       /* bitmap of allowed (non-MCS) rate indexes for rate control */
+       u32 rc_rateidx_mask[IEEE80211_NUM_BANDS];
++
++      bool rc_has_mcs_mask[IEEE80211_NUM_BANDS];
+       u8  rc_rateidx_mcs_mask[IEEE80211_NUM_BANDS][IEEE80211_HT_MCS_MASK_LEN];
+       union {
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1887,9 +1887,20 @@ static int ieee80211_set_bitrate_mask(st
+       }
+       for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
++              struct ieee80211_supported_band *sband = wiphy->bands[i];
++
+               sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
+               memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs,
+                      sizeof(mask->control[i].mcs));
++
++              sdata->rc_has_mcs_mask[i] = false;
++              if (!sband)
++                      continue;
++
++              if (memcmp(sdata->rc_rateidx_mcs_mask[i],
++                         sband->ht_cap.mcs.rx_mask,
++                         sizeof(sband->ht_cap.mcs.rx_mask)) != 0)
++                      sdata->rc_has_mcs_mask[i] = true;
+       }
+       return 0;
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -3590,6 +3590,7 @@ enum rate_control_changed {
+  *    (deprecated; this will be removed once drivers get updated to use
+  *    rate_idx_mask)
+  * @rate_idx_mask: user-requested rate mask (not MCS for now)
++ * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use)
+  * @skb: the skb that will be transmitted, the control information in it needs
+  *    to be filled in
+  * @bss: whether this frame is sent out in AP or IBSS mode
+@@ -3603,7 +3604,7 @@ struct ieee80211_tx_rate_control {
+       bool rts, short_preamble;
+       u8 max_rate_idx;
+       u32 rate_idx_mask;
+-      u8 rate_idx_mcs_mask[IEEE80211_HT_MCS_MASK_LEN];
++      u8 *rate_idx_mcs_mask;
+       bool bss;
+ };
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -640,9 +640,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
+               txrc.max_rate_idx = -1;
+       else
+               txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+-      memcpy(txrc.rate_idx_mcs_mask,
+-             tx->sdata->rc_rateidx_mcs_mask[tx->channel->band],
+-             sizeof(txrc.rate_idx_mcs_mask));
++
++      if (tx->sdata->rc_has_mcs_mask[tx->channel->band])
++              txrc.rate_idx_mcs_mask =
++                      tx->sdata->rc_rateidx_mcs_mask[tx->channel->band];
++
+       txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
+                   tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
+                   tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
+@@ -2455,8 +2457,6 @@ struct sk_buff *ieee80211_beacon_get_tim
+               txrc.max_rate_idx = -1;
+       else
+               txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1;
+-      memcpy(txrc.rate_idx_mcs_mask, sdata->rc_rateidx_mcs_mask[band],
+-             sizeof(txrc.rate_idx_mcs_mask));
+       txrc.bss = true;
+       rate_control_get_rate(sdata, NULL, &txrc);
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -461,9 +461,12 @@ void rate_control_get_rate(struct ieee80
+        * the common case.
+        */
+       mask = sdata->rc_rateidx_mask[info->band];
+-      memcpy(mcs_mask, sdata->rc_rateidx_mcs_mask[info->band],
+-             sizeof(mcs_mask));
+-      if (mask != (1 << txrc->sband->n_bitrates) - 1) {
++      if (mask != (1 << txrc->sband->n_bitrates) - 1 || txrc->rate_idx_mcs_mask) {
++              if (txrc->rate_idx_mcs_mask)
++                      memcpy(mcs_mask, txrc->rate_idx_mcs_mask, sizeof(mcs_mask));
++              else
++                      memset(mcs_mask, 0xff, sizeof(mcs_mask));
++
+               if (sta) {
+                       /* Filter out rates that the STA does not support */
+                       mask &= sta->sta.supp_rates[info->band];
diff --git a/package/mac80211/patches/564-ath9k_optimize_interrupt_mitigation.patch b/package/mac80211/patches/564-ath9k_optimize_interrupt_mitigation.patch
new file mode 100644 (file)
index 0000000..5674fbb
--- /dev/null
@@ -0,0 +1,30 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -237,21 +237,19 @@ static bool ar9003_hw_get_isr(struct ath
+               *masked = isr & ATH9K_INT_COMMON;
+-              if (ah->config.rx_intr_mitigation)
++              if (ah->config.rx_intr_mitigation) {
+                       if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+                               *masked |= ATH9K_INT_RXLP;
+-
+-              if (ah->config.tx_intr_mitigation)
+-                      if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
+-                              *masked |= ATH9K_INT_TX;
+-
+-              if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
++              } else if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
+                       *masked |= ATH9K_INT_RXLP;
+               if (isr & AR_ISR_HP_RXOK)
+                       *masked |= ATH9K_INT_RXHP;
+-              if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
++              if (ah->config.tx_intr_mitigation) {
++                      if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
++                              *masked |= ATH9K_INT_TX;
++              } else if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
+                       *masked |= ATH9K_INT_TX;
+                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {