From d7bc8b2f4a54862fbe5823ba2b9453de0e1670e9 Mon Sep 17 00:00:00 2001
From: nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Sat, 10 Mar 2012 12:59:40 +0000
Subject: mac80211/ath9k: some more performance improvements

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@30866 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../patches/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 ++++++++++++++++
 .../564-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)) {
-- 
cgit v1.2.3