Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: minstrel_ht: use bitfields to encode rate indexes

Get rid of a lot of divisions and modulo operations
Reduces code size and improves performance

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20210127055735.78599-1-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Felix Fietkau and committed by
Johannes Berg
a42fa256 9e6d5126

+79 -64
+64 -62
net/mac80211/rc80211_minstrel_ht.c
··· 379 379 static inline struct minstrel_rate_stats * 380 380 minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index) 381 381 { 382 - return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; 382 + return &mi->groups[MI_RATE_GROUP(index)].rates[MI_RATE_IDX(index)]; 383 383 } 384 384 385 385 static inline int minstrel_get_duration(int index) 386 386 { 387 - const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 388 - unsigned int duration = group->duration[index % MCS_GROUP_RATES]; 387 + const struct mcs_group *group = &minstrel_mcs_groups[MI_RATE_GROUP(index)]; 388 + unsigned int duration = group->duration[MI_RATE_IDX(index)]; 389 389 390 390 return duration << group->shift; 391 391 } ··· 398 398 if (mi->avg_ampdu_len) 399 399 return MINSTREL_TRUNC(mi->avg_ampdu_len); 400 400 401 - if (minstrel_ht_is_legacy_group(mi->max_tp_rate[0] / MCS_GROUP_RATES)) 401 + if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_tp_rate[0]))) 402 402 return 1; 403 403 404 404 duration = minstrel_get_duration(mi->max_tp_rate[0]); ··· 465 465 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob; 466 466 int j = MAX_THR_RATES; 467 467 468 - cur_group = index / MCS_GROUP_RATES; 469 - cur_idx = index % MCS_GROUP_RATES; 468 + cur_group = MI_RATE_GROUP(index); 469 + cur_idx = MI_RATE_IDX(index); 470 470 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg; 471 471 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob); 472 472 473 473 do { 474 - tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; 475 - tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; 474 + tmp_group = MI_RATE_GROUP(tp_list[j - 1]); 475 + tmp_idx = MI_RATE_IDX(tp_list[j - 1]); 476 476 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; 477 477 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, 478 478 tmp_prob); ··· 504 504 int max_gpr_group, max_gpr_idx; 505 505 int max_gpr_tp_avg, max_gpr_prob; 506 506 507 - cur_group = index / MCS_GROUP_RATES; 508 - cur_idx = index % MCS_GROUP_RATES; 509 - mg = &mi->groups[index / MCS_GROUP_RATES]; 510 - mrs = &mg->rates[index % MCS_GROUP_RATES]; 507 + cur_group = MI_RATE_GROUP(index); 508 + cur_idx = MI_RATE_IDX(index); 509 + mg = &mi->groups[cur_group]; 510 + mrs = &mg->rates[cur_idx]; 511 511 512 - tmp_group = *dest / MCS_GROUP_RATES; 513 - tmp_idx = *dest % MCS_GROUP_RATES; 512 + tmp_group = MI_RATE_GROUP(*dest); 513 + tmp_idx = MI_RATE_IDX(*dest); 514 514 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; 515 515 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 516 516 517 517 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from 518 518 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ 519 - max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES; 520 - max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; 519 + max_tp_group = MI_RATE_GROUP(mi->max_tp_rate[0]); 520 + max_tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); 521 521 max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg; 522 522 523 - if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) && 523 + if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(index)) && 524 524 !minstrel_ht_is_legacy_group(max_tp_group)) 525 525 return; 526 526 ··· 529 529 mrs->prob_avg < max_tp_prob) 530 530 return; 531 531 532 - max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; 533 - max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; 532 + max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate); 533 + max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate); 534 534 max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; 535 535 536 536 if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) { ··· 567 567 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob; 568 568 int i; 569 569 570 - tmp_group = tmp_legacy_tp_rate[0] / MCS_GROUP_RATES; 571 - tmp_idx = tmp_legacy_tp_rate[0] % MCS_GROUP_RATES; 570 + tmp_group = MI_RATE_GROUP(tmp_legacy_tp_rate[0]); 571 + tmp_idx = MI_RATE_IDX(tmp_legacy_tp_rate[0]); 572 572 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; 573 573 tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 574 574 575 - tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES; 576 - tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES; 575 + tmp_group = MI_RATE_GROUP(tmp_mcs_tp_rate[0]); 576 + tmp_idx = MI_RATE_IDX(tmp_mcs_tp_rate[0]); 577 577 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; 578 578 tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 579 579 ··· 600 600 if (!mi->sta->ht_cap.ht_supported) 601 601 return; 602 602 603 - tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / 604 - MCS_GROUP_RATES].streams; 603 + group = MI_RATE_GROUP(mi->max_tp_rate[0]); 604 + tmp_max_streams = minstrel_mcs_groups[group].streams; 605 605 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { 606 606 mg = &mi->groups[group]; 607 607 if (!mi->supported[group] || group == MINSTREL_CCK_GROUP) 608 608 continue; 609 609 610 - tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; 610 + tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate); 611 611 tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg; 612 612 613 613 if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) && ··· 644 644 int i, g, max_dur; 645 645 int tp_idx; 646 646 647 - tp_group = &minstrel_mcs_groups[mi->max_tp_rate[0] / MCS_GROUP_RATES]; 648 - tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; 647 + tp_group = &minstrel_mcs_groups[MI_RATE_GROUP(mi->max_tp_rate[0])]; 648 + tp_idx = MI_RATE_IDX(mi->max_tp_rate[0]); 649 649 650 650 max_dur = minstrel_get_duration(mi->max_tp_rate[0]); 651 651 if (faster_rate) ··· 670 670 if ((group->duration[i] << group->shift) > max_dur) 671 671 continue; 672 672 673 - idx = g * MCS_GROUP_RATES + i; 673 + idx = MI_RATE(g, i); 674 674 if (idx == mi->max_tp_rate[0]) 675 675 continue; 676 676 ··· 712 712 713 713 /* If no suitable rate was found, try to pick the next one in the group */ 714 714 if (!n_rates) { 715 - int g_idx = mi->max_tp_rate[0] / MCS_GROUP_RATES; 715 + int g_idx = MI_RATE_GROUP(mi->max_tp_rate[0]); 716 716 u16 supported = mi->supported[g_idx]; 717 717 718 - supported >>= mi->max_tp_rate[0] % MCS_GROUP_RATES; 718 + supported >>= MI_RATE_IDX(mi->max_tp_rate[0]); 719 719 for (i = 0; supported; supported >>= 1, i++) { 720 720 if (!(supported & 1)) 721 721 continue; ··· 854 854 mi->sample_slow = 0; 855 855 mi->sample_count = 0; 856 856 857 - memset(tmp_mcs_tp_rate, 0, sizeof(tmp_mcs_tp_rate)); 858 - memset(tmp_legacy_tp_rate, 0, sizeof(tmp_legacy_tp_rate)); 859 857 if (mi->supported[MINSTREL_CCK_GROUP]) 860 - for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) 861 - tmp_legacy_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; 858 + group = MINSTREL_CCK_GROUP; 862 859 else if (mi->supported[MINSTREL_OFDM_GROUP]) 863 - for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) 864 - tmp_legacy_tp_rate[j] = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; 860 + group = MINSTREL_OFDM_GROUP; 861 + else 862 + group = 0; 863 + 864 + index = MI_RATE(group, 0); 865 + for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) 866 + tmp_legacy_tp_rate[j] = index; 865 867 866 868 if (mi->supported[MINSTREL_VHT_GROUP_0]) 867 - index = MINSTREL_VHT_GROUP_0 * MCS_GROUP_RATES; 869 + group = MINSTREL_VHT_GROUP_0; 868 870 else if (ht_supported) 869 - index = MINSTREL_HT_GROUP_0 * MCS_GROUP_RATES; 871 + group = MINSTREL_HT_GROUP_0; 870 872 else if (mi->supported[MINSTREL_CCK_GROUP]) 871 - index = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; 873 + group = MINSTREL_CCK_GROUP; 872 874 else 873 - index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; 875 + group = MINSTREL_OFDM_GROUP; 874 876 877 + index = MI_RATE(group, 0); 875 878 tmp_max_prob_rate = index; 876 879 for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) 877 880 tmp_mcs_tp_rate[j] = index; ··· 891 888 892 889 /* (re)Initialize group rate indexes */ 893 890 for(j = 0; j < MAX_THR_RATES; j++) 894 - tmp_group_tp_rate[j] = MCS_GROUP_RATES * group; 891 + tmp_group_tp_rate[j] = MI_RATE(group, 0); 895 892 896 893 if (group == MINSTREL_CCK_GROUP && ht_supported) 897 894 tp_rate = tmp_legacy_tp_rate; ··· 900 897 if (!(mi->supported[group] & BIT(i))) 901 898 continue; 902 899 903 - index = MCS_GROUP_RATES * group + i; 900 + index = MI_RATE(group, i); 904 901 905 902 mrs = &mg->rates[i]; 906 903 mrs->retry_updated = false; ··· 932 929 continue; 933 930 934 931 mg = &mi->groups[group]; 935 - mg->max_group_prob_rate = MCS_GROUP_RATES * group; 932 + mg->max_group_prob_rate = MI_RATE(group, 0); 936 933 937 934 for (i = 0; i < MCS_GROUP_RATES; i++) { 938 935 if (!(mi->supported[group] & BIT(i))) 939 936 continue; 940 937 941 - index = MCS_GROUP_RATES * group + i; 938 + index = MI_RATE(group, i); 942 939 943 940 /* Find max probability rate per group and global */ 944 941 minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate, ··· 1025 1022 { 1026 1023 int group, orig_group; 1027 1024 1028 - orig_group = group = *idx / MCS_GROUP_RATES; 1025 + orig_group = group = MI_RATE_GROUP(*idx); 1029 1026 while (group > 0) { 1030 1027 group--; 1031 1028 ··· 1209 1206 ctime += (t_slot * cw) >> 1; 1210 1207 cw = min((cw << 1) | 1, mp->cw_max); 1211 1208 1212 - if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES)) { 1209 + if (minstrel_ht_is_legacy_group(MI_RATE_GROUP(index))) { 1213 1210 overhead = mi->overhead_legacy; 1214 1211 overhead_rtscts = mi->overhead_legacy_rtscts; 1215 1212 } else { ··· 1242 1239 minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 1243 1240 struct ieee80211_sta_rates *ratetbl, int offset, int index) 1244 1241 { 1245 - int group_idx = index / MCS_GROUP_RATES; 1242 + int group_idx = MI_RATE_GROUP(index); 1246 1243 const struct mcs_group *group = &minstrel_mcs_groups[group_idx]; 1247 1244 struct minstrel_rate_stats *mrs; 1248 1245 u8 idx; ··· 1262 1259 ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts; 1263 1260 } 1264 1261 1265 - index %= MCS_GROUP_RATES; 1262 + index = MI_RATE_IDX(index); 1266 1263 if (group_idx == MINSTREL_CCK_GROUP) 1267 1264 idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; 1268 1265 else if (group_idx == MINSTREL_OFDM_GROUP) ··· 1292 1289 static inline int 1293 1290 minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate) 1294 1291 { 1295 - int group = rate / MCS_GROUP_RATES; 1296 - rate %= MCS_GROUP_RATES; 1292 + int group = MI_RATE_GROUP(rate); 1293 + rate = MI_RATE_IDX(rate); 1297 1294 return mi->groups[group].rates[rate].prob_avg; 1298 1295 } 1299 1296 1300 1297 static int 1301 1298 minstrel_ht_get_max_amsdu_len(struct minstrel_ht_sta *mi) 1302 1299 { 1303 - int group = mi->max_prob_rate / MCS_GROUP_RATES; 1300 + int group = MI_RATE_GROUP(mi->max_prob_rate); 1304 1301 const struct mcs_group *g = &minstrel_mcs_groups[group]; 1305 - int rate = mi->max_prob_rate % MCS_GROUP_RATES; 1302 + int rate = MI_RATE_IDX(mi->max_prob_rate); 1306 1303 unsigned int duration; 1307 1304 1308 1305 /* Disable A-MSDU if max_prob_rate is bad */ ··· 1408 1405 return -1; 1409 1406 1410 1407 mrs = &mg->rates[sample_idx]; 1411 - sample_idx += sample_group * MCS_GROUP_RATES; 1408 + sample_idx += MI_RATE(sample_group, 0); 1412 1409 1413 1410 tp_rate1 = mi->max_tp_rate[0]; 1414 1411 ··· 1458 1455 * if the link is working perfectly. 1459 1456 */ 1460 1457 1461 - cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 / 1462 - MCS_GROUP_RATES].streams; 1458 + cur_max_tp_streams = minstrel_mcs_groups[MI_RATE_GROUP(tp_rate1)].streams; 1463 1459 if (sample_dur >= minstrel_get_duration(tp_rate2) && 1464 1460 (cur_max_tp_streams - 1 < 1465 1461 minstrel_mcs_groups[sample_group].streams || ··· 1486 1484 int sample_idx; 1487 1485 1488 1486 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && 1489 - !minstrel_ht_is_legacy_group(mi->max_prob_rate / MCS_GROUP_RATES)) 1487 + !minstrel_ht_is_legacy_group(MI_RATE_GROUP(mi->max_prob_rate))) 1490 1488 minstrel_aggr_check(sta, txrc->skb); 1491 1489 1492 1490 info->flags |= mi->tx_flags; ··· 1514 1512 if (sample_idx < 0) 1515 1513 return; 1516 1514 1517 - sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES]; 1518 - sample_idx %= MCS_GROUP_RATES; 1515 + sample_group = &minstrel_mcs_groups[MI_RATE_GROUP(sample_idx)]; 1516 + sample_idx = MI_RATE_IDX(sample_idx); 1519 1517 1520 1518 if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] && 1521 1519 (sample_idx >= 4) != txrc->short_preamble) ··· 1531 1529 int idx = sample_idx % ARRAY_SIZE(mp->ofdm_rates[0]); 1532 1530 rate->idx = mp->ofdm_rates[mi->band][idx]; 1533 1531 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { 1534 - ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES, 1532 + ieee80211_rate_set_vht(rate, MI_RATE_IDX(sample_idx), 1535 1533 sample_group->streams); 1536 1534 } else { 1537 1535 rate->idx = sample_idx + (sample_group->streams - 1) * 8; ··· 1900 1898 struct minstrel_ht_sta *mi = priv_sta; 1901 1899 int i, j, prob, tp_avg; 1902 1900 1903 - i = mi->max_tp_rate[0] / MCS_GROUP_RATES; 1904 - j = mi->max_tp_rate[0] % MCS_GROUP_RATES; 1901 + i = MI_RATE_GROUP(mi->max_tp_rate[0]); 1902 + j = MI_RATE_IDX(mi->max_tp_rate[0]); 1905 1903 prob = mi->groups[i].rates[j].prob_avg; 1906 1904 1907 1905 /* convert tp_avg from pkt per second in kbps */
+13
net/mac80211/rc80211_minstrel_ht.h
··· 6 6 #ifndef __RC_MINSTREL_HT_H 7 7 #define __RC_MINSTREL_HT_H 8 8 9 + #include <linux/bitfield.h> 10 + 9 11 /* number of highest throughput rates to consider*/ 10 12 #define MAX_THR_RATES 4 11 13 #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ ··· 58 56 #define MINSTREL_VHT_GROUP_0 (MINSTREL_OFDM_GROUP + 1) 59 57 60 58 #define MCS_GROUP_RATES 10 59 + 60 + #define MI_RATE_IDX_MASK GENMASK(3, 0) 61 + #define MI_RATE_GROUP_MASK GENMASK(15, 4) 62 + 63 + #define MI_RATE(_group, _idx) \ 64 + (FIELD_PREP(MI_RATE_GROUP_MASK, _group) | \ 65 + FIELD_PREP(MI_RATE_IDX_MASK, _idx)) 66 + 67 + #define MI_RATE_IDX(_rate) FIELD_GET(MI_RATE_IDX_MASK, _rate) 68 + #define MI_RATE_GROUP(_rate) FIELD_GET(MI_RATE_GROUP_MASK, _rate) 69 + 61 70 62 71 struct minstrel_priv { 63 72 struct ieee80211_hw *hw;
+2 -2
net/mac80211/rc80211_minstrel_ht_debugfs.c
··· 56 56 57 57 for (j = 0; j < MCS_GROUP_RATES; j++) { 58 58 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; 59 - int idx = i * MCS_GROUP_RATES + j; 59 + int idx = MI_RATE(i, j); 60 60 unsigned int duration; 61 61 62 62 if (!(mi->supported[i] & BIT(j))) ··· 201 201 202 202 for (j = 0; j < MCS_GROUP_RATES; j++) { 203 203 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; 204 - int idx = i * MCS_GROUP_RATES + j; 204 + int idx = MI_RATE(i, j); 205 205 unsigned int duration; 206 206 207 207 if (!(mi->supported[i] & BIT(j)))