From d7bc8b2f4a54862fbe5823ba2b9453de0e1670e9 Mon Sep 17 00:00:00 2001 From: nbd Date: Sat, 10 Mar 2012 12:59:40 +0000 Subject: [PATCH] mac80211/ath9k: some more performance improvements git-svn-id: svn://svn.openwrt.org/openwrt/trunk@30866 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../560-ath9k_optimize_beacon_tx.patch | 129 ++++++++++++++++++ .../patches/561-ath9k_optimize_hw_check.patch | 32 +++++ ...562-mac80211_remove_code_duplication.patch | 127 +++++++++++++++++ .../563-mac80211_optimize_mcs_rate_mask.patch | 97 +++++++++++++ ...-ath9k_optimize_interrupt_mitigation.patch | 30 ++++ 5 files changed, 415 insertions(+) create mode 100644 package/mac80211/patches/560-ath9k_optimize_beacon_tx.patch create mode 100644 package/mac80211/patches/561-ath9k_optimize_hw_check.patch create mode 100644 package/mac80211/patches/562-mac80211_remove_code_duplication.patch create mode 100644 package/mac80211/patches/563-mac80211_optimize_mcs_rate_mask.patch create mode 100644 package/mac80211/patches/564-ath9k_optimize_interrupt_mitigation.patch 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 index 000000000..cfa1eb7c3 --- /dev/null +++ b/package/mac80211/patches/560-ath9k_optimize_beacon_tx.patch @@ -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 index 000000000..d10fbede5 --- /dev/null +++ b/package/mac80211/patches/561-ath9k_optimize_hw_check.patch @@ -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 index 000000000..e411d766c --- /dev/null +++ b/package/mac80211/patches/562-mac80211_remove_code_duplication.patch @@ -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 index 000000000..316663856 --- /dev/null +++ b/package/mac80211/patches/563-mac80211_optimize_mcs_rate_mask.patch @@ -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 index 000000000..5674fbb9d --- /dev/null +++ b/package/mac80211/patches/564-ath9k_optimize_interrupt_mitigation.patch @@ -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)) {