mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 13:34:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			187 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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,
 |