349-mac80211-minstrel_ht-significantly-redesign-the-rate.patch 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. From: Felix Fietkau <[email protected]>
  2. Date: Fri, 22 Jan 2021 23:57:50 +0100
  3. Subject: [PATCH] mac80211: minstrel_ht: significantly redesign the rate
  4. probing strategy
  5. The biggest flaw in current minstrel_ht is the fact that it needs way too
  6. many probing packets to be able to quickly find the best rate.
  7. Depending on the wifi hardware and operating mode, this can significantly
  8. reduce throughput when not operating at the highest available data rate.
  9. In order to be able to significantly reduce the amount of rate sampling,
  10. we need a much smarter selection of probing rates.
  11. The new approach introduced by this patch maintains a limited set of
  12. available rates to be tested during a statistics window.
  13. They are split into distinct categories:
  14. - MINSTREL_SAMPLE_TYPE_INC - incremental rate upgrade:
  15. Pick the next rate group and find the first rate that is faster than
  16. the current max. throughput rate
  17. - MINSTREL_SAMPLE_TYPE_JUMP - random testing of higher rates:
  18. Pick a random rate from the next group that is faster than the current
  19. max throughput rate. This allows faster adaptation when the link changes
  20. significantly
  21. - MINSTREL_SAMPLE_TYPE_SLOW - test a rate between max_prob, max_tp2 and
  22. max_tp in order to reduce the gap between them
  23. In order to prioritize sampling, every 6 attempts are split into 3x INC,
  24. 2x JUMP, 1x SLOW.
  25. Available rates are checked and refilled on every stats window update.
  26. With this approach, we finally get a very small delta in throughput when
  27. comparing setting the optimal data rate as a fixed rate vs normal rate
  28. control operation.
  29. Signed-off-by: Felix Fietkau <[email protected]>
  30. ---
  31. --- a/net/mac80211/rc80211_minstrel_ht.c
  32. +++ b/net/mac80211/rc80211_minstrel_ht.c
  33. @@ -266,6 +266,14 @@ const struct mcs_group minstrel_mcs_grou
  34. const s16 minstrel_cck_bitrates[4] = { 10, 20, 55, 110 };
  35. const s16 minstrel_ofdm_bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 };
  36. static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
  37. +static const u8 minstrel_sample_seq[] = {
  38. + MINSTREL_SAMPLE_TYPE_INC,
  39. + MINSTREL_SAMPLE_TYPE_JUMP,
  40. + MINSTREL_SAMPLE_TYPE_INC,
  41. + MINSTREL_SAMPLE_TYPE_JUMP,
  42. + MINSTREL_SAMPLE_TYPE_INC,
  43. + MINSTREL_SAMPLE_TYPE_SLOW,
  44. +};
  45. static void
  46. minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
  47. @@ -620,77 +628,31 @@ minstrel_ht_prob_rate_reduce_streams(str
  48. }
  49. }
  50. -static bool
  51. -minstrel_ht_probe_group(struct minstrel_ht_sta *mi, const struct mcs_group *tp_group,
  52. - int tp_idx, const struct mcs_group *group)
  53. -{
  54. - if (group->bw < tp_group->bw)
  55. - return false;
  56. -
  57. - if (group->streams == tp_group->streams)
  58. - return true;
  59. -
  60. - if (tp_idx < 4 && group->streams == tp_group->streams - 1)
  61. - return true;
  62. -
  63. - return group->streams == tp_group->streams + 1;
  64. -}
  65. -
  66. -static void
  67. -minstrel_ht_find_probe_rates(struct minstrel_ht_sta *mi, u16 *rates, int *n_rates,
  68. - bool faster_rate)
  69. +static u16
  70. +__minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
  71. + enum minstrel_sample_type type)
  72. {
  73. - const struct mcs_group *group, *tp_group;
  74. - int i, g, max_dur;
  75. - int tp_idx;
  76. -
  77. - tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])];
  78. - tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]);
  79. -
  80. - max_dur = minstrel_get_duration(mi->max_tp_rate[0]);
  81. - if (faster_rate)
  82. - max_dur -= max_dur / 16;
  83. -
  84. - for (g = 0; g < MINSTREL_GROUPS_NB; g++) {
  85. - u16 supported = mi->supported[g];
  86. -
  87. - if (!supported)
  88. - continue;
  89. + u16 *rates = mi->sample[type].sample_rates;
  90. + u16 cur;
  91. + int i;
  92. - group = &minstrel_mcs_groups[g];
  93. - if (!minstrel_ht_probe_group(mi, tp_group, tp_idx, group))
  94. + for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) {
  95. + if (!rates[i])
  96. continue;
  97. - for (i = 0; supported; supported >>= 1, i++) {
  98. - int idx;
  99. -
  100. - if (!(supported & 1))
  101. - continue;
  102. -
  103. - if ((group->duration[i] << group->shift) > max_dur)
  104. - continue;
  105. -
  106. - idx = MI_RATE(g, i);
  107. - if (idx == mi->max_tp_rate[0])
  108. - continue;
  109. -
  110. - rates[(*n_rates)++] = idx;
  111. - break;
  112. - }
  113. + cur = rates[i];
  114. + rates[i] = 0;
  115. + return cur;
  116. }
  117. +
  118. + return 0;
  119. }
  120. static void
  121. minstrel_ht_rate_sample_switch(struct minstrel_priv *mp,
  122. struct minstrel_ht_sta *mi)
  123. {
  124. - struct minstrel_rate_stats *mrs;
  125. - u16 rates[MINSTREL_GROUPS_NB];
  126. - int n_rates = 0;
  127. - int probe_rate = 0;
  128. - bool faster_rate;
  129. - int i;
  130. - u8 random;
  131. + u16 rate;
  132. /*
  133. * Use rate switching instead of probing packets for devices with
  134. @@ -699,43 +661,11 @@ minstrel_ht_rate_sample_switch(struct mi
  135. if (mp->hw->max_rates > 1)
  136. return;
  137. - /*
  138. - * If the current EWMA prob is >75%, look for a rate that's 6.25%
  139. - * faster than the max tp rate.
  140. - * If that fails, look again for a rate that is at least as fast
  141. - */
  142. - mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
  143. - faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100);
  144. - minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate);
  145. - if (!n_rates && faster_rate)
  146. - minstrel_ht_find_probe_rates(mi, rates, &n_rates, false);
  147. -
  148. - /* If no suitable rate was found, try to pick the next one in the group */
  149. - if (!n_rates) {
  150. - int g_idx = MI_RATE_GROUP(mi->max_tp_rate[0]);
  151. - u16 supported = mi->supported[g_idx];
  152. -
  153. - supported >>= MI_RATE_IDX(mi->max_tp_rate[0]);
  154. - for (i = 0; supported; supported >>= 1, i++) {
  155. - if (!(supported & 1))
  156. - continue;
  157. -
  158. - probe_rate = mi->max_tp_rate[0] + i;
  159. - goto out;
  160. - }
  161. -
  162. + rate = __minstrel_ht_get_sample_rate(mi, MINSTREL_SAMPLE_TYPE_INC);
  163. + if (!rate)
  164. return;
  165. - }
  166. -
  167. - i = 0;
  168. - if (n_rates > 1) {
  169. - random = prandom_u32();
  170. - i = random % n_rates;
  171. - }
  172. - probe_rate = rates[i];
  173. -out:
  174. - mi->sample_rate = probe_rate;
  175. + mi->sample_rate = rate;
  176. mi->sample_mode = MINSTREL_SAMPLE_ACTIVE;
  177. }
  178. @@ -804,6 +734,274 @@ minstrel_ht_calc_rate_stats(struct minst
  179. mrs->attempts = 0;
  180. }
  181. +static bool
  182. +minstrel_ht_find_sample_rate(struct minstrel_ht_sta *mi, int type, int idx)
  183. +{
  184. + int i;
  185. +
  186. + for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) {
  187. + u16 cur = mi->sample[type].sample_rates[i];
  188. +
  189. + if (cur == idx)
  190. + return true;
  191. +
  192. + if (!cur)
  193. + break;
  194. + }
  195. +
  196. + return false;
  197. +}
  198. +
  199. +static int
  200. +minstrel_ht_move_sample_rates(struct minstrel_ht_sta *mi, int type,
  201. + u32 fast_rate_dur, u32 slow_rate_dur)
  202. +{
  203. + u16 *rates = mi->sample[type].sample_rates;
  204. + int i, j;
  205. +
  206. + for (i = 0, j = 0; i < MINSTREL_SAMPLE_RATES; i++) {
  207. + u32 duration;
  208. + bool valid = false;
  209. + u16 cur;
  210. +
  211. + cur = rates[i];
  212. + if (!cur)
  213. + continue;
  214. +
  215. + duration = minstrel_get_duration(cur);
  216. + switch (type) {
  217. + case MINSTREL_SAMPLE_TYPE_SLOW:
  218. + valid = duration > fast_rate_dur &&
  219. + duration < slow_rate_dur;
  220. + break;
  221. + case MINSTREL_SAMPLE_TYPE_INC:
  222. + case MINSTREL_SAMPLE_TYPE_JUMP:
  223. + valid = duration < fast_rate_dur;
  224. + break;
  225. + default:
  226. + valid = false;
  227. + break;
  228. + }
  229. +
  230. + if (!valid) {
  231. + rates[i] = 0;
  232. + continue;
  233. + }
  234. +
  235. + if (i == j)
  236. + continue;
  237. +
  238. + rates[j++] = cur;
  239. + rates[i] = 0;
  240. + }
  241. +
  242. + return j;
  243. +}
  244. +
  245. +static int
  246. +minstrel_ht_group_min_rate_offset(struct minstrel_ht_sta *mi, int group,
  247. + u32 max_duration)
  248. +{
  249. + u16 supported = mi->supported[group];
  250. + int i;
  251. +
  252. + for (i = 0; i < MCS_GROUP_RATES && supported; i++, supported >>= 1) {
  253. + if (!(supported & BIT(0)))
  254. + continue;
  255. +
  256. + if (minstrel_get_duration(MI_RATE(group, i)) >= max_duration)
  257. + continue;
  258. +
  259. + return i;
  260. + }
  261. +
  262. + return -1;
  263. +}
  264. +
  265. +/*
  266. + * Incremental update rates:
  267. + * Flip through groups and pick the first group rate that is faster than the
  268. + * highest currently selected rate
  269. + */
  270. +static u16
  271. +minstrel_ht_next_inc_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur)
  272. +{
  273. + struct minstrel_mcs_group_data *mg;
  274. + u8 type = MINSTREL_SAMPLE_TYPE_INC;
  275. + int i, index = 0;
  276. + u8 group;
  277. +
  278. + group = mi->sample[type].sample_group;
  279. + for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) {
  280. + group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups);
  281. + mg = &mi->groups[group];
  282. +
  283. + index = minstrel_ht_group_min_rate_offset(mi, group,
  284. + fast_rate_dur);
  285. + if (index < 0)
  286. + continue;
  287. +
  288. + index = MI_RATE(group, index & 0xf);
  289. + if (!minstrel_ht_find_sample_rate(mi, type, index))
  290. + goto out;
  291. + }
  292. + index = 0;
  293. +
  294. +out:
  295. + mi->sample[type].sample_group = group;
  296. +
  297. + return index;
  298. +}
  299. +
  300. +static int
  301. +minstrel_ht_next_group_sample_rate(struct minstrel_ht_sta *mi, int group,
  302. + u16 supported, int offset)
  303. +{
  304. + struct minstrel_mcs_group_data *mg = &mi->groups[group];
  305. + u16 idx;
  306. + int i;
  307. +
  308. + for (i = 0; i < MCS_GROUP_RATES; i++) {
  309. + idx = sample_table[mg->column][mg->index];
  310. + if (++mg->index >= MCS_GROUP_RATES) {
  311. + mg->index = 0;
  312. + if (++mg->column >= ARRAY_SIZE(sample_table))
  313. + mg->column = 0;
  314. + }
  315. +
  316. + if (idx < offset)
  317. + continue;
  318. +
  319. + if (!(supported & BIT(idx)))
  320. + continue;
  321. +
  322. + return MI_RATE(group, idx);
  323. + }
  324. +
  325. + return -1;
  326. +}
  327. +
  328. +/*
  329. + * Jump rates:
  330. + * Sample random rates, use those that are faster than the highest
  331. + * currently selected rate. Rates between the fastest and the slowest
  332. + * get sorted into the slow sample bucket, but only if it has room
  333. + */
  334. +static u16
  335. +minstrel_ht_next_jump_rate(struct minstrel_ht_sta *mi, u32 fast_rate_dur,
  336. + u32 slow_rate_dur, int *slow_rate_ofs)
  337. +{
  338. + struct minstrel_mcs_group_data *mg;
  339. + struct minstrel_rate_stats *mrs;
  340. + u32 max_duration = slow_rate_dur;
  341. + int i, index, offset;
  342. + u16 *slow_rates;
  343. + u16 supported;
  344. + u32 duration;
  345. + u8 group;
  346. +
  347. + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES)
  348. + max_duration = fast_rate_dur;
  349. +
  350. + slow_rates = mi->sample[MINSTREL_SAMPLE_TYPE_SLOW].sample_rates;
  351. + group = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group;
  352. + for (i = 0; i < ARRAY_SIZE(minstrel_mcs_groups); i++) {
  353. + u8 type;
  354. +
  355. + group = (group + 1) % ARRAY_SIZE(minstrel_mcs_groups);
  356. + mg = &mi->groups[group];
  357. +
  358. + supported = mi->supported[group];
  359. + if (!supported)
  360. + continue;
  361. +
  362. + offset = minstrel_ht_group_min_rate_offset(mi, group,
  363. + max_duration);
  364. + if (offset < 0)
  365. + continue;
  366. +
  367. + index = minstrel_ht_next_group_sample_rate(mi, group, supported,
  368. + offset);
  369. + if (index < 0)
  370. + continue;
  371. +
  372. + duration = minstrel_get_duration(index);
  373. + if (duration < fast_rate_dur)
  374. + type = MINSTREL_SAMPLE_TYPE_JUMP;
  375. + else
  376. + type = MINSTREL_SAMPLE_TYPE_SLOW;
  377. +
  378. + if (minstrel_ht_find_sample_rate(mi, type, index))
  379. + continue;
  380. +
  381. + if (type == MINSTREL_SAMPLE_TYPE_JUMP)
  382. + goto found;
  383. +
  384. + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES)
  385. + continue;
  386. +
  387. + if (duration >= slow_rate_dur)
  388. + continue;
  389. +
  390. + /* skip slow rates with high success probability */
  391. + mrs = minstrel_get_ratestats(mi, index);
  392. + if (mrs->prob_avg > MINSTREL_FRAC(95, 100))
  393. + continue;
  394. +
  395. + slow_rates[(*slow_rate_ofs)++] = index;
  396. + if (*slow_rate_ofs >= MINSTREL_SAMPLE_RATES)
  397. + max_duration = fast_rate_dur;
  398. + }
  399. + index = 0;
  400. +
  401. +found:
  402. + mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_group = group;
  403. +
  404. + return index;
  405. +}
  406. +
  407. +static void
  408. +minstrel_ht_refill_sample_rates(struct minstrel_ht_sta *mi)
  409. +{
  410. + u32 prob_dur = minstrel_get_duration(mi->max_prob_rate);
  411. + u32 tp_dur = minstrel_get_duration(mi->max_tp_rate[0]);
  412. + u32 tp2_dur = minstrel_get_duration(mi->max_tp_rate[1]);
  413. + u32 fast_rate_dur = min(min(tp_dur, tp2_dur), prob_dur);
  414. + u32 slow_rate_dur = max(max(tp_dur, tp2_dur), prob_dur);
  415. + u16 *rates;
  416. + int i, j;
  417. +
  418. + rates = mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates;
  419. + i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_INC,
  420. + fast_rate_dur, slow_rate_dur);
  421. + while (i < MINSTREL_SAMPLE_RATES) {
  422. + rates[i] = minstrel_ht_next_inc_rate(mi, tp_dur);
  423. + if (!rates[i])
  424. + break;
  425. +
  426. + i++;
  427. + }
  428. +
  429. + rates = mi->sample[MINSTREL_SAMPLE_TYPE_JUMP].sample_rates;
  430. + i = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_JUMP,
  431. + fast_rate_dur, slow_rate_dur);
  432. + j = minstrel_ht_move_sample_rates(mi, MINSTREL_SAMPLE_TYPE_SLOW,
  433. + fast_rate_dur, slow_rate_dur);
  434. + while (i < MINSTREL_SAMPLE_RATES) {
  435. + rates[i] = minstrel_ht_next_jump_rate(mi, fast_rate_dur,
  436. + slow_rate_dur, &j);
  437. + if (!rates[i])
  438. + break;
  439. +
  440. + i++;
  441. + }
  442. +
  443. + for (i = 0; i < ARRAY_SIZE(mi->sample); i++)
  444. + memcpy(mi->sample[i].cur_sample_rates, mi->sample[i].sample_rates,
  445. + sizeof(mi->sample[i].cur_sample_rates));
  446. +}
  447. +
  448. +
  449. /*
  450. * Update rate statistics and select new primary rates
  451. *
  452. @@ -848,8 +1046,6 @@ minstrel_ht_update_stats(struct minstrel
  453. mi->ampdu_packets = 0;
  454. }
  455. - mi->sample_count = 0;
  456. -
  457. if (mi->supported[MINSTREL_CCK_GROUP])
  458. group = MINSTREL_CCK_GROUP;
  459. else if (mi->supported[MINSTREL_OFDM_GROUP])
  460. @@ -884,8 +1080,6 @@ minstrel_ht_update_stats(struct minstrel
  461. if (!mi->supported[group])
  462. continue;
  463. - mi->sample_count++;
  464. -
  465. /* (re)Initialize group rate indexes */
  466. for(j = 0; j < MAX_THR_RATES; j++)
  467. tmp_group_tp_rate[j] = MI_RATE(group, 0);
  468. @@ -952,9 +1146,7 @@ minstrel_ht_update_stats(struct minstrel
  469. /* Try to increase robustness of max_prob_rate*/
  470. minstrel_ht_prob_rate_reduce_streams(mi);
  471. -
  472. - /* try to sample half of all available rates during each interval */
  473. - mi->sample_count *= 4;
  474. + minstrel_ht_refill_sample_rates(mi);
  475. if (sample)
  476. minstrel_ht_rate_sample_switch(mp, mi);
  477. @@ -971,6 +1163,7 @@ minstrel_ht_update_stats(struct minstrel
  478. /* Reset update timer */
  479. mi->last_stats_update = jiffies;
  480. + mi->sample_time = jiffies;
  481. }
  482. static bool
  483. @@ -1001,28 +1194,6 @@ minstrel_ht_txstat_valid(struct minstrel
  484. }
  485. static void
  486. -minstrel_set_next_sample_idx(struct minstrel_ht_sta *mi)
  487. -{
  488. - struct minstrel_mcs_group_data *mg;
  489. -
  490. - for (;;) {
  491. - mi->sample_group++;
  492. - mi->sample_group %= ARRAY_SIZE(minstrel_mcs_groups);
  493. - mg = &mi->groups[mi->sample_group];
  494. -
  495. - if (!mi->supported[mi->sample_group])
  496. - continue;
  497. -
  498. - if (++mg->index >= MCS_GROUP_RATES) {
  499. - mg->index = 0;
  500. - if (++mg->column >= ARRAY_SIZE(sample_table))
  501. - mg->column = 0;
  502. - }
  503. - break;
  504. - }
  505. -}
  506. -
  507. -static void
  508. minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
  509. {
  510. int group, orig_group;
  511. @@ -1107,14 +1278,6 @@ minstrel_ht_tx_status(void *priv, struct
  512. mi->ampdu_packets++;
  513. mi->ampdu_len += info->status.ampdu_len;
  514. - if (!mi->sample_wait && !mi->sample_tries && mi->sample_count > 0) {
  515. - int avg_ampdu_len = minstrel_ht_avg_ampdu_len(mi);
  516. -
  517. - mi->sample_wait = 16 + 2 * avg_ampdu_len;
  518. - mi->sample_tries = 1;
  519. - mi->sample_count--;
  520. - }
  521. -
  522. if (mi->sample_mode != MINSTREL_SAMPLE_IDLE)
  523. rate_sample = minstrel_get_ratestats(mi, mi->sample_rate);
  524. @@ -1386,97 +1549,20 @@ minstrel_ht_update_rates(struct minstrel
  525. rate_control_set_rates(mp->hw, mi->sta, rates);
  526. }
  527. -static int
  528. -minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
  529. +static u16
  530. +minstrel_ht_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
  531. {
  532. - struct minstrel_rate_stats *mrs;
  533. - struct minstrel_mcs_group_data *mg;
  534. - unsigned int sample_dur, sample_group, cur_max_tp_streams;
  535. - int tp_rate1, tp_rate2;
  536. - int sample_idx = 0;
  537. -
  538. - if (mp->hw->max_rates == 1 && mp->sample_switch &&
  539. - (mi->total_packets_cur >= SAMPLE_SWITCH_THR ||
  540. - mp->sample_switch == 1))
  541. - return -1;
  542. -
  543. - if (mi->sample_wait > 0) {
  544. - mi->sample_wait--;
  545. - return -1;
  546. - }
  547. -
  548. - if (!mi->sample_tries)
  549. - return -1;
  550. -
  551. - sample_group = mi->sample_group;
  552. - mg = &mi->groups[sample_group];
  553. - sample_idx = sample_table[mg->column][mg->index];
  554. - minstrel_set_next_sample_idx(mi);
  555. -
  556. - if (!(mi->supported[sample_group] & BIT(sample_idx)))
  557. - return -1;
  558. + u8 seq;
  559. - mrs = &mg->rates[sample_idx];
  560. - sample_idx += MI_RATE(sample_group, 0);
  561. -
  562. - tp_rate1 = mi->max_tp_rate[0];
  563. -
  564. - /* Set tp_rate2 to the second highest max_tp_rate */
  565. - if (minstrel_get_duration(mi->max_tp_rate[0]) >
  566. - minstrel_get_duration(mi->max_tp_rate[1])) {
  567. - tp_rate2 = mi->max_tp_rate[0];
  568. + if (mp->hw->max_rates > 1) {
  569. + seq = mi->sample_seq;
  570. + mi->sample_seq = (seq + 1) % ARRAY_SIZE(minstrel_sample_seq);
  571. + seq = minstrel_sample_seq[seq];
  572. } else {
  573. - tp_rate2 = mi->max_tp_rate[1];
  574. + seq = MINSTREL_SAMPLE_TYPE_INC;
  575. }
  576. - /*
  577. - * Sampling might add some overhead (RTS, no aggregation)
  578. - * to the frame. Hence, don't use sampling for the highest currently
  579. - * used highest throughput or probability rate.
  580. - */
  581. - if (sample_idx == mi->max_tp_rate[0] || sample_idx == mi->max_prob_rate)
  582. - return -1;
  583. -
  584. - /*
  585. - * Do not sample if the probability is already higher than 95%,
  586. - * or if the rate is 3 times slower than the current max probability
  587. - * rate, to avoid wasting airtime.
  588. - */
  589. - sample_dur = minstrel_get_duration(sample_idx);
  590. - if (mrs->prob_avg > MINSTREL_FRAC(95, 100) ||
  591. - minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
  592. - return -1;
  593. -
  594. -
  595. - /*
  596. - * For devices with no configurable multi-rate retry, skip sampling
  597. - * below the per-group max throughput rate, and only use one sampling
  598. - * attempt per rate
  599. - */
  600. - if (mp->hw->max_rates == 1 &&
  601. - (minstrel_get_duration(mg->max_group_tp_rate[0]) < sample_dur ||
  602. - mrs->attempts))
  603. - return -1;
  604. -
  605. - /* Skip already sampled slow rates */
  606. - if (sample_dur >= minstrel_get_duration(tp_rate1) && mrs->attempts)
  607. - return -1;
  608. -
  609. - /*
  610. - * Make sure that lower rates get sampled only occasionally,
  611. - * if the link is working perfectly.
  612. - */
  613. -
  614. - cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams;
  615. - if (sample_dur >= minstrel_get_duration(tp_rate2) &&
  616. - (cur_max_tp_streams - 1 <
  617. - minstrel_mcs_groups[sample_group].streams ||
  618. - sample_dur >= minstrel_get_duration(mi->max_prob_rate)))
  619. - return -1;
  620. -
  621. - mi->sample_tries--;
  622. -
  623. - return sample_idx;
  624. + return __minstrel_ht_get_sample_rate(mi, seq);
  625. }
  626. static void
  627. @@ -1488,7 +1574,7 @@ minstrel_ht_get_rate(void *priv, struct
  628. struct ieee80211_tx_rate *rate = &info->status.rates[0];
  629. struct minstrel_ht_sta *mi = priv_sta;
  630. struct minstrel_priv *mp = priv;
  631. - int sample_idx;
  632. + u16 sample_idx;
  633. if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
  634. !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate)))
  635. @@ -1504,11 +1590,19 @@ minstrel_ht_get_rate(void *priv, struct
  636. /* Don't use EAPOL frames for sampling on non-mrr hw */
  637. if (mp->hw->max_rates == 1 &&
  638. (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
  639. - sample_idx = -1;
  640. - else
  641. - sample_idx = minstrel_get_sample_rate(mp, mi);
  642. + return;
  643. +
  644. + if (mp->hw->max_rates == 1 && mp->sample_switch &&
  645. + (mi->total_packets_cur >= SAMPLE_SWITCH_THR ||
  646. + mp->sample_switch == 1))
  647. + return;
  648. +
  649. + if (time_is_before_jiffies(mi->sample_time))
  650. + return;
  651. - if (sample_idx < 0)
  652. + mi->sample_time = jiffies + MINSTREL_SAMPLE_INTERVAL;
  653. + sample_idx = minstrel_ht_get_sample_rate(mp, mi);
  654. + if (!sample_idx)
  655. return;
  656. sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)];
  657. @@ -1629,16 +1723,6 @@ minstrel_ht_update_caps(void *priv, stru
  658. mi->avg_ampdu_len = MINSTREL_FRAC(1, 1);
  659. - /* When using MRR, sample more on the first attempt, without delay */
  660. - if (mp->has_mrr) {
  661. - mi->sample_count = 16;
  662. - mi->sample_wait = 0;
  663. - } else {
  664. - mi->sample_count = 8;
  665. - mi->sample_wait = 8;
  666. - }
  667. - mi->sample_tries = 4;
  668. -
  669. if (!use_vht) {
  670. stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
  671. IEEE80211_HT_CAP_RX_STBC_SHIFT;
  672. --- a/net/mac80211/rc80211_minstrel_ht.h
  673. +++ b/net/mac80211/rc80211_minstrel_ht.h
  674. @@ -69,6 +69,8 @@
  675. #define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate)
  676. #define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate)
  677. +#define MINSTREL_SAMPLE_RATES 5 /* rates per sample type */
  678. +#define MINSTREL_SAMPLE_INTERVAL (HZ / 50)
  679. struct minstrel_priv {
  680. struct ieee80211_hw *hw;
  681. @@ -126,6 +128,13 @@ struct minstrel_rate_stats {
  682. bool retry_updated;
  683. };
  684. +enum minstrel_sample_type {
  685. + MINSTREL_SAMPLE_TYPE_INC,
  686. + MINSTREL_SAMPLE_TYPE_JUMP,
  687. + MINSTREL_SAMPLE_TYPE_SLOW,
  688. + __MINSTREL_SAMPLE_TYPE_MAX
  689. +};
  690. +
  691. struct minstrel_mcs_group_data {
  692. u8 index;
  693. u8 column;
  694. @@ -144,6 +153,12 @@ enum minstrel_sample_mode {
  695. MINSTREL_SAMPLE_PENDING,
  696. };
  697. +struct minstrel_sample_category {
  698. + u8 sample_group;
  699. + u16 sample_rates[MINSTREL_SAMPLE_RATES];
  700. + u16 cur_sample_rates[MINSTREL_SAMPLE_RATES];
  701. +};
  702. +
  703. struct minstrel_ht_sta {
  704. struct ieee80211_sta *sta;
  705. @@ -175,16 +190,14 @@ struct minstrel_ht_sta {
  706. /* tx flags to add for frames for this sta */
  707. u32 tx_flags;
  708. - u8 sample_wait;
  709. - u8 sample_tries;
  710. - u8 sample_count;
  711. + unsigned long sample_time;
  712. + struct minstrel_sample_category sample[__MINSTREL_SAMPLE_TYPE_MAX];
  713. +
  714. + u8 sample_seq;
  715. enum minstrel_sample_mode sample_mode;
  716. u16 sample_rate;
  717. - /* current MCS group to be sampled */
  718. - u8 sample_group;
  719. -
  720. u8 band;
  721. /* Bitfield of supported MCS rates of all groups */