- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/umac/src/rc/rc.c

Go to the documentation of this file.

    00001
    00017 /*
    00018  * INCLUDE FILES
    00019  ****************************************************************************************
    00020  */
    00021 #include "me.h"
    00022 #include "mm.h"
    00023 #include "me_utils.h"
    00024
    00025 #include "txl_cfm.h"
    00026 #include "rc.h"
    00027 #include "vif_mgmt.h"
    00028 #if RW_BFMER_EN
    00029 #include "bfr.h"
    00030 #endif
    00031
    00032 extern struct me_env_tag me_env;
    00033
    00034 /*
    00035  * PRIVATE VARIABLES
    00036  ****************************************************************************************
    00037  */
    00038
    00040 struct rc_sta_stats sta_stats[NX_REMOTE_STA_MAX];
    00041
    00046 static const uint32_t rc_duration_ht_ampdu[10*4*2] =
    00047 {
    00048     //BW20,GI800          BW20,GI400            BW40,GI800            BW40,GI400           MCS Index
    00049     [  0] =  1476923,     [  1] =  1329231,     [  2] =   711111,     [  3] =   640000, // MCS 0
    00050     [  8] =   738462,     [  9] =   664615,     [ 10] =   355556,     [ 11] =   320000, // MCS 1
    00051     [ 16] =   492308,     [ 17] =   443077,     [ 18] =   237037,     [ 19] =   213333, // MCS 2
    00052     [ 24] =   369231,     [ 25] =   332308,     [ 26] =   177778,     [ 27] =   160000, // MCS 3
    00053     [ 32] =   246154,     [ 33] =   221538,     [ 34] =   118519,     [ 35] =   106667, // MCS 4
    00054     [ 40] =   184615,     [ 41] =   166154,     [ 42] =    88889,     [ 43] =    80000, // MCS 5
    00055     [ 48] =   164103,     [ 49] =   147692,     [ 50] =    79012,     [ 51] =    71111, // MCS 6
    00056     [ 56] =   147692,     [ 57] =   132923,     [ 58] =    71111,     [ 59] =    64000, // MCS 7
    00057     [ 64] =   123077,     [ 65] =   110769,     [ 66] =    59259,     [ 67] =    53333, // MCS 8
    00058     [ 72] =   110769,     [ 73] =    99692,     [ 74] =    53333,     [ 75] =    48000, // MCS 9
    00059     //BW80,GI800          BW80,GI400            BW160,GI800           BW160,GI400          MCS Index
    00060     [  4] =   328205,     [  5] =   295385,     [  6] =   164103,     [  7] =   147692, // MCS 0
    00061     [ 12] =   164103,     [ 13] =   147692,     [ 14] =    82051,     [ 15] =    73846, // MCS 1
    00062     [ 20] =   109402,     [ 21] =    98462,     [ 22] =    54701,     [ 23] =    49231, // MCS 2
    00063     [ 28] =    82051,     [ 29] =    73846,     [ 30] =    41026,     [ 31] =    36923, // MCS 3
    00064     [ 36] =    54701,     [ 37] =    49231,     [ 38] =    27350,     [ 39] =    24615, // MCS 4
    00065     [ 44] =    41026,     [ 45] =    36923,     [ 46] =    20513,     [ 47] =    18462, // MCS 5
    00066     [ 52] =    36467,     [ 53] =    32821,     [ 54] =    18234,     [ 55] =    16410, // MCS 6
    00067     [ 60] =    32821,     [ 61] =    29538,     [ 62] =    16410,     [ 63] =    14769, // MCS 7
    00068     [ 68] =    27350,     [ 69] =    24615,     [ 70] =    13675,     [ 71] =    12308, // MCS 8
    00069     [ 76] =    24615,     [ 77] =    22154,     [ 78] =    12308,     [ 79] =    11077, // MCS 9
    00070 };
    00071
    00072 #if NX_HE
    00076 static const uint32_t rc_duration_he_ampdu[12*2*3] =
    00077 {
    00078     //BW20/40,GI0.8us    BW20/40,GI1.6us      BW20/40,GI3.2us    MCS Index
    00079     [  0] = 1115897,     [  1] = 1181538,     [  2] = 1312821,   // MCS 0
    00080     [  6] =  557949,     [  7] =  590769,     [  8] =  656410,   // MCS 1
    00081     [ 12] =  371966,     [ 13] =  393846,     [ 14] =  437607,   // MCS 2
    00082     [ 18] =  278974,     [ 19] =  295385,     [ 20] =  328205,   // MCS 3
    00083     [ 24] =  185983,     [ 25] =  196923,     [ 26] =  218803,   // MCS 4
    00084     [ 30] =  139487,     [ 31] =  147692,     [ 32] =  164103,   // MCS 5
    00085     [ 36] =  123989,     [ 37] =  131282,     [ 38] =  145869,   // MCS 6
    00086     [ 42] =  111590,     [ 43] =  118154,     [ 44] =  131282,   // MCS 7
    00087     [ 48] =   92991,     [ 49] =   98462,     [ 50] =  109402,   // MCS 8
    00088     [ 54] =   83692,     [ 55] =   88615,     [ 56] =   98462,   // MCS 9
    00089     [ 60] =   74393,     [ 61] =   78769,     [ 62] =   87521,   // MCS 10
    00090     [ 66] =   66954,     [ 67] =   70892,     [ 68] =   78769,   // MCS 11
    00091     //BW80/160,GI0.8us   BW80/160,GI1.6us     BW80/160,GI3.2us   MCS Index
    00092     [  3] =  266449,     [  4] =  282122,     [  5] =  313469,   // MCS 0
    00093     [  9] =  133224,     [ 10] =  141061,     [ 11] =  156735,   // MCS 1
    00094     [ 15] =   88816,     [ 16] =   94041,     [ 17] =  104490,   // MCS 2
    00095     [ 21] =   66612,     [ 22] =   70531,     [ 23] =   78367,   // MCS 3
    00096     [ 27] =   44408,     [ 28] =   47020,     [ 29] =   52245,   // MCS 4
    00097     [ 33] =   33306,     [ 34] =   35265,     [ 35] =   39184,   // MCS 5
    00098     [ 39] =   29605,     [ 40] =   31347,     [ 41] =   34830,   // MCS 6
    00099     [ 45] =   26645,     [ 46] =   28212,     [ 47] =   31347,   // MCS 7
    00100     [ 51] =   22204,     [ 52] =   23510,     [ 53] =   26122,   // MCS 8
    00101     [ 57] =   19985,     [ 58] =   21160,     [ 59] =   23511,   // MCS 9
    00102     [ 63] =   17763,     [ 64] =   18808,     [ 65] =   20898,   // MCS 10
    00103     [ 69] =   15988,     [ 70] =   16929,     [ 71] =   18810,   // MCS 11
    00104 };
    00105
    00109 static const uint32_t rc_duration_he_ru26[12*3] =
    00110 {
    00111     //GI0.8us            GI1.6us              GI3.2us            MCS Index
    00112     [  0] = 10880000,    [  1] = 11520000,    [  2] = 12800000,  // MCS 0
    00113     [  3] =  5440000,    [  4] =  5760000,    [  5] =  6400000,  // MCS 1
    00114     [  6] =  3626666,    [  7] =  3840000,    [  8] =  4266666,  // MCS 2
    00115     [  9] =  2720000,    [ 10] =  2880000,    [ 11] =  3200000,  // MCS 3
    00116     [ 12] =  1813333,    [ 13] =  1920000,    [ 14] =  2133333,  // MCS 4
    00117     [ 15] =  1360000,    [ 16] =  1440000,    [ 17] =  1600000,  // MCS 5
    00118     [ 18] =  1208888,    [ 19] =  1280000,    [ 20] =  1422222,  // MCS 6
    00119     [ 21] =  1088000,    [ 22] =  1152000,    [ 23] =  1280000,  // MCS 7
    00120     [ 24] =   906666,    [ 25] =   960000,    [ 26] =  1066666,  // MCS 8
    00121     [ 27] =   816000,    [ 28] =   864000,    [ 29] =   960000,  // MCS 9
    00122     [ 30] =   725333,    [ 31] =   768000,    [ 32] =   853333,  // MCS 10
    00123     [ 33] =   652800,    [ 34] =   691200,    [ 35] =   768000,  // MCS 11
    00124 };
    00125
    00129 static const uint32_t rc_duration_he_ru52[12*3] =
    00130 {
    00131     //GI0.8us            GI1.6us              GI3.2us            MCS Index
    00132     [  0] = 5440000,     [  1] = 5760000,     [  2] = 6400000,   // MCS 0
    00133     [  3] = 2720000,     [  4] = 2880000,     [  5] = 3200000,   // MCS 1
    00134     [  6] = 1813333,     [  7] = 1920000,     [  8] = 2133333,   // MCS 2
    00135     [  9] = 1360000,     [ 10] = 1440000,     [ 11] = 1600000,   // MCS 3
    00136     [ 12] =  906666,     [ 13] =  960000,     [ 14] = 1066666,   // MCS 4
    00137     [ 15] =  680000,     [ 16] =  720000,     [ 17] =  800000,   // MCS 5
    00138     [ 18] =  604444,     [ 19] =  640000,     [ 20] =  711111,   // MCS 6
    00139     [ 21] =  544000,     [ 22] =  576000,     [ 23] =  640000,   // MCS 7
    00140     [ 24] =  453333,     [ 25] =  480000,     [ 26] =  533333,   // MCS 8
    00141     [ 27] =  408000,     [ 28] =  432000,     [ 29] =  480000,   // MCS 9
    00142     [ 30] =  362666,     [ 31] =  384000,     [ 32] =  426666,   // MCS 10
    00143     [ 33] =  326400,     [ 34] =  345600,     [ 35] =  384000,   // MCS 11
    00144 };
    00145
    00149 static const uint32_t rc_duration_he_ru106[12*3] =
    00150 {
    00151     //GI0.8us            GI1.6us              GI3.2us            MCS Index
    00152     [  0] = 2560000,     [  1] = 2710588,     [  2] = 3011764,   // MCS 0
    00153     [  3] = 1280000,     [  4] = 1355294,     [  5] = 1505882,   // MCS 1
    00154     [  6] =  853333,     [  7] =  903529,     [  8] = 1003921,   // MCS 2
    00155     [  9] =  640000,     [ 10] =  677647,     [ 11] =  752941,   // MCS 3
    00156     [ 12] =  426666,     [ 13] =  451764,     [ 14] =  501960,   // MCS 4
    00157     [ 15] =  320000,     [ 16] =  338823,     [ 17] =  376470,   // MCS 5
    00158     [ 18] =  284444,     [ 19] =  301176,     [ 20] =  334640,   // MCS 6
    00159     [ 21] =  256000,     [ 22] =  271058,     [ 23] =  301176,   // MCS 7
    00160     [ 24] =  213333,     [ 25] =  225882,     [ 26] =  250980,   // MCS 8
    00161     [ 27] =  192000,     [ 28] =  203294,     [ 29] =  225882,   // MCS 9
    00162     [ 30] =  170666,     [ 31] =  180705,     [ 32] =  200784,   // MCS 10
    00163     [ 33] =  153600,     [ 34] =  162635,     [ 35] =  180705,   // MCS 11
    00164 };
    00165
    00166 static const uint32_t *rc_ru_duration[3] =
    00167 {
    00168     [0] = rc_duration_he_ru26,
    00169     [1] = rc_duration_he_ru52,
    00170     [2] = rc_duration_he_ru106,
    00171 };
    00172
    00173 #endif
    00174
    00179 static const uint32_t rc_duration_cck[4*2] =
    00180 {
    00181     //short preamble      long preamble       MCS Index
    00182     [  0] = 10452000,     [  1] = 10548000, // MCS 0
    00183     [  2] =  5380000,     [  3] =  5476000, // MCS 1
    00184     [  4] =  2315000,     [  5] =  2411000, // MCS 2
    00185     [  6] =  1439000,     [  7] =  1535000, // MCS 3
    00186 };
    00187
    00190 static const uint32_t rc_duration_non_ht[8] =
    00191 {
    00192                       // MCS Index
    00193     [  0] =  1600000, // MCS 4
    00194     [  1] =  1068000, // MCS 5
    00195     [  2] =   800000, // MCS 6
    00196     [  3] =   536000, // MCS 7
    00197     [  4] =   400000, // MCS 8
    00198     [  5] =   268000, // MCS 9
    00199     [  6] =   200000, // MCS 10
    00200     [  7] =   180000, // MCS 11
    00201 };
    00202
    00203 /*
    00204  * PRIVATE FUNCTIONS DECLARATION
    00205  ****************************************************************************************
    00206  */
    00207 static void rc_calc_prob_ewma(struct rc_rate_stats *rc_rs);
    00208 static uint16_t rc_set_previous_mcs_index(struct rc_sta_stats *rc_ss, uint16_t rate_config);
    00209 static uint16_t rc_set_next_mcs_index(struct rc_sta_stats *rc_ss, uint16_t rate_config);
    00210 static bool rc_check_rate_duplicated(struct rc_sta_stats *rc_ss, uint16_t rate_config);
    00211 static uint16_t rc_new_random_rate(struct rc_sta_stats *ss);
    00212 static bool rc_set_trial_tx(struct rc_sta_stats *rc_ss);
    00213 static bool rc_update_stats(struct rc_sta_stats *rc_ss, bool init);
    00214 static void rc_update_retry_chain(struct rc_sta_stats *rc_ss, uint32_t *cur_tp);
    00215 static void rc_get_new_samples(struct rc_sta_stats *rc_ss);
    00216 static bool rc_update_stats_fixed_rate(struct rc_sta_stats *rc_ss);
    00217
    00218 /*
    00219  * PRIVATE FUNCTIONS DEFINITION
    00220  ****************************************************************************************
    00221  */
    00222
    00232 static inline uint32_t ewma(uint32_t old_val, uint32_t new_val, uint32_t weight)
    00233 {
    00234     return ((new_val * (EWMA_DIV - weight) + old_val * weight) / EWMA_DIV);
    00235 }
    00236
    00244 static uint8_t rc_get_format_mod(uint16_t rate_config)
    00245 {
    00246     return (rate_config & FORMAT_MOD_TX_RCX_MASK) >> FORMAT_MOD_TX_RCX_OFT;
    00247 }
    00248
    00256 static uint8_t rc_get_bw(uint16_t rate_config)
    00257 {
    00258     return (rate_config & BW_TX_RCX_MASK) >> BW_TX_RCX_OFT;
    00259 }
    00260
    00268 static uint8_t rc_get_nss(uint16_t rate_config)
    00269 {
    00270     uint8_t nss = 0;
    00271     uint8_t format_mod = rc_get_format_mod(rate_config);
    00272
    00273     switch (format_mod)
    00274     {
    00275         case FORMATMOD_HT_MF:
    00276         case FORMATMOD_HT_GF:
    00277         {
    00278             nss = (rate_config & HT_NSS_MASK) >> HT_NSS_OFT;
    00279         } break;
    00280
    00281         #if NX_VHT || NX_HE
    00282         case FORMATMOD_VHT:
    00283         case FORMATMOD_HE_SU:
    00284         case FORMATMOD_HE_MU:
    00285         {
    00286             nss = (rate_config & VHT_NSS_MASK) >> VHT_NSS_OFT;
    00287         } break;
    00288         #endif
    00289
    00290         default:
    00291             break;
    00292     }
    00293
    00294     return nss;
    00295 }
    00296
    00304 static uint8_t rc_get_mcs_index(uint16_t rate_config)
    00305 {
    00306     uint8_t format_mod = rc_get_format_mod(rate_config);
    00307     uint8_t mcs = 0;
    00308
    00309     switch (format_mod)
    00310     {
    00311         case FORMATMOD_NON_HT:
    00312         case FORMATMOD_NON_HT_DUP_OFDM:
    00313         {
    00314             mcs = (rate_config & MCS_INDEX_TX_RCX_MASK) >> MCS_INDEX_TX_RCX_OFT;
    00315         } break;
    00316         case FORMATMOD_HT_MF:
    00317         case FORMATMOD_HT_GF:
    00318         {
    00319             mcs = (rate_config & HT_MCS_MASK) >> HT_MCS_OFT;
    00320         } break;
    00321
    00322         #if NX_VHT || NX_HE
    00323         case FORMATMOD_VHT:
    00324         case FORMATMOD_HE_SU:
    00325         case FORMATMOD_HE_MU:
    00326         {
    00327             mcs = (rate_config & VHT_MCS_MASK) >> VHT_MCS_OFT;
    00328         } break;
    00329         #endif
    00330
    00331         default:
    00332             break;
    00333     }
    00334
    00335     return mcs;
    00336 }
    00337
    00338 #if NX_HE
    00339
    00346 static uint8_t rc_get_he_gi(uint32_t rate_config)
    00347 {
    00348     return ((rate_config & HE_GI_TYPE_TX_RCX_MASK) >> HE_GI_TYPE_TX_RCX_OFT);
    00349 }
    00350 #endif
    00351
    00359 static uint8_t rc_get_sgi(uint32_t rate_config)
    00360 {
    00361     return ((rate_config & SHORT_GI_TX_RCX_MASK) >> SHORT_GI_TX_RCX_OFT);
    00362 }
    00363
    00371 static uint8_t rc_get_pre_type(uint16_t rate_config)
    00372 {
    00373     return (rate_config & PRE_TYPE_TX_RCX_MASK) >> PRE_TYPE_TX_RCX_OFT;
    00374 }
    00375
    00382 static void rc_calc_prob_ewma(struct rc_rate_stats *rc_rs)
    00383 {
    00384     uint32_t success = rc_rs->success;
    00385     uint32_t attempts = rc_rs->attempts;
    00386
    00387     if (attempts > 0)
    00388     {
    00389         rc_rs->sample_skipped = 0;
    00390         uint32_t cur_prob = RC_FRAC(success, attempts);
    00391
    00392         if (0 == rc_rs->old_prob_available)
    00393         {
    00394             if (cur_prob > 0)
    00395             {
    00396                 rc_rs->probability = cur_prob - 1;
    00397             }
    00398             else
    00399             {
    00400                 rc_rs->probability = 0;
    00401             }
    00402         }
    00403         else
    00404         {
    00405             rc_rs->probability = ewma(rc_rs->probability, cur_prob, EWMA_LEVEL);
    00406         }
    00407         rc_rs->old_prob_available = 1;
    00408     }
    00409     else
    00410     {
    00411         if (rc_rs->sample_skipped < 0xFF)
    00412         {
    00413             rc_rs->sample_skipped++;
    00414         }
    00415     }
    00416 }
    00417
    00427 static uint16_t rc_set_previous_mcs_index(struct rc_sta_stats *rc_ss, uint16_t rate_config)
    00428 {
    00429     uint16_t new_config = rate_config;
    00430     uint8_t format_mod = rc_get_format_mod(rate_config);
    00431     uint8_t mcs = rc_get_mcs_index(rate_config);
    00432
    00433     switch (format_mod)
    00434     {
    00435         case FORMATMOD_NON_HT:
    00436         case FORMATMOD_NON_HT_DUP_OFDM:
    00437         {
    00438             uint8_t mcs_min;
    00439             // Decrease only within the same modulation (DSSS/CCK or OFDM)
    00440             if (mcs < HW_RATE_6MBPS)
    00441                 mcs_min = rc_ss->r_idx_min;
    00442             else
    00443                 mcs_min = co_max(HW_RATE_6MBPS, rc_ss->r_idx_min);
    00444
    00445             while(mcs > mcs_min)
    00446             {
    00447                 mcs--;
    00448                 if (rc_ss->rate_map_l & CO_BIT(mcs))
    00449                 {
    00450                     new_config = (rate_config & ~MCS_INDEX_TX_RCX_MASK) | mcs;
    00451                     break;
    00452                 }
    00453             }
    00454         } break;
    00455         case FORMATMOD_HT_MF:
    00456         case FORMATMOD_HT_GF:
    00457         {
    00458             uint8_t nss = rc_get_nss(rate_config);
    00459             while (mcs > 0)
    00460             {
    00461                 mcs--;
    00462                 if (rc_ss->rate_map.ht[nss] & CO_BIT(mcs))
    00463                 {
    00464                     new_config = (rate_config & ~HT_MCS_MASK) | mcs;
    00465                     if (rc_ss->short_gi)
    00466                     {
    00467                         new_config |= SHORT_GI_TX_RCX_MASK;
    00468                     }
    00469                     break;
    00470                 }
    00471             }
    00472         } break;
    00473
    00474         #if NX_VHT
    00475         case FORMATMOD_VHT:
    00476         {
    00477             if (mcs > 0)
    00478             {
    00479                 new_config = (rate_config & ~VHT_MCS_MASK) | (mcs-1);
    00480                 if (rc_ss->short_gi)
    00481                 {
    00482                     new_config |= SHORT_GI_TX_RCX_MASK;
    00483                 }
    00484             }
    00485         } break;
    00486         #endif
    00487
    00488         #if NX_HE
    00489         case FORMATMOD_HE_SU:
    00490         {
    00491             if (mcs > 0)
    00492             {
    00493                 new_config = (rate_config & ~VHT_MCS_MASK) | (mcs-1);
    00494             }
    00495         } break;
    00496         #endif
    00497
    00498         default:
    00499             break;
    00500     }
    00501
    00502     return new_config;
    00503 }
    00504
    00514 static uint16_t rc_set_next_mcs_index(struct rc_sta_stats *rc_ss, uint16_t rate_config)
    00515 {
    00516     uint16_t new_config = rate_config;
    00517     uint8_t format_mod = rc_get_format_mod(rate_config);
    00518     uint8_t mcs = rc_get_mcs_index(rate_config);
    00519
    00520     switch (format_mod)
    00521     {
    00522         case FORMATMOD_NON_HT:
    00523         case FORMATMOD_NON_HT_DUP_OFDM:
    00524         {
    00525             uint8_t mcs_max;
    00526             // Increase only within the same modulation (DSSS/CCK or OFDM)
    00527             if (mcs >= HW_RATE_6MBPS)
    00528                 mcs_max = rc_ss->r_idx_max;
    00529             else
    00530                 mcs_max = co_min(HW_RATE_11MBPS, rc_ss->r_idx_max);
    00531
    00532             while(mcs < mcs_max)
    00533             {
    00534                 mcs++;
    00535                 if (rc_ss->rate_map_l & CO_BIT(mcs))
    00536                 {
    00537                     new_config = (rate_config & ~MCS_INDEX_TX_RCX_MASK) | mcs;
    00538                     break;
    00539                 }
    00540             }
    00541         } break;
    00542
    00543         case FORMATMOD_HT_MF:
    00544         case FORMATMOD_HT_GF:
    00545         {
    00546             uint8_t nss = rc_get_nss(rate_config);
    00547             while (mcs < rc_ss->mcs_max)
    00548             {
    00549                 mcs++;
    00550                 if (rc_ss->rate_map.ht[nss] & CO_BIT(mcs))
    00551                 {
    00552                     new_config = (rate_config & ~HT_MCS_MASK) | mcs;
    00553                     if (rc_ss->short_gi)
    00554                     {
    00555                         new_config |= SHORT_GI_TX_RCX_MASK;
    00556                     }
    00557                     break;
    00558                 }
    00559             }
    00560         } break;
    00561
    00562         #if NX_VHT
    00563         case FORMATMOD_VHT:
    00564         {
    00565             uint8_t nss = rc_get_nss(rate_config);
    00566             uint8_t mcs_max_ss = 7 + ((rc_ss->rate_map.vht >> (nss << 1)) & MAC_VHT_MCS_MAP_MSK);
    00567             if ((mcs < rc_ss->mcs_max) && ((mcs+1) <= mcs_max_ss))
    00568             {
    00569                 new_config = (rate_config & ~VHT_MCS_MASK) | (mcs+1);
    00570                 if (rc_ss->short_gi)
    00571                 {
    00572                     new_config |= SHORT_GI_TX_RCX_MASK;
    00573                 }
    00574             }
    00575         } break;
    00576         #endif
    00577
    00578         #if NX_HE
    00579         case FORMATMOD_HE_SU:
    00580         {
    00581             uint8_t nss = rc_get_nss(rate_config);
    00582             uint8_t mcs_max_ss = 7 + 2 * ((rc_ss->rate_map.he >> (nss << 1)) & MAC_HE_MCS_MAP_MSK);
    00583             if ((mcs < rc_ss->mcs_max) && ((mcs+1) <= mcs_max_ss))
    00584             {
    00585                 new_config = (rate_config & ~VHT_MCS_MASK) | (mcs+1);
    00586             }
    00587         } break;
    00588         #endif
    00589
    00590         default:
    00591             break;
    00592     }
    00593
    00594     return new_config;
    00595 }
    00596
    00605 static bool rc_check_rate_duplicated(struct rc_sta_stats *rc_ss, uint16_t rate_config)
    00606 {
    00607     uint32_t i = 0;
    00608     bool ret = 0;
    00609
    00610     while (i < rc_ss->no_samples)
    00611     {
    00612         if (rate_config == rc_ss->rate_stats[i].rate_config)
    00613         {
    00614             ret = 1;
    00615             break;
    00616         }
    00617         i++;
    00618     }
    00619     return ret;
    00620 }
    00621
    00622 #if NX_DEBUG
    00623
    00630 static void rc_check_rate_config(struct rc_sta_stats *rc_ss, uint16_t i)
    00631 {
    00632     uint16_t rate_config = rc_ss->rate_stats[i].rate_config;
    00633     uint8_t format_mod = rc_get_format_mod(rate_config);
    00634     uint8_t pre_type = rc_get_pre_type(rate_config);
    00635     uint8_t sgi = rc_get_sgi(rate_config);
    00636     uint8_t bw = rc_get_bw(rate_config);
    00637     uint8_t nss = rc_get_nss(rate_config);
    00638     uint8_t mcs = rc_get_mcs_index(rate_config);
    00639
    00640     #if NX_HE
    00641     ASSERT_ERR(format_mod <= FORMATMOD_HE_SU);
    00642     #elif NX_VHT
    00643     ASSERT_ERR(format_mod <= FORMATMOD_VHT);
    00644     #else
    00645     ASSERT_ERR(format_mod <= FORMATMOD_HT_GF);
    00646     #endif
    00647
    00648     // check format and modulation
    00649     switch (rc_ss->format_mod)
    00650     {
    00651         case FORMATMOD_NON_HT:
    00652         case FORMATMOD_NON_HT_DUP_OFDM:
    00653         {
    00654             ASSERT_ERR(format_mod < FORMATMOD_HT_MF);
    00655         } break;
    00656         case FORMATMOD_HT_MF:
    00657         case FORMATMOD_HT_GF:
    00658         {
    00659             if (rc_ss->r_idx_min <= HW_RATE_11MBPS)
    00660             {
    00661                 // DSSS/CCK
    00662                 ASSERT_ERR(format_mod < FORMATMOD_VHT);
    00663             }
    00664             else
    00665             {
    00666                 ASSERT_ERR((format_mod == FORMATMOD_HT_MF) || (format_mod == FORMATMOD_HT_GF));
    00667             }
    00668         } break;
    00669
    00670         #if NX_VHT
    00671         case FORMATMOD_VHT:
    00672         {
    00673             ASSERT_ERR(format_mod == FORMATMOD_VHT);
    00674         } break;
    00675         #endif
    00676
    00677         #if NX_HE
    00678         case FORMATMOD_HE_SU:
    00679         {
    00680             if (rc_ss->r_idx_min <= HW_RATE_11MBPS)
    00681             {
    00682                 // DSSS/CCK is possible
    00683                 ASSERT_ERR((format_mod == FORMATMOD_HE_SU) || (format_mod == FORMATMOD_NON_HT));
    00684             }
    00685             else
    00686             {
    00687                 ASSERT_ERR(format_mod == FORMATMOD_HE_SU);
    00688             }
    00689         } break;
    00690         #endif
    00691
    00692         default:
    00693             break;
    00694     }
    00695
    00696     switch (format_mod)
    00697     {
    00698         case FORMATMOD_NON_HT:
    00699         case FORMATMOD_NON_HT_DUP_OFDM:
    00700         {
    00701             if ((mcs <= HW_RATE_11MBPS) && (rc_ss->type == 1))
    00702             {
    00703                 ASSERT_ERR(pre_type == 1);
    00704             }
    00705             else
    00706             {
    00707                 ASSERT_ERR(pre_type <= 1);
    00708             }
    00709             ASSERT_ERR(sgi == 0);
    00710             ASSERT_ERR(bw == BW_20MHZ);
    00711             ASSERT_ERR(nss == 0);
    00712             ASSERT_ERR(mcs >= rc_ss->r_idx_min);
    00713             ASSERT_ERR(mcs <= rc_ss->r_idx_max);
    00714             ASSERT_ERR((rc_ss->rate_map_l & CO_BIT(mcs)));
    00715         }
    00716         break;
    00717
    00718         case FORMATMOD_HT_MF:
    00719         case FORMATMOD_HT_GF:
    00720         {
    00721             ASSERT_ERR(pre_type == 0);
    00722             ASSERT_ERR(sgi <= rc_ss->short_gi);
    00723             ASSERT_ERR(bw <= rc_ss->bw_max);
    00724             ASSERT_ERR(nss <= rc_ss->no_ss);
    00725             ASSERT_ERR(mcs <= rc_ss->mcs_max);
    00726             ASSERT_ERR((rc_ss->rate_map.ht[nss] & CO_BIT(mcs)));
    00727         }
    00728         break;
    00729
    00730         #if NX_VHT
    00731         case FORMATMOD_VHT:
    00732         {
    00733             ASSERT_ERR(pre_type == 0);
    00734             ASSERT_ERR(sgi <= rc_ss->short_gi);
    00735             ASSERT_ERR(bw <= rc_ss->bw_max);
    00736             ASSERT_ERR(nss <= rc_ss->no_ss);
    00737             ASSERT_ERR(mcs <= rc_ss->mcs_max);
    00738             ASSERT_ERR(mcs <= (7 + (rc_ss->rate_map.vht >> (nss << 1) & MAC_VHT_MCS_MAP_MSK)));
    00739             ASSERT_ERR(((mcs == 6) && (bw == BW_80MHZ) && ((nss == 3) || (nss == 6))) == 0);
    00740             ASSERT_ERR(((mcs == 9) && (bw == BW_20MHZ) && (nss != 2) && (nss != 5)) == 0);
    00741             ASSERT_ERR(((mcs == 9) && (bw == BW_80MHZ) && (nss == 5)) == 0);
    00742             ASSERT_ERR(((mcs == 9) && (bw == BW_160MHZ) && (nss == 2)) == 0);
    00743         }
    00744         break;
    00745         #endif
    00746
    00747         #if NX_HE
    00748         case FORMATMOD_HE_SU:
    00749         {
    00750             uint8_t gi = rc_get_he_gi(rate_config);
    00751             ASSERT_ERR(gi <= 2);
    00752             ASSERT_ERR(bw <= rc_ss->bw_max);
    00753             ASSERT_ERR(nss <= rc_ss->no_ss);
    00754             ASSERT_ERR(mcs <= rc_ss->mcs_max);
    00755             ASSERT_ERR(mcs <= (7 + 2 * (rc_ss->rate_map.he >> (nss << 1) & MAC_HE_MCS_MAP_MSK)));
    00756         }
    00757         break;
    00758         #endif
    00759
    00760         default:
    00761             break;
    00762     }
    00763 }
    00764
    00771 static void rc_check_stats_rate_config(struct rc_sta_stats *rc_ss)
    00772 {
    00773     uint32_t i;
    00774
    00775     for (i = 0; i < rc_ss->no_samples; i++)
    00776     {
    00777         rc_check_rate_config(rc_ss, i);
    00778     }
    00779 }
    00780 #endif
    00781
    00789 static uint16_t rc_new_random_rate(struct rc_sta_stats *rc_ss)
    00790 {
    00791     // pick a random rate
    00792     uint16_t rd = co_rand_hword();
    00793     uint8_t format = rc_ss->format_mod;
    00794     uint16_t rate_cfg = format << FORMAT_MOD_TX_RCX_OFT;
    00795     uint8_t bw_min = rc_ss->bw_max > BW_20MHZ ? (rc_ss->bw_max - 1) : rc_ss->bw_max;
    00796
    00797     switch (format)
    00798     {
    00799         case FORMATMOD_NON_HT:
    00800         case FORMATMOD_NON_HT_DUP_OFDM:
    00801         {
    00802             uint8_t r_idx_l_max = rc_ss->r_idx_max;
    00803             uint8_t r_idx_l_min = rc_ss->r_idx_min;
    00804             uint8_t r_idx = (((rd & MCS_INDEX_TX_RCX_MASK) >> MCS_INDEX_TX_RCX_OFT) %
    00805                     (r_idx_l_max - r_idx_l_min + 1)) + r_idx_l_min;
    00806             if ((rc_ss->rate_map_l & CO_BIT(r_idx)) == 0) // rate index not allowed
    00807             {
    00808                 r_idx = r_idx_l_max;
    00809             }
    00810
    00811             rate_cfg |= r_idx << MCS_INDEX_TX_RCX_OFT;
    00812
    00813             if (r_idx == HW_RATE_1MBPS) // rate index 0 (CCK 1Mbps) allows only long preamble
    00814             {
    00815                 rate_cfg |= PRE_TYPE_TX_RCX_MASK;
    00816             }
    00817             else if ((r_idx > HW_RATE_1MBPS) && (r_idx <= HW_RATE_11MBPS)) // CCK rate: set preamble type
    00818             {
    00819                 rate_cfg |= (rd & PRE_TYPE_TX_RCX_MASK) | (rc_ss->type << PRE_TYPE_TX_RCX_OFT);
    00820             }
    00821         } break;
    00822         case FORMATMOD_HT_MF:
    00823         case FORMATMOD_HT_GF:
    00824         {
    00825             uint8_t r_idx_max = rc_ss->r_idx_max;
    00826             uint8_t r_idx_min = rc_ss->r_idx_min;
    00827
    00828             if ((r_idx_min <= HW_RATE_11MBPS) &&
    00829                 (((rd & FORMAT_MOD_TX_RCX_MASK) >> FORMAT_MOD_TX_RCX_OFT) % 2)) // 2.4 GHz
    00830             {
    00831                 // CCK
    00832                 uint8_t r_idx = (((rd & MCS_INDEX_TX_RCX_MASK) >> MCS_INDEX_TX_RCX_OFT) %
    00833                                  (r_idx_max - r_idx_min + 1)) + r_idx_min;
    00834                 rate_cfg = FORMATMOD_NON_HT << FORMAT_MOD_TX_RCX_OFT;
    00835                 if ((rc_ss->rate_map_l & CO_BIT(r_idx)) == 0) // rate index not allowed
    00836                 {
    00837                     r_idx = r_idx_max;
    00838                 }
    00839                 rate_cfg |= r_idx << MCS_INDEX_TX_RCX_OFT;
    00840                 if (r_idx == HW_RATE_1MBPS) // MCS0 (1Mbps) allows only long preamble
    00841                 {
    00842                     rate_cfg |= PRE_TYPE_TX_RCX_MASK;
    00843                 }
    00844                 else
    00845                 {
    00846                     rate_cfg |= (rd & PRE_TYPE_TX_RCX_MASK) | (rc_ss->type << PRE_TYPE_TX_RCX_OFT);
    00847                 }
    00848             }
    00849             else
    00850             {
    00851                 uint8_t bw_max = rc_ss->bw_max;
    00852                 uint8_t short_gi = rc_ss->short_gi;
    00853                 uint8_t mcs_max = rc_ss->mcs_max;
    00854                 uint8_t no_ss_max = rc_ss->no_ss;
    00855                 uint8_t nss = ((rd & HT_NSS_MASK) >> HT_NSS_OFT) % (no_ss_max + 1);
    00856                 uint8_t mcs = ((rd & HT_MCS_MASK) >> HT_MCS_OFT) % (mcs_max + 1);
    00857                 if ((rc_ss->rate_map.ht[nss] & CO_BIT(mcs)) == 0) // rate index not allowed
    00858                 {
    00859                     mcs = mcs_max;
    00860                 }
    00861                 rate_cfg |= (((rd & SHORT_GI_TX_RCX_MASK) >> SHORT_GI_TX_RCX_OFT) % (short_gi + 1)) << SHORT_GI_TX_RCX_OFT;
    00862                 #if RC_USE_MAX_BW
    00863                 rate_cfg |= bw_max << BW_TX_RCX_OFT;
    00864                 #else
    00865                 rate_cfg |= ((((rd & BW_TX_RCX_MASK) >> BW_TX_RCX_OFT) % (bw_max - bw_min + 1)) + bw_min) << BW_TX_RCX_OFT;
    00866                 #endif
    00867                 rate_cfg |= nss << HT_NSS_OFT;
    00868                 rate_cfg |= mcs << HT_MCS_OFT;
    00869             }
    00870         } break;
    00871
    00872         #if NX_VHT
    00873         case FORMATMOD_VHT:
    00874         {
    00875             uint8_t bw_max = rc_ss->bw_max;
    00876             uint8_t short_gi = rc_ss->short_gi;
    00877             uint8_t no_ss_max = rc_ss->no_ss;
    00878             uint8_t mcs_max = rc_ss->mcs_max;
    00879
    00880             uint8_t mcs = ((rd & VHT_MCS_MASK) >> VHT_MCS_OFT) % (mcs_max + 1);
    00881             uint8_t no_ss = ((rd & VHT_NSS_MASK) >> VHT_NSS_OFT) % (no_ss_max + 1);
    00882             uint8_t bw = 0;
    00883
    00884             if (mcs > (7 + (rc_ss->rate_map.vht >> (no_ss << 1) & MAC_VHT_MCS_MAP_MSK)))
    00885             {
    00886                 mcs = 7 + (rc_ss->rate_map.vht >> (no_ss << 1) & MAC_VHT_MCS_MAP_MSK);
    00887             }
    00888
    00889             #if RC_USE_MAX_BW
    00890             bw = bw_max;
    00891             #else
    00892             bw = (((rd & BW_TX_RCX_MASK) >> BW_TX_RCX_OFT) % (bw_max - bw_min + 1)) + bw_min;
    00893             #endif
    00894             // do not allow some missing VHT rates
    00895             if ((mcs == 6) && (bw == BW_80MHZ) && ((no_ss == 3) || (no_ss == 6)))
    00896             {
    00897                 no_ss = no_ss - 1;
    00898             }
    00899             if (mcs == 9)
    00900             {
    00901                 if ((bw == BW_20MHZ) && (no_ss != 2) && (no_ss != 5))
    00902                 {
    00903                     mcs = 8;
    00904                 }
    00905                 if ((bw == BW_80MHZ) && (no_ss == 5))
    00906                 {
    00907                     no_ss = no_ss - 1;
    00908                 }
    00909                 if ((bw == BW_160MHZ) && (no_ss == 2))
    00910                 {
    00911                     no_ss = no_ss - 1;
    00912                 }
    00913             }
    00914             rate_cfg |= ((((rd & SHORT_GI_TX_RCX_MASK) >> SHORT_GI_TX_RCX_OFT) % (short_gi + 1)) << SHORT_GI_TX_RCX_OFT) |
    00915                         (bw << BW_TX_RCX_OFT) |
    00916                         (no_ss << VHT_NSS_OFT) |
    00917                         (mcs << MCS_INDEX_TX_RCX_OFT);
    00918         } break;
    00919         #endif
    00920
    00921         #if NX_HE
    00922         case FORMATMOD_HE_SU:
    00923         {
    00924             uint8_t bw_max = rc_ss->bw_max;
    00925             uint8_t no_ss_max = rc_ss->no_ss;
    00926             uint8_t mcs_max = rc_ss->mcs_max;
    00927
    00928             uint8_t mcs = ((rd & VHT_MCS_MASK) >> VHT_MCS_OFT) % (mcs_max + 1);
    00929             uint8_t no_ss = ((rd & VHT_NSS_MASK) >> VHT_NSS_OFT) % (no_ss_max + 1);
    00930             uint8_t gi = (rd & HE_GI_TYPE_TX_RCX_MASK) >> HE_GI_TYPE_TX_RCX_OFT;
    00931             uint8_t bw = 0;
    00932
    00933             if (mcs > (7 + 2 * (rc_ss->rate_map.he >> (no_ss << 1) & MAC_HE_MCS_MAP_MSK)))
    00934             {
    00935                 mcs = 7 + 2* (rc_ss->rate_map.he >> (no_ss << 1) & MAC_HE_MCS_MAP_MSK);
    00936             }
    00937
    00938             if (gi > 2)
    00939                 gi = 2;
    00940
    00941             #if RC_USE_MAX_BW
    00942             bw = bw_max;
    00943             #else
    00944             bw = (((rd & BW_TX_RCX_MASK) >> BW_TX_RCX_OFT) % (bw_max - bw_min + 1)) + bw_min;
    00945             #endif
    00946             rate_cfg |= (gi << HE_GI_TYPE_TX_RCX_OFT) |
    00947                         (bw << BW_TX_RCX_OFT) |
    00948                         (no_ss << VHT_NSS_OFT) |
    00949                         (mcs << MCS_INDEX_TX_RCX_OFT);
    00950         } break;
    00951         #endif
    00952
    00953         default:
    00954             break;
    00955     }
    00956
    00957     return rate_cfg;
    00958 }
    00959
    00967 static bool is_cck_group(uint16_t rate_config)
    00968 {
    00969     uint8_t format = rc_get_format_mod(rate_config);
    00970     uint8_t mcs = rc_get_mcs_index(rate_config);
    00971     bool is_cck = 0;
    00972
    00973     if ((format < FORMATMOD_HT_MF) && (mcs < HW_RATE_6MBPS))
    00974     {
    00975         is_cck = 1;
    00976     }
    00977
    00978     return is_cck;
    00979 }
    00980
    01005 static bool rc_set_trial_tx(struct rc_sta_stats *rc_ss)
    01006 {
    01007     struct rc_rate_stats *rc_rand = NULL;
    01008     int i;
    01009     uint16_t random_rate_idx = 0;
    01010     uint32_t cur_max_tp_streams;
    01011     uint32_t sample_streams;
    01012     uint32_t sample_dur;
    01013     uint32_t dur_retry_1;
    01014     uint32_t dur_retry_2;
    01015     uint32_t max_skipped;
    01016     uint8_t format_mod = rc_ss->format_mod;
    01017     #if NX_AMPDU_TX
    01018     bool tx_ampdu = (rc_ss->info & RC_AGG_TX_MASK) != 0;
    01019     #endif
    01020
    01021     // Update countdown for trial tx
    01022     rc_ss->sample_wait = RC_TRIAL_PERIOD * RC_TRUNC(rc_ss->avg_ampdu_len);
    01023
    01024     // Pick a random sample from the sample table
    01025     random_rate_idx = co_rand_hword() % rc_ss->no_samples;
    01026     for (i = 0; i < rc_ss->no_samples; i++)
    01027     {
    01028         random_rate_idx = (random_rate_idx + i) % rc_ss->no_samples;
    01029         rc_rand = &rc_ss->rate_stats[random_rate_idx];
    01030         // Sampling might add some overhead (RTS, no aggregation)
    01031         // to the frame. Hence, don't use sampling for the currently
    01032         // used rate.
    01033         if (random_rate_idx == rc_ss->retry_step_idx[0])
    01034         {
    01035             continue;
    01036         }
    01037         // Do not sample if the probability is already higher than 95%
    01038         // to avoid wasting airtime
    01039         if (rc_rand->probability > RC_FRAC(95, 100))
    01040         {
    01041             continue;
    01042         }
    01043         #if NX_AMPDU_TX
    01044         // Do not sample if the random sample is a DSSS/CCK rate and
    01045         // next packet is part of a AMPDU
    01046         if (tx_ampdu && (rc_get_format_mod(rc_rand->rate_config) < FORMATMOD_HT_MF))
    01047         {
    01048             continue;
    01049         }
    01050         #endif
    01051
    01052         // If all the previous tests are negative, we've found our sample rate, no need
    01053         // to loop further
    01054         break;
    01055     }
    01056
    01057     // Ensure we have a sample to try
    01058     if (i == rc_ss->no_samples)
    01059         return false;
    01060
    01061     sample_dur = rc_get_duration(rc_rand);
    01062     if (format_mod >= FORMATMOD_HT_MF)
    01063     {
    01064         // Make sure that lower rates get sampled only occasionally,
    01065         // if the link is working perfectly.
    01066         cur_max_tp_streams = rc_get_nss(rc_ss->rate_stats[rc_ss->retry_step_idx[0]].rate_config);
    01067         sample_streams = rc_get_nss(rc_rand->rate_config);
    01068         dur_retry_1 = rc_get_duration(&rc_ss->rate_stats[rc_ss->retry_step_idx[1]]);
    01069         dur_retry_2 = rc_get_duration(&rc_ss->rate_stats[rc_ss->retry_step_idx[2]]);
    01070         max_skipped = rc_ss->rate_stats[random_rate_idx].old_prob_available ? 32 : RC_TRUNC(rc_ss->avg_ampdu_len);
    01071         if ((sample_dur >= dur_retry_1) &&
    01072             (((cur_max_tp_streams - 1) < sample_streams) ||
    01073              (sample_dur >= dur_retry_2)))
    01074         {
    01075             if (rc_rand->sample_skipped < max_skipped)
    01076             {
    01077                 return false;
    01078             }
    01079             rc_ss->sample_slow += 1;
    01080             if (rc_ss->sample_slow > 2)
    01081             {
    01082                 if (rc_ss->sample_slow > 0xF)
    01083                 {
    01084                     rc_ss->sample_slow = 0xF;
    01085                 }
    01086                 return false;
    01087             }
    01088         }
    01089     }
    01090
    01091     // Set trial rate index
    01092     rc_ss->trial_idx = random_rate_idx;
    01093     rc_ss->trial_status = RC_TRIAL_STATUS_WAIT_CFM;
    01094
    01095     return true;
    01096 }
    01097
    01106 static bool rc_check_trial_tx(struct rc_sta_stats *rc_ss)
    01107 {
    01108     // Do not sample if fixed rate is set
    01109     if (rc_ss->info & RC_FIX_RATE_EN_MASK)
    01110         return false;
    01111
    01112     // Do not sample if a trial TX is already ongoing
    01113     if (rc_ss->trial_status != RC_TRIAL_STATUS_WAIT)
    01114         return false;
    01115
    01116     // Check if it's time for a trial transmission
    01117     if (rc_ss->sample_wait > 0)
    01118     {
    01119         rc_ss->sample_wait --;
    01120         return false;
    01121     }
    01122
    01123     // Check if sample table needs to be updated
    01124     if ((rc_ss->info & RC_SS_UPD_REQ_MASK) == RC_SS_UPD_REQ_MASK)
    01125     {
    01126         rc_get_new_samples(rc_ss);
    01127         rc_ss->info &= ~RC_SS_UPD_REQ_MASK;
    01128     }
    01129
    01130     // Get a random trial rate from the sample table
    01131     // and check if the rate can be inserted in the retry table
    01132     return (rc_set_trial_tx(rc_ss));
    01133 }
    01134
    01142 static void rc_sort_samples_tp(struct rc_sta_stats *rc_ss, uint32_t *cur_tp)
    01143 {
    01144     struct rc_rate_stats rc_ss_tmp;
    01145     uint32_t temp_tp;
    01146     uint16_t i, j, last;
    01147     uint32_t size = sizeof(rc_ss_tmp);
    01148
    01149     last = rc_ss->no_samples;
    01150     j = rc_ss->no_samples - 1;
    01151     while (last > 0)
    01152     {
    01153         last = 0;
    01154         for (i = 1; i < j; i++)
    01155         {
    01156             if (cur_tp[i] > cur_tp[i + 1])
    01157             {
    01158                 memmove(&rc_ss_tmp, &rc_ss->rate_stats[i], size);
    01159                 memmove(&rc_ss->rate_stats[i], &rc_ss->rate_stats[i+1], size);
    01160                 memmove(&rc_ss->rate_stats[i+1], &rc_ss_tmp, size);
    01161                 temp_tp = cur_tp[i];
    01162                 cur_tp[i] = cur_tp[i+1];
    01163                 cur_tp[i+1] = temp_tp;
    01164                 last = i;
    01165             }
    01166         }
    01167         j = last;
    01168     }
    01169 }
    01170
    01183 static bool rc_update_stats(struct rc_sta_stats *rc_ss, bool init)
    01184 {
    01185     bool upd = 0;
    01186     uint16_t i = 0;
    01187     uint32_t cur_tp[RC_MAX_N_SAMPLE];
    01188     uint16_t old_rate_cfg[RATE_CONTROL_STEPS];
    01189     struct rc_rate_stats *rc_rs;
    01190
    01191     // Set old retry chain steps
    01192     for (i = 0; i < RATE_CONTROL_STEPS; i++)
    01193     {
    01194         old_rate_cfg[i] = rc_ss->rate_stats[rc_ss->retry_step_idx[i]].rate_config;
    01195     }
    01196
    01197     if (rc_ss->ampdu_packets > 0)
    01198     {
    01199         // Calculate EWMA average number of MPDUs in each AMPDU frame
    01200         rc_ss->avg_ampdu_len = ewma(rc_ss->avg_ampdu_len,
    01201                                     RC_FRAC(rc_ss->ampdu_len, rc_ss->ampdu_packets),
    01202                                     EWMA_LEVEL);
    01203         rc_ss->ampdu_len = 0;
    01204         rc_ss->ampdu_packets = 0;
    01205     }
    01206
    01207     #if NX_HE
    01208     // Compute HE TB statistics
    01209     rc_rs = &rc_ss->rate_stats[RC_HE_STATS_IDX];
    01210     // Recalculate success probabilities and counters for a rate using EWMA
    01211     rc_calc_prob_ewma(rc_rs);
    01212     rc_rs->attempts = 0;
    01213     rc_rs->success = 0;
    01214     #endif
    01215
    01216     rc_ss->sample_slow = 0;
    01217
    01218     // Reset current TP and number of retries
    01219     for (i = 0; i < rc_ss->no_samples; i++)
    01220     {
    01221         cur_tp[i] = 0;
    01222         // Reset the number of request of SW retry before the TP calculation: this info is
    01223         // already given by the current probability of success
    01224         rc_ss->rate_stats[i].rate_allowed = 1;
    01225     }
    01226
    01227     // Calculate RC algorithm expected throughput for each sample of the stats table,
    01228     // then fill the retry table
    01229     if (rc_ss->fixed_rate_cfg == RC_FIXED_RATE_NOT_SET)
    01230     {
    01231         for (i = 0; i < rc_ss->no_samples; i++)
    01232         {
    01233             rc_rs = &rc_ss->rate_stats[i];
    01234             // Recalculate success probabilities and counters for a rate using EWMA
    01235             rc_calc_prob_ewma(rc_rs);
    01236             // Calculate expected throughput based on the average A-MPDU length, taking into
    01237             // account the expected number of retransmissions and their expected length
    01238             cur_tp[i] = rc_calc_tp(rc_ss, i);
    01239         }
    01240
    01241         // Sort sample table by TP
    01242         rc_sort_samples_tp(rc_ss, cur_tp);
    01243         // Update the retry chain with: max TP, 2nd max TP, max probability, lowest rate
    01244         rc_update_retry_chain(rc_ss, cur_tp);
    01245
    01246         if (init == 0)
    01247         {
    01248             // Keep in mind we have to update the sample table
    01249             rc_ss->info |= RC_SS_UPD_REQ_MASK;
    01250             // Reset statistics
    01251             for (i = 0; i < rc_ss->no_samples; i++)
    01252             {
    01253                 // Reset statistics
    01254                 rc_ss->rate_stats[i].attempts = 0;
    01255                 rc_ss->rate_stats[i].success = 0;
    01256             }
    01257         }
    01258     }
    01259     else
    01260     {
    01261         upd = rc_update_stats_fixed_rate(rc_ss);
    01262     }
    01263
    01264     // check if the retry chain is changed
    01265     for (i = 0; i < RATE_CONTROL_STEPS; i++)
    01266     {
    01267         if (old_rate_cfg[i] != rc_ss->rate_stats[rc_ss->retry_step_idx[i]].rate_config)
    01268         {
    01269             upd = 1;
    01270             break;
    01271         }
    01272     }
    01273
    01274     return upd;
    01275 }
    01276
    01290 static void rc_update_retry_chain(struct rc_sta_stats *rc_ss, uint32_t *cur_tp)
    01291 {
    01292     uint32_t max_prob_idx = 0;
    01293     uint32_t max_tp = 0;
    01294     uint32_t max_prob = 0;
    01295     uint16_t i;
    01296     uint16_t j;
    01297
    01298     // Set new steps 0 and 1 of the retry table
    01299     if (((rc_ss->info & RC_AGG_TX_MASK) == 0) && (cur_tp[0] > cur_tp[rc_ss->no_samples - 1]))
    01300     {
    01301         rc_ss->retry_step_idx[0] = 0;
    01302         j = 1;
    01303     }
    01304     else
    01305     {
    01306         rc_ss->retry_step_idx[0] = rc_ss->no_samples - 1;
    01307         j = 2;
    01308     }
    01309     // Allow CCK rates only if highest TP rate is a CCK rate
    01310     if (!is_cck_group(rc_ss->rate_stats[rc_ss->retry_step_idx[0]].rate_config))
    01311     {
    01312         // CCK not allowed
    01313         for (i = 0; i < (rc_ss->no_samples - 1); i++)
    01314         {
    01315             if (is_cck_group(rc_ss->rate_stats[i].rate_config))
    01316             {
    01317                 rc_ss->rate_stats[i].rate_allowed = 0;
    01318             }
    01319         }
    01320         rc_ss->rate_stats[rc_ss->retry_step_idx[0]].rate_allowed = 1;
    01321     }
    01322     rc_ss->retry_step_idx[1] = rc_ss->retry_step_idx[0];
    01323     for (i = j; i < rc_ss->no_samples; i++)
    01324     {
    01325         if (rc_ss->rate_stats[rc_ss->no_samples - i].rate_allowed)
    01326         {
    01327             rc_ss->retry_step_idx[1] = rc_ss->no_samples - i;
    01328             break;
    01329         }
    01330     }
    01331     // find max probability
    01332     max_prob_idx = rc_ss->retry_step_idx[1];
    01333     for (i = i + 1; i < rc_ss->no_samples; i++)
    01334     {
    01335         if (rc_ss->rate_stats[rc_ss->no_samples - i].rate_allowed)
    01336         {
    01337             max_prob_idx = rc_ss->no_samples - i;
    01338             break;
    01339         }
    01340     }
    01341     max_tp = cur_tp[max_prob_idx];
    01342     max_prob = rc_ss->rate_stats[max_prob_idx].probability;
    01343     for (i = 0; i < rc_ss->retry_step_idx[1]; i++)
    01344     {
    01345         if (rc_ss->rate_stats[i].rate_allowed == 0)
    01346         {
    01347             continue;
    01348         }
    01349         if (i == rc_ss->retry_step_idx[0])
    01350         {
    01351             continue;
    01352         }
    01353         if (rc_ss->rate_stats[i].probability >= RC_FRAC(95, 100))
    01354         {
    01355             if (cur_tp[i] >= max_tp)
    01356             {
    01357                 max_prob_idx = i;
    01358                 max_tp = cur_tp[i];
    01359                 max_prob = rc_ss->rate_stats[i].probability;
    01360             }
    01361         }
    01362         else if (rc_ss->rate_stats[i].probability >= max_prob)
    01363         {
    01364             max_prob_idx = i;
    01365             max_tp = cur_tp[i];
    01366             max_prob = rc_ss->rate_stats[i].probability;
    01367         }
    01368     }
    01369     // Set new step 2 of the retry table
    01370     rc_ss->retry_step_idx[2] = max_prob_idx;
    01371     // Set lowest rate (step 3) in the retry table
    01372     rc_ss->retry_step_idx[3] = 0;
    01373 }
    01374
    01383 static bool rc_check_valid_rate(struct rc_sta_stats *rc_ss, uint16_t rate_config)
    01384 {
    01385     uint8_t format = rc_get_format_mod(rate_config);
    01386     bool rate_allowed = 1;
    01387
    01388     switch (format)
    01389     {
    01390         case FORMATMOD_NON_HT:
    01391         case FORMATMOD_NON_HT_DUP_OFDM:
    01392         {
    01393             uint8_t r_idx = rc_get_mcs_index(rate_config);
    01394             if ((rc_ss->rate_map_l & CO_BIT(r_idx)) == 0) // rate index not allowed
    01395             {
    01396                 rate_allowed = 0;
    01397             }
    01398         } break;
    01399         case FORMATMOD_HT_MF:
    01400         case FORMATMOD_HT_GF:
    01401         {
    01402             uint8_t nss = rc_get_nss(rate_config);
    01403             uint8_t mcs = rc_get_mcs_index(rate_config);
    01404             if ((rc_ss->rate_map.ht[nss] & CO_BIT(mcs)) == 0) // rate index not allowed
    01405             {
    01406                 rate_allowed = 0;
    01407             }
    01408         } break;
    01409
    01410         #if NX_VHT
    01411         case FORMATMOD_VHT:
    01412         {
    01413             uint8_t bw = rc_get_bw(rate_config);
    01414             uint8_t nss = rc_get_nss(rate_config);
    01415             uint8_t mcs = rc_get_mcs_index(rate_config);
    01416             // check if MCS allowed in the rate bitmap
    01417             if (mcs > (7 + (rc_ss->rate_map.vht >> (nss << 1) & MAC_VHT_MCS_MAP_MSK)))
    01418             {
    01419                 rate_allowed = 0;
    01420             }
    01421             // do not allow some missing VHT rates
    01422             if ((mcs == 6) && (bw == BW_80MHZ) && ((nss == 3) || (nss == 6)))
    01423             {
    01424                 rate_allowed = 0;
    01425             }
    01426             else if (mcs == 9)
    01427             {
    01428                 if ((bw == BW_20MHZ) && (nss != 2) && (nss != 5))
    01429                 {
    01430                     rate_allowed = 0;
    01431                 }
    01432                 else if ((bw == BW_80MHZ) && (nss == 5))
    01433                 {
    01434                     rate_allowed = 0;
    01435                 }
    01436                 else if ((bw == BW_160MHZ) && (nss == 2))
    01437                 {
    01438                     rate_allowed = 0;
    01439                 }
    01440             }
    01441         } break;
    01442         #endif
    01443
    01444         #if NX_HE
    01445         case FORMATMOD_HE_SU:
    01446         {
    01447             uint8_t nss = rc_get_nss(rate_config);
    01448             uint8_t mcs = rc_get_mcs_index(rate_config);
    01449             // check if MCS allowed in the rate bitmap
    01450             if (mcs > (7 + 2 * (rc_ss->rate_map.vht >> (nss << 1) & MAC_VHT_MCS_MAP_MSK)))
    01451             {
    01452                 rate_allowed = 0;
    01453             }
    01454         } break;
    01455         #endif
    01456
    01457         default:
    01458             break;
    01459     }
    01460
    01461     return rate_allowed;
    01462 }
    01463
    01481 static void rc_get_new_sample_rates(struct rc_sta_stats *rc_ss,
    01482                                     uint16_t *new_rate_cfg_array,
    01483                                     uint8_t n_new_samples)
    01484 {
    01485     uint8_t i = 0;
    01486     uint16_t tmp_rate_cfg;
    01487     uint16_t max_tp_rate_cfg = rc_ss->rate_stats[rc_ss->retry_step_idx[0]].rate_config;
    01488     uint16_t max_tp_2_rate_cfg = rc_ss->rate_stats[rc_ss->retry_step_idx[1]].rate_config;
    01489
    01490     memset(new_rate_cfg_array, -1, n_new_samples*sizeof(*new_rate_cfg_array));
    01491
    01492     for (i = 0; i < n_new_samples; i++)
    01493     {
    01494         switch (i)
    01495         {
    01496             // Random rate
    01497             case 0:
    01498             {
    01499                 new_rate_cfg_array[i] =  rc_new_random_rate(rc_ss);
    01500             }
    01501             break;
    01502
    01503             // If max_tp is long guard, pick same configuration but short guard
    01504             // If max_tp is short guard, pick same configuration but long guard
    01505             case 1:
    01506             {
    01507                 #if NX_HE
    01508                 if (rc_get_format_mod(max_tp_rate_cfg) == FORMATMOD_HE_SU)
    01509                 {
    01510                     uint8_t gi = (rc_get_he_gi(max_tp_rate_cfg) + 1) % 3;
    01511                     max_tp_rate_cfg &= ~HE_GI_TYPE_TX_RCX_MASK;
    01512                     new_rate_cfg_array[i] = max_tp_rate_cfg | (gi << HE_GI_TYPE_TX_RCX_OFT);
    01513                 }
    01514                 else
    01515                 #endif
    01516                 if ((rc_get_format_mod(max_tp_rate_cfg) >= (uint8_t)FORMATMOD_HT_MF) &&
    01517                     (rc_ss->short_gi == 1))
    01518                 {
    01519                     new_rate_cfg_array[i] = max_tp_rate_cfg ^ SHORT_GI_TX_RCX_MASK;
    01520                 }
    01521             }
    01522             break;
    01523
    01524             // MCS index above the best throughput rate
    01525             case 2:
    01526             {
    01527                 tmp_rate_cfg = rc_set_next_mcs_index(rc_ss, max_tp_rate_cfg);
    01528                 if ((tmp_rate_cfg != max_tp_rate_cfg) &&
    01529                     (rc_check_valid_rate(rc_ss, tmp_rate_cfg)))
    01530                 {
    01531                     new_rate_cfg_array[i] = tmp_rate_cfg;
    01532                 }
    01533             }
    01534             break;
    01535
    01536             // MCS index below the best throughput rate
    01537             case 3:
    01538             {
    01539                 tmp_rate_cfg = rc_set_previous_mcs_index(rc_ss, max_tp_rate_cfg);
    01540                 if ((tmp_rate_cfg != max_tp_rate_cfg) &&
    01541                     (rc_check_valid_rate(rc_ss, tmp_rate_cfg)))
    01542                 {
    01543                     new_rate_cfg_array[i] = tmp_rate_cfg;
    01544                 }
    01545             }
    01546             break;
    01547
    01548             // MCS index above the 2nd best throughput rate
    01549             case 4:
    01550             {
    01551                 tmp_rate_cfg = rc_set_next_mcs_index(rc_ss, max_tp_2_rate_cfg);
    01552                 if ((tmp_rate_cfg != max_tp_2_rate_cfg) &&
    01553                     (rc_check_valid_rate(rc_ss, tmp_rate_cfg)))
    01554                 {
    01555                     new_rate_cfg_array[i] = tmp_rate_cfg;
    01556                 }
    01557             }
    01558             break;
    01559
    01560             // MCS index below the 2nd best throughput rate
    01561             case 5:
    01562             {
    01563                 tmp_rate_cfg = rc_set_previous_mcs_index(rc_ss, max_tp_2_rate_cfg);
    01564                 if ((tmp_rate_cfg != max_tp_2_rate_cfg) &&
    01565                     (rc_check_valid_rate(rc_ss, tmp_rate_cfg)))
    01566                 {
    01567                     new_rate_cfg_array[i] = tmp_rate_cfg;
    01568                 }
    01569             }
    01570             break;
    01571
    01572             default:
    01573                 break;
    01574         }
    01575     }
    01576 }
    01577
    01590 static void rc_get_new_samples(struct rc_sta_stats *rc_ss)
    01591 {
    01592     // select new samples and reset statistics
    01593     uint32_t new_sample = 0;
    01594     uint16_t new_rate_cfg_array[RC_MAX_N_SAMPLE-4];
    01595     uint16_t i = 1;
    01596
    01597     if (rc_ss->no_samples < RC_MAX_N_SAMPLE)
    01598     {
    01599         return;
    01600     }
    01601
    01602     rc_get_new_sample_rates(rc_ss, new_rate_cfg_array, RC_MAX_N_SAMPLE-4);
    01603
    01604     while (i < rc_ss->no_samples)
    01605     {
    01606         struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[i];
    01607         uint16_t tmp_rate_cfg;
    01608
    01609         // check if the sample has to be replaced and if a new sample in the list is available
    01610         if (((rc_rs->probability < RC_FRAC(50, 100)) || (rc_rs->sample_skipped > 10)) &&
    01611             (i != rc_ss->retry_step_idx[0]) &&
    01612             (i != rc_ss->retry_step_idx[1]) &&
    01613             (i != rc_ss->retry_step_idx[2]) &&
    01614             (new_sample < (RC_MAX_N_SAMPLE-4)))
    01615         {
    01616             tmp_rate_cfg = new_rate_cfg_array[new_sample];
    01617             if ((tmp_rate_cfg != (uint16_t)-1) && (!rc_check_rate_duplicated(rc_ss, tmp_rate_cfg)))
    01618             {
    01619                 rc_rs->rate_config = tmp_rate_cfg;
    01620                 // reset new sample probability
    01621                 rc_rs->probability = 0;
    01622                 rc_rs->old_prob_available = 0;
    01623                 #if NX_DEBUG
    01624                 // sanity check
    01625                 rc_check_rate_config(rc_ss, i);
    01626                 #endif
    01627                 // next sample in the table
    01628                 i += 1;
    01629             }
    01630             new_sample += 1;
    01631         }
    01632         else
    01633         {
    01634             // go to next sample in the table
    01635             i += 1;
    01636         }
    01637     }
    01638 }
    01639
    01647 static uint16_t rc_get_lowest_rate_config(struct rc_sta_stats *rc_ss)
    01648 {
    01649     uint16_t rate_config = 0;
    01650
    01651     switch (rc_ss->format_mod)
    01652     {
    01653         case FORMATMOD_NON_HT:
    01654         case FORMATMOD_NON_HT_DUP_OFDM:
    01655         {
    01656             if (rc_ss->r_idx_min == 0) // CCK
    01657             {
    01658                 // CCK group: lowest rate has preamble type long, rate index 0, BW_20MHZ
    01659                 rate_config = (FORMATMOD_NON_HT << FORMAT_MOD_TX_RCX_OFT) |
    01660                         (1 << PRE_TYPE_TX_RCX_OFT);
    01661             }
    01662             else
    01663             {
    01664                 // NON-HT: lowest rate has lowest allowed rate index, BW_20MHZ
    01665                 rate_config = (FORMATMOD_NON_HT << FORMAT_MOD_TX_RCX_OFT) |
    01666                         (rc_ss->r_idx_min << MCS_INDEX_TX_RCX_OFT);
    01667             }
    01668         } break;
    01669         case FORMATMOD_HT_MF:
    01670         case FORMATMOD_HT_GF:
    01671         {
    01672             if (rc_ss->r_idx_min == 0) // CCK
    01673             {
    01674                 // CCK group: lowest rate has preamble type long, rate index 0, BW_20MHZ
    01675                 rate_config = (FORMATMOD_NON_HT << FORMAT_MOD_TX_RCX_OFT) |
    01676                         (1 << PRE_TYPE_TX_RCX_OFT);
    01677             }
    01678             else
    01679             {
    01680                 // HT group: lowest rate is HT, MCS0, BW_20MHZ
    01681                 rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT);
    01682             }
    01683         } break;
    01684
    01685         #if NX_VHT
    01686         case FORMATMOD_VHT:
    01687         {
    01688             // VHT only: lowest rate is MCS0, BW_20MHZ
    01689             rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT);
    01690         } break;
    01691         #endif
    01692
    01693         #if NX_HE
    01694         case FORMATMOD_HE_SU:
    01695         {
    01696             if (rc_ss->r_idx_min == 0) // CCK
    01697             {
    01698                 // CCK group: lowest rate has preamble type long, rate index 0, BW_20MHZ
    01699                 rate_config = (FORMATMOD_NON_HT << FORMAT_MOD_TX_RCX_OFT) |
    01700                               (1 << PRE_TYPE_TX_RCX_OFT);
    01701             }
    01702             else
    01703             {
    01704                 // HE group: lowest rate is HE, MCS0, BW_20MHZ. GI1.6
    01705                 rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT) |
    01706                               GI_TYPE_1_6;
    01707             }
    01708         } break;
    01709         #endif
    01710
    01711         default:
    01712             break;
    01713     }
    01714
    01715     return rate_config;
    01716 }
    01717
    01727 static uint16_t rc_get_initial_rate_config(struct rc_sta_stats *rc_ss)
    01728 {
    01729     uint16_t rate_config = 0;
    01730
    01731     switch (rc_ss->format_mod)
    01732     {
    01733         case FORMATMOD_NON_HT:
    01734         case FORMATMOD_NON_HT_DUP_OFDM:
    01735         {
    01736             rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT) |
    01737                     (rc_ss->type << PRE_TYPE_TX_RCX_OFT) |
    01738                     (rc_ss->r_idx_max << MCS_INDEX_TX_RCX_OFT);
    01739         } break;
    01740         case FORMATMOD_HT_MF:
    01741         case FORMATMOD_HT_GF:
    01742         {
    01743             uint8_t mcs = 31 - co_clz((uint32_t)rc_ss->rate_map.ht[rc_ss->no_ss]);
    01744             rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT) |
    01745                     (rc_ss->short_gi << SHORT_GI_TX_RCX_OFT) |
    01746                     (rc_ss->bw_max << BW_TX_RCX_OFT) |
    01747                     (rc_ss->no_ss << HT_NSS_OFT) |
    01748                     (mcs << MCS_INDEX_TX_RCX_OFT);
    01749         } break;
    01750
    01751         #if NX_VHT
    01752         case FORMATMOD_VHT:
    01753         {
    01754             rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT) |
    01755                     (rc_ss->short_gi << SHORT_GI_TX_RCX_OFT) |
    01756                     (rc_ss->bw_max << BW_TX_RCX_OFT) |
    01757                     (rc_ss->format_mod == FORMATMOD_VHT ? rc_ss->no_ss << VHT_NSS_OFT : rc_ss->no_ss << HT_NSS_OFT) |
    01758                     (7 << MCS_INDEX_TX_RCX_OFT);
    01759         } break;
    01760         #endif
    01761
    01762         #if NX_HE
    01763         case FORMATMOD_HE_SU:
    01764         {
    01765             rate_config = (rc_ss->format_mod << FORMAT_MOD_TX_RCX_OFT) |
    01766                           (rc_ss->bw_max << BW_TX_RCX_OFT) |
    01767                           (rc_ss->no_ss << VHT_NSS_OFT) |
    01768                           (7 << MCS_INDEX_TX_RCX_OFT) | GI_TYPE_0_8;
    01769         } break;
    01770         #endif
    01771
    01772         default:
    01773             break;
    01774     }
    01775
    01776     return rate_config;
    01777 }
    01778
    01789 static uint16_t rc_get_num_samples(struct rc_sta_stats *rc_ss)
    01790 {
    01791     uint32_t i, j;
    01792     uint16_t n_sample = 0;
    01793
    01794     switch (rc_ss->format_mod)
    01795     {
    01796         case FORMATMOD_NON_HT:
    01797         case FORMATMOD_NON_HT_DUP_OFDM:
    01798         {
    01799             uint16_t r_map = rc_ss->rate_map_l;
    01800             n_sample += (r_map & 1); // HW_RATE_1MBPS: only long preamble
    01801             for (i = HW_RATE_2MBPS; i <= HW_RATE_11MBPS; i++)
    01802             {
    01803                 n_sample += (((r_map >> i) & 1) << (1-rc_ss->type));
    01804             }
    01805             for (i = HW_RATE_6MBPS; i <= HW_RATE_54MBPS; i++)
    01806             {
    01807                 n_sample += ((r_map >> i) & 1);
    01808             }
    01809         } break;
    01810
    01811         case FORMATMOD_HT_MF:
    01812         case FORMATMOD_HT_GF:
    01813         {
    01814             uint32_t mult = ((rc_ss->bw_max + 1) << rc_ss->short_gi) * (rc_ss->no_ss + 1);
    01815             uint8_t mcs_map = rc_ss->rate_map.ht[0];
    01816             for (j = 0; j < 8; j++)  // MCS 0-7
    01817             {
    01818                 n_sample += ((mcs_map & 1) * mult);
    01819                 mcs_map = mcs_map >> 1;
    01820             }
    01821             // cck rates
    01822             uint16_t r_map = rc_ss->rate_map_l;
    01823             n_sample += (r_map & 1); // HW_RATE_1MBPS: only long preamble
    01824             for (i = HW_RATE_2MBPS; i <= HW_RATE_11MBPS; i++)
    01825             {
    01826                 n_sample += (((r_map >> i) & 1) << (1-rc_ss->type));
    01827             }
    01828         } break;
    01829
    01830         #if NX_VHT
    01831         case FORMATMOD_VHT:
    01832         {
    01833             // VHT rates
    01834             uint32_t mult = ((rc_ss->bw_max + 1) << rc_ss->short_gi) * (rc_ss->no_ss + 1);
    01835             uint8_t n_mcs;
    01836             switch (rc_ss->rate_map.vht & MAC_VHT_MCS_MAP_MSK)
    01837             {
    01838                 case 0:
    01839                     n_mcs = 8;
    01840                     break;
    01841                 case 1:
    01842                 case 2:
    01843                     n_mcs = 9;
    01844                     break;
    01845                 default:
    01846                     n_mcs = 8;
    01847                     break;
    01848             }
    01849             n_sample = n_mcs * mult;
    01850         } break;
    01851         #endif
    01852
    01853         #if NX_HE
    01854         case FORMATMOD_HE_SU:
    01855         {
    01856             // HE rates
    01857             uint32_t mult = ((rc_ss->bw_max + 1) * (rc_ss->short_gi + 1)) * (rc_ss->no_ss + 1);
    01858             uint8_t n_mcs;
    01859             switch (rc_ss->rate_map.he & MAC_HE_MCS_MAP_MSK)
    01860             {
    01861                 case 0:
    01862                     n_mcs = 8;
    01863                     break;
    01864                 case 1:
    01865                     n_mcs = 9;
    01866                     break;
    01867                 case 2:
    01868                     n_mcs = 10;
    01869                     break;
    01870                 default:
    01871                     n_mcs = 8;
    01872                     break;
    01873             }
    01874             n_sample = n_mcs * mult;
    01875         } break;
    01876         #endif
    01877
    01878         default:
    01879             break;
    01880     }
    01881
    01882     if (n_sample > RC_MAX_N_SAMPLE)
    01883     {
    01884         n_sample = RC_MAX_N_SAMPLE;
    01885     }
    01886
    01887     return n_sample;
    01888 }
    01889
    01900 static void rc_set_rate_configs(struct rc_sta_stats *rc_ss)
    01901 {
    01902     uint16_t i;
    01903
    01904     // Reset rate configuration
    01905     for (i = 0; i < rc_ss->no_samples; i++)
    01906     {
    01907         struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[i];
    01908         rc_rs->rate_config = 0xFFFF;
    01909         rc_rs->attempts = 0;
    01910         rc_rs->success = 0;
    01911         rc_rs->probability = 0;
    01912         rc_rs->sample_skipped = 0;
    01913         rc_rs->old_prob_available = 0;
    01914         rc_rs->rate_allowed = 1;
    01915     }
    01916
    01917     // Set base rate configuration (lowest allowed rate) as sample number 0
    01918     rc_ss->rate_stats[0].rate_config = rc_get_lowest_rate_config(rc_ss);
    01919     // Set last sample: highest rate index for NON-HT, MCS7 or highest allowed for HT,
    01920     // MCS7 for VHT
    01921     rc_ss->rate_stats[rc_ss->no_samples - 1].rate_config = rc_get_initial_rate_config(rc_ss);
    01922     // Set initial sample rates (do not use duplicated samples) - sample 0 is always the lowest rate
    01923     for (i = 1; i < (rc_ss->no_samples - 1);)
    01924     {
    01925         // Get random rates for the other samples
    01926         uint16_t tmp_rate = rc_new_random_rate(rc_ss);
    01927         // do not use duplicated samples
    01928         if (!rc_check_rate_duplicated(rc_ss, tmp_rate))
    01929         {
    01930             rc_ss->rate_stats[i].rate_config = tmp_rate;
    01931             i++;
    01932         }
    01933     }
    01934     #if NX_DEBUG
    01935     rc_check_stats_rate_config(rc_ss);
    01936     #endif
    01937 }
    01938
    01950 static void rc_init_rates(uint8_t sta_idx)
    01951 {
    01952     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    01953     struct sta_pol_tbl_cntl *pt = &sta->pol_tbl;
    01954     struct rc_sta_stats *rc_ss = pt->sta_stats;
    01955     ASSERT_ERR(rc_ss != NULL);
    01956     uint16_t i;
    01957
    01958     // Select new random rates for the stats table
    01959     rc_set_rate_configs(rc_ss);
    01960
    01961     // set retry chain steps 0, 1 and 2
    01962     for (i = 0; i < (RATE_CONTROL_STEPS-1); i++)
    01963     {
    01964         rc_ss->retry_step_idx[i] = (rc_ss->no_samples - 1) - i;
    01965     }
    01966     // Set lowest rate (entry 0 of the sample table) as last step of the retry chain
    01967     rc_ss->retry_step_idx[RATE_CONTROL_STEPS-1] = 0;
    01968     // Initialize average AMPDU length
    01969     rc_ss->avg_ampdu_len = RC_FRAC(1, 1);
    01970     // Disable fixed rate
    01971     rc_ss->fixed_rate_cfg = RC_FIXED_RATE_NOT_SET;
    01972     // Reset RC flags
    01973     rc_ss->info = 0;
    01974     // Initialize RC algorithm table
    01975     rc_update_stats(rc_ss, 1);
    01976     // Initialize trial period
    01977     rc_ss->sample_wait =  5;
    01978     // Initialize trial index
    01979     rc_ss->trial_idx = rc_ss->no_samples - RATE_CONTROL_STEPS;
    01980     // Initialize trial status
    01981     rc_ss->trial_status = RC_TRIAL_STATUS_WAIT;
    01982 }
    01983
    01984 #if NX_AMSDU_TX
    01985
    01991 static void rc_set_max_amsdu_len(struct rc_sta_stats *rc_ss)
    01992 {
    01993     uint8_t step_0_idx = rc_ss->retry_step_idx[rc_ss->sw_retry_step];
    01994     uint16_t rate_config = rc_ss->rate_stats[step_0_idx].rate_config;
    01995     uint16_t max_amsdu_size = 0;
    01996
    01997     // Allow A-MSDU only if higher MCS are used (i.e >= MCS5)
    01998     if (rc_get_mcs_index(rate_config) >= 5)
    01999     {
    02000         // set the max size of AMSDU depending on the number of spatial streams:
    02001         // - 1 SS: max size 4
    02002         // - 2 SS: max size 6
    02003         // - 3-8 SS: max size 6
    02004         if (rc_ss->no_ss == 0)
    02005         {
    02006             max_amsdu_size = 4;
    02007         }
    02008         else if (rc_ss->no_ss == 1)
    02009         {
    02010             max_amsdu_size = 6;
    02011         }
    02012         else
    02013         {
    02014             max_amsdu_size = 6;
    02015         }
    02016     }
    02017     else
    02018     {
    02019         max_amsdu_size = 0;
    02020     }
    02021     rc_ss->curr_amsdu_len = co_min(rc_ss->max_amsdu_len, max_amsdu_size*1550);
    02022 }
    02023 #endif //NX_AMSDU_TX
    02024
    02025 #if NX_AMPDU_TX
    02026
    02038 static void rc_set_aggregation_flag(struct rc_sta_stats *rc_ss, bool *tx_ampdu)
    02039 {
    02040     bool agg_enabled = 1;
    02041
    02042     // check if aggregation has to be disabled
    02043     do
    02044     {
    02045         // disable aggregation only for stations allowing legacy rates
    02046         if (rc_ss->r_idx_min > HW_RATE_54MBPS)
    02047         {
    02048             break;
    02049         }
    02050         // disable aggregation if one of the steps 0-2 is a DSSS/CCK rate
    02051         uint16_t rate_0 = rc_ss->rate_stats[rc_ss->retry_step_idx[0]].rate_config;
    02052         uint16_t rate_1 = rc_ss->rate_stats[rc_ss->retry_step_idx[1]].rate_config;
    02053         uint16_t rate_2 = rc_ss->rate_stats[rc_ss->retry_step_idx[2]].rate_config;
    02054         if (rc_get_format_mod(rate_0) < FORMATMOD_HT_MF ||
    02055             rc_get_format_mod(rate_1) < FORMATMOD_HT_MF ||
    02056             rc_get_format_mod(rate_2) < FORMATMOD_HT_MF)
    02057         {
    02058             agg_enabled = 0;
    02059             break;
    02060         }
    02061         // If fixed rate is set, do not disable aggregation because of low probability
    02062         if (rc_ss->info & RC_FIX_RATE_EN_MASK)
    02063         {
    02064             break;
    02065         }
    02066         // disable aggregation if first step:
    02067         // 1 SS, probability of success < 10%. MCS0 or MCS1
    02068         uint8_t step_0 = rc_ss->sw_retry_step;
    02069         uint16_t step_0_idx = rc_ss->retry_step_idx[step_0];
    02070         struct rc_rate_stats *stats_step_0 = &rc_ss->rate_stats[step_0_idx];
    02071         uint8_t step_0_mcs = rc_get_mcs_index(stats_step_0->rate_config);
    02072         uint8_t step_0_nss = rc_get_nss(stats_step_0->rate_config);
    02073         if (((step_0_mcs <= 2) &&
    02074             (step_0_nss == 0) &&
    02075             (stats_step_0->probability < RC_FRAC(10, 100))) ||
    02076             (stats_step_0->probability < RC_FRAC(1, 100)))
    02077         {
    02078             agg_enabled = 0;
    02079         }
    02080     } while (0);
    02081
    02082     rc_ss->info &= ~RC_AGG_ALLOWED_MASK;
    02083     rc_ss->info |= (agg_enabled << RC_AGG_ALLOWED_OFT);
    02084
    02085     if (tx_ampdu != NULL)
    02086         *tx_ampdu = agg_enabled;
    02087 }
    02088 #endif //NX_AMPDU_TX
    02089
    02100 static bool rc_update_stats_fixed_rate(struct rc_sta_stats *rc_ss)
    02101 {
    02102     bool update_requested = 0;
    02103     uint16_t i = 0;
    02104
    02105     // Fixed rate request
    02106     if (rc_ss->info & RC_FIX_RATE_REQ_MASK)
    02107     {
    02108         uint8_t idx = 0;
    02109         // Check if selected rate is in the sample table
    02110         while (idx < rc_ss->no_samples)
    02111         {
    02112             if (rc_ss->fixed_rate_cfg == rc_ss->rate_stats[idx].rate_config)
    02113             {
    02114                 break;
    02115             }
    02116             idx++;
    02117         }
    02118         // If not present in the sample table, insert it
    02119         if (idx == rc_ss->no_samples)
    02120         {
    02121             idx = rc_ss->no_samples - 1;
    02122             rc_ss->rate_stats[idx].rate_config = rc_ss->fixed_rate_cfg;
    02123             rc_ss->rate_stats[idx].probability = 0;
    02124         }
    02125         // Set retry chain
    02126         for (i = 0; i < 3; i++)
    02127         {
    02128             rc_ss->retry_step_idx[i] = idx;
    02129         }
    02130         // Reset statistics
    02131         for (i = 0; i < rc_ss->no_samples; i++)
    02132         {
    02133             rc_ss->rate_stats[i].attempts = 0;
    02134             rc_ss->rate_stats[i].success = 0;
    02135         }
    02136         // Reset trial status
    02137         rc_ss->trial_status = RC_TRIAL_STATUS_WAIT;
    02138         // Set fix rate status
    02139         rc_ss->info &= ~RC_FIX_RATE_STATUS_MASK;
    02140         rc_ss->info |= RC_FIX_RATE_EN_MASK;
    02141         update_requested = 1;
    02142     }
    02143     // Fixed rate is set: update statistics and reset counters
    02144     else
    02145     {
    02146         uint8_t step_0_idx = rc_ss->retry_step_idx[0];
    02147         struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[step_0_idx];
    02148         // Calculate success probability
    02149         rc_calc_prob_ewma(rc_rs);
    02150         // Reset statistics
    02151         for (i = 0; i < rc_ss->no_samples; i++)
    02152         {
    02153             rc_ss->rate_stats[i].attempts = 0;
    02154             rc_ss->rate_stats[i].success = 0;
    02155         }
    02156     }
    02157
    02158     return update_requested;
    02159 }
    02160
    02172 static void rc_update_counters(struct txdesc *txdesc, uint32_t attempts,
    02173                                uint32_t failures, bool tx_ampdu)
    02174 {
    02175     uint8_t sta_idx = txdesc->host.staid;
    02176     bool trial_tx;
    02177     #if NX_HE
    02178     bool he_tb = false;
    02179     #endif
    02180     struct sta_info_tag *sta;
    02181     struct sta_pol_tbl_cntl *rc;
    02182     struct rc_sta_stats *rc_ss;
    02183
    02184     if (sta_idx >= NX_REMOTE_STA_MAX)
    02185         return;
    02186
    02187     trial_tx = ((txdesc->host.flags & TXU_CNTRL_RC_TRIAL) == TXU_CNTRL_RC_TRIAL);
    02188     #if NX_HE
    02189     he_tb = (txdesc->lmac.hw_desc->thd.statinfo & HE_TB_TX_BIT) != 0;
    02190     #endif
    02191     sta = &sta_info_tab[sta_idx];
    02192     if (sta->inst_nbr == 0xFF)
    02193         return;
    02194
    02195     rc = &sta->pol_tbl;
    02196     rc_ss = rc->sta_stats;
    02197     ASSERT_ERR(rc_ss != NULL);
    02198
    02199     // Check if we need to take into account the result of this transmission to update
    02200     // the statistics. This is not the case if the packet was transmitted using a older
    02201     // retry chain version than the currently active one or if it was transmitted in a HE
    02202     // TB PPDU
    02203     if ((RC_CONTROL_GET(txdesc->umac.rc_control, RETRY_CHAIN_VER) != rc_ss->retry_chain_ver)
    02204         #if NX_HE
    02205         && !he_tb
    02206         #endif
    02207        )
    02208     {
    02209         if (trial_tx)
    02210             rc_ss->trial_status = RC_TRIAL_STATUS_WAIT;
    02211         return;
    02212     }
    02213
    02214     PROF_RC_UPD_COUNTERS_SET();
    02215
    02216     // update the number of AMPDUs transmitted
    02217     rc_ss->ampdu_packets += 1;
    02218
    02219     #if NX_AMPDU_TX
    02220     if (tx_ampdu)
    02221     {
    02222         struct rc_rate_stats *rc_rs;
    02223         // update the number of MPDUs transmitted (success and failures)
    02224         rc_ss->ampdu_len += attempts;
    02225         #if NX_HE
    02226         if (he_tb)
    02227         {
    02228             rc_rs = &rc_ss->rate_stats[RC_HE_STATS_IDX];
    02229         }
    02230         else
    02231         #endif
    02232         // update for trial tx
    02233         if (trial_tx)
    02234         {
    02235             PROF_RC_UPD_COUNTERS_TRIAL_SET();
    02236             // Set number of attempts and success for the trial rate
    02237             rc_rs = &rc_ss->rate_stats[rc_ss->trial_idx];
    02238             rc_ss->trial_status = RC_TRIAL_STATUS_WAIT;
    02239             PROF_RC_UPD_COUNTERS_TRIAL_CLR();
    02240         }
    02241         else
    02242         {
    02243             // Set number of attempts and success for first rate of the retry chain
    02244             uint8_t retry_step = RC_CONTROL_GET(txdesc->umac.rc_control, SW_RETRY_STEP);
    02245             uint16_t step_0_idx = rc_ss->retry_step_idx[retry_step];
    02246             rc_rs = &rc_ss->rate_stats[step_0_idx];
    02247
    02248             // Check if we should derogate from the normal policy table for next A-MPDU
    02249             // transmissions. We consider that having more than 50% PER inside a A-MPDU
    02250             // will create many retries, and in such case we decrease the MCS until we
    02251             // get good PER again
    02252             if ((2 * failures) > attempts)
    02253             {
    02254                 PROF_RC_SW_RETRY_SET();
    02255                 if (rc_ss->sw_retry_step < 2)
    02256                     rc_ss->sw_retry_step++;
    02257                 else if (rc_ss->sw_retry_step == 2)
    02258                     // Force the statistics to be computed earlier
    02259                     rc_ss->last_rc_time -= (RC_PERIOD_TOUT * 3) / 4;
    02260                 PROF_RC_SW_RETRY_CLR();
    02261             }
    02262             else if (rc_ss->sw_retry_step)
    02263             {
    02264                 // PER is OK, increase again the MCS
    02265                 rc_ss->sw_retry_step--;
    02266             }
    02267         }
    02268         rc_rs->attempts += attempts;
    02269         rc_rs->success += (attempts - failures);
    02270         ASSERT_ERR(rc_rs->attempts >= rc_rs->success);
    02271     }
    02272     else
    02273     #endif
    02274     {
    02275         // update the number of MPDUs transmitted (success and failures)
    02276         rc_ss->ampdu_len += 1;
    02277         #if NX_HE
    02278         if (he_tb)
    02279         {
    02280             struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[RC_HE_STATS_IDX];
    02281             rc_rs->attempts += attempts;
    02282             rc_rs->success += (attempts - failures);
    02283         }
    02284         else
    02285         #endif
    02286         // update for trial tx
    02287         if (trial_tx)
    02288         {
    02289             PROF_RC_UPD_COUNTERS_TRIAL_SET();
    02290             // update the number of attempts and success for each rate of the retry chain
    02291             for (uint32_t i = 0; (i < RATE_CONTROL_STEPS) && (attempts > 0); i++)
    02292             {
    02293                 uint16_t rate_idx;
    02294                 struct rc_rate_stats *rc_rs;
    02295                 if (i == 0)
    02296                     rate_idx = rc_ss->trial_idx;
    02297                 else if (i == 1)
    02298                     rate_idx = rc_ss->retry_step_idx[0];
    02299                 else
    02300                     rate_idx = rc_ss->retry_step_idx[i];
    02301
    02302                 rc_rs = &rc_ss->rate_stats[rate_idx];
    02303                 if (failures >= RC_MAX_NUM_RETRY)
    02304                 {
    02305                     rc_rs->attempts += RC_MAX_NUM_RETRY;
    02306                     attempts -= RC_MAX_NUM_RETRY;
    02307                     failures -= RC_MAX_NUM_RETRY;
    02308                 }
    02309                 else
    02310                 {
    02311                     rc_rs->attempts += attempts;
    02312                     rc_rs->success += (attempts - failures);
    02313                     attempts = 0;
    02314                     failures = 0;
    02315                 }
    02316                 ASSERT_ERR(rc_rs->attempts >= rc_rs->success);
    02317             }
    02318             rc_ss->trial_status = RC_TRIAL_STATUS_WAIT;
    02319             PROF_RC_UPD_COUNTERS_TRIAL_CLR();
    02320         }
    02321         else
    02322         {
    02323             // update the number of attempts and success for each rate of the retry chain
    02324             for (uint32_t i = 0; (i < RATE_CONTROL_STEPS) && (attempts > 0); i++)
    02325             {
    02326                 uint16_t rate_idx = rc_ss->retry_step_idx[i];
    02327                 struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[rate_idx];
    02328                 if (failures >= RC_MAX_NUM_RETRY)
    02329                 {
    02330                     rc_rs->attempts += RC_MAX_NUM_RETRY;
    02331                     attempts -= RC_MAX_NUM_RETRY;
    02332                     failures -= RC_MAX_NUM_RETRY;
    02333                 }
    02334                 else
    02335                 {
    02336                     rc_rs->attempts += attempts;
    02337                     rc_rs->success += (attempts - failures);
    02338                     attempts = 0;
    02339                     failures = 0;
    02340                 }
    02341                 ASSERT_ERR(rc_rs->attempts >= rc_rs->success);
    02342             }
    02343         }
    02344     }
    02345     PROF_RC_UPD_COUNTERS_CLR();
    02346 }
    02347
    02348 /*
    02349  * PUBLIC FUNCTIONS DEFINITION
    02350  ****************************************************************************************
    02351  */
    02352 void rc_cfm_singleton(struct txdesc *txdesc)
    02353 {
    02354     // Check the status
    02355     struct tx_cfm_tag *cfm = txl_cfm_tag_get(txdesc);
    02356     uint32_t status = cfm->status;
    02357     uint32_t retry_cnt = ((status & NUM_MPDU_RETRIES_MSK) >> NUM_MPDU_RETRIES_OFT);
    02358     uint32_t trials;
    02359     uint32_t failures;
    02360
    02361     // Compute the statistics
    02362     trials = retry_cnt + 1;
    02363     failures = retry_cnt + ((status & RETRY_LIMIT_REACHED_BIT) != 0);
    02364
    02365     // Update statistics
    02366     rc_update_counters(txdesc, trials, failures, 0);
    02367 }
    02368
    02369 void rc_cfm_ampdu(struct txdesc *txdesc, uint32_t txed, uint32_t txok)
    02370 {
    02371     // Update statistics
    02372     rc_update_counters(txdesc, txed, (txed - txok), 1);
    02373 }
    02374
    02375 void rc_check(struct txdesc *txdesc)
    02376 {
    02377     struct hostdesc *host = &txdesc->host;
    02378     uint8_t sta_idx = host->staid;
    02379     struct sta_info_tag *sta;
    02380     struct sta_pol_tbl_cntl *rc;
    02381     struct rc_sta_stats *rc_ss;
    02382     bool update = false;
    02383     #if NX_AMPDU_TX
    02384     bool tx_ampdu;
    02385     #endif
    02386
    02387     if (sta_idx >= NX_REMOTE_STA_MAX)
    02388     {
    02389         txdesc->umac.rc_control = 0;
    02390         return;
    02391     }
    02392
    02393     sta = &sta_info_tab[sta_idx];
    02394     rc = &sta->pol_tbl;
    02395     rc_ss = rc->sta_stats;
    02396     ASSERT_ERR(rc_ss != NULL);
    02397
    02398     #if NX_AMPDU_TX
    02399     tx_ampdu = (txdesc->umac.flags & AMPDU_BIT) ? true : false;
    02400     // update ampdu tx
    02401     if (((rc_ss->info & RC_AGG_ALLOWED_MASK) == 0) || !tx_ampdu)
    02402     {
    02403         rc_ss->info &= ~RC_AGG_TX_MASK;
    02404     }
    02405     else
    02406     {
    02407         rc_ss->info |= RC_AGG_TX_MASK;
    02408     }
    02409     #endif
    02410
    02411     // Check if it is time to run the RC algorithm
    02412     if (hal_machw_time_past(rc_ss->last_rc_time + RC_PERIOD_TOUT))
    02413     {
    02414         PROF_RC_STATS_CALC_SET();
    02415         // Calculate statistics and update retry chain
    02416         update |= rc_update_stats(rc_ss, 0);
    02417         // Reset trial status
    02418         rc_ss->trial_status = RC_TRIAL_STATUS_WAIT;
    02419         // Reset SW retry step
    02420         rc_ss->sw_retry_step = 0;
    02421         // Increase retry chain version
    02422         rc_ss->retry_chain_ver = (rc_ss->retry_chain_ver + 1) % 4;
    02423         // Update RC timer
    02424         rc_ss->last_rc_time = hal_machw_time();
    02425
    02426         PROF_RC_STATS_CALC_CLR();
    02427     }
    02428
    02429     txdesc->umac.rc_control = rc_ss->retry_chain_ver << RC_RETRY_CHAIN_VER_OFT;
    02430     #if NX_AMPDU_TX
    02431     txdesc->umac.rc_control |= rc_ss->sw_retry_step << RC_SW_RETRY_STEP_OFT;
    02432     #endif
    02433
    02434     if (update)
    02435     {
    02436         #if NX_AMSDU_TX
    02437         // Set maximum AMSDU len
    02438         rc_set_max_amsdu_len(rc_ss);
    02439         #endif
    02440         #if NX_AMPDU_TX
    02441         rc_set_aggregation_flag(rc_ss, &tx_ampdu);
    02442         if (!tx_ampdu)
    02443         {
    02444             txdesc->umac.flags &= ~AMPDU_BIT;
    02445         }
    02446         #endif
    02447         // Keep in mind we have to update the rate
    02448         rc->upd_field |= CO_BIT(STA_MGMT_POL_UPD_RATE);
    02449     }
    02450
    02451     // check if the retry chain has to be updated due to a trial tx
    02452     if (rc_check_trial_tx(rc_ss))
    02453     {
    02454         txdesc->host.flags |= TXU_CNTRL_RC_TRIAL;
    02455         #if NX_AMPDU_TX
    02456         txdesc->umac.rc_control &= ~RC_SW_RETRY_STEP_MSK;
    02457         if (tx_ampdu)
    02458             txdesc->umac.flags |= WHICHDESC_AMPDU_FIRST;
    02459         #endif
    02460         // Keep in mind we have to update the trial rate
    02461         rc->upd_field |= CO_BIT(STA_MGMT_POL_TRIAL_RATE);
    02462     }
    02463 }
    02464
    02465 void rc_init(struct sta_info_tag *sta)
    02466 {
    02467     struct sta_pol_tbl_cntl *rc = &sta->pol_tbl;
    02468     struct tx_policy_tbl *pol = &rc->buf_ctrl->policy_tbl;
    02469     uint8_t hw_key_idx = MM_STA_TO_KEY(sta->staid);
    02470
    02471     // Set pointer to station RC statistics
    02472     ASSERT_ERR(sta->staid < NX_REMOTE_STA_MAX);
    02473     rc->sta_stats = &sta_stats[sta->staid];
    02474     ASSERT_ERR(rc->sta_stats != NULL);
    02475
    02476     struct rc_sta_stats *rc_ss = rc->sta_stats;
    02477     uint32_t phy_cntrl_info1 = phy_get_ntx() << NX_TX_PT_OFT;
    02478     uint32_t phy_cntrl_info2 = TX_NTX_2_ANTENNA_SET(phy_get_ntx());
    02479     int i;
    02480
    02481     memset(rc_ss, 0, sizeof(*rc_ss));
    02482
    02483     // Check if the peer is a HT, VHT or HE device
    02484     // If it is supporting all those modes, we will choose only one of them for the
    02485     // rate control, i.e. the one bringing the highest performance:
    02486     //   1. HE
    02487     //   2. VHT
    02488     //   3. HT
    02489     if (STA_CAPA(sta, HT))
    02490     {
    02491         struct mac_htcapability *htcap = &sta->info.ht_cap;
    02492         uint16_t max_mpdu_head_tail = MAC_LONG_QOS_HTC_MAC_HDR_LEN + MAC_FCS_LEN;
    02493         #if RW_WAPI_EN
    02494         max_mpdu_head_tail += WPI_IV_LEN + WPI_MIC_LEN;
    02495         #else
    02496         max_mpdu_head_tail += IV_LEN + EIV_LEN + MIC_LEN + ICV_LEN;
    02497         #endif
    02498
    02499         // set the bitmap for legacy rates
    02500         rc_ss->rate_map_l = me_legacy_rate_bitfield_build(&sta->info.rate_set, false);
    02501         #if NX_HE
    02502         if (STA_CAPA(sta, HE))
    02503         {
    02504             struct mac_hecapability *hecap = &sta->info.he_cap;
    02505             struct mac_hecapability *hecaploc = &me_env.he_cap;
    02506             uint8_t color = 0;
    02507             struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
    02508             struct me_bss_info *bss = &vif->bss_info;
    02509             // HE configurations
    02510             rc_ss->format_mod = FORMATMOD_HE_SU;
    02511             rc_ss->no_ss = co_min(me_11ac_nss_max(hecap->mcs_supp.rx_mcs_80),
    02512                                   me_11ac_nss_max(hecaploc->mcs_supp.tx_mcs_80));
    02513             ASSERT_ERR(rc_ss->no_ss < 8);
    02514             // Set the bitmap for HE rates
    02515             rc_ss->rate_map.he = me_rate_bitfield_vht_build(hecap->mcs_supp.rx_mcs_80,
    02516                                                             hecaploc->mcs_supp.tx_mcs_80);
    02517             rc_ss->mcs_max = co_min(me_11ax_mcs_max(hecap->mcs_supp.rx_mcs_80),
    02518                                     me_11ax_mcs_max(hecaploc->mcs_supp.tx_mcs_80));
    02519             ASSERT_ERR(rc_ss->mcs_max < 12);
    02520             // remove legacy OFDM rates from the map
    02521             rc_ss->rate_map_l = rc_ss->rate_map_l & ~0xFF0;
    02522             rc_ss->r_idx_min = me_legacy_ridx_min(rc_ss->rate_map_l);
    02523             ASSERT_ERR((rc_ss->r_idx_min <= HW_RATE_11MBPS) || (rc_ss->r_idx_min == MAC_RATESET_LEN));
    02524             rc_ss->r_idx_max = me_legacy_ridx_max(rc_ss->rate_map_l);
    02525             ASSERT_ERR((rc_ss->r_idx_max <= HW_RATE_11MBPS) || (rc_ss->r_idx_max == MAC_RATESET_LEN));
    02526             rc_ss->type = (rc->ppdu_tx_cfg & PRE_TYPE_TX_RCX_MASK) >> PRE_TYPE_TX_RCX_OFT;
    02527
    02528             // Check whether LDPC coding shall be used for transmission to the STA.
    02529             // To do that we ensure first that our PHY is able to use LDPC coding for
    02530             // transmission, and that the peer is able to receive it.
    02531             // We also check our LDPC capability in RX. This check is not mandatory, but
    02532             // it allows disabling completely the LDPC support, in case it is required for
    02533             // testing. Indeed for such purpose our LDPC RX capability advertised to the
    02534             // peers can be manually disabled using a parameter of the WiFi driver. Doing
    02535             // that will therefore also disable the LDPC in TX.
    02536             if (phy_ldpc_tx_supported() &&
    02537                 HE_PHY_CAPA_BIT_IS_SET(hecaploc, LDPC_CODING_IN_PAYLOAD) &&
    02538                 HE_PHY_CAPA_BIT_IS_SET(hecap, LDPC_CODING_IN_PAYLOAD))
    02539             {
    02540                 phy_cntrl_info1 |= FEC_CODING_PT_BIT;
    02541             }
    02542
    02543             // Check if we need to get the MAX A-MSDU from the VHT or HT capabilities
    02544             if (STA_CAPA(sta, VHT))
    02545             {
    02546                 struct mac_vhtcapability *vhtcap = &sta->info.vht_cap;
    02547                 switch (vhtcap->vht_capa_info & MAC_VHTCAPA_MAX_MPDU_LENGTH_MSK)
    02548                 {
    02549                     case MAC_VHTCAPA_MAX_MPDU_LENGTH_3895:
    02550                         rc_ss->max_amsdu_len = 3895 - max_mpdu_head_tail;
    02551                         break;
    02552                     case MAC_VHTCAPA_MAX_MPDU_LENGTH_7991:
    02553                         rc_ss->max_amsdu_len = 7991 - max_mpdu_head_tail;
    02554                         break;
    02555                     case MAC_VHTCAPA_MAX_MPDU_LENGTH_11454:
    02556                         rc_ss->max_amsdu_len = 11454 - max_mpdu_head_tail;
    02557                         break;
    02558                     default:
    02559                         rc_ss->max_amsdu_len = 3895 - max_mpdu_head_tail;
    02560                         break;
    02561                 }
    02562             }
    02563             else
    02564             {
    02565                 if (htcap->ht_capa_info & MAC_HTCAPA_AMSDU)
    02566                 {
    02567                     rc_ss->max_amsdu_len = 7935;
    02568                 }
    02569                 else
    02570                 {
    02571                     rc_ss->max_amsdu_len = 3839;
    02572                 }
    02573             }
    02574
    02575             if (!(bss->he_oper & MAC_HE_OPER_BSS_COLOR_DISABLED_BIT))
    02576                 color = (bss->he_oper & MAC_HE_OPER_BSS_COLOR_MASK) >>
    02577                                                            MAC_HE_OPER_BSS_COLOR_OFT;
    02578             phy_cntrl_info2 |= BMCHANGE_BIT | UPLINK_FLAG_BIT | (color << BSS_COLOR_OFT) |
    02579                                (4 << PKT_EXTENSION_OFT);
    02580         }
    02581         else
    02582         #endif
    02583         #if NX_VHT
    02584         if (STA_CAPA(sta, VHT))
    02585         {
    02586             struct mac_vhtcapability *vhtcap = &sta->info.vht_cap;
    02587             struct mac_vhtcapability *vhtcaploc = &me_env.vht_cap;
    02588             // VHT configurations
    02589             rc_ss->format_mod = FORMATMOD_VHT;
    02590             rc_ss->no_ss = co_min(me_11ac_nss_max(vhtcap->rx_mcs_map),
    02591                                   me_11ac_nss_max(vhtcaploc->tx_mcs_map));
    02592             ASSERT_ERR(rc_ss->no_ss < 8);
    02593             // Set the bitmap for VHT rates
    02594             rc_ss->rate_map.vht = me_rate_bitfield_vht_build(vhtcap->rx_mcs_map,
    02595                                                              vhtcaploc->tx_mcs_map);
    02596             rc_ss->mcs_max = co_min(me_11ac_mcs_max(vhtcap->rx_mcs_map),
    02597                                     me_11ac_mcs_max(vhtcaploc->tx_mcs_map));
    02598             ASSERT_ERR(rc_ss->mcs_max < 10);
    02599             // legacy configurations
    02600             rc_ss->type = 0;
    02601             // remove legacy OFDM rates from the map
    02602             rc_ss->rate_map_l = 0;
    02603             rc_ss->r_idx_min = me_legacy_ridx_min(rc_ss->rate_map_l);
    02604             rc_ss->r_idx_max = me_legacy_ridx_max(rc_ss->rate_map_l);
    02605
    02606             // Check whether LDPC coding shall be used for transmission to the STA.
    02607             // To do that we ensure first that our PHY is able to use LDPC coding for
    02608             // transmission, and that the peer is able to receive it.
    02609             // We also check our LDPC capability in RX. This check is not mandatory, but
    02610             // it allows disabling completely the LDPC support, in case it is required for
    02611             // testing. Indeed for such purpose our LDPC RX capability advertised to the
    02612             // peers can be manually disabled using a parameter of the WiFi driver. Doing
    02613             // that will therefore also disable the LDPC in TX.
    02614             if (phy_ldpc_tx_supported() &&
    02615                 (vhtcaploc->vht_capa_info & MAC_VHTCAPA_RXLDPC) &&
    02616                 (vhtcap->vht_capa_info & MAC_VHTCAPA_RXLDPC))
    02617             {
    02618                 phy_cntrl_info1 |= FEC_CODING_PT_BIT;
    02619             }
    02620
    02621             switch (vhtcap->vht_capa_info & MAC_VHTCAPA_MAX_MPDU_LENGTH_MSK)
    02622             {
    02623                 case MAC_VHTCAPA_MAX_MPDU_LENGTH_3895:
    02624                     rc_ss->max_amsdu_len = 3895 - max_mpdu_head_tail;
    02625                     break;
    02626                 case MAC_VHTCAPA_MAX_MPDU_LENGTH_7991:
    02627                     rc_ss->max_amsdu_len = 7991 - max_mpdu_head_tail;
    02628                     break;
    02629                 case MAC_VHTCAPA_MAX_MPDU_LENGTH_11454:
    02630                     rc_ss->max_amsdu_len = 11454 - max_mpdu_head_tail;
    02631                     break;
    02632                 default:
    02633                     rc_ss->max_amsdu_len = 3895 - max_mpdu_head_tail;
    02634                     break;
    02635             }
    02636         }
    02637         else
    02638         #endif
    02639         {
    02640             struct mac_htcapability *htcaploc = &me_env.ht_cap;
    02641             // HT configurations
    02642             rc_ss->format_mod = FORMATMOD_HT_MF;
    02643             rc_ss->no_ss = co_min(me_11n_nss_max(htcap->mcs_rate),
    02644                                   me_11n_nss_max(htcaploc->mcs_rate));
    02645             ASSERT_ERR(rc_ss->no_ss <= 3);
    02646             // Set the bitmap for HT rates
    02647             memcpy(rc_ss->rate_map.ht, htcap->mcs_rate, sizeof(rc_ss->rate_map.ht));
    02648             // MCS0-7 must be supported by all HT STA (but not always set in HT capab)
    02649             rc_ss->rate_map.ht[0] = 0xFF;
    02650             rc_ss->mcs_max = 7;
    02651
    02652             // legacy configurations
    02653             // remove legacy OFDM rates from the map
    02654             rc_ss->rate_map_l = rc_ss->rate_map_l & ~0xFF0;
    02655             rc_ss->r_idx_min = me_legacy_ridx_min(rc_ss->rate_map_l);
    02656             ASSERT_ERR((rc_ss->r_idx_min <= HW_RATE_11MBPS) || (rc_ss->r_idx_min == MAC_RATESET_LEN));
    02657             rc_ss->r_idx_max = me_legacy_ridx_max(rc_ss->rate_map_l);
    02658             ASSERT_ERR((rc_ss->r_idx_max <= HW_RATE_11MBPS) || (rc_ss->r_idx_max == MAC_RATESET_LEN));
    02659             rc_ss->type = (rc->ppdu_tx_cfg & PRE_TYPE_TX_RCX_MASK) >> PRE_TYPE_TX_RCX_OFT;
    02660
    02661             // Check whether LDPC coding shall be used for transmission to the STA.
    02662             // To do that we ensure first that our PHY is able to use LDPC coding for
    02663             // transmission, and that the peer is able to receive it.
    02664             // We also check our LDPC capability in RX. This check is not mandatory, but
    02665             // it allows disabling completely the LDPC support, in case it is required for
    02666             // testing. Indeed for such purpose our LDPC RX capability advertised to the
    02667             // peers can be manually disabled using a parameter of the WiFi driver. Doing
    02668             // that will therefore also disable the LDPC in TX.
    02669             if (phy_ldpc_tx_supported() &&
    02670                 (htcaploc->ht_capa_info & MAC_HTCAPA_LDPC) &&
    02671                 (htcap->ht_capa_info & MAC_HTCAPA_LDPC))
    02672             {
    02673                 phy_cntrl_info1 |= FEC_CODING_PT_BIT;
    02674             }
    02675             if (htcap->ht_capa_info & MAC_HTCAPA_AMSDU)
    02676             {
    02677                 #if NX_AMPDU_TX
    02678                 rc_ss->max_amsdu_len = 4095 - max_mpdu_head_tail;
    02679                 #else
    02680                 rc_ss->max_amsdu_len = 7935;
    02681                 #endif
    02682             }
    02683             else
    02684             {
    02685                 rc_ss->max_amsdu_len = 3839;
    02686             }
    02687         }
    02688         // bandwidth
    02689         rc_ss->bw_max = sta->info.bw_cur;
    02690         ASSERT_ERR(rc_ss->bw_max <= BW_160MHZ);
    02691         // guard interval
    02692         switch(sta->info.bw_cur)
    02693         {
    02694             case BW_20MHZ:
    02695                 if (htcap->ht_capa_info & MAC_HTCAPA_SHORTGI_20)
    02696                     rc_ss->short_gi = 1;
    02697                 break;
    02698             case BW_40MHZ:
    02699                 if (htcap->ht_capa_info & MAC_HTCAPA_SHORTGI_40)
    02700                     rc_ss->short_gi = 1;
    02701                 break;
    02702             #if NX_VHT
    02703             case BW_80MHZ:
    02704                 if (sta->info.vht_cap.vht_capa_info & MAC_VHTCAPA_SHORT_GI_80)
    02705                     rc_ss->short_gi = 1;
    02706                 break;
    02707             case BW_160MHZ:
    02708                 if (sta->info.vht_cap.vht_capa_info & MAC_VHTCAPA_SHORT_GI_160)
    02709                     rc_ss->short_gi = 1;
    02710                 break;
    02711             #endif
    02712             default:
    02713                 break;
    02714         }
    02715     }
    02716     else
    02717     {
    02718         // set the bitmap for legacy rates
    02719         rc_ss->rate_map_l = me_legacy_rate_bitfield_build(&sta->info.rate_set, false);
    02720         rc_ss->r_idx_min = me_legacy_ridx_min(rc_ss->rate_map_l);
    02721         ASSERT_ERR(rc_ss->r_idx_min < MAC_RATESET_LEN);
    02722         rc_ss->r_idx_max = me_legacy_ridx_max(rc_ss->rate_map_l);
    02723         ASSERT_ERR(rc_ss->r_idx_max < MAC_RATESET_LEN);
    02724         rc_ss->mcs_max = 0xFF;
    02725         rc_ss->bw_max = sta->info.bw_cur;
    02726         ASSERT_ERR(rc_ss->bw_max == BW_20MHZ);
    02727         // preamble type: 0=short and long, 1=only long
    02728         rc_ss->type = (rc->ppdu_tx_cfg & PRE_TYPE_TX_RCX_MASK) >> PRE_TYPE_TX_RCX_OFT;
    02729     }
    02730     // Set number of samples for statistics
    02731     rc_ss->no_samples = rc_get_num_samples(rc_ss);
    02732     ASSERT_ERR(rc_ss->no_samples >= 1);
    02733     ASSERT_ERR(rc_ss->no_samples <= RC_MAX_N_SAMPLE);
    02734
    02735     dbg(D_CRT "%s: station_id=%i format_mod=%i pre_type=%i short_gi=%i max_bw=%i\n",
    02736             __func__, sta->staid, rc_ss->format_mod, rc_ss->type, rc_ss->short_gi, rc_ss->bw_max);
    02737     dbg(D_CRT "%s: nss_max=%i mcs_max=%i r_idx_min=%i r_idx_max=%i no_samples=%i\n",
    02738             __func__, rc_ss->no_ss, rc_ss->mcs_max, rc_ss->r_idx_min, rc_ss->r_idx_max, rc_ss->no_samples);
    02739
    02740     // Init RC algorithm
    02741     rc_init_rates(sta->staid);
    02742
    02743     // Set current rate configuration
    02744     for (i = 0; i < RATE_CONTROL_STEPS; i++)
    02745     {
    02746         uint8_t idx = rc_ss->retry_step_idx[i];
    02747         pol->ratecntrlinfo[i] =
    02748             (RC_MAX_NUM_RETRY << N_RETRY_RCX_OFT) | rc_ss->rate_stats[idx].rate_config;
    02749     }
    02750
    02751     #if NX_AMSDU_TX
    02752     // Set maximum AMSDU len
    02753     rc_set_max_amsdu_len(rc_ss);
    02754     #endif
    02755     #if NX_AMPDU_TX
    02756     rc_set_aggregation_flag(rc_ss, NULL);
    02757     #endif
    02758
    02759     // Init last_rc_time
    02760     rc_ss->last_rc_time = hal_machw_time();
    02761
    02762     pol->upatterntx    = POLICY_TABLE_PATTERN;
    02763     pol->maccntrlinfo1 = hw_key_idx << KEYSRAM_INDEX_RA_OFT;
    02764     pol->maccntrlinfo2 = 0xFFFF0704;
    02765     pol->phycntrlinfo1 = phy_cntrl_info1;
    02766     pol->phycntrlinfo2 = phy_cntrl_info2;
    02767     #if RW_BFMER_EN
    02768     if (bfr_is_enabled())
    02769     {
    02770         /*
    02771          * If frame is not beamformed, the SMM Index field indicates the spatial mapping in the
    02772          * modem.
    02773          *      0 = Stream 0 on antenna 0 and stream 1 on antenna 1
    02774          *      2 = Stream mixed on antenna 0 and antenna 1
    02775          */
    02776         pol->phycntrlinfo2 |= 2 << SMM_INDEX_PT_OFT;
    02777     }
    02778     #endif
    02779     rc->buf_ctrl->mac_control_info = EXPECTED_ACK_NORMAL_ACK | LOW_RATE_RETRY;
    02780     rc->buf_ctrl->phy_control_info = sta->paid_gid;
    02781
    02782     // Set update rate flag
    02783     rc->upd_field |= CO_BIT(STA_MGMT_POL_UPD_RATE) | CO_BIT(STA_MGMT_POL_UPD_TX_POWER);
    02784 }
    02785
    02786
    02787 uint32_t rc_get_duration(struct rc_rate_stats *rate_stats)
    02788 {
    02789     uint32_t duration = 0;
    02790     uint32_t idx;
    02791     uint16_t rate_config = rate_stats->rate_config;
    02792     uint8_t format_mod = rc_get_format_mod(rate_config);
    02793     uint8_t mcs = rc_get_mcs_index(rate_config);
    02794
    02795     switch (format_mod)
    02796     {
    02797         case FORMATMOD_NON_HT:
    02798         case FORMATMOD_NON_HT_DUP_OFDM:
    02799         {
    02800             if (mcs < HW_RATE_6MBPS)
    02801             {
    02802                 uint8_t pre_type = rc_get_pre_type(rate_config);
    02803                 idx = (uint32_t)(mcs << 1) | pre_type;
    02804                 duration = rc_duration_cck[idx];
    02805             }
    02806             else
    02807             {
    02808                 idx = (mcs - HW_RATE_6MBPS);
    02809                 duration = rc_duration_non_ht[idx];
    02810             }
    02811         } break;
    02812
    02813         case FORMATMOD_HT_MF:
    02814         case FORMATMOD_HT_GF:
    02815         #if NX_VHT
    02816         case FORMATMOD_VHT:
    02817         #endif
    02818         {
    02819             uint8_t bw = rc_get_bw(rate_config);
    02820             uint8_t gi = rc_get_sgi(rate_config);
    02821             idx = (mcs << 3) | (bw << 1) | gi;
    02822             duration = rc_duration_ht_ampdu[idx] / (rc_get_nss(rate_config) + 1);
    02823         } break;
    02824
    02825         #if NX_HE
    02826         case FORMATMOD_HE_MU:
    02827         {
    02828             uint8_t ru_size = rate_stats->ru_and_length & 0x07;
    02829             if (ru_size < 3)
    02830             {
    02831                 duration = rc_ru_duration[ru_size][mcs * 3 + rc_get_he_gi(rate_config)] /
    02832                                                            (rc_get_nss(rate_config) + 1);
    02833             }
    02834             else
    02835             {
    02836                 uint8_t bw = ru_size - 3;
    02837                 uint8_t gi = rc_get_he_gi(rate_config);
    02838                 int shift = bw & 0x01;
    02839                 idx = (mcs * 6) + ((bw >> 1) * 3) + gi;
    02840                 duration = (rc_duration_he_ampdu[idx] >> shift)  / (rc_get_nss(rate_config) + 1);
    02841             }
    02842         } break;
    02843
    02844         case FORMATMOD_HE_SU:
    02845         {
    02846             uint8_t bw = rc_get_bw(rate_config);
    02847             uint8_t gi = rc_get_he_gi(rate_config);
    02848             int shift = bw & 0x01;
    02849             idx = (mcs * 6) + ((bw >> 1) * 3) + gi;
    02850             duration = (rc_duration_he_ampdu[idx] >> shift)  / (rc_get_nss(rate_config) + 1);
    02851         } break;
    02852         #endif
    02853
    02854         default:
    02855             break;
    02856     }
    02857
    02858     return duration;
    02859 }
    02860
    02861 void rc_update_sample_table(uint8_t sta_idx)
    02862 {
    02863     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    02864     struct sta_pol_tbl_cntl *rc = &sta->pol_tbl;
    02865     struct rc_sta_stats *rc_ss = rc->sta_stats;
    02866     uint32_t cur_tp[RC_MAX_N_SAMPLE];
    02867     ASSERT_ERR(rc_ss != NULL);
    02868
    02869     // Update number of samples
    02870     rc_ss->no_samples = rc_get_num_samples(rc_ss);
    02871     ASSERT_ERR(rc_ss->no_samples >= 1);
    02872     ASSERT_ERR(rc_ss->no_samples <= RC_MAX_N_SAMPLE);
    02873
    02874     // Select new random rates for the stats table
    02875     rc_set_rate_configs(rc_ss);
    02876
    02877     // Update the retry chain with: max TP, 2nd max TP, max probability, lowest rate
    02878     rc_update_retry_chain(rc_ss, cur_tp);
    02879
    02880     #if NX_AMSDU_TX
    02881     // Set maximum AMSDU len
    02882     rc_set_max_amsdu_len(rc_ss);
    02883     #endif
    02884     #if NX_AMPDU_TX
    02885     rc_set_aggregation_flag(rc_ss, NULL);
    02886     #endif
    02887     // Keep in mind we have to update the rate
    02888     rc->upd_field |= CO_BIT(STA_MGMT_POL_UPD_RATE);
    02889 }
    02890
    02891 void rc_update_bw_nss_max(uint8_t sta_idx, uint8_t bw_max, uint8_t nss_max)
    02892 {
    02893     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    02894     struct sta_pol_tbl_cntl *rc = &sta->pol_tbl;
    02895     struct rc_sta_stats *rc_ss = rc->sta_stats;
    02896     ASSERT_ERR(rc_ss != NULL);
    02897
    02898     if ((bw_max == rc_ss->bw_max) && (nss_max == rc_ss->no_ss))
    02899         return;
    02900
    02901     rc_ss->bw_max = bw_max;
    02902     ASSERT_ERR(rc_ss->bw_max <= BW_160MHZ);
    02903     rc_ss->no_ss = nss_max;
    02904     ASSERT_ERR(rc_ss->no_ss < 8);
    02905
    02906     // If fixed rate is set, do not update the sample table
    02907     if (rc_ss->info & RC_FIX_RATE_EN_MASK)
    02908     {
    02909         // keep in mind that we need to update the sample table after the fixed rate time
    02910         rc_ss->info |= RC_FIX_RATE_UPD_SS_REQ_MASK;
    02911         return;
    02912     }
    02913
    02914     // Update sample table according with new bw and nss
    02915     rc_update_sample_table(sta_idx);
    02916
    02917 }
    02918
    02919 void rc_update_preamble_type(uint8_t sta_idx, uint8_t preamble_type)
    02920 {
    02921     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    02922     struct sta_pol_tbl_cntl *rc = &sta->pol_tbl;
    02923     struct rc_sta_stats *rc_ss = rc->sta_stats;
    02924     uint16_t i = 0;
    02925     uint32_t cur_tp[RC_MAX_N_SAMPLE];
    02926     ASSERT_ERR(rc_ss != NULL);
    02927
    02928     if (rc_ss->type == preamble_type)
    02929         return;
    02930
    02931     // Save preamble type
    02932     rc_ss->type = preamble_type;
    02933
    02934     // Do changes to the rate only if we move to long preamble
    02935     if (!preamble_type)
    02936         return;
    02937
    02938     // If fixed rate is set, do not update the sample table
    02939     if (rc_ss->info & RC_FIX_RATE_EN_MASK)
    02940     {
    02941         // keep in mind that we need to update the sample table after the fixed rate time
    02942         rc_ss->info |= RC_FIX_RATE_UPD_SS_REQ_MASK;
    02943         return;
    02944     }
    02945
    02946     for (i = 0; i < rc_ss->no_samples; i++)
    02947     {
    02948         struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[i];
    02949         uint16_t rate_cfg = rc_rs->rate_config;
    02950
    02951         // Check if the rate is a CCK one
    02952         if (is_cck_group(rc_rs->rate_config))
    02953         {
    02954             // Set long preamble
    02955             rate_cfg |= PRE_TYPE_TX_RCX_MASK;
    02956
    02957             while (rc_check_rate_duplicated(rc_ss, rate_cfg))
    02958             {
    02959                 rate_cfg = rc_new_random_rate(rc_ss);
    02960             }
    02961         }
    02962
    02963         rc_rs->rate_allowed = 1;
    02964         rc_rs->rate_config = rate_cfg;
    02965         rc_rs->probability = 0;
    02966         rc_rs->old_prob_available = 0;
    02967         cur_tp[i] = 0;
    02968     }
    02969
    02970     // Sort sample table by TP
    02971     rc_sort_samples_tp(rc_ss, cur_tp);
    02972     // Update the retry chain with: max TP, 2nd max TP, max probability, lowest rate
    02973     rc_update_retry_chain(rc_ss, cur_tp);
    02974
    02975     #if NX_AMSDU_TX
    02976     // Set maximum AMSDU len
    02977     rc_set_max_amsdu_len(rc_ss);
    02978     #endif
    02979     // Keep in mind we have to update the rate
    02980     rc->upd_field |= CO_BIT(STA_MGMT_POL_UPD_RATE);
    02981 }
    02982
    02983 void rc_init_bcmc_rate(struct sta_info_tag *sta, uint8_t basic_rate_idx)
    02984 {
    02985     struct sta_pol_tbl_cntl *rc = &sta->pol_tbl;
    02986     struct tx_policy_tbl *pol = &rc->buf_ctrl->policy_tbl;
    02987     uint8_t i;
    02988     uint16_t rate_config;
    02989     uint8_t type = (rc->ppdu_tx_cfg & PRE_TYPE_TX_RCX_MASK) >> PRE_TYPE_TX_RCX_OFT;
    02990     // Set rate configuration
    02991     rate_config = ((basic_rate_idx < HW_RATE_6MBPS ? type : 0) << PRE_TYPE_TX_RCX_OFT) |
    02992                   (basic_rate_idx << MCS_INDEX_TX_RCX_OFT);
    02993     // Set the basic rate idx for all the steps of the retry chain
    02994     for (i = 0; i < RATE_CONTROL_STEPS; i++)
    02995     {
    02996         pol->ratecntrlinfo[i] = (1 << N_RETRY_RCX_OFT) | rate_config;
    02997     }
    02998 }
    02999
    03000 bool rc_check_fixed_rate_config(struct rc_sta_stats *rc_ss, uint16_t fixed_rate_config)
    03001 {
    03002     uint8_t fixed_rate_ft = rc_get_format_mod(fixed_rate_config);
    03003     bool update = 0;
    03004
    03005     do
    03006     {
    03007         // Check format and modulation
    03008         if (fixed_rate_ft > rc_ss->format_mod)
    03009         {
    03010             break;
    03011         }
    03012         if ((rc_ss->format_mod == FORMATMOD_HE_SU) && (fixed_rate_ft != FORMATMOD_HE_SU)
    03013          && (rc_ss->r_idx_min > HW_RATE_11MBPS))
    03014         {
    03015             break;
    03016         }
    03017         if ((rc_ss->format_mod == FORMATMOD_VHT) && (fixed_rate_ft != FORMATMOD_VHT))
    03018         {
    03019             break;
    03020         }
    03021         if (((rc_ss->format_mod == FORMATMOD_HT_MF) || (rc_ss->format_mod == FORMATMOD_HT_GF)) &&
    03022             ((fixed_rate_ft < FORMATMOD_HT_MF) && (rc_ss->r_idx_min > HW_RATE_11MBPS)))
    03023         {
    03024             break;
    03025         }
    03026         if (fixed_rate_ft < FORMATMOD_HT_MF)
    03027         {
    03028             // Check preamble type
    03029             if ((rc_get_pre_type(fixed_rate_config) == 0) && (rc_ss->type == 1))
    03030             {
    03031                 break;
    03032             }
    03033         }
    03034         else
    03035         {
    03036             // Check guard interval
    03037             if (fixed_rate_ft < FORMATMOD_HE_SU)
    03038             {
    03039                 if ((rc_get_sgi(fixed_rate_config) == 1) && (rc_ss->short_gi == 0))
    03040                 {
    03041                     break;
    03042                 }
    03043             }
    03044             // Check bandwidth
    03045             if (rc_get_bw(fixed_rate_config) > rc_ss->bw_max)
    03046             {
    03047                 break;
    03048             }
    03049             // Check number of spatial streams
    03050             if (rc_get_nss(fixed_rate_config) > rc_ss->no_ss)
    03051             {
    03052                 break;
    03053             }
    03054         }
    03055         // Check MCS / rate index
    03056         if (rc_check_valid_rate(rc_ss, fixed_rate_config) == 0)
    03057         {
    03058             break;
    03059         }
    03060
    03061         update = 1;
    03062
    03063     } while (0);
    03064
    03065     return update;
    03066 }
    03067
    03068 uint32_t rc_calc_tp(struct rc_sta_stats *rc_ss, uint8_t sample_idx)
    03069 {
    03070     uint64_t cur_tp;
    03071     uint32_t nsecs = 0;
    03072
    03073     struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[sample_idx];
    03074     uint16_t rate_config = rc_rs->rate_config;
    03075     uint32_t prob = rc_rs->probability;
    03076     uint16_t avg_ampdu = RC_TRUNC(rc_ss->avg_ampdu_len);
    03077
    03078     if (prob < RC_FRAC(1, 10))
    03079     {
    03080         cur_tp = 0;
    03081     }
    03082     else
    03083     {
    03084         if (!is_cck_group(rate_config))
    03085         {
    03086             // By default use fixed overhead time of 60 usec (ack) + 48 usec + backoff
    03087             uint32_t overhead = 218;
    03088             if (rc_get_format_mod(rate_config) == FORMATMOD_HE_MU)
    03089                 // In HE TB we add also the overhead of the trigger frame reception
    03090                 overhead = 330;
    03091
    03092             nsecs = 1000 * overhead / avg_ampdu;
    03093         }
    03094         nsecs += rc_get_duration(rc_rs);
    03095
    03096         // Compute the expected user data throughput (i.e. the one that would be reported
    03097         // by iperf when sending a UDP stream) based on the rate on transmission
    03098         // and its probability of success
    03099         cur_tp = 910000 * ((prob * 1000) / nsecs);
    03100         cur_tp = RC_TRUNC(cur_tp);
    03101     }
    03102
    03103     return cur_tp;
    03104 }
    03105
    03106 void rc_trial_check_bfm_stbc_htc(struct txl_buffer_control *buf_ctrl, uint32_t trial_rate,
    03107                                  bool can_use_bfm, bool use_stbc, uint8_t stbc_nss,
    03108                                  uint8_t nc, uint8_t ntx, bool can_use_htc)
    03109 {
    03110     uint8_t nss = 0;
    03111     uint32_t trial_config = trial_rate &
    03112                           (MCS_INDEX_TX_RCX_MASK | BW_TX_RCX_MASK |
    03113                            SHORT_GI_TX_RCX_MASK | PRE_TYPE_TX_RCX_MASK |
    03114                            FORMAT_MOD_TX_RCX_MASK);
    03115     uint32_t format = (trial_config & FORMAT_MOD_TX_RCX_MASK) >>
    03116                         FORMAT_MOD_TX_RCX_OFT;
    03117
    03118     // Get the number of SS of this frame
    03119     if (format >= FORMATMOD_HT_MF)
    03120     {
    03121         uint32_t mcs_idx = (trial_config & MCS_INDEX_TX_RCX_MASK) >>
    03122                             MCS_INDEX_TX_RCX_OFT;
    03123         #if NX_VHT
    03124         if (format == FORMATMOD_VHT)
    03125         {
    03126             // Extract NSS
    03127             nss = (mcs_idx & VHT_NSS_MASK) >> VHT_NSS_OFT;
    03128         }
    03129         else
    03130         #endif
    03131         {
    03132             // Extract NSS
    03133             nss = (mcs_idx & HT_NSS_MASK) >> HT_NSS_OFT;
    03134         }
    03135
    03136         // Check if we can use STBC for this rate
    03137         if (use_stbc && (nss == stbc_nss))
    03138         {
    03139             buf_ctrl->tx_flags |= TX_SWDESC_UMAC_TRIAL_STBC_BIT;
    03140         }
    03141         else
    03142         {
    03143             buf_ctrl->tx_flags &= ~TX_SWDESC_UMAC_TRIAL_STBC_BIT;
    03144         }
    03145
    03146         // Check if beamforming can be use with this policy table
    03147         #if RW_BFMER_EN
    03148         if (can_use_bfm)
    03149         {
    03150             if ((format != FORMATMOD_VHT) || (nss > nc) || (nss == ntx))
    03151             {
    03152                 can_use_bfm = false;
    03153             }
    03154         }
    03155         #endif //(RW_BFMER_EN)
    03156     }
    03157     else
    03158     {
    03159         #if RW_BFMER_EN
    03160         can_use_bfm = false;
    03161         #endif
    03162         #if NX_HE
    03163         can_use_htc = false;
    03164         #endif
    03165     }
    03166
    03167     #if RW_BFMER_EN
    03168     // Allow/Disallow Beamforming
    03169     if (can_use_bfm)
    03170     {
    03171         buf_ctrl->tx_flags |= TX_SWDESC_UMAC_TRIAL_BEAMFORM_BIT;
    03172     }
    03173     else
    03174     {
    03175         buf_ctrl->tx_flags &= ~TX_SWDESC_UMAC_TRIAL_BEAMFORM_BIT;
    03176     }
    03177     #endif
    03178
    03179     #if NX_HE
    03180     // Allow/Disallow +HTC
    03181     if (can_use_htc)
    03182         buf_ctrl->tx_flags |= TX_SWDESC_UMAC_TRIAL_HTC_BIT;
    03183     else
    03184         buf_ctrl->tx_flags &= ~TX_SWDESC_UMAC_TRIAL_HTC_BIT;
    03185     #endif
    03186 }
    03187
    03189