From 00bc7f0357d082e73699fb561776088e48e53101 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Dec 2016 11:48:12 +0100 Subject: mac80211: merge a number of minstrel/minstrel_ht performance and memory usage improvements Signed-off-by: Felix Fietkau --- ...nstrel-store-probability-variance-instead.patch | 186 +++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 package/kernel/mac80211/patches/340-mac80211-minstrel-store-probability-variance-instead.patch (limited to 'package/kernel/mac80211/patches/340-mac80211-minstrel-store-probability-variance-instead.patch') 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, -- cgit v1.2.3