From: Felix Fietkau Date: Thu, 15 Dec 2016 10:48:12 +0000 (+0100) Subject: mac80211: merge a number of minstrel/minstrel_ht performance and memory usage improve... X-Git-Tag: v17.01.0-rc1~502 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=00bc7f0357d082e73699fb561776088e48e53101;p=openwrt%2Fstaging%2Fxback.git mac80211: merge a number of minstrel/minstrel_ht performance and memory usage improvements Signed-off-by: Felix Fietkau --- 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 0000000000..5e5992e6b4 --- /dev/null +++ b/package/kernel/mac80211/patches/334-mac80211-minstrel_ht-move-supported-bitrate-mask-out.patch @@ -0,0 +1,196 @@ +From: Felix Fietkau +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 +--- + +--- 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 0000000000..7a6e8cdb91 --- /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 +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 +--- + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -14,6 +14,7 @@ + #include + #include + #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 0000000000..40d03001c6 --- /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 +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 +--- + +--- 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 0000000000..066e1d1445 --- /dev/null +++ b/package/kernel/mac80211/patches/337-mac80211-check-for-MCS-in-ieee80211_duration-before-.patch @@ -0,0 +1,34 @@ +From: Felix Fietkau +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 +--- + +--- 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 0000000000..f25b0a8a8c --- /dev/null +++ b/package/kernel/mac80211/patches/338-mac80211-minstrel-remove-cur_prob-from-debugfs.patch @@ -0,0 +1,192 @@ +From: Felix Fietkau +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 +--- + +--- 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 0000000000..0416cf5900 --- /dev/null +++ b/package/kernel/mac80211/patches/339-mac80211-minstrel-reduce-MINSTREL_SCALE.patch @@ -0,0 +1,22 @@ +From: Felix Fietkau +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 +--- + +--- 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 0000000000..f679a43224 --- /dev/null +++ b/package/kernel/mac80211/patches/340-mac80211-minstrel-store-probability-variance-instead.patch @@ -0,0 +1,186 @@ +From: Felix Fietkau +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 +Signed-off-by: Felix Fietkau +--- + +--- 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 0000000000..570cd19ee4 --- /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 +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 +--- + +--- 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 0000000000..39d3c99e74 --- /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 +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 +--- + +--- 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;