- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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

Go to the documentation of this file.

    00001
    00013 /*
    00014  * INCLUDE FILES
    00015  ****************************************************************************************
    00016  */
    00017 #include "me_utils.h"
    00018 #include "co_math.h"
    00019 #include "sta_mgmt.h"
    00020 #include "vif_mgmt.h"
    00021 #include "mac_ie.h"
    00022 #include "hal_desc.h"
    00023 #include "mac_frame.h"
    00024 #include "me.h"
    00025 #include "mm.h"
    00026 #include "rc.h"
    00027 #include "me_mgmtframe.h"
    00028 #include "tpc.h"
    00029 #include "txl_cfm.h"
    00030 #include "txl_he.h"
    00031 #if (RW_BFMER_EN)
    00032 #include "bfr.h"
    00033 #endif //(RW_BFMER_EN)
    00034
    00035 /*
    00036  * DEFINES
    00037  ****************************************************************************************
    00038  */
    00039 #if NX_HE
    00041 #define ME_BSS_COLOR_MSK (MAC_HE_OPER_BSS_COLOR_DISABLED_BIT |                           \
    00042                           MAC_HE_OPER_BSS_COLOR_PARTIAL_BIT | MAC_HE_OPER_BSS_COLOR_MASK)
    00043 #endif
    00044
    00045 /*
    00046  * FUNCTION IMPLEMENTATION
    00047  ****************************************************************************************
    00048  */
    00059 static void me_chan_ctxt_update(struct vif_info_tag *vif)
    00060 {
    00061     struct me_bss_info *bss = &vif->bss_info;
    00062     struct mm_chan_ctxt_update_req *req = KE_MSG_ALLOC(MM_CHAN_CTXT_UPDATE_REQ, TASK_MM,
    00063                                                        TASK_ME, mm_chan_ctxt_update_req);
    00064
    00065     // Sanity check - We shall have a channel context assigned when this procedure is
    00066     // executed
    00067     ASSERT_ERR(vif->chan_ctxt != NULL);
    00068
    00069     // Fill-in the channel context addition request
    00070     req->chan_index = vif->chan_ctxt->idx;
    00071     req->chan = bss->chan;
    00072
    00073     // Send the message
    00074     ke_msg_send(req);
    00075 }
    00076
    00077 bool me_set_sta_ht_vht_param(struct sta_info_tag *sta, struct me_bss_info *bss)
    00078 {
    00079     struct sta_capa_info *info = &sta->info;
    00080
    00081     uint8_t local_supp_bw = me_env.phy_bw_max;
    00082     uint8_t peer_supp_bw = PHY_CHNL_BW_20;
    00083     uint8_t local_stbc_nss = me_env.stbc_nss;
    00084     uint8_t peer_stbc_nss;
    00085     bool smps = false;
    00086
    00087     #if NX_HE
    00088     if (STA_CAPA(sta, HE))
    00089     {
    00090         uint8_t chan_width_set = HE_PHY_CAPA_VAL_GET(&info->he_cap, CHAN_WIDTH_SET);
    00091         bool stbc_rx_under_80 = HE_PHY_CAPA_BIT_IS_SET(&info->he_cap, STBC_RX_UNDER_80MHZ);
    00092         bool stbc_rx_above_80 = HE_PHY_CAPA_BIT_IS_SET(&info->he_cap, STBC_RX_ABOVE_80MHZ);
    00093
    00094         // Check the peer supported BW
    00095         if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_80PLUS80_MHZ_IN_5G)
    00096             peer_supp_bw = PHY_CHNL_BW_80P80;
    00097         else if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_160MHZ_IN_5G)
    00098             peer_supp_bw = PHY_CHNL_BW_160;
    00099         else if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_40MHZ_80MHZ_IN_5G)
    00100             peer_supp_bw = PHY_CHNL_BW_80;
    00101         else if (chan_width_set & HE_PHY_CAPA_CHAN_WIDTH_SET_40MHZ_IN_2G)
    00102             peer_supp_bw = PHY_CHNL_BW_40;
    00103
    00104         if (peer_supp_bw > PHY_CHNL_BW_80)
    00105             peer_stbc_nss = stbc_rx_under_80 & stbc_rx_above_80 ? 1 : 0;
    00106         else
    00107             peer_stbc_nss = stbc_rx_under_80 ? 1 : 0;
    00108
    00109         local_stbc_nss = me_env.he_stbc_nss;
    00110     }
    00111     else
    00112     #endif
    00113     #if NX_VHT
    00114     if (STA_CAPA(sta, VHT))
    00115     {
    00116         // Check the peer supported BW
    00117         switch (info->vht_cap.vht_capa_info & MAC_VHTCAPA_SUPP_CHAN_WIDTH_MSK)
    00118         {
    00119             case MAC_VHTCAPA_SUPP_CHAN_WIDTH_160:
    00120                 peer_supp_bw = PHY_CHNL_BW_160;
    00121                 break;
    00122             case MAC_VHTCAPA_SUPP_CHAN_WIDTH_160_80P80:
    00123                 peer_supp_bw = PHY_CHNL_BW_80P80;
    00124                 break;
    00125             default:
    00126                 peer_supp_bw = PHY_CHNL_BW_80;
    00127                 break;
    00128         }
    00129         peer_stbc_nss = (info->vht_cap.vht_capa_info & MAC_VHTCAPA_RXSTBC_MSK) >>
    00130                                                         MAC_VHTCAPA_RXSTBC_OFT;
    00131         peer_stbc_nss = (peer_stbc_nss <= 4) ? peer_stbc_nss : 0;
    00132     }
    00133     else
    00134     #endif
    00135     {
    00136         peer_stbc_nss = (info->ht_cap.ht_capa_info & MAC_HTCAPA_RX_STBC_MSK) >>
    00137                                                         MAC_HTCAPA_RX_STBC_OFT;
    00138
    00139         if (info->ht_cap.ht_capa_info & MAC_HTCAPA_40_MHZ)
    00140             peer_supp_bw = PHY_CHNL_BW_40;
    00141     }
    00142
    00143     info->phy_bw_max = co_min(peer_supp_bw, local_supp_bw);
    00144     info->bw_cur = me_phy2mac_bw(me_get_sta_bw(info->phy_bw_max, bss->chan.type));
    00145     info->stbc_nss = co_min(peer_stbc_nss, local_stbc_nss);
    00146
    00147     if ((info->ht_cap.ht_capa_info & MAC_HTCAPA_SMPS_MSK) !=
    00148                                            MAC_HTCAPA_SMPS_DISABLE)
    00149         smps = true;
    00150
    00151     return (smps);
    00152 }
    00153
    00154 uint8_t me_11ac_mcs_max(uint16_t mcs_map)
    00155 {
    00156     uint8_t mcs_max;
    00157
    00158     switch (mcs_map & MAC_VHT_MCS_MAP_MSK)
    00159     {
    00160         case MAC_VHT_MCS_MAP_0_7:
    00161             mcs_max = 7;
    00162             break;
    00163         case MAC_VHT_MCS_MAP_0_8:
    00164             mcs_max = 8;
    00165             break;
    00166         case MAC_VHT_MCS_MAP_0_9:
    00167             mcs_max = 9;
    00168             break;
    00169         default:
    00170             mcs_max = 7;
    00171             break;
    00172     }
    00173
    00174     return(mcs_max);
    00175 }
    00176
    00177 uint8_t me_11ax_mcs_max(uint16_t mcs_map)
    00178 {
    00179     uint8_t mcs_max;
    00180
    00181     switch (mcs_map & MAC_HE_MCS_MAP_MSK)
    00182     {
    00183         case MAC_HE_MCS_MAP_0_7:
    00184             mcs_max = 7;
    00185             break;
    00186         case MAC_HE_MCS_MAP_0_9:
    00187             mcs_max = 9;
    00188             break;
    00189         case MAC_HE_MCS_MAP_0_11:
    00190             mcs_max = 11;
    00191             break;
    00192         default:
    00193             mcs_max = 7;
    00194             break;
    00195     }
    00196
    00197     return(mcs_max);
    00198 }
    00199
    00200 uint8_t me_11ac_nss_max(uint16_t mcs_map)
    00201 {
    00202     uint8_t nss_max;
    00203
    00204     // Go through the MCS map to check how many SS are supported
    00205     for (nss_max = 7; nss_max > 0; nss_max--)
    00206     {
    00207         if (((mcs_map >> (2 * nss_max)) & MAC_VHT_MCS_MAP_MSK) != MAC_VHT_MCS_MAP_NONE)
    00208             break;
    00209     }
    00210
    00211     return(nss_max);
    00212 }
    00213
    00214 uint8_t me_11n_nss_max(uint8_t *mcs_set)
    00215 {
    00216     uint8_t nss_max;
    00217
    00218     // Go through the MCS map to check how many SS are supported
    00219     for (nss_max = 3; nss_max > 0; nss_max--)
    00220     {
    00221         if (mcs_set[nss_max] != 0)
    00222             break;
    00223     }
    00224
    00225     return(nss_max);
    00226 }
    00227
    00228 uint8_t me_legacy_ridx_min(uint16_t rate_map)
    00229 {
    00230     uint8_t i;
    00231
    00232     for (i = 0; i < MAC_RATESET_LEN; i++)
    00233     {
    00234         if (rate_map & (1 << i))
    00235         {
    00236             break;
    00237         }
    00238     }
    00239
    00240     return i;
    00241 }
    00242
    00243 uint8_t me_legacy_ridx_max(uint16_t rate_map)
    00244 {
    00245     uint8_t i;
    00246     uint8_t mcs_max;
    00247
    00248     if (rate_map != 0 )
    00249     {
    00250         for (i = 0; i < MAC_RATESET_LEN; i++)
    00251         {
    00252             if (rate_map & (1 << (HW_RATE_54MBPS - i)))
    00253             {
    00254                 break;
    00255             }
    00256         }
    00257         mcs_max = HW_RATE_54MBPS - i;
    00258     }
    00259     else
    00260     {
    00261         mcs_max = MAC_RATESET_LEN;
    00262     }
    00263
    00264     return mcs_max;
    00265 }
    00266
    00267 void me_get_ampdu_params(struct mac_htcapability const *ht_cap,
    00268                          struct mac_vhtcapability const *vht_cap,
    00269                          struct mac_hecapability const *he_cap,
    00270                          uint16_t *ampdu_size_max_ht,
    00271                          uint32_t *ampdu_size_max_vht,
    00272                          uint32_t *ampdu_size_max_he,
    00273                          uint8_t *ampdu_spacing_min)
    00274 {
    00275     *ampdu_size_max_ht = 0;
    00276     *ampdu_size_max_vht = 0;
    00277     *ampdu_size_max_he = 0;
    00278
    00279     if (ht_cap)
    00280     {
    00281         #if NX_VHT
    00282         int vht_exp = 0;
    00283         #endif
    00284         int ht_exp = (ht_cap->a_mpdu_param & MAC_AMPDU_LEN_EXP_MSK) >>
    00285                                                                MAC_AMPDU_LEN_EXP_OFT;
    00286         int min_spc = (ht_cap->a_mpdu_param & MAC_AMPDU_MIN_SPACING_MSK) >>
    00287                                                             MAC_AMPDU_MIN_SPACING_OFT;
    00288         *ampdu_spacing_min = (min_spc < 3)?1:(0x01 << (min_spc - 3));
    00289         *ampdu_size_max_ht = (1 << (MAC_HT_MAX_AMPDU_FACTOR + ht_exp)) - 1;
    00290
    00291         #if NX_VHT
    00292         if (vht_cap)
    00293         {
    00294             vht_exp = (vht_cap->vht_capa_info & MAC_VHTCAPA_MAX_A_MPDU_LENGTH_EXP_MSK) >>
    00295                                                     MAC_VHTCAPA_MAX_A_MPDU_LENGTH_EXP_OFT;
    00296             *ampdu_size_max_vht = (1 << (MAC_HT_MAX_AMPDU_FACTOR + vht_exp)) - 1;
    00297         }
    00298         #endif
    00299
    00300         #if NX_HE
    00301         if (he_cap)
    00302         {
    00303             int he_exp_ext = HE_MAC_CAPA_VAL_GET(he_cap, MAX_A_AMPDU_LEN_EXP);
    00304             if (vht_cap)
    00305             {
    00306                 if (vht_exp == 7)
    00307                     *ampdu_size_max_he = (1 << (MAC_HT_MAX_AMPDU_FACTOR
    00308                                                          + 7 + he_exp_ext)) - 1;
    00309                 else
    00310                     *ampdu_size_max_he = *ampdu_size_max_vht;
    00311             }
    00312             else
    00313             {
    00314                 if (ht_exp == 3)
    00315                     *ampdu_size_max_he = (1 << (MAC_HT_MAX_AMPDU_FACTOR
    00316                                                          + 3 + he_exp_ext)) - 1;
    00317                 else
    00318                     *ampdu_size_max_he = *ampdu_size_max_ht;
    00319             }
    00320         }
    00321         #endif
    00322     }
    00323 }
    00324
    00333 static void me_erp_prot_check(uint32_t erp_addr, uint16_t *prot_status)
    00334 {
    00335     /*
    00336      * Extract received ERP parameters field value
    00337      *      Bit 0 - NonERP Present
    00338      *      Bit 1 - Use Protection
    00339      *      Bit 2 - Barker Preamble Mode
    00340      */
    00341     uint8_t erp_val = co_read8p(erp_addr + MAC_ERP_PARAM_OFT);
    00342
    00343     // Clear current ERP Protection status
    00344     *prot_status &= ~MAC_PROT_ERP_STATUS_MASK;
    00345
    00346     if (erp_val & MAC_ERP_NON_ERP_PRESENT)
    00347     {
    00348         // Non_ERP STA present
    00349         *prot_status |= MAC_PROT_NONERP_PRESENT_BIT;
    00350     }
    00351
    00352     if (erp_val & MAC_ERP_USE_PROTECTION)
    00353     {
    00354         // Use protection
    00355         *prot_status |= MAC_PROT_USE_PROTECTION_BIT;
    00356     }
    00357
    00358     if (erp_val & MAC_ERP_BARKER_PREAMBLE_MODE)
    00359     {
    00360         // Barker Preamble Mode
    00361         *prot_status |= MAC_PROT_BARKER_PREAMB_BIT;
    00362     }
    00363 }
    00364
    00373 static void me_pol_tbl_prot_upd(struct sta_info_tag *sta, uint16_t prot_status)
    00374 {
    00375     // Policy Table Info
    00376     struct sta_pol_tbl_cntl *pol_tbl = &sta->pol_tbl;
    00377     // VIF Interface
    00378     struct vif_info_tag *vif;
    00379
    00380     // Reset Protection Configuration in the policy table info structure
    00381     pol_tbl->prot_cfg = 0;
    00382
    00383     // Require update of protection configuration field in policy table
    00384     pol_tbl->upd_field |= CO_BIT(STA_MGMT_POL_UPD_PROT);
    00385
    00386     /*
    00387      ***********************************************************************
    00388      * NAV Protection Frame Exchange
    00389      *      If Protection has to be enabled, CTS-to-self mechanism is used
    00390      *      Protection will be enabled in following case:
    00391      *          - ERP element's Use Protection Bit set to 1 (11b protection)
    00392      ***********************************************************************
    00393      */
    00394     if (prot_status & MAC_PROT_USE_PROTECTION_BIT)
    00395     {
    00396         // Use CTS-to-self
    00397         pol_tbl->prot_cfg |= PROT_SELF_CTS;
    00398
    00399         // Get VIF interface
    00400         vif = &vif_info_tab[sta->inst_nbr];
    00401
    00402         // 802.11b protection required, use highest 11b rate allowed by AP
    00403         pol_tbl->prot_cfg |= ((vif->bss_info.high_11b_rate) << MCS_INDEX_PROT_TX_RCX_OFT);
    00404     }
    00405
    00406     // Reset PPDU TX Configuration in the policy table info structure
    00407     pol_tbl->ppdu_tx_cfg = 0;
    00408
    00409     /*
    00410      ***********************************************************************
    00411      * Preamble Type of PPDU for Transmission
    00412      ***********************************************************************
    00413      */
    00414     if (!(prot_status & MAC_PROT_BARKER_PREAMB_BIT))
    00415     {
    00416         pol_tbl->ppdu_tx_cfg |= PRE_TYPE_TX_RCX_MASK;
    00417     }
    00418     // Update preamble type in the RC algorithm
    00419     rc_update_preamble_type(sta->staid, (pol_tbl->ppdu_tx_cfg > 0));
    00420 }
    00421
    00430 static void me_pol_tbl_bw_upd(struct sta_info_tag *sta, uint8_t new_phy_bw)
    00431 {
    00432     // Policy Table Info
    00433     struct sta_pol_tbl_cntl *pol_tbl = &sta->pol_tbl;
    00434     uint8_t new_bw = me_phy2mac_bw(me_get_sta_bw(sta->info.phy_bw_max, new_phy_bw));
    00435
    00436     // Check if the new bandwidth of BSS is compliant with the supported one
    00437     if (new_bw != sta->info.bw_cur)
    00438     {
    00439         struct sta_capa_info *info = &sta->info;
    00440         uint8_t local_supp_nss = 0;
    00441         uint8_t peer_supp_nss = 0;
    00442         uint8_t nss;
    00443
    00444         #if NX_HE
    00445         if (STA_CAPA(sta, HE))
    00446         {
    00447             ASSERT_ERR(LOCAL_CAPA(HE));
    00448
    00449             // Check the peer and local supported NSS (HE)
    00450             peer_supp_nss = me_11ac_nss_max(info->he_cap.mcs_supp.rx_mcs_80);
    00451             local_supp_nss = me_11ac_nss_max(me_env.he_cap.mcs_supp.tx_mcs_80);
    00452
    00453             nss = co_min(local_supp_nss, peer_supp_nss);
    00454         }
    00455         else
    00456         #endif
    00457         #if NX_VHT
    00458         if (STA_CAPA(sta, VHT))
    00459         {
    00460             ASSERT_ERR(LOCAL_CAPA(VHT));
    00461
    00462             // Check the peer and local supported NSS (VHT)
    00463             peer_supp_nss = me_11ac_nss_max(info->vht_cap.rx_mcs_map);
    00464             local_supp_nss = me_11ac_nss_max(me_env.vht_cap.tx_mcs_map);
    00465
    00466             nss = co_min(local_supp_nss, peer_supp_nss);
    00467         }
    00468         else
    00469         #endif
    00470         {
    00471             ASSERT_ERR(LOCAL_CAPA(HT));
    00472             // Check the peer and local supported NSS (VHT)
    00473             peer_supp_nss = me_11n_nss_max(info->ht_cap.mcs_rate);
    00474             local_supp_nss = me_11n_nss_max(me_env.ht_cap.mcs_rate);
    00475
    00476             nss = co_min(local_supp_nss, peer_supp_nss);
    00477         }
    00478         // Compute new BW
    00479         sta->info.bw_cur = new_bw;
    00480
    00481         // Update max BW allowed in the RC algorithm
    00482         rc_update_bw_nss_max(sta->staid, sta->info.bw_cur, nss);
    00483
    00484         // Require update of protection configuration field in policy table
    00485         pol_tbl->upd_field |= CO_BIT(STA_MGMT_POL_UPD_BW);
    00486     }
    00487 }
    00488
    00489 #if NX_HE
    00490
    00499 static void me_pol_tbl_bss_color_upd(struct sta_info_tag *sta)
    00500 {
    00501     if (STA_CAPA(sta, HE))
    00502     {
    00503         struct sta_pol_tbl_cntl *pol_tbl = &sta->pol_tbl;
    00504         pol_tbl->upd_field |= CO_BIT(STA_MGMT_POL_UPD_BSS_COLOR);
    00505     }
    00506 }
    00507 #endif
    00508
    00517 uint8_t me_rate_translate(uint8_t rate)
    00518 {
    00519     uint8_t hwrate = 0;
    00520
    00521     rate &= ~MAC_BASIC_RATE;
    00522     switch(rate)
    00523     {
    00524         case MAC_RATE_1MBPS:
    00525             hwrate = HW_RATE_1MBPS;
    00526             break;
    00527         case MAC_RATE_2MBPS:
    00528             hwrate = HW_RATE_2MBPS;
    00529             break;
    00530         case MAC_RATE_5_5MBPS:
    00531             hwrate = HW_RATE_5_5MBPS;
    00532             break;
    00533         case MAC_RATE_11MBPS:
    00534             hwrate = HW_RATE_11MBPS;
    00535             break;
    00536         case MAC_RATE_48MBPS:
    00537             hwrate = HW_RATE_48MBPS;
    00538             break;
    00539         case MAC_RATE_24MBPS:
    00540             hwrate = HW_RATE_24MBPS;
    00541             break;
    00542         case MAC_RATE_12MBPS:
    00543             hwrate = HW_RATE_12MBPS;
    00544             break;
    00545         case MAC_RATE_6MBPS:
    00546             hwrate = HW_RATE_6MBPS;
    00547             break;
    00548         case MAC_RATE_54MBPS:
    00549             hwrate = HW_RATE_54MBPS;
    00550             break;
    00551         case MAC_RATE_36MBPS:
    00552             hwrate = HW_RATE_36MBPS;
    00553             break;
    00554         case MAC_RATE_18MBPS:
    00555             hwrate = HW_RATE_18MBPS;
    00556             break;
    00557         case MAC_RATE_9MBPS:
    00558             hwrate = HW_RATE_9MBPS;
    00559             break;
    00560         default:
    00561             hwrate = 0xFF;
    00562     }
    00563     return(hwrate);
    00564 }
    00565
    00566 uint16_t me_legacy_rate_bitfield_build(struct mac_rateset const *rateset, bool basic_only)
    00567 {
    00568     int i;
    00569     uint16_t rates = 0;
    00570
    00571     // Build the legacy rates bitfield
    00572     for (i = 0; i < rateset->length; i++)
    00573     {
    00574         // If the current rate is not basic, then we go to the next one
    00575         if (basic_only && !(rateset->array[i] & MAC_BASIC_RATE))
    00576             continue;
    00577
    00578         // Convert the rate into an index
    00579         int bit_pos = me_rate_translate(rateset->array[i]);
    00580
    00581         // Check if the rate is consistent
    00582         ASSERT_WARN(bit_pos < MAC_RATESET_LEN);
    00583
    00584         // Set the corresponding bit in the bitfield
    00585         if (bit_pos < MAC_RATESET_LEN)
    00586         {
    00587             rates |= CO_BIT(bit_pos);
    00588         }
    00589     }
    00590
    00591     return (rates);
    00592 }
    00593
    00594 uint16_t me_rate_bitfield_vht_build(uint16_t mcs_map_1, uint16_t mcs_map_2)
    00595 {
    00596     uint8_t i;
    00597     uint16_t mcs_map = 0xFFFF;
    00598
    00599     for (i = 0; i < 8; i++)
    00600     {
    00601         uint8_t mcs_cfg_1 = (mcs_map_1 >> (i << 1)) & MAC_VHT_MCS_MAP_MSK;
    00602         uint8_t mcs_cfg_2 = (mcs_map_2 >> (i << 1)) & MAC_VHT_MCS_MAP_MSK;
    00603         if ((mcs_cfg_1 == MAC_VHT_MCS_MAP_NONE) || (mcs_cfg_2 == MAC_VHT_MCS_MAP_NONE))
    00604         {
    00605             break;
    00606         }
    00607         else
    00608         {
    00609             mcs_map &= ~(MAC_VHT_MCS_MAP_MSK << (i << 1));
    00610             mcs_map |= (co_min(mcs_cfg_1, mcs_cfg_2) & MAC_VHT_MCS_MAP_MSK) << (i << 1);
    00611         }
    00612     }
    00613
    00614     return mcs_map;
    00615 }
    00616
    00617 uint16_t me_build_capability(uint8_t vif_idx)
    00618 {
    00619     uint16_t capa_info = 0;
    00620     struct vif_info_tag *vif = &vif_info_tab[vif_idx];
    00621
    00622     capa_info |= MAC_CAPA_ESS;
    00623 //    if (vif->type == VIF_AP)
    00624 //        // add ESS
    00625 //        capa_info |= MAC_CAPA_ESS;
    00626 //    else if (vif->type == VIF_IBSS)
    00627 //        // add the IBSS mode
    00628 //        capa_info |= MAC_CAPA_IBSS;
    00629
    00630     // add Qos
    00631     //capa_info |= MAC_CAPA_QOS;
    00632
    00633     // add privacy
    00634     capa_info &= ~MAC_CAPA_PRIVA;
    00635
    00636     // Preamble
    00637     capa_info |= MAC_CAPA_SHORT_PREAMBLE;
    00638     // add slot policy
    00639     capa_info |= MAC_CAPA_SHORT_SLOT;
    00640     // add PBCC
    00641
    00642     // add channel agility
    00643
    00644     if (vif->bss_info.chan.band == PHY_BAND_5G)
    00645         capa_info |= MAC_CAPA_SPECTRUM;
    00646
    00647     // add BA
    00648     // immediate BA supported
    00649     //capa_info |= MAC_CAPA_IMMEDIATE_BA;
    00650
    00651     return capa_info;
    00652 }
    00653
    00654 #if NX_HE
    00655 uint32_t me_build_bss_color_reg(struct me_bss_info *bss)
    00656 {
    00657     uint32_t bss_color = bss->he_oper & MAC_HE_OPER_BSS_COLOR_MASK;
    00658
    00659     // Format as per BSS COLOR register format
    00660     bss_color = bss->he_oper & MAC_HE_OPER_BSS_COLOR_MASK;
    00661     bss_color >>= MAC_HE_OPER_BSS_COLOR_OFT;
    00662     bss_color <<= NXMAC_BSS_COLOR_LSB;
    00663     bss_color |= NXMAC_BSS_COLOR_EN_BIT;
    00664     if (!(bss->he_oper & MAC_HE_OPER_BSS_COLOR_DISABLED_BIT))
    00665         bss_color |= NXMAC_BSS_COLOR_EN_BIT;
    00666     if (bss->he_oper & MAC_HE_OPER_BSS_COLOR_PARTIAL_BIT)
    00667         bss_color |= NXMAC_PARTIAL_BSS_COLOR_EN_BIT;
    00668
    00669     return bss_color;
    00670 }
    00671 #endif
    00672
    00673 void me_init_rate(struct sta_info_tag *sta)
    00674 {
    00675     rc_init(sta);
    00676     me_update_buffer_control(sta);
    00677 }
    00678
    00679
    00680 void me_init_bcmc_rate(struct sta_info_tag *sta)
    00681 {
    00682     struct sta_pol_tbl_cntl *rc = &sta->pol_tbl;
    00683     struct mac_rateset *rates = &sta->info.rate_set;
    00684     uint8_t max_rate = 0;
    00685     int i;
    00686
    00687     ASSERT_ERR(rates->length != 0);
    00688     for (i = 0; i < rates->length; i++)
    00689     {
    00690         if ((rates->array[i] & ~MAC_BASIC_RATE) > max_rate)
    00691             max_rate = rates->array[i] & ~MAC_BASIC_RATE;
    00692     }
    00693
    00694     rc_init_bcmc_rate(sta, me_rate_translate(max_rate));
    00695
    00696     rc->upd_field = 0;
    00697 }
    00698
    00699
    00700 struct txl_buffer_control *me_update_buffer_control(struct sta_info_tag *sta)
    00701 {
    00702     // Policy Table Info
    00703     struct sta_pol_tbl_cntl *pol_tbl = &sta->pol_tbl;
    00704     struct txl_buffer_control *buf_ctrl = pol_tbl->buf_ctrl;
    00705
    00706     // Check if a field has to be updated
    00707     if (pol_tbl->upd_field)
    00708     {
    00709         int i;
    00710         uint8_t stbc_nss = 0;
    00711         uint8_t sta_stbc_nss = 0;
    00712         int use_stbc = 0;
    00713         // Next TX Policy Table
    00714         struct tx_policy_tbl *pol = &buf_ctrl->policy_tbl;
    00715         // Rate control info
    00716         uint32_t rate_info[RATE_CONTROL_STEPS];
    00717         // Power control info
    00718         uint32_t pwr_info[RATE_CONTROL_STEPS];
    00719         // PHY control information 1 and 2
    00720         uint32_t phycntrlinfo1, phycntrlinfo2;
    00721         // Trial rate info
    00722         uint32_t trial_rate;
    00723         #if NX_HE
    00724         // Indicate if used rates allow this frame to contain a +HTC if sent as singleton
    00725         bool can_use_htc = (buf_ctrl->tx_flags & TX_SWDESC_UMAC_HTC_BIT) != 0;
    00726         #else
    00727         bool can_use_htc = false;
    00728         #endif
    00729         #if RW_BFMER_EN
    00730         // Indicate if used rates allow this frame to be beamformed if sent as singleton
    00731         bool can_use_bfm = (buf_ctrl->tx_flags & TX_SWDESC_UMAC_BEAMFORM_BIT) != 0;
    00732         // Nc received in the latest beamforming report
    00733         uint8_t nc = bfr_get_last_nc(sta->staid);
    00734         // Read number of antennas
    00735         uint8_t ntx = phy_get_ntx();
    00736         can_use_bfm = (nc != BFR_INVALID_NC);
    00737         #else
    00738         bool can_use_bfm = false;
    00739         uint8_t nc = 0, ntx = 0;
    00740         #endif //(RW_BFMER_EN)
    00741
    00742         // Get the currently used rate control information
    00743         phycntrlinfo1 = pol->phycntrlinfo1;
    00744         phycntrlinfo2 = pol->phycntrlinfo2;
    00745         for (i = 0; i < RATE_CONTROL_STEPS; i++)
    00746         {
    00747             rate_info[i] = pol->ratecntrlinfo[i];
    00748             pwr_info[i] = pol->powercntrlinfo[i];
    00749         }
    00750
    00751         // Update rate configuration (pre_type, short_gi, bw, nss, mcs)
    00752         if (pol_tbl->upd_field & CO_BIT(STA_MGMT_POL_UPD_RATE))
    00753         {
    00754             PROF_RC_UPD_RETRY_CHAIN_SET();
    00755
    00756             struct rc_sta_stats *rc_ss = pol_tbl->sta_stats;
    00757             sta_stbc_nss = sta->info.stbc_nss;
    00758             #if NX_HE
    00759             can_use_htc = true;
    00760             #endif
    00761             for (i = 0; i < RATE_CONTROL_STEPS; i++)
    00762             {
    00763                 uint8_t nss = 0;
    00764                 uint16_t idx = rc_ss->retry_step_idx[i];
    00765                 uint32_t new_rate_info = (RC_MAX_NUM_RETRY << N_RETRY_RCX_OFT) |
    00766                                          (rc_ss->rate_stats[idx].rate_config &
    00767                                           (MCS_INDEX_TX_RCX_MASK | BW_TX_RCX_MASK |
    00768                                            SHORT_GI_TX_RCX_MASK | PRE_TYPE_TX_RCX_MASK |
    00769                                            FORMAT_MOD_TX_RCX_MASK));
    00770                 uint32_t format = (new_rate_info & FORMAT_MOD_TX_RCX_MASK) >>
    00771                                                                FORMAT_MOD_TX_RCX_OFT;
    00772
    00773                 // Get the number of SS of this frame
    00774                 if (format >= FORMATMOD_HT_MF)
    00775                 {
    00776                     uint32_t mcs_idx = (new_rate_info & MCS_INDEX_TX_RCX_MASK)
    00777                                                                  >> MCS_INDEX_TX_RCX_OFT;
    00778                     #if NX_VHT
    00779                     if (format == FORMATMOD_VHT)
    00780                     {
    00781                         // Extract NSS
    00782                         nss = (mcs_idx & VHT_NSS_MASK) >> VHT_NSS_OFT;
    00783                     }
    00784                     else
    00785                     #endif
    00786                     #if NX_HE
    00787                     if (format == FORMATMOD_HE_SU)
    00788                     {
    00789                         // Extract NSS
    00790                         nss = (mcs_idx & VHT_NSS_MASK) >> VHT_NSS_OFT;
    00791
    00792                         // Set LTF type
    00793                         txl_he_ltf_type_set(new_rate_info, &pwr_info[i]);
    00794                     }
    00795                     else
    00796                     #endif
    00797                     {
    00798                         // Extract NSS
    00799                         nss = (mcs_idx & HT_NSS_MASK) >> HT_NSS_OFT;
    00800                     }
    00801
    00802                     // Check if we have to enable or disable STBC
    00803                     if (i == 0)
    00804                     {
    00805                         if (nss < sta_stbc_nss)
    00806                         {
    00807                             stbc_nss = nss;
    00808                             use_stbc = 1;
    00809                         }
    00810                     }
    00811                     else if (use_stbc && (nss != stbc_nss))
    00812                     {
    00813                         use_stbc = 0;
    00814                     }
    00815                 }
    00816
    00817                 // Clear the current configuration
    00818                 rate_info[i] &= ~(N_RETRY_RCX_MASK | MCS_INDEX_TX_RCX_MASK |
    00819                                   BW_TX_RCX_MASK | SHORT_GI_TX_RCX_MASK |
    00820                                   PRE_TYPE_TX_RCX_MASK | FORMAT_MOD_TX_RCX_MASK);
    00821                 // Set new configuration
    00822                 rate_info[i] |= new_rate_info;
    00823
    00824                 // Check if beamforming can be used with this policy table
    00825                 #if RW_BFMER_EN
    00826                 if (can_use_bfm)
    00827                 {
    00828                     if ((format != FORMATMOD_VHT) || (nss > nc) || (nss == ntx))
    00829                     {
    00830                         can_use_bfm = false;
    00831                     }
    00832                 }
    00833                 #endif //(RW_BFMER_EN)
    00834                 #if NX_HE
    00835                 if (can_use_htc)
    00836                 {
    00837                     if (format < FORMATMOD_HT_MF)
    00838                     {
    00839                         can_use_htc = false;
    00840                     }
    00841                 }
    00842                 #endif
    00843             }
    00844
    00845             // Check if STBC can be used with this policy table
    00846             phycntrlinfo1 &= ~STBC_PT_MASK;
    00847             if (use_stbc)
    00848             {
    00849                 phycntrlinfo1 |= (stbc_nss + 1) << STBC_PT_OFT;
    00850             }
    00851
    00852             #if RW_BFMER_EN
    00853             // Allow/Disallow Beamforming based on the previous check
    00854             if (can_use_bfm)
    00855                 buf_ctrl->tx_flags |= TX_SWDESC_UMAC_BEAMFORM_BIT;
    00856             else
    00857                 buf_ctrl->tx_flags &= ~TX_SWDESC_UMAC_BEAMFORM_BIT;
    00858             #endif
    00859             #if NX_HE
    00860             if (can_use_htc)
    00861                 buf_ctrl->tx_flags |= TX_SWDESC_UMAC_HTC_BIT;
    00862             else
    00863                 buf_ctrl->tx_flags &= ~TX_SWDESC_UMAC_HTC_BIT;
    00864             #endif
    00865
    00866             // Force an update of the protection configuration because some
    00867             // new rates might have to be protected, some others might have to be
    00868             // unprotected
    00869             pol_tbl->upd_field |= CO_BIT(STA_MGMT_POL_UPD_PROT);
    00870             PROF_RC_UPD_RETRY_CHAIN_CLR();
    00871         }
    00872
    00873         // Update trial rate configuration (pre_type, short_gi, bw, nss, mcs)
    00874         if (pol_tbl->upd_field & CO_BIT(STA_MGMT_POL_TRIAL_RATE))
    00875         {
    00876             PROF_RC_UPD_RETRY_CHAIN_TRIAL_SET();
    00877
    00878             struct rc_sta_stats *rc_ss = pol_tbl->sta_stats;
    00879             uint8_t idx = rc_ss->trial_idx;
    00880             uint32_t new_rate_info = (RC_MAX_NUM_RETRY << N_RETRY_RCX_OFT) |
    00881                                      (rc_ss->rate_stats[idx].rate_config &
    00882                                       (MCS_INDEX_TX_RCX_MASK | BW_TX_RCX_MASK |
    00883                                        SHORT_GI_TX_RCX_MASK | PRE_TYPE_TX_RCX_MASK |
    00884                                        FORMAT_MOD_TX_RCX_MASK));
    00885
    00886             // Clear the current configuration
    00887             trial_rate = pol->ratecntrlinfo[0];
    00888             trial_rate &= ~(N_RETRY_RCX_MASK | MCS_INDEX_TX_RCX_MASK |
    00889                           BW_TX_RCX_MASK | SHORT_GI_TX_RCX_MASK |
    00890                           PRE_TYPE_TX_RCX_MASK | FORMAT_MOD_TX_RCX_MASK);
    00891
    00892             // Set trial rate configuration
    00893             rc_ss->trial_rate = trial_rate | new_rate_info;
    00894             // Check if STBC can be used with this policy table
    00895             use_stbc = (phycntrlinfo1 & STBC_PT_MASK) != 0;
    00896             stbc_nss = ((phycntrlinfo1 & STBC_PT_MASK) >> STBC_PT_OFT) - 1;
    00897
    00898             // Check if STBC and Beamforming can be used for the trial transmission
    00899             rc_trial_check_bfm_stbc_htc(buf_ctrl, rc_ss->trial_rate,
    00900                                         can_use_bfm, use_stbc, stbc_nss, nc, ntx,
    00901                                         can_use_htc);
    00902
    00903             PROF_RC_UPD_RETRY_CHAIN_TRIAL_CLR();
    00904         }
    00905
    00906         if (pol_tbl->upd_field & CO_BIT(STA_MGMT_POL_UPD_PROT))
    00907         {
    00908             for (i = 0; i < RATE_CONTROL_STEPS; i++)
    00909             {
    00910                 uint8_t format = (rate_info[i] & FORMAT_MOD_TX_RCX_MASK) >>
    00911                                                                FORMAT_MOD_TX_RCX_OFT;
    00912                 uint8_t rate = (rate_info[i] & MCS_INDEX_TX_RCX_MASK) >>
    00913                                                                MCS_INDEX_TX_RCX_OFT;
    00914                 // Protect only OFDM transmissions
    00915                 if ((format >= FORMATMOD_NON_HT_DUP_OFDM) || (rate >= HW_RATE_6MBPS))
    00916                 {
    00917                     // Clear the current used Protection Fields
    00918                     rate_info[i] &= ~STA_MGMT_PROT_HW_MASK;
    00919
    00920                     // Apply computed values
    00921                     rate_info[i] |= pol_tbl->prot_cfg;
    00922                 }
    00923             }
    00924         }
    00925
    00926         // update Tx power
    00927         if (pol_tbl->upd_field & CO_BIT(STA_MGMT_POL_UPD_TX_POWER))
    00928         {
    00929             struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
    00930             uint8_t idx;
    00931
    00932             tpc_get_vif_tx_power(vif, NULL, &idx);
    00933             for (i = 0; i < RATE_CONTROL_STEPS; i++)
    00934             {
    00935                 pwr_info[i] &= ~TX_PWR_LEVEL_MASK;
    00936                 pwr_info[i] |= TX_PWR_LEVEL_SET(idx);
    00937             }
    00938         }
    00939
    00940         #if NX_HE
    00941         // update BSS color
    00942         if (pol_tbl->upd_field & CO_BIT(STA_MGMT_POL_UPD_BSS_COLOR))
    00943         {
    00944             struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
    00945             struct me_bss_info *bss = &vif->bss_info;
    00946             uint8_t color = 0;
    00947
    00948             phycntrlinfo2 &= ~BSS_COLOR_MASK;
    00949             if (!(bss->he_oper & MAC_HE_OPER_BSS_COLOR_DISABLED_BIT))
    00950                 color = (bss->he_oper & MAC_HE_OPER_BSS_COLOR_MASK) >>
    00951                                                            MAC_HE_OPER_BSS_COLOR_OFT;
    00952             phycntrlinfo2 |= (color << BSS_COLOR_OFT);
    00953         }
    00954         #endif
    00955
    00956         // Update the policy table (needs to be done with interrupt disabled
    00957         // as this table can be copied in IRQ context before transmission)
    00958         GLOBAL_INT_DISABLE();
    00959         pol->phycntrlinfo1 = phycntrlinfo1;
    00960         pol->phycntrlinfo2 = phycntrlinfo2;
    00961         for (i = 0; i < RATE_CONTROL_STEPS; i++)
    00962         {
    00963             pol->ratecntrlinfo[i] = rate_info[i];
    00964             pol->powercntrlinfo[i] = pwr_info[i];
    00965         }
    00966         GLOBAL_INT_RESTORE();
    00967
    00968         // Clear update bit field
    00969         pol_tbl->upd_field = 0;
    00970     }
    00971
    00972     return (buf_ctrl);
    00973 }
    00974
    00975 void me_bw_check(uint32_t ht_op_addr, uint32_t vht_op_addr, struct me_bss_info *bss)
    00976 {
    00977     struct mac_chan_op *chan = &bss->chan;
    00978
    00979     // By default we consider that the BW will be 20MHz
    00980     chan->type = PHY_CHNL_BW_20;
    00981     chan->center1_freq = bss->chan.prim20_freq;
    00982     chan->center2_freq = 0;
    00983
    00984     // Check if there is a HT operation element
    00985     if ((ht_op_addr != 0) && (me_env.phy_bw_max >= PHY_CHNL_BW_40))
    00986     {
    00987         uint8_t sec_ch_oft = co_read8p(ht_op_addr + MAC_HT_OPER_PRIM_CH_OFT + 1) & 3;
    00988         if (sec_ch_oft != 0)
    00989         {
    00990             // Compute the secondary channel frequency offset
    00991             int8_t freq_offset = (sec_ch_oft == 1) ? 10 : -10;
    00992             chan->center1_freq += freq_offset;
    00993             chan->type = PHY_CHNL_BW_40;
    00994         }
    00995     }
    00996
    00997     // Check if there is a VHT operation element
    00998     #if NX_VHT
    00999     if ((vht_op_addr != 0) && (me_env.phy_bw_max >= PHY_CHNL_BW_80))
    01000     {
    01001         uint8_t chan_width = co_read8p(vht_op_addr + MAC_VHT_CHAN_WIDTH_OFT) & 3;
    01002         uint8_t center0 = co_read8p(vht_op_addr + MAC_VHT_CENTER_FREQ0_OFT);
    01003         uint8_t center1 = co_read8p(vht_op_addr + MAC_VHT_CENTER_FREQ1_OFT);
    01004         me_vht_bandwidth_parse(chan_width, center0, center1, chan);
    01005     }
    01006     #endif
    01007 }
    01008
    01009 void me_beacon_check(uint8_t vif_idx, uint16_t length, uint32_t bcn_addr)
    01010 {
    01011     // Check if ERP field is present in the received beacon
    01012     uint32_t addr, ht_op_addr = 0, vht_op_addr = 0;
    01013     // Get VIF interface
    01014     struct vif_info_tag *vif      = &vif_info_tab[vif_idx];
    01015     struct sta_info_tag *sta = (struct sta_info_tag *)co_list_pick(&vif->sta_list);
    01016     struct me_bss_info *bss = &vif->bss_info;
    01017     // Keep current Protection status and BW
    01018     uint16_t cur_prot_status = bss->prot_status;
    01019     uint8_t cur_phy_bw = bss->chan.type;
    01020     uint8_t cur_pwr_const = bss->power_constraint;
    01021     #if NX_HE
    01022     uint32_t cur_bss_color = bss->he_oper & ME_BSS_COLOR_MSK;
    01023     #endif
    01024     uint8_t csa_count, csa_mode;
    01025     uint32_t var_part_addr = bcn_addr + MAC_BEACON_VARIABLE_PART_OFT;
    01026     uint32_t var_part_len = length - MAC_BEACON_VARIABLE_PART_OFT;
    01027
    01028     // Reset protection status before the checks
    01029     bss->prot_status = 0;
    01030
    01031     /*
    01032      *================================================================
    01033      * Check if ERP field is present in the received beacon
    01034      *================================================================
    01035      */
    01036     if (bss->chan.band == PHY_BAND_2G4)
    01037     {
    01038         addr = mac_ie_erp_find(var_part_addr, var_part_len);
    01039
    01040         if (addr)
    01041         {
    01042             me_erp_prot_check(addr, &bss->prot_status);
    01043         }
    01044     }
    01045
    01046     /*
    01047      *================================================================
    01048      * Check if WMM element changed
    01049      *================================================================
    01050      */
    01051     if (BSS_CAPA(bss, QOS) && (vif->type == VIF_STA))
    01052     {
    01053         bool changed;
    01054
    01055         // Extract WMM element
    01056         me_extract_edca_params(var_part_addr, var_part_len, &bss->edca_param, &changed);
    01057
    01058         if (changed)
    01059         {
    01060             // EDCA parameters
    01061             for (int i = 0; i < AC_MAX; i++)
    01062             {
    01063                 struct mm_set_edca_req *edca = KE_MSG_ALLOC(MM_SET_EDCA_REQ, TASK_MM,
    01064                                                             TASK_ME, mm_set_edca_req);
    01065                 #if NX_UAPSD
    01066                 bool uapsd = (vif->u.sta.uapsd_queues & ~CO_BIT(i)) != 0;
    01067                 #else
    01068                 bool uapsd = false;
    01069                 #endif
    01070
    01071                 edca->ac_param = bss->edca_param.ac_param[i];
    01072                 edca->hw_queue = i;
    01073                 edca->inst_nbr = vif->index;
    01074                 edca->uapsd = uapsd;
    01075
    01076                 ke_msg_send(edca);
    01077             }
    01078         }
    01079     }
    01080
    01081     /*
    01082      *================================================================
    01083      * Check if HT and VHT Operation Element are present in
    01084      * the received beacon
    01085      *================================================================
    01086      */
    01087     if (LOCAL_CAPA(HT))
    01088     {
    01089         ht_op_addr = mac_ie_ht_oper_find(var_part_addr, var_part_len);
    01090
    01091         #if NX_VHT || NX_HE
    01092         /*
    01093          *================================================================
    01094          * Check if VHT Operation and/or Operation Mode Notification Element
    01095          * is present in the received beacon
    01096          *================================================================
    01097          */
    01098         if (LOCAL_CAPA(VHT) || LOCAL_CAPA(HE))
    01099         {
    01100             vht_op_addr = mac_ie_vht_oper_find(var_part_addr, var_part_len);
    01101
    01102             if (vif->type == VIF_STA)
    01103             {
    01104                 uint32_t op_mode_notif_addr = mac_ie_op_mode_notif_find(var_part_addr,
    01105                                                                         var_part_len);
    01106
    01107                 if (op_mode_notif_addr)
    01108                 {
    01109                     uint8_t opmode = co_read8p(op_mode_notif_addr + MAC_INFOELT_INFO_OFT);
    01110                     struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.ap_id];
    01111
    01112                     // This frame is valid if peer device is VHT or HE capable
    01113                     if ((STA_CAPA(sta, VHT) || STA_CAPA(sta, HE)) &&
    01114                         !(opmode & MAC_OPMODE_RXNSS_TYPE_BIT))
    01115                     {
    01116                         uint8_t bw = (opmode & MAC_OPMODE_BW_MSK) >> MAC_OPMODE_BW_OFT;
    01117                         uint8_t nss = (opmode & MAC_OPMODE_RXNSS_MSK) >> MAC_OPMODE_RXNSS_OFT;
    01118
    01119                         // Update maximum supported bandwidth
    01120                         me_sta_bw_nss_max_upd(vif->u.sta.ap_id, bw, nss);
    01121                     }
    01122                 }
    01123
    01124                 #if NX_HE
    01125                 if (BSS_CAPA(bss, HE))
    01126                 {
    01127                     bool changed;
    01128                     struct mm_set_uora_req *req = KE_MSG_ALLOC(MM_SET_UORA_REQ, TASK_MM,
    01129                                                                TASK_ME, mm_set_uora_req);
    01130
    01131                     me_extract_uora_params(var_part_addr, var_part_len, req);
    01132                     // Send the UORA parameters to the LMAC
    01133                     ke_msg_send(req);
    01134
    01135                     me_extract_mu_edca_params(var_part_addr, var_part_len,
    01136                                               &bss->mu_edca_param, &changed);
    01137
    01138                     if (changed)
    01139                     {
    01140                         // Send the MU EDCA parameters to the LMAC
    01141                         struct mm_set_mu_edca_req *req =
    01142                                                KE_MSG_ALLOC(MM_SET_MU_EDCA_REQ, TASK_MM,
    01143                                                             TASK_ME, mm_set_mu_edca_req);
    01144
    01145                         for (int i = 0; i < AC_MAX; i++)
    01146                         {
    01147                             req->param[i] = bss->mu_edca_param.ac_param[i];
    01148                         }
    01149
    01150                         ke_msg_send(req);
    01151                     }
    01152                 }
    01153                 #endif
    01154             }
    01155             #if NX_HE
    01156             if (LOCAL_CAPA(HE))
    01157             {
    01158                 uint16_t txop_dur_rts_thres = MAC_HE_OPER_TXOP_DUR_RTS_THRES_DISABLED;
    01159                 // Retrieve the HE operation field
    01160                 if (me_extract_he_oper(var_part_addr, var_part_len, bss))
    01161                 {
    01162                     txop_dur_rts_thres = (bss->he_oper & MAC_HE_OPER_TXOP_DUR_RTS_THRES_MSK)
    01163                                                         >> MAC_HE_OPER_TXOP_DUR_RTS_THRES_OFT;
    01164                 }
    01165                 // As per 802.11ax, update threshold only if it is non-NULL in the element
    01166                 if (txop_dur_rts_thres)
    01167                 {
    01168                     struct mm_set_txop_rts_thres_req *req =
    01169                                          KE_MSG_ALLOC(MM_SET_TXOP_RTS_THRES_REQ, TASK_MM,
    01170                                                       TASK_ME, mm_set_txop_rts_thres_req);
    01171
    01172                     req->txop_dur_rts_thres = txop_dur_rts_thres;
    01173                     req->inst_nbr = vif->index;
    01174
    01175                     ke_msg_send(req);
    01176                 }
    01177                 // Check if BSS color has changed and update it if necessary
    01178                 if (cur_bss_color != (bss->he_oper & ME_BSS_COLOR_MSK))
    01179                 {
    01180                     struct mm_set_bss_color_req *req =
    01181                                          KE_MSG_ALLOC(MM_SET_BSS_COLOR_REQ, TASK_MM,
    01182                                                       TASK_ME, mm_set_bss_color_req);
    01183
    01184                     req->bss_color = me_build_bss_color_reg(bss);
    01185
    01186                     ke_msg_send(req);
    01187                 }
    01188             }
    01189             #endif
    01190         }
    01191         #endif
    01192     }
    01193     me_bw_check(ht_op_addr, vht_op_addr, bss);
    01194
    01195     // Check for channel switch
    01196     csa_count = me_extract_csa(var_part_addr, var_part_len, &csa_mode, &vif->csa_channel);
    01197     if (csa_count)
    01198     {
    01199         if (vif->type == VIF_STA)
    01200         {
    01201             if ((!vif->u.sta.csa_count) &&
    01202                 (csa_mode == MAC_SWITCH_MODE_TX_TRAFFIC_STOP))
    01203             {
    01204                 mm_send_csa_traffic_ind(vif->index, false);
    01205             }
    01206             vif->u.sta.csa_count = csa_count;
    01207         }
    01208         #if NX_BCN_AUTONOMOUS_TX
    01209         else if (vif->type == VIF_AP) // if not defined this function is not called for AP itf
    01210         {
    01211             vif->u.ap.csa_count = csa_count;
    01212         }
    01213         #endif
    01214     }
    01215
    01216     // Check if power constraint changed
    01217     me_extract_power_constraint(var_part_addr, var_part_len, bss);
    01218
    01219     if (cur_pwr_const != bss->power_constraint)
    01220         tpc_update_vif_tx_power(vif);
    01221
    01222     // Check if we need to change the channel context
    01223     if (cur_phy_bw < bss->chan.type)
    01224     {
    01225         me_chan_ctxt_update(vif);
    01226     }
    01227
    01228     // Update the protection and BW of STA linked to this VIF
    01229     while (sta != NULL)
    01230     {
    01231         if (cur_prot_status != bss->prot_status)
    01232         {
    01233             // Update Policy Table for Protection Frames
    01234             me_pol_tbl_prot_upd(sta, bss->prot_status);
    01235         }
    01236
    01237         if (cur_phy_bw != bss->chan.type)
    01238         {
    01239             me_pol_tbl_bw_upd(sta, bss->chan.type);
    01240         }
    01241
    01242         #if NX_HE
    01243         if (cur_bss_color != (bss->he_oper & ME_BSS_COLOR_MSK))
    01244         {
    01245             me_pol_tbl_bss_color_upd(sta);
    01246         }
    01247         #endif
    01248
    01249         sta = (struct sta_info_tag *)co_list_next(&sta->list_hdr);
    01250     }
    01251 }
    01252
    01253 void me_sta_bw_nss_max_upd(uint8_t sta_idx, uint8_t bw, uint8_t nss)
    01254 {
    01255     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    01256     struct sta_pol_tbl_cntl *pol_tbl = &sta->pol_tbl;
    01257     struct sta_capa_info *info = &sta->info;
    01258     struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
    01259     uint8_t local_supp_nss = 0;
    01260     uint8_t peer_supp_nss = 0;
    01261
    01262     #if NX_HE
    01263     if (STA_CAPA(sta, HE))
    01264     {
    01265         ASSERT_ERR(LOCAL_CAPA(HE));
    01266
    01267         // Check the peer and local supported NSS (HE)
    01268         peer_supp_nss = me_11ac_nss_max(info->he_cap.mcs_supp.rx_mcs_80);
    01269         local_supp_nss = me_11ac_nss_max(me_env.he_cap.mcs_supp.tx_mcs_80);
    01270
    01271         nss = co_min(nss, co_min(local_supp_nss, peer_supp_nss));
    01272     }
    01273     else
    01274     #endif
    01275     #if NX_VHT
    01276     if (STA_CAPA(sta, VHT))
    01277     {
    01278         ASSERT_ERR(LOCAL_CAPA(VHT));
    01279
    01280         // Check the peer and local supported NSS (VHT)
    01281         peer_supp_nss = me_11ac_nss_max(info->vht_cap.rx_mcs_map);
    01282         local_supp_nss = me_11ac_nss_max(me_env.vht_cap.tx_mcs_map);
    01283
    01284         nss = co_min(nss, co_min(local_supp_nss, peer_supp_nss));
    01285     }
    01286     else
    01287     #endif
    01288     {
    01289         ASSERT_ERR(LOCAL_CAPA(HT));
    01290
    01291         // Check the peer and local supported NSS (VHT)
    01292         peer_supp_nss = me_11n_nss_max(info->ht_cap.mcs_rate);
    01293         local_supp_nss = me_11n_nss_max(me_env.ht_cap.mcs_rate);
    01294
    01295         nss = co_min(nss, co_min(local_supp_nss, peer_supp_nss));
    01296     }
    01297
    01298     bw = co_min(bw, me_phy2mac_bw(info->phy_bw_max));
    01299
    01300     #if NX_TDLS
    01301     if (sta_idx == vif->u.sta.tdls_chsw_sta_idx)
    01302     {
    01303         info->bw_cur = bw;
    01304     }
    01305     else
    01306     #endif
    01307     {
    01308         info->bw_cur = co_min(bw, me_phy2mac_bw(vif->bss_info.chan.type));
    01309     }
    01310
    01311     // Update max BW allowed in the RC algorithm
    01312     rc_update_bw_nss_max(sta->staid, info->bw_cur, nss);
    01313
    01314     // Require update of protection configuration field in policy table
    01315     pol_tbl->upd_field |= CO_BIT(STA_MGMT_POL_UPD_BW);
    01316 }
    01317
    01318 uint16_t me_tx_cfm_amsdu(struct txdesc *txdesc)
    01319 {
    01320     struct hostdesc *host = &txdesc->host;
    01321     struct sta_info_tag *sta = &sta_info_tab[host->staid];
    01322
    01323     if (host->tid == 0xff)
    01324         return 0;
    01325
    01326     if (sta->inst_nbr == 0xFF)
    01327        return 0;
    01328
    01329     #if NX_AMPDU_TX
    01330     // AMSDU allowed only under BA (because of retry)
    01331     if (sta->ba_info[host->tid].bam_idx_tx == BAM_INVALID_TASK_IDX)
    01332         return 0;
    01333
    01334     if (!bam_env[sta->ba_info[host->tid].bam_idx_tx].amsdu)
    01335         return 0;
    01336     #endif
    01337
    01338     // Get the max aggregation size
    01339     return rc_get_max_amsdu_len(sta);
    01340 }
    01341
    01342 void me_vht_bandwidth_parse(uint8_t width, uint8_t center0, uint8_t center1,
    01343                             struct mac_chan_op *chan)
    01344 {
    01345     int delta = 0;
    01346
    01347     if ((width == 0) || (width >= 4))
    01348         return;
    01349
    01350     chan->center1_freq = phy_channel_to_freq(chan->band, center0);
    01351     chan->center2_freq = phy_channel_to_freq(chan->band, center1);
    01352
    01353     switch (width)
    01354     {
    01355         case 1:
    01356             // 80MHz, 160MHz or 80+80MHz channel
    01357             // center0: center of the 80MHz channel that contains the primary
    01358             // center1: 0 (for 80MHz)
    01359             //          center of the 160MHz channel (for 160MHz)
    01360             //          center of the secondary 80MHz channel (for 80+80MHz)
    01361             if (chan->center2_freq)
    01362             {
    01363                 if (chan->center1_freq > chan->center2_freq)
    01364                     delta = chan->center1_freq - chan->center2_freq;
    01365                 else
    01366                     delta = chan->center2_freq - chan->center1_freq;
    01367             }
    01368
    01369             if ((delta == 40) && (me_env.phy_bw_max >= PHY_CHNL_BW_160))
    01370             {
    01371                 chan->type = PHY_CHNL_BW_160;
    01372                 chan->center1_freq = chan->center2_freq;
    01373                 chan->center2_freq = 0;
    01374             }
    01375             else if ((delta > 40) && (me_env.phy_bw_max == PHY_CHNL_BW_80P80))
    01376             {
    01377                 chan->type = PHY_CHNL_BW_80P80;
    01378             }
    01379             else
    01380             {
    01381                 chan->type = PHY_CHNL_BW_80;
    01382                 chan->center2_freq = 0;
    01383             }
    01384             break;
    01385         case 2:
    01386             // 160MHZ channel
    01387             // center0: center of the 160MHz channel
    01388             // center1: 0
    01389             if (me_env.phy_bw_max >= PHY_CHNL_BW_160)
    01390             {
    01391                 chan->type = PHY_CHNL_BW_160;
    01392             }
    01393             else
    01394             {
    01395                 // 160MHz not supported, only use the 80MHz that contains the primary channel
    01396                 chan->type = PHY_CHNL_BW_80;
    01397                 if (chan->center1_freq < chan->prim20_freq)
    01398                     chan->center1_freq += 40;
    01399                 else
    01400                     chan->center1_freq -= 40;
    01401             }
    01402             break;
    01403         case 3:
    01404             // 80+80Mhz channel
    01405             // center0: center of the primary 80MHz channel
    01406             // center1: center of the secondary 80MHz channel
    01407             if (me_env.phy_bw_max == PHY_CHNL_BW_80P80)
    01408             {
    01409                 chan->type = PHY_CHNL_BW_80P80;
    01410             }
    01411             else
    01412             {
    01413                 // 80+80MHZ not supported, only used priumary 80MHz channel
    01414                 chan->type = PHY_CHNL_BW_80;
    01415                 chan->center2_freq = 0;
    01416             }
    01417             break;
    01418         default:
    01419             break;
    01420     }
    01421 }
    01422