340-mac80211-minstrel-store-probability-variance-instead.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. From: Felix Fietkau <nbd@nbd.name>
  2. Date: Wed, 14 Dec 2016 20:17:06 +0100
  3. Subject: [PATCH] mac80211: minstrel: store probability variance instead of
  4. standard deviation
  5. This avoids the costly int_sqrt calls in the statistics update and moves
  6. it to the debugfs code instead.
  7. This also fixes an overflow in the previous standard deviation
  8. calculation.
  9. Signed-off-by: Thomas Huehn <thomas.huehn@evernet-eg.de>
  10. Signed-off-by: Felix Fietkau <nbd@nbd.name>
  11. ---
  12. --- a/net/mac80211/rc80211_minstrel.c
  13. +++ b/net/mac80211/rc80211_minstrel.c
  14. @@ -168,10 +168,10 @@ minstrel_calc_rate_stats(struct minstrel
  15. mrs->prob_ewma = cur_prob;
  16. } else {
  17. /* update exponential weighted moving variance */
  18. - mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd,
  19. - cur_prob,
  20. - mrs->prob_ewma,
  21. - EWMA_LEVEL);
  22. + mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv,
  23. + cur_prob,
  24. + mrs->prob_ewma,
  25. + EWMA_LEVEL);
  26. /*update exponential weighted moving avarage */
  27. mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma,
  28. --- a/net/mac80211/rc80211_minstrel.h
  29. +++ b/net/mac80211/rc80211_minstrel.h
  30. @@ -36,21 +36,16 @@ minstrel_ewma(int old, int new, int weig
  31. }
  32. /*
  33. - * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation
  34. + * Perform EWMV (Exponentially Weighted Moving Variance) calculation
  35. */
  36. static inline int
  37. -minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight)
  38. +minstrel_ewmv(int old_ewmv, int cur_prob, int prob_ewma, int weight)
  39. {
  40. - int diff, incr, tmp_var;
  41. + int diff, incr;
  42. - /* calculate exponential weighted moving variance */
  43. - diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 1000000);
  44. + diff = cur_prob - prob_ewma;
  45. incr = (EWMA_DIV - weight) * diff / EWMA_DIV;
  46. - tmp_var = old_ewmsd * old_ewmsd;
  47. - tmp_var = weight * (tmp_var + diff * incr / 1000000) / EWMA_DIV;
  48. -
  49. - /* return standard deviation */
  50. - return (u16) int_sqrt(tmp_var);
  51. + return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV;
  52. }
  53. struct minstrel_rate_stats {
  54. @@ -65,7 +60,7 @@ struct minstrel_rate_stats {
  55. * prob_ewma - exponential weighted moving average of prob
  56. * prob_ewmsd - exp. weighted moving standard deviation of prob */
  57. unsigned int prob_ewma;
  58. - u16 prob_ewmsd;
  59. + u16 prob_ewmv;
  60. /* maximum retry counts */
  61. u8 retry_count;
  62. @@ -151,6 +146,14 @@ struct minstrel_debugfs_info {
  63. char buf[];
  64. };
  65. +/* Get EWMSD (Exponentially Weighted Moving Standard Deviation) * 10 */
  66. +static inline int
  67. +minstrel_get_ewmsd10(struct minstrel_rate_stats *mrs)
  68. +{
  69. + unsigned int ewmv = mrs->prob_ewmv;
  70. + return int_sqrt(MINSTREL_TRUNC(ewmv * 1000 * 1000));
  71. +}
  72. +
  73. extern const struct rate_control_ops mac80211_minstrel;
  74. void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
  75. void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
  76. --- a/net/mac80211/rc80211_minstrel_debugfs.c
  77. +++ b/net/mac80211/rc80211_minstrel_debugfs.c
  78. @@ -93,6 +93,7 @@ minstrel_stats_open(struct inode *inode,
  79. for (i = 0; i < mi->n_rates; i++) {
  80. struct minstrel_rate *mr = &mi->r[i];
  81. struct minstrel_rate_stats *mrs = &mi->r[i].stats;
  82. + unsigned int prob_ewmsd;
  83. *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' ';
  84. *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' ';
  85. @@ -108,6 +109,7 @@ minstrel_stats_open(struct inode *inode,
  86. tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
  87. tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
  88. eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
  89. + prob_ewmsd = minstrel_get_ewmsd10(mrs);
  90. p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
  91. " %3u %3u %-3u "
  92. @@ -115,7 +117,7 @@ minstrel_stats_open(struct inode *inode,
  93. tp_max / 10, tp_max % 10,
  94. tp_avg / 10, tp_avg % 10,
  95. eprob / 10, eprob % 10,
  96. - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
  97. + prob_ewmsd / 10, prob_ewmsd % 10,
  98. mrs->retry_count,
  99. mrs->last_success,
  100. mrs->last_attempts,
  101. @@ -159,6 +161,7 @@ minstrel_stats_csv_open(struct inode *in
  102. for (i = 0; i < mi->n_rates; i++) {
  103. struct minstrel_rate *mr = &mi->r[i];
  104. struct minstrel_rate_stats *mrs = &mi->r[i].stats;
  105. + unsigned int prob_ewmsd;
  106. p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : ""));
  107. p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : ""));
  108. @@ -174,13 +177,14 @@ minstrel_stats_csv_open(struct inode *in
  109. tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100));
  110. tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma);
  111. eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
  112. + prob_ewmsd = minstrel_get_ewmsd10(mrs);
  113. p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,"
  114. "%llu,%llu,%d,%d\n",
  115. tp_max / 10, tp_max % 10,
  116. tp_avg / 10, tp_avg % 10,
  117. eprob / 10, eprob % 10,
  118. - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
  119. + prob_ewmsd / 10, prob_ewmsd % 10,
  120. mrs->retry_count,
  121. mrs->last_success,
  122. mrs->last_attempts,
  123. --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
  124. +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
  125. @@ -41,6 +41,7 @@ minstrel_ht_stats_dump(struct minstrel_h
  126. struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
  127. static const int bitrates[4] = { 10, 20, 55, 110 };
  128. int idx = i * MCS_GROUP_RATES + j;
  129. + unsigned int prob_ewmsd;
  130. if (!(mi->supported[i] & BIT(j)))
  131. continue;
  132. @@ -84,6 +85,7 @@ minstrel_ht_stats_dump(struct minstrel_h
  133. tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
  134. tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
  135. eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
  136. + prob_ewmsd = minstrel_get_ewmsd10(mrs);
  137. p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u"
  138. " %3u %3u %-3u "
  139. @@ -91,7 +93,7 @@ minstrel_ht_stats_dump(struct minstrel_h
  140. tp_max / 10, tp_max % 10,
  141. tp_avg / 10, tp_avg % 10,
  142. eprob / 10, eprob % 10,
  143. - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
  144. + prob_ewmsd / 10, prob_ewmsd % 10,
  145. mrs->retry_count,
  146. mrs->last_success,
  147. mrs->last_attempts,
  148. @@ -185,6 +187,7 @@ minstrel_ht_stats_csv_dump(struct minstr
  149. struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j];
  150. static const int bitrates[4] = { 10, 20, 55, 110 };
  151. int idx = i * MCS_GROUP_RATES + j;
  152. + unsigned int prob_ewmsd;
  153. if (!(mi->supported[i] & BIT(j)))
  154. continue;
  155. @@ -225,13 +228,14 @@ minstrel_ht_stats_csv_dump(struct minstr
  156. tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
  157. tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma);
  158. eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000);
  159. + prob_ewmsd = minstrel_get_ewmsd10(mrs);
  160. p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"
  161. "%u,%llu,%llu,",
  162. tp_max / 10, tp_max % 10,
  163. tp_avg / 10, tp_avg % 10,
  164. eprob / 10, eprob % 10,
  165. - mrs->prob_ewmsd / 10, mrs->prob_ewmsd % 10,
  166. + prob_ewmsd / 10, prob_ewmsd % 10,
  167. mrs->retry_count,
  168. mrs->last_success,
  169. mrs->last_attempts,