00001
00020
00021
00022
00023
00024
00025 #include "bfr.h"
00026
00027 #if (RW_BFMER_EN)
00028
00029
00030 #include "sta_mgmt.h"
00031
00032 #include "vif_mgmt.h"
00033
00034 #include "co_status.h"
00035
00036 #include "hal_dma.h"
00037
00038 #include "rxl_hwdesc.h"
00039
00040 #include "tpc.h"
00041 #if NX_MFP
00042
00043 #include "mfp.h"
00044
00045 #include "txu_cntrl.h"
00046 #endif
00047
00048 #include "td.h"
00049 #include "ke_timer.h"
00050
00051
00052
00053
00054
00055
00060 #define BFR_NB_BIT_PHY_SU (4)
00061
00065 #define BFR_NB_BIT_PHY_MU (7)
00066
00070 #define BFR_NB_BIT_PSY_SU (6)
00071
00075 #define BFR_NB_BIT_PSY_MU (9)
00076
00078 #define BFR_NDPA_SU_DURATION (56)
00080 #define BFR_NDP_DURATION (47)
00082 #define BFR_BRP_DURATION (52)
00084 #define BFR_BCR_DURATION (8)
00086 #define BFR_SIFS_DURATION (14)
00087
00088
00089
00090
00091
00092
00100 #define BFR_GET_REPORT_DURATION(length) \
00101 (((length + 20) / 20) * BFR_BCR_DURATION) \
00102
00103
00111 #define BFR_STA_INFO_SET_AID12(sta_info, aid) \
00112 (sta_info = (aid & BFR_NDPA_AID12_MASK)) \
00113
00114
00122 #define BFR_STA_INFO_SET_FBACK_TYPE(sta_info, fback_type) \
00123 (sta_info |= (fback_type << BFR_NPDA_FBACK_POS)) \
00124
00125
00133 #define BFR_STA_INFO_SET_NC_INDEX(sta_info, nc_index) \
00134 (sta_info |= (nc_index << BFR_NPDA_NC_IDX_POS)) \
00135
00136
00153 #define BFR_VHT_MIMO_GET_VALUE(vht_mimo_ctrl, field) \
00154 ((vht_mimo_ctrl >> BFR_MIMO_CTRL_ ## field ## _OFFSET) & \
00155 BFR_MIMO_CTRL_ ## field ## _MASK) \
00156
00157
00164 #define BFR_IS_STATUS_BIT_SET(status, bit_pos) \
00165 (status & (1 << bit_pos)) \
00166
00167
00174 #define BFR_SET_STATUS_BIT(status, bit_pos) \
00175 (status |= (1 << bit_pos)) \
00176
00177
00184 #define BFR_RESET_STATUS_BIT(status, bit_pos) \
00185 (status &= ~(1 << bit_pos)) \
00186
00187
00196 #define BFR_GET_NA(nc, nr) \
00197 (nc * ((2 * nr) - nc - 1)) \
00198
00199
00200
00201
00202
00203
00205 struct bfr_mem_node bfr_nodes[BFR_MEM_NODE_NB];
00207 struct bfr_info_sta bfr_sta_infos[NX_REMOTE_STA_MAX];
00209 uint16_t bfr_smm_ptrs[BFR_MEM_REP_NB_MAX];
00211 struct bfr_env_tag bfr_env;
00212
00220 const uint16_t bfr_ns[] = {
00221 [PHY_CHNL_BW_20] = 52,
00222 [PHY_CHNL_BW_40] = 108,
00223 [PHY_CHNL_BW_80] = 234,
00224 [PHY_CHNL_BW_160] = 468,
00225 [PHY_CHNL_BW_80P80] = 468,
00226 };
00227
00235 const uint8_t bfr_nsp[] = {
00236 [PHY_CHNL_BW_20] = 30,
00237 [PHY_CHNL_BW_40] = 58,
00238 [PHY_CHNL_BW_80] = 122,
00239 [PHY_CHNL_BW_160] = 244,
00240 [PHY_CHNL_BW_80P80] = 244,
00241 };
00242
00243
00244
00245
00246
00247
00248 static void bfr_start_next_calibration(void);
00249 static void bfr_calibrate(void);
00250
00251
00252
00253
00254
00261 __INLINE uint8_t bfr_get_bw(struct vif_info_tag *vif)
00262 {
00263 uint8_t bw;
00264 #if (!NX_CHNL_CTXT)
00265 struct phy_channel_info phy_info;
00266 phy_get_channel(&phy_info, PHY_PRIM);
00267 bw = (uint8_t) PHY_INFO_BW(phy_info);
00268 #else
00269 ASSERT_ERR(vif->chan_ctxt);
00270 bw = vif->chan_ctxt->channel.type;
00271 #endif
00272 ASSERT_ERR(bw < PHY_CHNL_BW_OTHER);
00273 return bw;
00274 }
00275
00282 static void bfr_calib_tmr_exp_cb(void *env)
00283 {
00284
00285 bfr_calibrate();
00286
00287
00288 mm_timer_set(&bfr_env.calib_tmr, ke_time() + bfr_env.calib_tmr_dur);
00289 }
00290
00303 static void bfr_end_calibration_for_sta(struct bfr_info_sta *bfr, bool updated)
00304 {
00305
00306 BFR_RESET_STATUS_BIT(bfr->status, BFR_STA_CALIBRATE);
00307
00308 if (updated)
00309 {
00310
00311 BFR_SET_STATUS_BIT(bfr->status, BFR_STA_REPORT_UPDATED);
00312
00313 BFR_SET_STATUS_BIT(bfr->status, BFR_STA_HAS_VALID_REPORT);
00314
00315
00316 bfr->last_calib_time = hal_machw_time();
00317
00318 bfr->host_report_idx ^= 1;
00319 }
00320
00321
00322 if (bfr_env.status == BFR_STATUS_SU_CALIB)
00323 {
00324
00325 PROF_BFR_SU_CALIB_CLR();
00326
00327 bfr_env.status = BFR_STATUS_IDLE;
00328 }
00329 else
00330 {
00331
00332 bfr_env.nb_reports--;
00333
00334
00335 if (bfr_env.nb_reports == 0)
00336 {
00337
00338 PROF_BFR_MU_CALIB_CLR();
00339
00340 bfr_env.status = BFR_STATUS_IDLE;
00341 }
00342 }
00343
00344
00345 if (bfr_env.status == BFR_STATUS_IDLE)
00346 {
00347 bfr_start_next_calibration();
00348 }
00349 }
00350
00362 static void bfr_tx_frame_cfm(void *env, uint32_t status)
00363 {
00364
00365 struct bfr_info_sta *bfr = (struct bfr_info_sta *)env;
00366
00367
00368 if (bfr->sta_idx != INVALID_STA_IDX)
00369 {
00370
00371
00372
00373
00374
00375
00376 if (!(status & DESC_DONE_TX_BIT) || (status & RETRY_LIMIT_REACHED_BIT))
00377 {
00378
00379 bfr_end_calibration_for_sta(bfr, false);
00380
00381 }
00382
00383 }
00384 }
00385
00396 static void bfr_dma_upload_cfm(void *env)
00397 {
00398
00399 struct bfr_info_sta *bfr = (struct bfr_info_sta *)env;
00400
00401
00402 PROF_BFR_UPLOAD_CLR();
00403
00404
00405 if (bfr->sta_idx != INVALID_STA_IDX)
00406 {
00407
00408 bfr->nb_segments--;
00409
00410
00411 if (bfr->nb_segments == 0)
00412 {
00413
00414 bfr_end_calibration_for_sta(bfr, true);
00415 }
00416 }
00417 }
00418
00426 static bool bfr_is_vht_bfr(uint8_t *frame)
00427 {
00428
00429 bool is_vht_bfr = false;
00430
00431 do
00432 {
00433
00434 struct mac_hdr *mac_hdr = (struct mac_hdr *)frame;
00435
00436
00437 if (!((mac_hdr->fctl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_ACTION_NO_ACK))
00438 {
00439 break;
00440 }
00441
00442
00443 if (co_read8p(CPU2HW(frame) + BFR_VHT_BFR_CATEGORY_OFFSET) != MAC_VHT_ACTION_CATEGORY)
00444 {
00445 break;
00446 }
00447
00448
00449 if (co_read8p(CPU2HW(frame) + BFR_VHT_BFR_VHT_ACTION_OFFSET) != MAC_COMP_BEAMFORMING_VHT_ACTION)
00450 {
00451 break;
00452 }
00453
00454 is_vht_bfr = true;
00455 } while (0);
00456
00457 return (is_vht_bfr);
00458 }
00459
00471 static bool bfr_is_frame_bf_compliant(struct txdesc *txdesc, struct bfr_info_sta *bfr)
00472 {
00473
00474 bool bf_compliant = false;
00475
00476 do
00477 {
00478 #if (RW_MUMIMO_TX_EN)
00479
00480 if (is_in_mumimo_ppdu(txdesc))
00481 {
00482 bf_compliant = true;
00483 break;
00484 }
00485 else
00486 #endif //(RW_MUMIMO_TX_EN)
00487 {
00488 #if (NX_AMPDU_TX)
00489 if (is_mpdu_agg(txdesc))
00490 {
00491 if (is_mpdu_first(txdesc))
00492 {
00493
00494 uint32_t tx_nss;
00495
00496
00497 if (((txdesc->umac.phy_flags & FORMAT_MOD_TX_RCX_MASK) >> FORMAT_MOD_TX_RCX_OFT)
00498 != FORMATMOD_VHT)
00499 {
00500 break;
00501 }
00502
00503 tx_nss = ((((txdesc->umac.phy_flags & MCS_INDEX_TX_RCX_MASK) >> MCS_INDEX_TX_RCX_OFT)
00504 & VHT_NSS_MASK) >> VHT_NSS_OFT);
00505
00506
00507 if (tx_nss == phy_get_ntx())
00508 {
00509 break;
00510 }
00511
00512
00513 if ((uint8_t)tx_nss > bfr->last_rx_nc)
00514 {
00515 break;
00516 }
00517 }
00518 else
00519 {
00520 break;
00521 }
00522 }
00523 else
00524 #endif //(NX_AMPDU_TX)
00525 {
00526
00527 if (!bfr_is_bfmed_sglt_allowed(txdesc))
00528 {
00529 break;
00530 }
00531 }
00532 }
00533
00534
00535 bf_compliant = true;
00536 } while (0);
00537
00538 return (bf_compliant);
00539 }
00540
00549 static void bfr_increase_nb_frames(struct bfr_mem_node *node)
00550 {
00551 if (node->nb_frames == 0)
00552 {
00553 bfr_env.nb_used_nodes++;
00554 }
00555
00556 node->nb_frames++;
00557 }
00558
00566 static void bfr_remove_node(struct bfr_mem_node *node)
00567 {
00568
00569 co_list_extract(&bfr_env.nodes, &node->hdr);
00570
00571
00572 if (node->sta_idx != INVALID_STA_IDX)
00573 {
00574
00575 struct bfr_info_sta *bfr = &bfr_sta_infos[node->sta_idx];
00576
00577
00578 ASSERT_ERR(bfr->node == node);
00579
00580
00581 bfr->node = NULL;
00582 }
00583
00584 ASSERT_WARN(node->smm_index < BFR_MEM_REP_NB_MAX);
00585
00586
00587 bfr_smm_ptrs[node->smm_index] = 0;
00588 node->smm_index = BFR_INVALID_SMM_INDEX;
00589 node->sta_idx = INVALID_STA_IDX;
00590
00591
00592 co_list_push_back(&bfr_env.free_nodes, &node->hdr);
00593 }
00594
00609 static bool bfr_check_next_nodes(uint16_t needed_length, struct bfr_mem_node **start_node,
00610 uint8_t *nb_nodes)
00611 {
00612
00613 uint16_t rem_len = needed_length;
00614
00615 struct bfr_mem_node *cnode = (*start_node);
00616
00617
00618 *nb_nodes = 0;
00619
00620
00621 while (cnode && rem_len)
00622 {
00623
00624 struct bfr_mem_node *next_node = (struct bfr_mem_node *)cnode->hdr.next;
00625
00626
00627 (*nb_nodes)++;
00628
00629
00630 if (cnode->nb_frames)
00631 {
00632
00633 *start_node = cnode;
00634 break;
00635 }
00636
00637
00638 rem_len -= co_min(rem_len, cnode->length);
00639
00640 if (!rem_len)
00641 {
00642 break;
00643 }
00644
00645
00646 if (next_node)
00647 {
00648
00649 rem_len -= co_min(rem_len, next_node->start_addr - (cnode->start_addr + cnode->length));
00650 }
00651 else
00652 {
00653
00654 rem_len -= co_min(rem_len, bfr_env.bfr_mem_eaddr - (cnode->start_addr + cnode->length));
00655 }
00656
00657
00658 cnode = next_node;
00659 }
00660
00661
00662 return (rem_len == 0);
00663 }
00664
00674 static struct bfr_mem_node *bfr_get_node(uint16_t length)
00675 {
00676
00677 uint16_t pad_length = (length & 0xFFFC) + 4;
00678
00679
00680 struct bfr_mem_node *cnode = (struct bfr_mem_node *)co_list_pick(&bfr_env.nodes);
00681
00682 struct bfr_mem_node *nnode = NULL;
00683
00684 struct bfr_mem_node *pnode = NULL;
00685
00686
00687 struct bfr_mem_node *bnode = NULL;
00688
00689 uint16_t best_addr = 0;
00690
00691 uint8_t nb_nodes = 0xFF;
00692
00693 if (!cnode)
00694 {
00695
00696 best_addr = BFR_MEM_START_ADDR;
00697 nb_nodes = 0;
00698 }
00699 else
00700 {
00701
00702 uint16_t start_addr = BFR_MEM_START_ADDR;
00703
00704
00705 while (cnode)
00706 {
00707
00708 uint16_t ava_length = cnode->start_addr - start_addr;
00709
00710
00711 if (ava_length >= pad_length)
00712 {
00713
00714 nb_nodes = 0;
00715 bnode = pnode;
00716 best_addr = start_addr;
00717 break;
00718 }
00719 else
00720 {
00721 do
00722 {
00723
00724 uint8_t new_nb_nodes = 0xFF;
00725
00726
00727 if (nb_nodes == 1)
00728 {
00729 break;
00730 }
00731
00732
00733 if (!bfr_check_next_nodes(pad_length - ava_length, &cnode, &new_nb_nodes))
00734 {
00735 break;
00736 }
00737
00738 if (new_nb_nodes < nb_nodes)
00739 {
00740
00741 nb_nodes = new_nb_nodes;
00742 best_addr = start_addr;
00743 bnode = pnode;
00744 }
00745
00746 } while (0);
00747 }
00748
00749
00750 start_addr = cnode->start_addr + cnode->length;
00751
00752
00753 pnode = cnode;
00754 cnode = (struct bfr_mem_node *)cnode->hdr.next;
00755 }
00756
00757
00758 if (best_addr == 0)
00759 {
00760
00761 uint16_t ava_length = bfr_env.bfr_mem_eaddr - start_addr;
00762
00763
00764 if (ava_length >= pad_length)
00765 {
00766
00767 nb_nodes = 0;
00768 bnode = pnode;
00769 best_addr = start_addr;
00770 }
00771 }
00772 }
00773
00774
00775 if (best_addr != 0)
00776 {
00777
00778 while (nb_nodes)
00779 {
00780
00781 cnode = (bnode)
00782 ? (struct bfr_mem_node *)bnode->hdr.next
00783 : (struct bfr_mem_node *)co_list_pick(&bfr_env.nodes);
00784
00785
00786 bfr_remove_node(cnode);
00787
00788 nb_nodes--;
00789 }
00790
00791
00792 nnode = (struct bfr_mem_node *)co_list_pop_front(&bfr_env.free_nodes);
00793
00794
00795 ASSERT_ERR(nnode);
00796
00797
00798 nnode->start_addr = best_addr;
00799 nnode->length = pad_length;
00800 nnode->nb_frames = 0;
00801
00802
00803 co_list_insert_after(&bfr_env.nodes, (bnode) ? &bnode->hdr : NULL, &nnode->hdr);
00804 }
00805
00806
00807 return (nnode);
00808 }
00809
00818 static uint8_t bfr_get_smm_index(struct bfr_mem_node *node)
00819 {
00820 uint8_t smm_index = BFR_INVALID_SMM_INDEX;
00821
00822
00823 for (int i = 0; i < BFR_MEM_REP_NB_MAX; i++)
00824 {
00825 uint16_t *smm_ptr = &bfr_smm_ptrs[i];
00826
00827 if (*smm_ptr == 0)
00828 {
00829
00830 uint32_t a_bfr;
00831 uint32_t index_val;
00832
00833 *smm_ptr = node->start_addr;
00834 smm_index = i;
00835
00836
00837 a_bfr = BFR_MEM_BASE_ADDR + ((smm_index >> 1) * 4);
00838
00839 if (smm_index & 1)
00840 {
00841 uint16_t *adj_smm_ptr = &bfr_smm_ptrs[i - 1];
00842
00843 index_val = (uint32_t)(*adj_smm_ptr) | ((uint32_t)(*smm_ptr) << 16);
00844 }
00845 else
00846 {
00847 uint16_t *adj_smm_ptr = &bfr_smm_ptrs[i + 1];
00848
00849 index_val = (uint32_t)(*smm_ptr) | ((uint32_t)(*adj_smm_ptr) << 16);
00850 }
00851
00852
00853 REG_PL_WR(a_bfr, index_val);
00854
00855 break;
00856 }
00857 }
00858
00859 return (smm_index);
00860 }
00861
00875 static uint16_t bfr_get_report_max_length(struct bfr_info_sta *bfr, bool mu)
00876 {
00877
00878 uint32_t length;
00879
00880 uint8_t nr, nc, b_phy, b_psy, na;
00881
00882 uint16_t ns;
00883
00884 uint8_t bw = bfr_get_bw(&vif_info_tab[bfr->vif_idx]);
00885
00886 if (mu)
00887 {
00888 nc = bfr->bfee_nss + 1;
00889 b_phy = BFR_NB_BIT_PHY_MU;
00890 b_psy = BFR_NB_BIT_PSY_MU;
00891 }
00892 else
00893 {
00894 nc = 1;
00895 b_phy = BFR_NB_BIT_PHY_SU;
00896 b_psy = BFR_NB_BIT_PSY_SU;
00897 }
00898
00899 nr = bfr_env.bfer_nss + 1;
00900 na = BFR_GET_NA(nc, nr);
00901 ns = bfr_ns[bw];
00902
00903
00904 length = (8 * nc) + (ns * na * ((b_phy + b_psy) >> 1));
00905
00906
00907 if (mu)
00908 {
00909
00910 uint8_t nsp = bfr_nsp[bw];
00911
00912 length += 4 * nc * nsp;
00913 }
00914
00915
00916 return (uint16_t)(length / 8);
00917 }
00918
00934 static struct txdesc *bfr_prep_ndpa(struct bfr_info_sta *bfr, uint8_t *nb_devs)
00935 {
00936
00937 struct tx_hd *thd = NULL;
00938
00939 struct bfr_info_sta *next_bfr;
00940
00941 struct vif_info_tag *vif;
00942
00943 struct txl_frame_desc_tag *frame = NULL;
00944 struct mac_hdr_ctrl *mac_hdr;
00945
00946 struct tx_policy_tbl *pol_tbl;
00947 uint32_t paid_gid;
00948
00949
00950
00951 do
00952 {
00953
00954 *nb_devs = 1;
00955
00956
00957 bfr->sta_info &= BFR_NDPA_AID12_MASK;
00958
00959 vif = &vif_info_tab[bfr->vif_idx];
00960
00961
00962 bfr_env.calib_bw = bfr_get_bw(vif);
00963
00964 if (!BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_MU_CAPABLE))
00965 {
00966 break;
00967 }
00968
00969
00970 BFR_STA_INFO_SET_FBACK_TYPE(bfr->sta_info, BFR_MU_TYPE);
00971 BFR_STA_INFO_SET_NC_INDEX(bfr->sta_info, 0);
00972
00973
00974 if (vif->type == VIF_STA)
00975 {
00976 break;
00977 }
00978
00979 next_bfr = (struct bfr_info_sta *)bfr->hdr.next;
00980
00981
00982
00983
00984
00985 while (next_bfr)
00986 {
00987 #if (NX_CHNL_CTXT)
00988
00989 struct vif_info_tag *next_vif;
00990 #endif //(NX_CHNL_CTXT)
00991
00992
00993 if ((bfr->vif_idx != next_bfr->vif_idx) ||
00994 !BFR_IS_STATUS_BIT_SET(next_bfr->status, BFR_STA_MU_CAPABLE))
00995 {
00996 break;
00997 }
00998
00999 #if (NX_CHNL_CTXT)
01000 next_vif = &vif_info_tab[next_bfr->vif_idx];
01001
01002
01003 if (next_vif->chan_ctxt != vif->chan_ctxt)
01004 {
01005 break;
01006 }
01007 #endif //(NX_CHNL_CTXT)
01008
01009
01010 (*nb_devs)++;
01011
01012
01013 next_bfr->sta_info &= BFR_NDPA_AID12_MASK;
01014
01015
01016 BFR_STA_INFO_SET_FBACK_TYPE(next_bfr->sta_info, BFR_MU_TYPE);
01017 BFR_STA_INFO_SET_NC_INDEX(next_bfr->sta_info, 0);
01018
01019 next_bfr = (struct bfr_info_sta *)next_bfr->hdr.next;
01020 }
01021 } while (0);
01022
01023 next_bfr = bfr;
01024
01025
01026 if (*nb_devs == 1)
01027 {
01028
01029 bfr->sta_info &= BFR_NDPA_AID12_MASK;
01030 }
01031
01032
01033 frame = txl_frame_get(TX_DEFAULT_NDPA_BRP,
01034 BFR_NDPA_SU_LEN + ((*nb_devs - 1) * BFR_NDPA_STA_INFO_LEN));
01035
01036
01037 if (frame == NULL)
01038 return NULL;
01039
01040
01041 mac_hdr = txl_buffer_payload_get(&frame->txdesc);
01042
01043
01044 mac_hdr->fctl = MAC_FCTRL_VHT_NDPA;
01045
01046 mac_hdr->durid = BFR_NDPA_SU_DURATION + BFR_SIFS_DURATION + BFR_NDP_DURATION;
01047
01048
01049 for (int i = 0; i < *nb_devs; i++)
01050 {
01051 mac_hdr->durid += (BFR_SIFS_DURATION
01052 + BFR_GET_REPORT_DURATION(bfr_get_report_max_length(next_bfr, (*nb_devs > 1))));
01053
01054 next_bfr = (struct bfr_info_sta *)next_bfr->hdr.next;
01055 }
01056
01057 next_bfr = bfr;
01058
01059
01060
01061
01062
01063
01064 if (*nb_devs == 1)
01065 {
01066 struct sta_info_tag *sta = &sta_info_tab[bfr->sta_idx];
01067 mac_hdr->addr1 = *sta_mgmt_get_peer_addr(bfr->sta_idx);
01068 paid_gid = sta->paid_gid;
01069 }
01070 else
01071 {
01072 mac_hdr->addr1 = mac_addr_bcst;
01073 paid_gid = 63 << GID_TX_OFT;
01074 }
01075 mac_hdr->addr2 = *vif_mgmt_get_addr(bfr->vif_idx);
01076
01077
01078 for (int i = 0; i < *nb_devs; i++)
01079 {
01080
01081 co_write16p(CPU2HW(mac_hdr) + BFR_NDPA_STA_INFO_OFFSET + (i * BFR_NDPA_STA_INFO_LENGTH),
01082 next_bfr->sta_info);
01083
01084
01085 next_bfr->last_token = bfr_env.token;
01086
01087 next_bfr = (struct bfr_info_sta *)next_bfr->hdr.next;
01088 }
01089
01090
01091 co_write8p(CPU2HW(mac_hdr) + BFR_NDPA_DIALOG_TOKEN_OFFSET,
01092 bfr_env.token << BFR_NPDA_TOKEN_POS);
01093
01094
01095 bfr_env.token = (bfr_env.token + 1) & BFR_NDPA_TOKEN_MAX;
01096
01097
01098
01099
01100
01101
01102 thd = &frame->txdesc.lmac.hw_desc->thd;
01103 thd->macctrlinfo1 |= (mac_hdr->durid << PROT_FRM_DURATION_OFT);
01104 thd->macctrlinfo1 &= ~EXPECTED_ACK_MSK;
01105 thd->macctrlinfo2 |= DONT_TOUCH_DUR;
01106
01107 thd->nextfrmexseq_ptr = 0;
01108 thd->nextmpdudesc_ptr = 0;
01109 thd->macctrlinfo2 &= ~(WHICHDESC_MSK | UNDER_BA_SETUP_BIT);
01110 thd->phyctrlinfo = paid_gid;
01111 thd->statinfo = 0;
01112
01113
01114 pol_tbl = (struct tx_policy_tbl *)HW2CPU(thd->policyentryaddr);
01115
01116
01117 pol_tbl->ratecntrlinfo[0] &= ~BW_TX_RCX_MASK;
01118 pol_tbl->ratecntrlinfo[0] |= ((uint32_t)bfr_env.calib_bw << BW_TX_RCX_OFT);
01119
01120 #if (NX_CHNL_CTXT || NX_P2P)
01121
01122 frame->txdesc.host.vif_idx = bfr->vif_idx;
01123 frame->txdesc.host.staid = bfr->sta_idx;
01124 #endif //(NX_CHNL_CTXT || NX_P2P)
01125
01126 return (&(frame->txdesc));
01127 }
01128
01141 static struct txdesc *bfr_prep_ndp(struct bfr_info_sta *bfr, uint8_t nb_devs)
01142 {
01143
01144 struct txl_frame_desc_tag *frame = txl_frame_get(TX_DEFAULT_NDP, 0);
01145
01146 struct tx_hd *thd;
01147
01148 struct tx_policy_tbl *pol_tbl;
01149
01150 if (frame == NULL)
01151 return NULL;
01152
01153
01154 frame->cfm.cfm_func = bfr_tx_frame_cfm;
01155 frame->cfm.env = bfr;
01156
01157
01158
01159
01160
01161
01162 thd = &frame->txdesc.lmac.hw_desc->thd;
01163 thd->macctrlinfo1 &= ~EXPECTED_ACK_MSK;
01164 thd->macctrlinfo1 |= EXPECTED_ACK_NORMAL_ACK;
01165 thd->macctrlinfo2 &= ~DONT_TOUCH_DUR;
01166 thd->phyctrlinfo &= ~(GID_TX_MASK | PAID_TX_MASK);
01167 if (nb_devs > 1)
01168 {
01169 thd->phyctrlinfo = 63 << GID_TX_OFT;
01170 }
01171 else
01172 {
01173 struct sta_info_tag *sta = &sta_info_tab[bfr->sta_idx];
01174 thd->phyctrlinfo = sta->paid_gid;
01175 }
01176
01177 thd->nextfrmexseq_ptr = 0;
01178 thd->nextmpdudesc_ptr = 0;
01179 thd->macctrlinfo2 &= ~(WHICHDESC_MSK | UNDER_BA_SETUP_BIT);
01180 thd->statinfo = 0;
01181
01182
01183 pol_tbl = (struct tx_policy_tbl *)HW2CPU(thd->policyentryaddr);
01184
01185
01186 pol_tbl->ratecntrlinfo[0] &= ~BW_TX_RCX_MASK;
01187 pol_tbl->ratecntrlinfo[0] |= ((uint32_t)bfr_env.calib_bw << BW_TX_RCX_OFT);
01188
01189 #if (NX_CHNL_CTXT || NX_P2P)
01190
01191 frame->txdesc.host.vif_idx = bfr->vif_idx;
01192 frame->txdesc.host.staid = bfr->sta_idx;
01193 #endif //(NX_CHNL_CTXT || NX_P2P)
01194
01195 return (&(frame->txdesc));
01196 }
01197
01209 static struct txdesc *bfr_prep_bfr_poll(struct bfr_info_sta *bfr)
01210 {
01211
01212 struct txl_frame_desc_tag *frame = txl_frame_get(TX_DEFAULT_NDPA_BRP, BFR_BRP_LEN);
01213
01214 struct tx_hd *thd;
01215 struct mac_hdr_ctrl *mac_hdr;
01216
01217 struct tx_policy_tbl *pol_tbl;
01218 struct sta_info_tag *sta = &sta_info_tab[bfr->sta_idx];
01219
01220
01221 if (frame == NULL)
01222 {
01223 return NULL;
01224 }
01225
01226
01227 mac_hdr = txl_buffer_payload_get(&frame->txdesc);
01228
01229
01230 mac_hdr->fctl = MAC_FCTRL_BFM_REPORT_POLL;
01231 mac_hdr->durid = 0;
01232 mac_hdr->addr1 = *sta_mgmt_get_peer_addr(bfr->sta_idx);
01233 mac_hdr->addr2 = *vif_mgmt_get_addr(bfr->vif_idx);
01234
01235
01236 co_write8p(CPU2HW(mac_hdr) + BFR_BRP_RETX_BITMAP_OFFSET, 0xFF);
01237
01238
01239
01240
01241
01242
01243 thd = &frame->txdesc.lmac.hw_desc->thd;
01244 thd->macctrlinfo1 &= ~EXPECTED_ACK_MSK;
01245 thd->macctrlinfo1 |= EXPECTED_ACK_NORMAL_ACK;
01246 thd->macctrlinfo2 &= ~DONT_TOUCH_DUR;
01247
01248 thd->nextfrmexseq_ptr = 0;
01249 thd->nextmpdudesc_ptr = 0;
01250 thd->macctrlinfo2 &= ~(WHICHDESC_MSK | UNDER_BA_SETUP_BIT);
01251 thd->statinfo = 0;
01252 thd->phyctrlinfo = sta->paid_gid;
01253
01254
01255 pol_tbl = (struct tx_policy_tbl *)HW2CPU(thd->policyentryaddr);
01256
01257
01258 pol_tbl->ratecntrlinfo[0] &= ~BW_TX_RCX_MASK;
01259 pol_tbl->ratecntrlinfo[0] |= ((uint32_t)bfr_env.calib_bw << BW_TX_RCX_OFT);
01260
01261
01262 frame->cfm.cfm_func = bfr_tx_frame_cfm;
01263 frame->cfm.env = bfr;
01264
01265 #if (NX_CHNL_CTXT || NX_P2P)
01266
01267 frame->txdesc.host.vif_idx = bfr->vif_idx;
01268 frame->txdesc.host.staid = bfr->sta_idx;
01269 #endif //(NX_CHNL_CTXT || NX_P2P)
01270
01271 return (&(frame->txdesc));
01272 }
01273
01301 static uint8_t bfr_upload_report(struct bfr_info_sta *bfr, struct rxdesc *rxdesc,
01302 uint8_t *frame)
01303 {
01304
01305 uint8_t status = BFR_RX_STATUS_VALID;
01306
01307
01308 struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
01309
01310
01311 uint16_t report_idx = bfr->host_report_idx ^ 1;
01312
01313 uint32_t host_addr = bfr->host_report_addr[report_idx];
01314
01315 uint32_t vht_mimo_ctrl = co_read32p(CPU2HW(frame) + BFR_VHT_BFR_VHT_MIMO_CTRL_OFFSET);
01316
01317
01318
01319
01320 uint16_t payload_offset = BFR_VHT_REPORT_OFFSET;
01321
01322 uint16_t upload_len = dma_hdrdesc->hd.frmlen;
01323
01324
01325 if ((BFR_VHT_MIMO_GET_VALUE(vht_mimo_ctrl, CHAN_WIDTH) != bfr_env.calib_bw)
01326 )
01327 {
01328 return (BFR_RX_STATUS_ERROR);
01329 }
01330
01331
01332 PROF_BFR_UPLOAD_SET();
01333
01334 if (!BFR_VHT_MIMO_GET_VALUE(vht_mimo_ctrl, FIRST_SEGM))
01335 {
01336
01337 host_addr += bfr->host_report_len[report_idx];
01338 }
01339 else
01340 {
01341
01342 bfr->host_report_len[report_idx] = 0;
01343
01344 bfr->nb_segments = 1 + BFR_VHT_MIMO_GET_VALUE(vht_mimo_ctrl, REM_SEGM);
01345
01346
01347 payload_offset -= 2;
01348
01349
01350 co_write16p(CPU2HW(frame) + BFR_VHT_BFR_VHT_MIMO_CTRL_OFFSET + 1,
01351 (uint16_t)vht_mimo_ctrl);
01352
01353
01354 bfr->last_rx_nc = BFR_VHT_MIMO_GET_VALUE(vht_mimo_ctrl, NC);
01355 }
01356
01357 upload_len -= payload_offset;
01358
01359 bfr->host_report_len[report_idx] += upload_len;
01360 if (bfr->host_report_len[report_idx] > bfr->host_max_report_len)
01361 {
01362
01363 bfr_end_calibration_for_sta(bfr, false);
01364
01365
01366 return BFR_RX_STATUS_ERROR;
01367 }
01368
01369
01370 rxl_mpdu_partial_transfer(rxdesc, upload_len, host_addr, payload_offset,
01371 bfr_dma_upload_cfm, bfr);
01372
01373 return (status);
01374 }
01375
01390 static uint8_t bfr_download_report(struct bfr_info_sta *bfr, struct dma_desc *dma_desc_bfr)
01391 {
01392
01393 struct bfr_mem_node *node = NULL;
01394
01395 struct bfr_mem_node *sta_node = bfr->node;
01396
01397 uint16_t report_idx = bfr->host_report_idx;
01398
01399
01400 PROF_BFR_DOWNLOAD_SET();
01401
01402
01403 if (sta_node)
01404 {
01405 do
01406 {
01407 if (sta_node->nb_frames)
01408 {
01409
01410 sta_node->sta_idx = INVALID_STA_IDX;
01411 break;
01412 }
01413
01414
01415 if (((bfr->host_report_len[report_idx] & 0xFFFC) + 4) != sta_node->length)
01416 {
01417
01418 bfr_remove_node(sta_node);
01419 break;
01420 }
01421
01422
01423 node = sta_node;
01424 } while (0);
01425 }
01426
01427
01428 if (!node && (bfr_env.nb_used_nodes < BFR_MEM_NODE_NB))
01429 {
01430 node = bfr_get_node(bfr->host_report_len[report_idx]);
01431
01432
01433 if (node)
01434 {
01435
01436 bfr->node = node;
01437 node->sta_idx = bfr->sta_idx;
01438
01439
01440 node->smm_index = bfr_get_smm_index(node);
01441
01442
01443 ASSERT_ERR(node->smm_index != BFR_INVALID_SMM_INDEX);
01444 }
01445 }
01446
01447
01448 if (node)
01449 {
01450
01451 dma_desc_bfr->src = bfr->host_report_addr[report_idx];
01452 dma_desc_bfr->dest = BFR_MEM_BASE_ADDR + node->start_addr;
01453 dma_desc_bfr->length = bfr->host_report_len[report_idx];
01454 dma_desc_bfr->ctrl = 0;
01455 }
01456
01457
01458 PROF_BFR_DOWNLOAD_CLR();
01459
01460 return ((node) ? node->smm_index : BFR_INVALID_SMM_INDEX);
01461 }
01462
01471 static void bfr_start_next_calibration(void)
01472 {
01473
01474 struct bfr_info_sta *bfr;
01475
01476 uint8_t nb_devs;
01477
01478 int i, nb_pkts = 0;
01479
01480 bool bfr_poll_ok;
01481
01482 struct txdesc *txdesc;
01483
01484 struct txdesc *calib_txdesc[2 + RW_USER_MAX];
01485
01486 do
01487 {
01488
01489 if (bfr_env.status != BFR_STATUS_IDLE)
01490 break;
01491
01492
01493 bfr = (struct bfr_info_sta *)co_list_pick(&bfr_env.calib_sched);
01494 if (!bfr)
01495 break;
01496
01497
01498 ASSERT_ERR(bfr->sta_idx != INVALID_STA_IDX);
01499
01500
01501 txdesc = bfr_prep_ndpa(bfr, &nb_devs);
01502 if (!txdesc)
01503 break;
01504
01505
01506 calib_txdesc[nb_pkts++] = txdesc;
01507
01508
01509 txdesc = bfr_prep_ndp(bfr, nb_devs);
01510 if (!txdesc)
01511 break;
01512
01513
01514 calib_txdesc[nb_pkts++] = txdesc;
01515
01516
01517 bfr_poll_ok = true;
01518 for (i = 1; i < nb_devs; i++)
01519 {
01520
01521 bfr = (struct bfr_info_sta *)co_list_next(&bfr->hdr);
01522 ASSERT_ERR(bfr != NULL);
01523
01524
01525 txdesc = bfr_prep_bfr_poll(bfr);
01526 if (!txdesc)
01527 {
01528 bfr_poll_ok = false;
01529 break;
01530 }
01531
01532
01533 calib_txdesc[nb_pkts++] = txdesc;
01534 }
01535
01536
01537 if (!bfr_poll_ok)
01538 break;
01539
01540
01541 if (nb_devs > 1)
01542 {
01543
01544 PROF_BFR_MU_CALIB_SET();
01545
01546
01547 bfr_env.nb_reports = nb_devs;
01548
01549
01550 bfr_env.status = BFR_STATUS_MU_CALIB;
01551 }
01552 else
01553 {
01554
01555 PROF_BFR_SU_CALIB_SET();
01556
01557
01558 bfr_env.status = BFR_STATUS_SU_CALIB;
01559 }
01560
01561 for (i = 0; i < nb_devs; i++)
01562 {
01563
01564 bfr = (struct bfr_info_sta *)co_list_pop_front(&bfr_env.calib_sched);
01565 co_list_push_back(&bfr_env.bfee_sta_list, &bfr->hdr);
01566
01567
01568 BFR_SET_STATUS_BIT(bfr->status, BFR_STA_CALIBRATE);
01569 }
01570
01571
01572
01573
01574
01575
01576 GLOBAL_INT_DISABLE();
01577 for (i = 0; i < nb_pkts; i++)
01578 {
01579 txl_cntrl_push_int(calib_txdesc[i], AC_VO);
01580 }
01581 GLOBAL_INT_RESTORE();
01582
01583
01584 return;
01585 } while (0);
01586
01587
01588
01589
01590 for (i = 0; i < nb_pkts; i++)
01591 {
01592
01593 txl_frame_release(calib_txdesc[i], false);
01594 }
01595 }
01596
01603 static void bfr_calibrate(void)
01604 {
01605
01606 uint32_t current_time = ke_time();
01607
01608 struct bfr_info_sta *su_bfr = NULL;
01609
01610 struct bfr_info_sta *bfr = (struct bfr_info_sta *)co_list_pick(&bfr_env.bfee_sta_list);
01611
01612
01613 while (bfr)
01614 {
01615
01616 struct bfr_info_sta *next_bfr = (struct bfr_info_sta *)bfr->hdr.next;
01617
01618 do
01619 {
01620
01621 if (BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_CALIBRATE))
01622 {
01623 break;
01624 }
01625
01626
01627
01628
01629
01630
01631 if (!td_sta_has_tx_traffic(bfr->sta_idx))
01632 {
01633 if (ke_time_abs_cmp(current_time, bfr->last_calib_time + BFR_CALIB_MAX_DELAY))
01634 {
01635 break;
01636 }
01637 }
01638
01639 #if (NX_UMAC_PRESENT)
01640
01641 if (sta_mgmt_is_in_ps(bfr->sta_idx))
01642 {
01643 break;
01644 }
01645 #endif //(NX_UMAC_PRESENT)
01646
01647
01648 co_list_extract(&bfr_env.bfee_sta_list, &bfr->hdr);
01649
01650
01651
01652
01653
01654
01655 if (!BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_MU_CAPABLE))
01656 {
01657 if (!su_bfr)
01658 {
01659 su_bfr = bfr;
01660 }
01661
01662
01663 co_list_push_back(&bfr_env.calib_sched, &bfr->hdr);
01664 }
01665 else
01666 {
01667
01668 co_list_insert_before(&bfr_env.calib_sched, (struct co_list_hdr *)su_bfr,
01669 &bfr->hdr);
01670 }
01671 } while (0);
01672
01673
01674 bfr = next_bfr;
01675 }
01676
01677
01678 bfr_start_next_calibration();
01679 }
01680
01687 static void bfr_init_sta_info(struct bfr_info_sta *bfr)
01688 {
01689
01690 memset(bfr, 0, sizeof(struct bfr_info_sta));
01691
01692
01693 bfr->sta_idx = INVALID_STA_IDX;
01694 }
01695
01701 static void bfr_init_index_table(void)
01702 {
01703 for (int i = 0; i < (BFR_MEM_REP_NB_MAX / 2); i++)
01704 {
01705 uint32_t *bfr_ptr = HW2CPU(BFR_MEM_BASE_ADDR + (i * 4));
01706
01707 *bfr_ptr = 0;
01708 }
01709 }
01710
01711
01712
01713
01714
01715
01716 void bfr_init(void)
01717 {
01718 struct bfr_mem_node *node;
01719
01720
01721 memset(&bfr_env, 0, sizeof(bfr_env));
01722
01723
01724 bfr_env.bfr_enabled = hal_machw_bfmer_support();
01725
01726 if (bfr_is_enabled())
01727 {
01728
01729 bfr_env.bfr_mem_eaddr = (phy_get_bfr_mem_size() << 10);
01730
01731
01732 memset(&bfr_nodes[0], 0, BFR_MEM_NODE_NB * sizeof(struct bfr_mem_node));
01733
01734
01735 for (int i = 0; i < BFR_MEM_NODE_NB; i++)
01736 {
01737
01738 node = &bfr_nodes[i];
01739
01740
01741 node->idx = i;
01742
01743 co_list_push_back(&bfr_env.free_nodes, &node->hdr);
01744 }
01745
01746
01747 for (int i = 0; i < NX_REMOTE_STA_MAX; i++)
01748 {
01749 bfr_init_sta_info(&bfr_sta_infos[i]);
01750 }
01751
01752
01753 for (int i = 0; i < BFR_MEM_REP_NB_MAX; i++)
01754 {
01755 bfr_smm_ptrs[i] = 0;
01756 }
01757
01758
01759 bfr_env.calib_tmr.cb = bfr_calib_tmr_exp_cb;
01760
01761 bfr_env.calib_tmr_dur = BFR_CALIB_TMR_DFLT_DUR;
01762
01763
01764 bfr_init_index_table();
01765
01766
01767 bfr_env.bfer_nss = phy_get_nss();
01768
01769 PROF_SMM_IDX_SET(0xF);
01770 }
01771 else
01772 {
01773 dbg(D_CRT "Disable Beamformer as MAC and/or PHY does not support it\n");
01774 }
01775 }
01776
01777 void bfr_add_sta_ind(uint8_t sta_idx, bool mu_capable, uint16_t aid, uint32_t host_addr,
01778 uint16_t host_length, uint8_t nss)
01779 {
01780
01781 struct vif_info_tag *vif = &vif_info_tab[sta_mgmt_get_vif_idx(sta_idx)];
01782 uint8_t band = vif_mgmt_get_band(vif);
01783
01784
01785 if (band == PHY_BAND_5G)
01786 {
01787
01788 struct bfr_info_sta *bfr = &bfr_sta_infos[sta_idx];
01789
01790
01791 bfr->sta_idx = sta_idx;
01792 bfr->host_max_report_len = host_length/2;
01793 bfr->host_report_addr[0] = host_addr;
01794 bfr->host_report_addr[1] = host_addr + bfr->host_max_report_len;
01795 bfr->host_report_idx = 0;
01796 bfr->bfee_nss = nss;
01797 bfr->vif_idx = sta_mgmt_get_vif_idx(sta_idx);
01798 bfr->last_calib_time = hal_machw_time();
01799
01800 if (vif->type == VIF_AP)
01801 {
01802 BFR_STA_INFO_SET_AID12(bfr->sta_info, aid);
01803 }
01804 else
01805 {
01806
01807 BFR_STA_INFO_SET_AID12(bfr->sta_info, 0);
01808 }
01809
01810 if (mu_capable)
01811 {
01812 BFR_SET_STATUS_BIT(bfr->status, BFR_STA_MU_CAPABLE);
01813 }
01814
01815
01816 if (co_list_is_empty(&bfr_env.bfee_sta_list) && co_list_is_empty(&bfr_env.calib_sched))
01817 {
01818 mm_timer_set(&bfr_env.calib_tmr, hal_machw_time() + bfr_env.calib_tmr_dur);
01819 }
01820
01821
01822 co_list_push_back(&bfr_env.bfee_sta_list, &bfr->hdr);
01823 }
01824 }
01825
01826 void bfr_del_sta_ind(uint8_t sta_idx)
01827 {
01828
01829 struct bfr_info_sta *bfr = &bfr_sta_infos[sta_idx];
01830
01831 do
01832 {
01833 if (bfr->sta_idx == INVALID_STA_IDX)
01834 {
01835 break;
01836 }
01837
01838
01839 co_list_extract(&bfr_env.bfee_sta_list, &bfr->hdr);
01840 co_list_extract(&bfr_env.calib_sched, &bfr->hdr);
01841
01842
01843 if (BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_CALIBRATE))
01844 {
01845 bfr_end_calibration_for_sta(bfr, false);
01846 }
01847
01848
01849 if (co_list_is_empty(&bfr_env.bfee_sta_list) && co_list_is_empty(&bfr_env.calib_sched))
01850 {
01851 mm_timer_clear(&bfr_env.calib_tmr);
01852 }
01853
01854 if (bfr->node)
01855 {
01856 if (bfr->node->nb_frames)
01857 {
01858 bfr->node->sta_idx = INVALID_STA_IDX;
01859 }
01860 else
01861 {
01862
01863 bfr_remove_node(bfr->node);
01864 }
01865 }
01866
01867
01868 bfr_init_sta_info(bfr);
01869 } while (0);
01870 }
01871
01872 uint8_t bfr_rx_frame_ind(uint8_t sta_idx, struct rxdesc *rxdesc, uint8_t *frame)
01873 {
01874
01875 uint8_t status = BFR_RX_STATUS_NOT_VALID;
01876
01877 do
01878 {
01879
01880 struct bfr_info_sta *bfr = &bfr_sta_infos[sta_idx];
01881
01882 uint32_t vht_mimo_ctrl;
01883
01884
01885 if (bfr->sta_idx == INVALID_STA_IDX)
01886 {
01887 break;
01888 }
01889
01890
01891 if (!BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_CALIBRATE))
01892 {
01893 break;
01894 }
01895
01896
01897 if (!bfr_is_vht_bfr(frame))
01898 {
01899 break;
01900 }
01901
01902
01903 PROF_BFR_RX_BFR_SET();
01904
01905 vht_mimo_ctrl = co_read32p(CPU2HW(frame) + BFR_VHT_BFR_VHT_MIMO_CTRL_OFFSET);
01906
01907
01908 if (bfr->last_token != BFR_VHT_MIMO_GET_VALUE(vht_mimo_ctrl, TOKEN))
01909 {
01910
01911 bfr_end_calibration_for_sta(bfr, false);
01912 break;
01913 }
01914
01915
01916 status = bfr_upload_report(bfr, rxdesc, frame);
01917
01918 if (status == BFR_RX_STATUS_ERROR)
01919 {
01920
01921 bfr_end_calibration_for_sta(bfr, false);
01922 }
01923
01924
01925 PROF_BFR_RX_BFR_CLR();
01926 } while (0);
01927
01928 return (status);
01929 }
01930
01931 bool bfr_tx_frame_ind(struct txdesc *txdesc, struct dma_desc *dma_desc_bfr)
01932 {
01933
01934 struct bfr_info_sta *bfr;
01935
01936 bool download = false;
01937
01938 uint8_t smm_index = BFR_INVALID_SMM_INDEX;
01939
01940 do
01941 {
01942 if (txdesc->host.staid == INVALID_STA_IDX)
01943 {
01944 break;
01945 }
01946
01947 bfr = &bfr_sta_infos[txdesc->host.staid];
01948
01949
01950 if (bfr->sta_idx == INVALID_STA_IDX)
01951 {
01952 break;
01953 }
01954
01955
01956 if (!bfr_is_frame_bf_compliant(txdesc, bfr))
01957 {
01958 break;
01959 }
01960
01961
01962 PROF_BFR_TX_IND_SET();
01963
01964
01965 if (bfr->node)
01966 {
01967
01968
01969
01970
01971 if (!BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_REPORT_UPDATED))
01972 {
01973 struct bfr_mem_node *node = bfr->node;
01974
01975 smm_index = node->smm_index;
01976
01977
01978 bfr_increase_nb_frames(bfr->node);
01979
01980
01981 txdesc->lmac.bfr_node = bfr->node;
01982 break;
01983 }
01984 }
01985
01986
01987 if (!BFR_IS_STATUS_BIT_SET(bfr->status, BFR_STA_HAS_VALID_REPORT))
01988 {
01989 break;
01990 }
01991
01992
01993 smm_index = bfr_download_report(bfr, dma_desc_bfr);
01994
01995 if (smm_index != BFR_INVALID_SMM_INDEX)
01996 {
01997
01998 BFR_RESET_STATUS_BIT(bfr->status, BFR_STA_REPORT_UPDATED);
01999
02000 download = true;
02001
02002
02003 bfr_increase_nb_frames(bfr->node);
02004
02005
02006 txdesc->lmac.bfr_node = bfr->node;
02007 }
02008 } while (0);
02009
02010
02011 PROF_BFR_TX_IND_CLR();
02012 PROF_SMM_IDX_SET(smm_index);
02013
02014 return (download);
02015 }
02016
02017 void bfr_tx_cfm(struct txdesc *txdesc)
02018 {
02019 do
02020 {
02021
02022 struct bfr_mem_node *node = txdesc->lmac.bfr_node;
02023
02024 if (!node)
02025 {
02026
02027 break;
02028 }
02029
02030
02031 PROF_BFR_TX_CFM_SET();
02032
02033
02034
02035 GLOBAL_INT_DISABLE();
02036
02037
02038 ASSERT_WARN(node->nb_frames);
02039
02040
02041 node->nb_frames--;
02042
02043 if (!node->nb_frames)
02044 {
02045 bfr_env.nb_used_nodes--;
02046 }
02047
02048
02049
02050
02051
02052 if ((node->sta_idx == INVALID_STA_IDX) && (!node->nb_frames))
02053 {
02054 bfr_remove_node(node);
02055 }
02056
02057 GLOBAL_INT_RESTORE();
02058
02059
02060 PROF_BFR_TX_CFM_CLR();
02061 } while (0);
02062 }
02063
02064 #if (NX_UMAC_PRESENT)
02065 uint8_t bfr_get_last_nc(uint8_t sta_idx)
02066 {
02067
02068 struct bfr_info_sta *bfr = &bfr_sta_infos[sta_idx];
02069
02070 uint8_t nc = BFR_INVALID_NC;
02071
02072 do
02073 {
02074
02075 if (bfr->sta_idx == INVALID_STA_IDX)
02076 {
02077 break;
02078 }
02079
02080 nc = bfr->last_rx_nc;
02081 } while (0);
02082
02083 return (nc);
02084 }
02085 #endif //(NX_UMAC_PRESENT)
02086
02087 #if RW_MUMIMO_TX_EN
02088
02097 static void bfr_group_update_cfm(void *env, uint32_t status)
02098 {
02099
02100 struct mm_mu_group_update_req const *param = env;
02101 struct ke_msg *msg = ke_param2msg(param);
02102
02103
02104 ke_msg_send_basic(MM_MU_GROUP_UPDATE_CFM, msg->src_id, msg->dest_id);
02105
02106
02107 ke_msg_free(msg);
02108 }
02109
02110 void bfr_group_update_req(struct mm_mu_group_update_req const *param)
02111 {
02112 uint8_t sta_idx = param->sta_idx;
02113 struct txl_frame_desc_tag *frame;
02114 struct mac_hdr *buf;
02115 struct tx_hd *thd;
02116 uint32_t length = 0;
02117 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
02118 struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
02119 uint32_t payload;
02120 int txtype;
02121 int i;
02122
02123
02124 txtype = vif_mgmt_get_txtype(vif);
02125 frame = txl_frame_get(txtype, NX_TXFRAME_LEN);
02126 if (frame == NULL)
02127 {
02128 bfr_group_update_cfm((void *)param, 0);
02129 return;
02130 }
02131
02132
02133 tpc_update_frame_tx_power(vif, frame);
02134
02135
02136 buf = txl_buffer_payload_get(&frame->txdesc);
02137
02138
02139 buf->fctl = MAC_FCTRL_ACTION;
02140
02141 buf->durid = 0;
02142
02143 MAC_ADDR_CPY(&buf->addr1, sta_mgmt_get_peer_addr(sta_idx));
02144
02145 MAC_ADDR_CPY(&buf->addr2, vif_mgmt_get_addr(sta->inst_nbr));
02146
02147 MAC_ADDR_CPY(&buf->addr3, vif_mgmt_get_addr(sta->inst_nbr));
02148 buf->seq = txl_get_seq_ctrl();
02149
02150
02151 frame->cfm.cfm_func = bfr_group_update_cfm;
02152 frame->cfm.env = (void *)param;
02153
02154 #if (NX_CHNL_CTXT || NX_P2P)
02155
02156 frame->txdesc.host.vif_idx = sta->inst_nbr;
02157 frame->txdesc.host.staid = sta_idx;
02158 #endif //(NX_CHNL_CTXT || NX_P2P)
02159
02160 length = MAC_SHORT_MAC_HDR_LEN;
02161
02162 #if NX_MFP
02163 frame->txdesc.umac.head_len = 0;
02164 frame->txdesc.umac.tail_len = 0;
02165 if (MFP_UNICAST_PROT == mfp_protect_mgmt_frame(&frame->txdesc, buf->fctl,
02166 MAC_VHT_ACTION_CATEGORY))
02167 {
02168 txu_cntrl_protect_mgmt_frame(&frame->txdesc, buf, MAC_SHORT_MAC_HDR_LEN);
02169 length += frame->txdesc.umac.head_len;
02170 }
02171 #endif
02172
02173 payload = CPU2HW(buf) + length;
02174 length += MAC_GROUP_ID_MGT_PAYL_LENGTH;
02175
02176 co_write8p(payload, MAC_VHT_ACTION_CATEGORY);
02177 co_write8p(payload + MAC_ACTION_ACTION_OFT, MAC_GROUP_ID_MGMT_VHT_ACTION);
02178
02179
02180 for (i = 0; i < 8; i++)
02181 {
02182 co_write8p(payload + MAC_GROUP_ID_MGT_MEMBERSHIP_OFT + i, 0);
02183 }
02184
02185
02186 for (i = 0; i < 16; i++)
02187 {
02188 co_write8p(payload + MAC_GROUP_ID_MGT_USER_POS_OFT + i, 0);
02189 }
02190
02191
02192 for (i = 0; i < param->group_cnt; i++)
02193 {
02194 int group_id = param->groups[i].group_id;
02195 uint8_t user_pos = param->groups[i].user_pos;
02196 int group_byte_idx = group_id / 8;
02197 int group_bit = group_id % 8;
02198 int user_byte_idx = group_id / 4;
02199 int user_bit = (group_id % 4) * 2;
02200 uint32_t membership_addr = payload + MAC_GROUP_ID_MGT_MEMBERSHIP_OFT + group_byte_idx;
02201 uint32_t userpos_addr = payload + MAC_GROUP_ID_MGT_USER_POS_OFT + user_byte_idx;
02202
02203 co_write8p(membership_addr, co_read8p(membership_addr) | (1 << group_bit));
02204 co_write8p(userpos_addr, co_read8p(userpos_addr) | (user_pos << user_bit));
02205 }
02206
02207 #if NX_MFP
02208 length += frame->txdesc.umac.tail_len;
02209 #endif
02210 thd = &frame->txdesc.lmac.hw_desc->thd;
02211 thd->dataendptr = (uint32_t)thd->datastartptr + length - 1;
02212 thd->frmlen = length + MAC_FCS_LEN;
02213
02214
02215 txl_frame_push(frame, AC_VO);
02216 }
02217 #endif //RW_MUMIMO_TX_EN
02218
02219 #endif //(RW_BFMER_EN)
02220