mac80211: merge a number of minstrel/minstrel_ht performance and memory usage improvements
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
6f77b8d510
commit
00bc7f0357
@ -0,0 +1,196 @@
|
||||
From: Felix Fietkau <nbd@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@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) {
|
@ -0,0 +1,70 @@
|
||||
From: Felix Fietkau <nbd@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@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);
|
@ -0,0 +1,22 @@
|
||||
From: Felix Fietkau <nbd@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@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
|
@ -0,0 +1,34 @@
|
||||
From: Felix Fietkau <nbd@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@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;
|
@ -0,0 +1,192 @@
|
||||
From: Felix Fietkau <nbd@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@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,
|
@ -0,0 +1,22 @@
|
||||
From: Felix Fietkau <nbd@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@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)
|
||||
|
@ -0,0 +1,186 @@
|
||||
From: Felix Fietkau <nbd@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@evernet-eg.de>
|
||||
Signed-off-by: Felix Fietkau <nbd@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,
|
@ -0,0 +1,20 @@
|
||||
From: Felix Fietkau <nbd@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@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 */
|
@ -0,0 +1,80 @@
|
||||
From: Felix Fietkau <nbd@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@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;
|
Loading…
Reference in New Issue
Block a user