[source] mac80211: merge a number of minstrel/minstrel_ht performance and memory usage improvements

LEDE Commits lede-commits at lists.infradead.org
Mon Dec 19 04:53:58 PST 2016


nbd pushed a commit to source.git, branch master:
https://git.lede-project.org/00bc7f0357d082e73699fb561776088e48e53101

commit 00bc7f0357d082e73699fb561776088e48e53101
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Thu Dec 15 11:48:12 2016 +0100

    mac80211: merge a number of minstrel/minstrel_ht performance and memory usage improvements
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...nstrel_ht-move-supported-bitrate-mask-out.patch | 196 +++++++++++++++++++++
 ...nstrel_ht-move-short-preamble-check-out-o.patch |  70 ++++++++
 ...nstrel_ht-make-att_hist-and-succ_hist-u32.patch |  22 +++
 ...eck-for-MCS-in-ieee80211_duration-before-.patch |  34 ++++
 ...211-minstrel-remove-cur_prob-from-debugfs.patch | 192 ++++++++++++++++++++
 ...9-mac80211-minstrel-reduce-MINSTREL_SCALE.patch |  22 +++
 ...nstrel-store-probability-variance-instead.patch | 186 +++++++++++++++++++
 ...instrel-make-prob_ewma-u16-instead-of-u32.patch |  20 +++
 ...nstrel_ht-remove-obsolete-if-for-3-stream.patch |  80 +++++++++
 9 files changed, 822 insertions(+)

diff --git a/package/kernel/mac80211/patches/334-mac80211-minstrel_ht-move-supported-bitrate-mask-out.patch b/package/kernel/mac80211/patches/334-mac80211-minstrel_ht-move-supported-bitrate-mask-out.patch
new file mode 100644
index 0000000..5e5992e
--- /dev/null
+++ b/package/kernel/mac80211/patches/334-mac80211-minstrel_ht-move-supported-bitrate-mask-out.patch
@@ -0,0 +1,196 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 19:33:23 +0100
+Subject: [PATCH] mac80211: minstrel_ht: move supported bitrate mask out of
+ group data
+
+Improves dcache footprint by ensuring that fewer cache lines need to be
+touched.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -301,7 +301,7 @@ minstrel_ht_get_stats(struct minstrel_pr
+ 				break;
+ 
+ 		/* short preamble */
+-		if (!(mi->groups[group].supported & BIT(idx)))
++		if (!(mi->supported[group] & BIT(idx)))
+ 			idx += 4;
+ 	}
+ 	return &mi->groups[group].rates[idx];
+@@ -486,7 +486,7 @@ minstrel_ht_prob_rate_reduce_streams(str
+ 			  MCS_GROUP_RATES].streams;
+ 	for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
+ 		mg = &mi->groups[group];
+-		if (!mg->supported || group == MINSTREL_CCK_GROUP)
++		if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
+ 			continue;
+ 
+ 		tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
+@@ -540,7 +540,7 @@ minstrel_ht_update_stats(struct minstrel
+ 	for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
+ 
+ 		mg = &mi->groups[group];
+-		if (!mg->supported)
++		if (!mi->supported[group])
+ 			continue;
+ 
+ 		mi->sample_count++;
+@@ -550,7 +550,7 @@ minstrel_ht_update_stats(struct minstrel
+ 			tmp_group_tp_rate[j] = group;
+ 
+ 		for (i = 0; i < MCS_GROUP_RATES; i++) {
+-			if (!(mg->supported & BIT(i)))
++			if (!(mi->supported[group] & BIT(i)))
+ 				continue;
+ 
+ 			index = MCS_GROUP_RATES * group + i;
+@@ -636,7 +636,7 @@ minstrel_set_next_sample_idx(struct mins
+ 		mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups);
+ 		mg = &mi->groups[mi->sample_group];
+ 
+-		if (!mg->supported)
++		if (!mi->supported[mi->sample_group])
+ 			continue;
+ 
+ 		if (++mg->index >= MCS_GROUP_RATES) {
+@@ -657,7 +657,7 @@ minstrel_downgrade_rate(struct minstrel_
+ 	while (group > 0) {
+ 		group--;
+ 
+-		if (!mi->groups[group].supported)
++		if (!mi->supported[group])
+ 			continue;
+ 
+ 		if (minstrel_mcs_groups[group].streams >
+@@ -994,7 +994,7 @@ minstrel_get_sample_rate(struct minstrel
+ 	sample_idx = sample_table[mg->column][mg->index];
+ 	minstrel_set_next_sample_idx(mi);
+ 
+-	if (!(mg->supported & BIT(sample_idx)))
++	if (!(mi->supported[sample_group] & BIT(sample_idx)))
+ 		return -1;
+ 
+ 	mrs = &mg->rates[sample_idx];
+@@ -1052,7 +1052,7 @@ static void
+ minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp,
+ 				    struct minstrel_ht_sta *mi, bool val)
+ {
+-	u8 supported = mi->groups[MINSTREL_CCK_GROUP].supported;
++	u8 supported = mi->supported[MINSTREL_CCK_GROUP];
+ 
+ 	if (!supported || !mi->cck_supported_short)
+ 		return;
+@@ -1061,7 +1061,7 @@ minstrel_ht_check_cck_shortpreamble(stru
+ 		return;
+ 
+ 	supported ^= mi->cck_supported_short | (mi->cck_supported_short << 4);
+-	mi->groups[MINSTREL_CCK_GROUP].supported = supported;
++	mi->supported[MINSTREL_CCK_GROUP] = supported;
+ }
+ 
+ static void
+@@ -1154,7 +1154,7 @@ minstrel_ht_update_cck(struct minstrel_p
+ 			mi->cck_supported_short |= BIT(i);
+ 	}
+ 
+-	mi->groups[MINSTREL_CCK_GROUP].supported = mi->cck_supported;
++	mi->supported[MINSTREL_CCK_GROUP] = mi->cck_supported;
+ }
+ 
+ static void
+@@ -1233,7 +1233,7 @@ minstrel_ht_update_caps(void *priv, stru
+ 		u32 gflags = minstrel_mcs_groups[i].flags;
+ 		int bw, nss;
+ 
+-		mi->groups[i].supported = 0;
++		mi->supported[i] = 0;
+ 		if (i == MINSTREL_CCK_GROUP) {
+ 			minstrel_ht_update_cck(mp, mi, sband, sta);
+ 			continue;
+@@ -1265,8 +1265,8 @@ minstrel_ht_update_caps(void *priv, stru
+ 			if (use_vht && minstrel_vht_only)
+ 				continue;
+ #endif
+-			mi->groups[i].supported = mcs->rx_mask[nss - 1];
+-			if (mi->groups[i].supported)
++			mi->supported[i] = mcs->rx_mask[nss - 1];
++			if (mi->supported[i])
+ 				n_supported++;
+ 			continue;
+ 		}
+@@ -1292,10 +1292,10 @@ minstrel_ht_update_caps(void *priv, stru
+ 		else
+ 			bw = BW_20;
+ 
+-		mi->groups[i].supported = minstrel_get_valid_vht_rates(bw, nss,
++		mi->supported[i] = minstrel_get_valid_vht_rates(bw, nss,
+ 				vht_cap->vht_mcs.tx_mcs_map);
+ 
+-		if (mi->groups[i].supported)
++		if (mi->supported[i])
+ 			n_supported++;
+ 	}
+ 
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -52,9 +52,6 @@ struct minstrel_mcs_group_data {
+ 	u8 index;
+ 	u8 column;
+ 
+-	/* bitfield of supported MCS rates of this group */
+-	u16 supported;
+-
+ 	/* sorted rate set within a MCS group*/
+ 	u16 max_group_tp_rate[MAX_THR_RATES];
+ 	u16 max_group_prob_rate;
+@@ -101,6 +98,9 @@ struct minstrel_ht_sta {
+ 	u8 cck_supported;
+ 	u8 cck_supported_short;
+ 
++	/* Bitfield of supported MCS rates of all groups */
++	u16 supported[MINSTREL_GROUPS_NB];
++
+ 	/* MCS rate group info and statistics */
+ 	struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB];
+ };
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -24,7 +24,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 	char gimode = 'L';
+ 	u32 gflags;
+ 
+-	if (!mi->groups[i].supported)
++	if (!mi->supported[i])
+ 		return p;
+ 
+ 	mg = &minstrel_mcs_groups[i];
+@@ -42,7 +42,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 		static const int bitrates[4] = { 10, 20, 55, 110 };
+ 		int idx = i * MCS_GROUP_RATES + j;
+ 
+-		if (!(mi->groups[i].supported & BIT(j)))
++		if (!(mi->supported[i] & BIT(j)))
+ 			continue;
+ 
+ 		if (gflags & IEEE80211_TX_RC_MCS) {
+@@ -170,7 +170,7 @@ minstrel_ht_stats_csv_dump(struct minstr
+ 	char gimode = 'L';
+ 	u32 gflags;
+ 
+-	if (!mi->groups[i].supported)
++	if (!mi->supported[i])
+ 		return p;
+ 
+ 	mg = &minstrel_mcs_groups[i];
+@@ -188,7 +188,7 @@ minstrel_ht_stats_csv_dump(struct minstr
+ 		static const int bitrates[4] = { 10, 20, 55, 110 };
+ 		int idx = i * MCS_GROUP_RATES + j;
+ 
+-		if (!(mi->groups[i].supported & BIT(j)))
++		if (!(mi->supported[i] & BIT(j)))
+ 			continue;
+ 
+ 		if (gflags & IEEE80211_TX_RC_MCS) {
diff --git a/package/kernel/mac80211/patches/335-mac80211-minstrel_ht-move-short-preamble-check-out-o.patch b/package/kernel/mac80211/patches/335-mac80211-minstrel_ht-move-short-preamble-check-out-o.patch
new file mode 100644
index 0000000..7a6e8cd
--- /dev/null
+++ b/package/kernel/mac80211/patches/335-mac80211-minstrel_ht-move-short-preamble-check-out-o.patch
@@ -0,0 +1,70 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:06:08 +0100
+Subject: [PATCH] mac80211: minstrel_ht: move short preamble check out of
+ get_rate
+
+Test short preamble support in minstrel_ht_update_caps instead of
+looking at the per-packet flag. Makes the code more efficient.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -14,6 +14,7 @@
+ #include <linux/ieee80211.h>
+ #include <net/mac80211.h>
+ #include "rate.h"
++#include "sta_info.h"
+ #include "rc80211_minstrel.h"
+ #include "rc80211_minstrel_ht.h"
+ 
+@@ -1049,22 +1050,6 @@ minstrel_get_sample_rate(struct minstrel
+ }
+ 
+ static void
+-minstrel_ht_check_cck_shortpreamble(struct minstrel_priv *mp,
+-				    struct minstrel_ht_sta *mi, bool val)
+-{
+-	u8 supported = mi->supported[MINSTREL_CCK_GROUP];
+-
+-	if (!supported || !mi->cck_supported_short)
+-		return;
+-
+-	if (supported & (mi->cck_supported_short << (val * 4)))
+-		return;
+-
+-	supported ^= mi->cck_supported_short | (mi->cck_supported_short << 4);
+-	mi->supported[MINSTREL_CCK_GROUP] = supported;
+-}
+-
+-static void
+ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+                      struct ieee80211_tx_rate_control *txrc)
+ {
+@@ -1087,7 +1072,6 @@ minstrel_ht_get_rate(void *priv, struct
+ 		minstrel_aggr_check(sta, txrc->skb);
+ 
+ 	info->flags |= mi->tx_flags;
+-	minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble);
+ 
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ 	if (mp->fixed_rate_idx != -1)
+@@ -1168,6 +1152,7 @@ minstrel_ht_update_caps(void *priv, stru
+ 	struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
+ 	u16 ht_cap = sta->ht_cap.cap;
+ 	struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
++	struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
+ 	int use_vht;
+ 	int n_supported = 0;
+ 	int ack_dur;
+@@ -1302,6 +1287,9 @@ minstrel_ht_update_caps(void *priv, stru
+ 	if (!n_supported)
+ 		goto use_legacy;
+ 
++	if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))
++		mi->cck_supported_short |= mi->cck_supported_short << 4;
++
+ 	/* create an initial rate table with the lowest supported rates */
+ 	minstrel_ht_update_stats(mp, mi);
+ 	minstrel_ht_update_rates(mp, mi);
diff --git a/package/kernel/mac80211/patches/336-mac80211-minstrel_ht-make-att_hist-and-succ_hist-u32.patch b/package/kernel/mac80211/patches/336-mac80211-minstrel_ht-make-att_hist-and-succ_hist-u32.patch
new file mode 100644
index 0000000..40d0300
--- /dev/null
+++ b/package/kernel/mac80211/patches/336-mac80211-minstrel_ht-make-att_hist-and-succ_hist-u32.patch
@@ -0,0 +1,22 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:09:14 +0100
+Subject: [PATCH] mac80211: minstrel_ht: make att_hist and succ_hist u32
+ instead of u64
+
+They are only used for debugging purposes and take a very long time to
+overflow. Visibly reduces the size of the per-sta rate control data.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -59,7 +59,7 @@ struct minstrel_rate_stats {
+ 	u16 success, last_success;
+ 
+ 	/* total attempts/success counters */
+-	u64 att_hist, succ_hist;
++	u32 att_hist, succ_hist;
+ 
+ 	/* statistis of packet delivery probability
+ 	 *  cur_prob  - current prob within last update intervall
diff --git a/package/kernel/mac80211/patches/337-mac80211-check-for-MCS-in-ieee80211_duration-before-.patch b/package/kernel/mac80211/patches/337-mac80211-check-for-MCS-in-ieee80211_duration-before-.patch
new file mode 100644
index 0000000..066e1d1
--- /dev/null
+++ b/package/kernel/mac80211/patches/337-mac80211-check-for-MCS-in-ieee80211_duration-before-.patch
@@ -0,0 +1,34 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:12:25 +0100
+Subject: [PATCH] mac80211: check for MCS in ieee80211_duration before fetching
+ chanctx
+
+Makes the code a bit more efficient
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -63,6 +63,10 @@ static __le16 ieee80211_duration(struct
+ 	struct ieee80211_chanctx_conf *chanctx_conf;
+ 	u32 rate_flags = 0;
+ 
++	/* assume HW handles this */
++	if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
++		return 0;
++
+ 	rcu_read_lock();
+ 	chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf);
+ 	if (chanctx_conf) {
+@@ -71,10 +75,6 @@ static __le16 ieee80211_duration(struct
+ 	}
+ 	rcu_read_unlock();
+ 
+-	/* assume HW handles this */
+-	if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
+-		return 0;
+-
+ 	/* uh huh? */
+ 	if (WARN_ON_ONCE(tx->rate.idx < 0))
+ 		return 0;
diff --git a/package/kernel/mac80211/patches/338-mac80211-minstrel-remove-cur_prob-from-debugfs.patch b/package/kernel/mac80211/patches/338-mac80211-minstrel-remove-cur_prob-from-debugfs.patch
new file mode 100644
index 0000000..f25b0a8
--- /dev/null
+++ b/package/kernel/mac80211/patches/338-mac80211-minstrel-remove-cur_prob-from-debugfs.patch
@@ -0,0 +1,192 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:13:58 +0100
+Subject: [PATCH] mac80211: minstrel: remove cur_prob from debugfs
+
+This field is redundant, because it is simply last success divided by
+last attempt count. Removing it from the rate stats struct saves about
+1.2 KiB per HT station.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel.c
++++ b/net/mac80211/rc80211_minstrel.c
+@@ -159,21 +159,23 @@ minstrel_update_rates(struct minstrel_pr
+ void
+ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs)
+ {
++	unsigned int cur_prob;
++
+ 	if (unlikely(mrs->attempts > 0)) {
+ 		mrs->sample_skipped = 0;
+-		mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
++		cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
+ 		if (unlikely(!mrs->att_hist)) {
+-			mrs->prob_ewma = mrs->cur_prob;
++			mrs->prob_ewma = cur_prob;
+ 		} else {
+ 			/* update exponential weighted moving variance */
+ 			mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
+-							 mrs->cur_prob,
++							 cur_prob,
+ 							 mrs->prob_ewma,
+ 							 EWMA_LEVEL);
+ 
+ 			/*update exponential weighted moving avarage */
+ 			mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
+-						       mrs->cur_prob,
++						       cur_prob,
+ 						       EWMA_LEVEL);
+ 		}
+ 		mrs->att_hist += mrs->attempts;
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -62,10 +62,8 @@ struct minstrel_rate_stats {
+ 	u32 att_hist, succ_hist;
+ 
+ 	/* statistis of packet delivery probability
+-	 *  cur_prob  - current prob within last update intervall
+ 	 *  prob_ewma - exponential weighted moving average of prob
+ 	 *  prob_ewmsd - exp. weighted moving standard deviation of prob */
+-	unsigned int cur_prob;
+ 	unsigned int prob_ewma;
+ 	u16 prob_ewmsd;
+ 
+--- a/net/mac80211/rc80211_minstrel_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_debugfs.c
+@@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode,
+ {
+ 	struct minstrel_sta_info *mi = inode->i_private;
+ 	struct minstrel_debugfs_info *ms;
+-	unsigned int i, tp_max, tp_avg, prob, eprob;
++	unsigned int i, tp_max, tp_avg, eprob;
+ 	char *p;
+ 
+ 	ms = kmalloc(2048, GFP_KERNEL);
+@@ -86,9 +86,9 @@ minstrel_stats_open(struct inode *inode,
+ 	p = ms->buf;
+ 	p += sprintf(p, "\n");
+ 	p += sprintf(p,
+-		     "best   __________rate_________    ________statistics________    ________last_______    ______sum-of________\n");
++		     "best   __________rate_________    ________statistics________    ____last_____    ______sum-of________\n");
+ 	p += sprintf(p,
+-		     "rate  [name idx airtime max_tp]  [avg(tp) avg(prob) sd(prob)]  [prob.|retry|suc|att]  [#success | #attempts]\n");
++		     "rate  [name idx airtime max_tp]  [avg(tp) avg(prob) sd(prob)]  [retry|suc|att]  [#success | #attempts]\n");
+ 
+ 	for (i = 0; i < mi->n_rates; i++) {
+ 		struct minstrel_rate *mr = &mi->r[i];
+@@ -107,17 +107,15 @@ minstrel_stats_open(struct inode *inode,
+ 
+ 		tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
+ 		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
+-		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
+ 
+ 		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u    %3u.%1u"
+-				"     %3u.%1u %3u   %3u %-3u   "
++				"     %3u   %3u %-3u   "
+ 				"%9llu   %-9llu\n",
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+ 				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
+-				prob / 10, prob % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
+@@ -148,7 +146,7 @@ minstrel_stats_csv_open(struct inode *in
+ {
+ 	struct minstrel_sta_info *mi = inode->i_private;
+ 	struct minstrel_debugfs_info *ms;
+-	unsigned int i, tp_max, tp_avg, prob, eprob;
++	unsigned int i, tp_max, tp_avg, eprob;
+ 	char *p;
+ 
+ 	ms = kmalloc(2048, GFP_KERNEL);
+@@ -175,16 +173,14 @@ minstrel_stats_csv_open(struct inode *in
+ 
+ 		tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
+ 		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
+-		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
+ 
+-		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
++		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
+ 				"%llu,%llu,%d,%d\n",
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+ 				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
+-				prob / 10, prob % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -19,7 +19,7 @@ static char *
+ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
+ {
+ 	const struct mcs_group *mg;
+-	unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
++	unsigned int j, tp_max, tp_avg, eprob, tx_time;
+ 	char htmode = '2';
+ 	char gimode = 'L';
+ 	u32 gflags;
+@@ -83,17 +83,15 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 
+ 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+ 		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
+-		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
+ 
+ 		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u    %3u.%1u"
+-				"     %3u.%1u %3u   %3u %-3u   "
++				"     %3u   %3u %-3u   "
+ 				"%9llu   %-9llu\n",
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+ 				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
+-				prob / 10, prob % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
+@@ -130,9 +128,9 @@ minstrel_ht_stats_open(struct inode *ino
+ 
+ 	p += sprintf(p, "\n");
+ 	p += sprintf(p,
+-		     "              best   ____________rate__________    ________statistics________    ________last_______    ______sum-of________\n");
++		     "              best   ____________rate__________    ________statistics________    _____last____    ______sum-of________\n");
+ 	p += sprintf(p,
+-		     "mode guard #  rate  [name   idx airtime  max_tp]  [avg(tp) avg(prob) sd(prob)]  [prob.|retry|suc|att]  [#success | #attempts]\n");
++		     "mode guard #  rate  [name   idx airtime  max_tp]  [avg(tp) avg(prob) sd(prob)]  [retry|suc|att]  [#success | #attempts]\n");
+ 
+ 	p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
+ 	for (i = 0; i < MINSTREL_CCK_GROUP; i++)
+@@ -165,7 +163,7 @@ static char *
+ minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p)
+ {
+ 	const struct mcs_group *mg;
+-	unsigned int j, tp_max, tp_avg, prob, eprob, tx_time;
++	unsigned int j, tp_max, tp_avg, eprob, tx_time;
+ 	char htmode = '2';
+ 	char gimode = 'L';
+ 	u32 gflags;
+@@ -226,16 +224,14 @@ minstrel_ht_stats_csv_dump(struct minstr
+ 
+ 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+ 		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
+-		prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
+ 
+-		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
++		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
+ 				"%u,%llu,%llu,",
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+ 				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
+-				prob / 10, prob % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
diff --git a/package/kernel/mac80211/patches/339-mac80211-minstrel-reduce-MINSTREL_SCALE.patch b/package/kernel/mac80211/patches/339-mac80211-minstrel-reduce-MINSTREL_SCALE.patch
new file mode 100644
index 0000000..0416cf5
--- /dev/null
+++ b/package/kernel/mac80211/patches/339-mac80211-minstrel-reduce-MINSTREL_SCALE.patch
@@ -0,0 +1,22 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:15:33 +0100
+Subject: [PATCH] mac80211: minstrel: reduce MINSTREL_SCALE
+
+The loss of a bit of extra precision does not hurt the calculation, 12
+bits is still enough to calculate probabilities well. Reducing the scale
+makes it easier to avoid overflows
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -14,7 +14,7 @@
+ #define SAMPLE_COLUMNS	10	/* number of columns in sample table */
+ 
+ /* scaled fraction values */
+-#define MINSTREL_SCALE  16
++#define MINSTREL_SCALE  12
+ #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
+ #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
+ 
diff --git a/package/kernel/mac80211/patches/340-mac80211-minstrel-store-probability-variance-instead.patch b/package/kernel/mac80211/patches/340-mac80211-minstrel-store-probability-variance-instead.patch
new file mode 100644
index 0000000..f679a43
--- /dev/null
+++ b/package/kernel/mac80211/patches/340-mac80211-minstrel-store-probability-variance-instead.patch
@@ -0,0 +1,186 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:17:06 +0100
+Subject: [PATCH] mac80211: minstrel: store probability variance instead of
+ standard deviation
+
+This avoids the costly int_sqrt calls in the statistics update and moves
+it to the debugfs code instead.
+This also fixes an overflow in the previous standard deviation
+calculation.
+
+Signed-off-by: Thomas Huehn <thomas.huehn at evernet-eg.de>
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel.c
++++ b/net/mac80211/rc80211_minstrel.c
+@@ -168,10 +168,10 @@ minstrel_calc_rate_stats(struct minstrel
+ 			mrs->prob_ewma = cur_prob;
+ 		} else {
+ 			/* update exponential weighted moving variance */
+-			mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
+-							 cur_prob,
+-							 mrs->prob_ewma,
+-							 EWMA_LEVEL);
++			mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv,
++							cur_prob,
++							mrs->prob_ewma,
++							EWMA_LEVEL);
+ 
+ 			/*update exponential weighted moving avarage */
+ 			mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -36,21 +36,16 @@ minstrel_ewma(int old, int new, int weig
+ }
+ 
+ /*
+- * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation
++ * Perform EWMV (Exponentially Weighted Moving Variance) calculation
+  */
+ static inline int
+-minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight)
++minstrel_ewmv(int old_ewmv, int cur_prob, int prob_ewma, int weight)
+ {
+-	int diff, incr, tmp_var;
++	int diff, incr;
+ 
+-	/* calculate exponential weighted moving variance */
+-	diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000);
++	diff = cur_prob - prob_ewma;
+ 	incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
+-	tmp_var = old_ewmsd * old_ewmsd;
+-	tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV;
+-
+-	/* return standard deviation */
+-	return (u16) int_sqrt(tmp_var);
++	return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV;
+ }
+ 
+ struct minstrel_rate_stats {
+@@ -65,7 +60,7 @@ struct minstrel_rate_stats {
+ 	 *  prob_ewma - exponential weighted moving average of prob
+ 	 *  prob_ewmsd - exp. weighted moving standard deviation of prob */
+ 	unsigned int prob_ewma;
+-	u16 prob_ewmsd;
++	u16 prob_ewmv;
+ 
+ 	/* maximum retry counts */
+ 	u8 retry_count;
+@@ -151,6 +146,14 @@ struct minstrel_debugfs_info {
+ 	char buf[];
+ };
+ 
++/* Get EWMSD (Exponentially Weighted Moving Standard Deviation) * 10 */
++static inline int
++minstrel_get_ewmsd10(struct minstrel_rate_stats *mrs)
++{
++	unsigned int ewmv = mrs->prob_ewmv;
++	return int_sqrt(MINSTREL_TRUNC(ewmv * 1000 * 1000));
++}
++
+ extern const struct rate_control_ops mac80211_minstrel;
+ void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
+ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
+--- a/net/mac80211/rc80211_minstrel_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_debugfs.c
+@@ -93,6 +93,7 @@ minstrel_stats_open(struct inode *inode,
+ 	for (i = 0; i < mi->n_rates; i++) {
+ 		struct minstrel_rate *mr = &mi->r[i];
+ 		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
++		unsigned int prob_ewmsd;
+ 
+ 		*(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
+ 		*(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
+@@ -108,6 +109,7 @@ minstrel_stats_open(struct inode *inode,
+ 		tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
+ 		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
++		prob_ewmsd = minstrel_get_ewmsd10(mrs);
+ 
+ 		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u    %3u.%1u"
+ 				"     %3u   %3u %-3u   "
+@@ -115,7 +117,7 @@ minstrel_stats_open(struct inode *inode,
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+-				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
++				prob_ewmsd / 10, prob_ewmsd % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
+@@ -159,6 +161,7 @@ minstrel_stats_csv_open(struct inode *in
+ 	for (i = 0; i < mi->n_rates; i++) {
+ 		struct minstrel_rate *mr = &mi->r[i];
+ 		struct minstrel_rate_stats *mrs = &mi->r[i].stats;
++		unsigned int prob_ewmsd;
+ 
+ 		p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));
+ 		p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : ""));
+@@ -174,13 +177,14 @@ minstrel_stats_csv_open(struct inode *in
+ 		tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
+ 		tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
++		prob_ewmsd = minstrel_get_ewmsd10(mrs);
+ 
+ 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
+ 				"%llu,%llu,%d,%d\n",
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+-				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
++				prob_ewmsd / 10, prob_ewmsd % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -41,6 +41,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
+ 		static const int bitrates[4] = { 10, 20, 55, 110 };
+ 		int idx = i * MCS_GROUP_RATES + j;
++		unsigned int prob_ewmsd;
+ 
+ 		if (!(mi->supported[i] & BIT(j)))
+ 			continue;
+@@ -84,6 +85,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+ 		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
++		prob_ewmsd = minstrel_get_ewmsd10(mrs);
+ 
+ 		p += sprintf(p, "%4u.%1u    %4u.%1u     %3u.%1u    %3u.%1u"
+ 				"     %3u   %3u %-3u   "
+@@ -91,7 +93,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+-				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
++				prob_ewmsd / 10, prob_ewmsd % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
+@@ -185,6 +187,7 @@ minstrel_ht_stats_csv_dump(struct minstr
+ 		struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
+ 		static const int bitrates[4] = { 10, 20, 55, 110 };
+ 		int idx = i * MCS_GROUP_RATES + j;
++		unsigned int prob_ewmsd;
+ 
+ 		if (!(mi->supported[i] & BIT(j)))
+ 			continue;
+@@ -225,13 +228,14 @@ minstrel_ht_stats_csv_dump(struct minstr
+ 		tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+ 		tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
+ 		eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
++		prob_ewmsd = minstrel_get_ewmsd10(mrs);
+ 
+ 		p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
+ 				"%u,%llu,%llu,",
+ 				tp_max / 10, tp_max % 10,
+ 				tp_avg / 10, tp_avg % 10,
+ 				eprob / 10, eprob % 10,
+-				mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
++				prob_ewmsd / 10, prob_ewmsd % 10,
+ 				mrs->retry_count,
+ 				mrs->last_success,
+ 				mrs->last_attempts,
diff --git a/package/kernel/mac80211/patches/341-mac80211-minstrel-make-prob_ewma-u16-instead-of-u32.patch b/package/kernel/mac80211/patches/341-mac80211-minstrel-make-prob_ewma-u16-instead-of-u32.patch
new file mode 100644
index 0000000..570cd19
--- /dev/null
+++ b/package/kernel/mac80211/patches/341-mac80211-minstrel-make-prob_ewma-u16-instead-of-u32.patch
@@ -0,0 +1,20 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:19:56 +0100
+Subject: [PATCH] mac80211: minstrel: make prob_ewma u16 instead of u32
+
+Saves about 1.2 KiB memory per station
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel.h
++++ b/net/mac80211/rc80211_minstrel.h
+@@ -59,7 +59,7 @@ struct minstrel_rate_stats {
+ 	/* statistis of packet delivery probability
+ 	 *  prob_ewma - exponential weighted moving average of prob
+ 	 *  prob_ewmsd - exp. weighted moving standard deviation of prob */
+-	unsigned int prob_ewma;
++	u16 prob_ewma;
+ 	u16 prob_ewmv;
+ 
+ 	/* maximum retry counts */
diff --git a/package/kernel/mac80211/patches/342-mac80211-minstrel_ht-remove-obsolete-if-for-3-stream.patch b/package/kernel/mac80211/patches/342-mac80211-minstrel_ht-remove-obsolete-if-for-3-stream.patch
new file mode 100644
index 0000000..39d3c99
--- /dev/null
+++ b/package/kernel/mac80211/patches/342-mac80211-minstrel_ht-remove-obsolete-if-for-3-stream.patch
@@ -0,0 +1,80 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 14 Dec 2016 20:23:29 +0100
+Subject: [PATCH] mac80211: minstrel_ht: remove obsolete #if for >= 3 streams
+
+This was added during early development when 3x3 hardware was not very
+common yet. This is completely unnecessary now.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -155,67 +155,47 @@ MODULE_PARM_DESC(minstrel_vht_only,
+ const struct mcs_group minstrel_mcs_groups[] = {
+ 	MCS_GROUP(1, 0, BW_20),
+ 	MCS_GROUP(2, 0, BW_20),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	MCS_GROUP(3, 0, BW_20),
+-#endif
+ 
+ 	MCS_GROUP(1, 1, BW_20),
+ 	MCS_GROUP(2, 1, BW_20),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	MCS_GROUP(3, 1, BW_20),
+-#endif
+ 
+ 	MCS_GROUP(1, 0, BW_40),
+ 	MCS_GROUP(2, 0, BW_40),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	MCS_GROUP(3, 0, BW_40),
+-#endif
+ 
+ 	MCS_GROUP(1, 1, BW_40),
+ 	MCS_GROUP(2, 1, BW_40),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	MCS_GROUP(3, 1, BW_40),
+-#endif
+ 
+ 	CCK_GROUP,
+ 
+ #ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ 	VHT_GROUP(1, 0, BW_20),
+ 	VHT_GROUP(2, 0, BW_20),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	VHT_GROUP(3, 0, BW_20),
+-#endif
+ 
+ 	VHT_GROUP(1, 1, BW_20),
+ 	VHT_GROUP(2, 1, BW_20),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	VHT_GROUP(3, 1, BW_20),
+-#endif
+ 
+ 	VHT_GROUP(1, 0, BW_40),
+ 	VHT_GROUP(2, 0, BW_40),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	VHT_GROUP(3, 0, BW_40),
+-#endif
+ 
+ 	VHT_GROUP(1, 1, BW_40),
+ 	VHT_GROUP(2, 1, BW_40),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	VHT_GROUP(3, 1, BW_40),
+-#endif
+ 
+ 	VHT_GROUP(1, 0, BW_80),
+ 	VHT_GROUP(2, 0, BW_80),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	VHT_GROUP(3, 0, BW_80),
+-#endif
+ 
+ 	VHT_GROUP(1, 1, BW_80),
+ 	VHT_GROUP(2, 1, BW_80),
+-#if MINSTREL_MAX_STREAMS >= 3
+ 	VHT_GROUP(3, 1, BW_80),
+ #endif
+-#endif
+ };
+ 
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;



More information about the lede-commits mailing list