00001
00020
00021
00022
00023
00024 #include "co_int.h"
00025 #include "co_bool.h"
00026 #include <string.h>
00027
00028 #include "dbg_assert.h"
00029 #include "mac.h"
00030 #include "mac_frame.h"
00031 #include "mm.h"
00032 #include "macif.h"
00033 #include "rxl_hwdesc.h"
00034 #include "txl_buffer.h"
00035 #include "tx_swdesc.h"
00036 #include "txl_he.h"
00037 #include "txl_cfm.h"
00038 #include "txl_agg.h"
00039 #include "txl_cntrl.h"
00040 #include "rxl_cntrl.h"
00041 #include "reg_mac_pl.h"
00042 #include "reg_mac_core.h"
00043 #include "dbg.h"
00044 #include "sta_mgmt.h"
00045 #include "vif_mgmt.h"
00046
00047
00048 #if NX_MAC_HE
00049
00050
00051
00052
00053
00059 static const uint16_t TX_HE_RATE_TO_MIN_SEP[12*2*3] =
00060 {
00061
00062 [ 0] = 2, [ 1] = 2, [ 2] = 1,
00063 [ 6] = 3, [ 7] = 3, [ 8] = 2,
00064 [ 12] = 4, [ 13] = 4, [ 14] = 3,
00065 [ 18] = 5, [ 19] = 5, [ 20] = 4,
00066 [ 24] = 7, [ 25] = 7, [ 26] = 6,
00067 [ 30] = 9, [ 31] = 9, [ 32] = 8,
00068 [ 36] = 10, [ 37] = 10, [ 38] = 9,
00069 [ 42] = 11, [ 43] = 11, [ 44] = 10,
00070 [ 48] = 13, [ 49] = 13, [ 50] = 11,
00071 [ 54] = 15, [ 55] = 14, [ 56] = 13,
00072 [ 60] = 17, [ 61] = 16, [ 62] = 14,
00073 [ 66] = 18, [ 67] = 17, [ 68] = 16,
00074
00075 [ 3] = 5, [ 4] = 5, [ 5] = 4,
00076 [ 9] = 10, [ 10] = 9, [ 11] = 8,
00077 [ 15] = 14, [ 16] = 13, [ 17] = 12,
00078 [ 21] = 19, [ 22] = 18, [ 23] = 16,
00079 [ 27] = 28, [ 28] = 26, [ 29] = 23,
00080 [ 33] = 37, [ 34] = 35, [ 35] = 31,
00081 [ 39] = 41, [ 40] = 39, [ 41] = 35,
00082 [ 45] = 46, [ 46] = 43, [ 47] = 39,
00083 [ 51] = 55, [ 52] = 52, [ 53] = 46,
00084 [ 57] = 61, [ 58] = 57, [ 59] = 52,
00085 [ 63] = 68, [ 64] = 64, [ 65] = 58,
00086 [ 69] = 76, [ 70] = 71, [ 71] = 64,
00087 };
00088
00093 static const uint16_t TX_HE_RATE_TO_32US_LEN[12*2*3] =
00094 {
00095
00096 [ 0] = 34, [ 1] = 32, [ 2] = 29,
00097 [ 6] = 68, [ 7] = 65, [ 8] = 58,
00098 [ 12] = 103, [ 13] = 97, [ 14] = 87,
00099 [ 18] = 137, [ 19] = 130, [ 20] = 117,
00100 [ 24] = 206, [ 25] = 195, [ 26] = 175,
00101 [ 30] = 275, [ 31] = 260, [ 32] = 234,
00102 [ 36] = 309, [ 37] = 292, [ 38] = 263,
00103 [ 42] = 344, [ 43] = 325, [ 44] = 292,
00104 [ 48] = 412, [ 49] = 390, [ 50] = 351,
00105 [ 54] = 458, [ 55] = 433, [ 56] = 390,
00106 [ 60] = 516, [ 61] = 487, [ 62] = 438,
00107 [ 66] = 573, [ 67] = 541, [ 68] = 487,
00108
00109 [ 3] = 144, [ 4] = 136, [ 5] = 122,
00110 [ 9] = 288, [ 10] = 272, [ 11] = 245,
00111 [ 15] = 432, [ 16] = 408, [ 17] = 367,
00112 [ 21] = 576, [ 22] = 544, [ 23] = 490,
00113 [ 27] = 864, [ 28] = 816, [ 29] = 735,
00114 [ 33] = 1152, [ 34] = 1088, [ 35] = 980,
00115 [ 39] = 1297, [ 40] = 1225, [ 41] = 1102,
00116 [ 45] = 1441, [ 46] = 1361, [ 47] = 1225,
00117 [ 51] = 1729, [ 52] = 1633, [ 53] = 1470,
00118 [ 57] = 1921, [ 58] = 1814, [ 59] = 1633,
00119 [ 63] = 2161, [ 64] = 2041, [ 65] = 1837,
00120 [ 69] = 2401, [ 70] = 2268, [ 71] = 2041,
00121 };
00122
00127 static const uint16_t TX_HE_26_TONE_TO_MIN_SEP[12*3] =
00128 {
00129
00130 [ 0] = 1, [ 1] = 1, [ 2] = 1,
00131 [ 3] = 1, [ 4] = 1, [ 5] = 1,
00132 [ 6] = 1, [ 7] = 1, [ 8] = 1,
00133 [ 9] = 1, [ 10] = 1, [ 11] = 1,
00134 [ 12] = 1, [ 13] = 1, [ 14] = 1,
00135 [ 15] = 1, [ 16] = 1, [ 17] = 1,
00136 [ 18] = 1, [ 19] = 1, [ 20] = 1,
00137 [ 21] = 2, [ 22] = 2, [ 23] = 1,
00138 [ 24] = 2, [ 25] = 2, [ 26] = 2,
00139 [ 27] = 2, [ 28] = 2, [ 29] = 2,
00140 [ 30] = 2, [ 31] = 2, [ 32] = 2,
00141 [ 33] = 2, [ 34] = 2, [ 35] = 2,
00142 };
00143
00148 static const uint16_t TX_HE_52_TONE_TO_MIN_SEP[12*3] =
00149 {
00150
00151 [ 0] = 1, [ 1] = 1, [ 2] = 1,
00152 [ 3] = 1, [ 4] = 1, [ 5] = 1,
00153 [ 6] = 1, [ 7] = 1, [ 8] = 1,
00154 [ 9] = 1, [ 10] = 1, [ 11] = 1,
00155 [ 12] = 2, [ 13] = 2, [ 14] = 2,
00156 [ 15] = 2, [ 16] = 2, [ 17] = 2,
00157 [ 18] = 2, [ 19] = 2, [ 20] = 2,
00158 [ 21] = 3, [ 22] = 3, [ 23] = 2,
00159 [ 24] = 3, [ 25] = 3, [ 26] = 3,
00160 [ 27] = 3, [ 28] = 3, [ 29] = 3,
00161 [ 30] = 4, [ 31] = 4, [ 32] = 3,
00162 [ 33] = 4, [ 34] = 4, [ 35] = 4,
00163 };
00164
00169 static const uint16_t TX_HE_106_TONE_TO_MIN_SEP[12*3] =
00170 {
00171
00172 [ 0] = 1, [ 1] = 1, [ 2] = 1,
00173 [ 3] = 1, [ 4] = 1, [ 5] = 1,
00174 [ 6] = 2, [ 7] = 2, [ 8] = 2,
00175 [ 9] = 2, [ 10] = 2, [ 11] = 2,
00176 [ 12] = 3, [ 13] = 3, [ 14] = 3,
00177 [ 15] = 4, [ 16] = 4, [ 17] = 4,
00178 [ 18] = 5, [ 19] = 4, [ 20] = 4,
00179 [ 21] = 5, [ 22] = 5, [ 23] = 4,
00180 [ 24] = 6, [ 25] = 6, [ 26] = 5,
00181 [ 27] = 7, [ 28] = 6, [ 29] = 6,
00182 [ 30] = 8, [ 31] = 7, [ 32] = 6,
00183 [ 33] = 8, [ 34] = 8, [ 35] = 7,
00184 };
00185
00188 static const uint8_t fragb2b1_to_bitmap_len[4] =
00189 {
00190 [0] = 8,
00191 [1] = 16,
00192 [2] = 32,
00193 [3] = 4
00194 };
00195
00197 enum
00198 {
00199 RU_26TONE = 0,
00200 RU_52TONE,
00201 RU_106TONE,
00202 RU_242TONE,
00203 RU_484TONE,
00204 RU_996TONE,
00205 RU_2x996TONE,
00206 };
00207
00208 static const uint16_t *ru_1us_tables[3] =
00209 {
00210 [RU_26TONE] = TX_HE_26_TONE_TO_MIN_SEP,
00211 [RU_52TONE] = TX_HE_52_TONE_TO_MIN_SEP,
00212 [RU_106TONE] = TX_HE_106_TONE_TO_MIN_SEP,
00213 };
00214
00216 #define TX_HE_TB_PROG_MIN_TIME 10
00217
00219 #define TX_HE_TB_TIMEOUT 7000
00220
00222 #define TX_HE_TRIG_PERIOD 5000
00223
00225 #define TX_MU_EDCA_TIMER_PERIOD (8 * 1024)
00226
00228 #define TX_HE_TB_MIN_PSDU_LEN CO_ALIGN4_HI(DELIMITER_LEN + MAC_QOS_NULL_FRAME_SIZE + \
00229 MAC_HTC_LEN + MAC_FCS_LEN)
00230
00232 #define BSR_SF_MAX 32768
00233
00235 #define BSR_QSIZE_MAX 254
00236
00238 #define BSR_BUFFERED_MAX (BSR_QSIZE_MAX * BSR_SF_MAX)
00239
00241 #define HTC_HE_UPH_DEF (MAC_HTC_HE_CTRL_ID_UPH | (0x07 << MAC_HTC_HE_CTRL_INFO_OFT))
00242
00243
00244
00245
00246
00248 struct tx_he_tb_bsrp_qos_null_desc
00249 {
00251 struct tx_hd thd;
00253 struct tx_pbd pbd;
00255 uint16_t qos_ctrl;
00256 };
00257
00259 struct tx_he_tb_bsrp_desc
00260 {
00262 struct tx_hd a_thd;
00264 struct mac_hdr hdr;
00266 struct tx_he_tb_bsrp_qos_null_desc qos_null[TID_MAX];
00267 };
00268
00270 struct tx_he_tb_qos_null_desc
00271 {
00273 struct tx_hd thd;
00275 struct mac_hdr_qos_htc payl;
00276 };
00277
00280 struct tx_he_tb_ndp_desc
00281 {
00283 struct tx_hd thd;
00284 };
00285
00287 struct tx_he_tb_desc
00288 {
00290 struct tx_he_tb_bsrp_desc brsp;
00292 struct tx_he_tb_qos_null_desc qos_null;
00294 struct tx_he_tb_ndp_desc ndp;
00296 struct tx_policy_tbl tb_pol;
00297 };
00298
00299
00300
00301
00302
00303 struct txl_he_env_tag txl_he_env;
00304
00306 static struct tx_he_tb_desc he_tb_desc __SHAREDRAM;
00307
00308
00309
00310
00311
00342 __INLINE uint8_t txl_he_bsr_get_sf_and_qsize(uint32_t buffered_all, uint32_t buffered_high,
00343 uint8_t *qsize_all, uint8_t *qsize_high)
00344 {
00345 uint8_t sf;
00346
00347 if (buffered_all <= 4048)
00348 {
00349 sf = 0;
00350 *qsize_all = (CO_ALIGNx_HI(buffered_all, 16)) / 16;
00351 *qsize_high = (CO_ALIGNx_HI(buffered_high, 16)) / 16;
00352 }
00353 else if (buffered_all <= 64768)
00354 {
00355 sf = 1;
00356 *qsize_all = (CO_ALIGNx_HI(buffered_all, 256)) / 256;
00357 *qsize_high = (CO_ALIGNx_HI(buffered_high, 256)) / 256;
00358 }
00359 else if (buffered_all <= 518144)
00360 {
00361 sf = 2;
00362 *qsize_all = (CO_ALIGNx_HI(buffered_all, 2048)) / 2048;
00363 *qsize_high = (CO_ALIGNx_HI(buffered_high, 2048)) / 2048;
00364 }
00365 else
00366 {
00367 buffered_all = (buffered_all > BSR_BUFFERED_MAX) ? BSR_BUFFERED_MAX : buffered_all;
00368 buffered_high = (buffered_high > BSR_BUFFERED_MAX) ? BSR_BUFFERED_MAX : buffered_high;
00369 sf = 3;
00370 *qsize_all = (CO_ALIGNx_HI(buffered_all, 32768)) / 32768;
00371 *qsize_high = (CO_ALIGNx_HI(buffered_high, 32768)) / 32768;
00372 }
00373
00374 return sf;
00375 }
00376
00387 static uint32_t txl_he_dur_to_len(uint32_t rc)
00388 {
00389 uint32_t mcs_idx = (rc & MCS_INDEX_TX_RCX_MASK) >> MCS_INDEX_TX_RCX_OFT;
00390 uint32_t gi = (rc & HE_GI_TYPE_TX_RCX_MASK) >> HE_GI_TYPE_TX_RCX_OFT;
00391 uint32_t bw = (rc & BW_TX_RCX_MASK) >> BW_TX_RCX_OFT;
00392 int idx = mcs_idx * 6 + 3 * (bw >> 1) + gi;
00393 int shift = bw & 0x01;
00394 return (((uint32_t)TX_HE_RATE_TO_32US_LEN[idx]) << shift);
00395 }
00396
00407 static void txl_he_txop_dur_rtscts_thres_apply(uint32_t *rc, uint32_t frm_len,
00408 uint16_t txop_dur_rts_thres)
00409 {
00410 uint32_t rc_loc = *rc;
00411
00412 if (txl_he_is_he_su(rc_loc))
00413 {
00414
00415
00416 uint32_t thres = txl_he_dur_to_len(rc_loc) * (txop_dur_rts_thres - 1);
00417
00418 if (frm_len > thres)
00419 {
00420
00421
00422 if ((rc_loc & PROT_FRM_EX_RCX_MASK) != PROT_NO_PROT)
00423 {
00424
00425 rc_loc &= ~PROT_FRM_EX_RCX_MASK;
00426 rc_loc |= PROT_RTS_CTS;
00427 }
00428 else
00429 {
00430 uint8_t bw, rate, mcs;
00431
00432
00433 bw = (rc_loc & BW_TX_RCX_MASK) >> BW_TX_RCX_OFT;
00434 mcs = rc_loc & VHT_MCS_MASK;
00435 rate = mcs > 2 ? HW_RATE_24MBPS : HW_RATE_6MBPS;
00436 rc_loc &= ~(PROT_FRM_EX_RCX_MASK | MCS_INDEX_PROT_TX_RCX_MASK | BW_PROT_TX_RCX_MASK |
00437 FORMAT_MOD_PROT_TX_RCX_MASK);
00438 rc_loc |= (bw << BW_PROT_TX_RCX_OFT) | (rate << MCS_INDEX_PROT_TX_RCX_OFT) | PROT_RTS_CTS;
00439 rc_loc |= FORMATMOD_NON_HT_DUP_OFDM << FORMAT_MOD_PROT_TX_RCX_OFT;
00440 }
00441
00442 *rc = rc_loc;
00443 }
00444 }
00445 }
00446
00459 static bool txl_he_edca_queue_halted(uint8_t ac)
00460 {
00461
00462 switch (ac)
00463 {
00464 #if NX_BEACONING
00465 case AC_BCN:
00466 return(nxmac_tx_bcn_state_getf() == 0);
00467 #endif
00468 case AC_VO:
00469 return(nxmac_tx_ac_3_state_getf() == 0);
00470 case AC_VI:
00471 return(nxmac_tx_ac_2_state_getf() == 0);
00472 case AC_BE:
00473 return(nxmac_tx_ac_1_state_getf() == 0);
00474 case AC_BK:
00475 return(nxmac_tx_ac_0_state_getf() == 0);
00476 default:
00477 ASSERT_ERR(0);
00478 break;
00479 }
00480 return false;
00481 }
00482
00493 static void txl_he_restart_edca(uint8_t ac)
00494 {
00495 struct mu_edca_param_tag *mu_edca_param = &txl_he_env.mu_edca.params[ac];
00496
00497 if (!mu_edca_param->edca_off)
00498 return;
00499
00500 mu_edca_param->edca_off = false;
00501
00502 if (mu_edca_param->first_frame_exch)
00503 txl_cntrl_newhead(CPU2HW(mu_edca_param->first_frame_exch), ac);
00504
00505 mu_edca_param->first_frame_exch = NULL;
00506 }
00507
00518 static void txl_he_mu_edca_timer(void *env)
00519 {
00520 struct mu_edca_tag *mu_edca = &txl_he_env.mu_edca;
00521 uint32_t *edca_reg = HW2CPU(NXMAC_EDCA_AC_0_ADDR);
00522 uint8_t mu_edca_active = 0;
00523
00524
00525
00526 GLOBAL_INT_DISABLE();
00527
00528
00529 for (int i = 0; i < AC_MAX; i++)
00530 {
00531 uint8_t ac_bit = CO_BIT(i);
00532
00533
00534 if (mu_edca->edca_stopping & ac_bit)
00535 {
00536 if (!txl_he_edca_queue_halted(i))
00537 {
00538
00539 mu_edca_active |= ac_bit;
00540 continue;
00541 }
00542
00543 mu_edca->edca_stopping &= ~ac_bit;
00544 }
00545
00546
00547 if (mu_edca->he_tb_activity & ac_bit)
00548 {
00549 uint8_t aifsn = mu_edca->params[i].edca & 0x0F;
00550 mu_edca->he_tb_activity &= ~ac_bit;
00551 if (aifsn)
00552 {
00553
00554 edca_reg[i] = mu_edca->params[i].edca;
00555
00556
00557 txl_he_restart_edca(i);
00558 }
00559 else if (!mu_edca->params[i].edca_off)
00560 {
00561
00562 mu_edca->params[i].edca_off = true;
00563 mu_edca->edca_stopping |= ac_bit;
00564 }
00565
00566
00567 mu_edca->params[i].timer = mu_edca->params[i].timeout;
00568
00569 mu_edca_active |= ac_bit;
00570 }
00571
00572 else if (mu_edca->params[i].timer > 0)
00573 {
00574
00575 mu_edca->params[i].timer--;
00576
00577 if (mu_edca->params[i].timer == 0)
00578 {
00579
00580 edca_reg[i] = txl_he_env.tb_vif->txq_params[i];
00581
00582
00583 txl_he_restart_edca(i);
00584 }
00585 else
00586 {
00587
00588 mu_edca_active |= ac_bit;
00589 }
00590 }
00591 }
00592
00593
00594 if (mu_edca_active)
00595 mm_timer_set(&mu_edca->timer, hal_machw_time() + TX_MU_EDCA_TIMER_PERIOD);
00596 else
00597 mu_edca->timer.cb = NULL;
00598
00599
00600 GLOBAL_INT_RESTORE();
00601 }
00602
00612 static void txl_he_mu_edca_start(uint8_t ac)
00613 {
00614 struct mu_edca_tag *mu_edca = &txl_he_env.mu_edca;
00615
00616
00617 if (!mu_edca->valid)
00618 return;
00619
00620
00621 mu_edca->he_tb_activity |= CO_BIT(ac);
00622
00623
00624 if (!txl_he_env.mu_edca.timer.cb)
00625 {
00626 ASSERT_REC(txl_he_edca_queue_halted(ac));
00627 mu_edca->timer.cb = txl_he_mu_edca_timer;
00628 txl_he_mu_edca_timer(mu_edca);
00629 }
00630
00631 }
00632
00641 static void txl_he_mu_edca_stop(void)
00642 {
00643 struct mu_edca_tag *mu_edca = &txl_he_env.mu_edca;
00644 uint32_t *edca_reg = HW2CPU(NXMAC_EDCA_AC_0_ADDR);
00645
00646
00647 for (int i = 0; i < AC_MAX; i++)
00648 {
00649
00650 edca_reg[i] = txl_he_env.tb_vif->txq_params[i];
00651
00652
00653 txl_he_restart_edca(i);
00654 }
00655
00656
00657 mm_timer_clear(&mu_edca->timer);
00658 mu_edca->timer.cb = NULL;
00659 }
00660
00661 #if NX_UMAC_PRESENT && NX_BEACONING
00662
00673 static void txl_he_trig_time(void *env)
00674 {
00675 struct sta_info_tag *sta = (struct sta_info_tag *)env;
00676
00677 if (sta->valid)
00678 {
00679 mm_timer_set(&txl_he_env.trig_timer, hal_machw_time() + TX_HE_TRIG_PERIOD);
00680 txl_frame_send_he_trigger(sta->staid, HE_TRIG_TYPE_BASIC, 2500, 37, 5, AC_VI,
00681 NULL, NULL);
00682 }
00683 else
00684 {
00685 txl_he_env.trig_timer.cb = NULL;
00686 txl_he_env.trig_timer.env = NULL;
00687 }
00688 }
00689 #endif // NX_UMAC_PRESENT && NX_BEACONING
00690
00696 static void txl_he_tb_halt_queue(void)
00697 {
00698 nxmac_dma_cntrl_set(NXMAC_HALT_TB_AFTER_TXOP_BIT);
00699 while(nxmac_tx_tb_state_getf() != 0);
00700 nxmac_dma_cntrl_clear(NXMAC_HALT_TB_AFTER_TXOP_BIT);
00701 }
00702
00709 __INLINE void txl_he_tb_timer_start(void)
00710 {
00711 nxmac_abs_timer_set(HAL_HE_TB_TIMER, hal_machw_time() + TX_HE_TB_TIMEOUT);
00712 nxmac_timers_int_event_clear(HAL_HE_TB_TIMER_BIT);
00713 nxmac_timers_int_un_mask_set(nxmac_timers_int_un_mask_get() | HAL_HE_TB_TIMER_BIT);
00714
00715 txl_he_env.tb_ongoing = true;
00716 }
00717
00724 __INLINE void txl_he_tb_timer_clear(void)
00725 {
00726 uint32_t timer_msk = nxmac_timers_int_un_mask_get();
00727
00728 nxmac_timers_int_un_mask_set(timer_msk & ~HAL_HE_TB_TIMER_BIT);
00729 nxmac_timers_int_event_clear(HAL_HE_TB_TIMER_BIT);
00730
00731 txl_he_env.tb_ongoing = false;
00732 }
00733
00745 static uint32_t txl_he_tb_psdulen_get(void)
00746 {
00747 uint32_t common;
00748 uint32_t user;
00749 uint32_t l_length;
00750 uint32_t gi_ltf_type;
00751 uint32_t mcs;
00752 uint32_t rulen;
00753 uint32_t psdulen;
00754 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
00755
00756
00757 common = nxmac_rx_he_trig_common_info_get();
00758 user = nxmac_rx_he_trig_user_info_get();
00759 l_length = (common & NXMAC_UL_LENGTH_MASK) >> NXMAC_UL_LENGTH_LSB;
00760 gi_ltf_type = (common & NXMAC_UL_GILTF_TYPE_MASK) >> NXMAC_UL_GILTF_TYPE_LSB;
00761 mcs = (user & NXMAC_UL_MCS_MASK) >> NXMAC_UL_MCS_LSB;
00762 rulen = (user & NXMAC_UL_RU_SIZE_MASK) >> NXMAC_UL_RU_SIZE_LSB;
00763 he_tb->trig_type = (common & NXMAC_UL_TRIGGER_TYPE_MASK) >> NXMAC_UL_TRIGGER_TYPE_LSB;
00764 he_tb->ul_bw = (common & NXMAC_UL_BW_MASK) >> NXMAC_UL_BW_LSB;
00765 he_tb->ul_length = l_length;
00766 he_tb->gi_type = gi_ltf_type < 2 ? 1 : 2;
00767 he_tb->uora = (user & NXMAC_UL_RU_TYPE_BIT) != 0 ? true : false;
00768 he_tb->ul_mcs = mcs;
00769 he_tb->ul_nss = (user & NXMAC_UL_NSS_MASK) >> NXMAC_UL_NSS_LSB;
00770 he_tb->ru_size = rulen;
00771 if (he_tb->trig_type == HE_TRIG_TYPE_BASIC)
00772 {
00773 uint32_t td_user = (user & NXMAC_TD_USER_INFO_SUBFIELD_MASK)
00774 >> NXMAC_TD_USER_INFO_SUBFIELD_LSB;
00775 he_tb->pref_ac = mac_aci2ac[(td_user & HE_TRIG_PREF_AC_MSK) >> HE_TRIG_PREF_AC_OFT];
00776 he_tb->spacing_factor = (td_user & HE_TRIG_SPC_FACTOR_MSK) >> HE_TRIG_SPC_FACTOR_OFT;
00777 }
00778
00779 while (!nxmac_ul_psdu_len_valid_getf());
00780 psdulen = nxmac_ul_psdu_len_getf();
00781
00782 return CO_ALIGN4_LO(psdulen);
00783 }
00784
00791 static void txl_he_tb_params_compute(void)
00792 {
00793 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
00794 uint16_t len_1us;
00795 uint32_t max_len_phy;
00796 struct sta_info_tag *sta = he_tb->sta;
00797
00798
00799 max_len_phy = txl_he_tb_psdulen_get();
00800
00801
00802 switch (he_tb->ru_size)
00803 {
00804 case RU_26TONE:
00805 case RU_52TONE:
00806 case RU_106TONE:
00807 len_1us = ru_1us_tables[he_tb->ru_size][he_tb->ul_mcs * 3 + he_tb->gi_type];
00808 break;
00809 default:
00810 len_1us = txl_he_idx_to_1us_len_get(he_tb->ul_mcs * 6 + he_tb->gi_type,
00811 he_tb->ru_size - 3);
00812 break;
00813 }
00814
00815 he_tb->max_len = co_min(max_len_phy, sta->ampdu_size_max_he);
00816 he_tb->mmss = len_1us * (uint16_t)sta->ampdu_spacing_min *
00817 (uint16_t)(1 << he_tb->spacing_factor);
00818
00819 he_tb->uph = MAC_HTC_HE(MAC_HTC_HE_CTRL(UPH, nxmac_he_tbuph_control_getf()));
00820 }
00821
00837 static int txl_he_m_ba_aid_tid_len(struct ba_msta_aid_tid_info *aid_tid_info,
00838 int remaining_len)
00839 {
00840 int len;
00841 uint16_t frag;
00842 uint16_t aid = (aid_tid_info->aid_tid & BA_MULTI_STA_AID_MSK) >> BA_MULTI_STA_AID_OFT;
00843
00844 if (aid == 2045)
00845 {
00846 return 12;
00847 }
00848 else if (aid_tid_info->aid_tid & BA_MULTI_STA_ACK_BIT)
00849 {
00850 return 2;
00851 }
00852 else if (remaining_len < (int)sizeof_b(*aid_tid_info))
00853 {
00854 return -1;
00855 }
00856
00857
00858 frag = aid_tid_info->ssc_bitmap.ssc & MAC_SEQCTRL_FRAG_MSK;
00859
00860 if (frag & CO_BIT(3))
00861 return -1;
00862
00863 len = fragb2b1_to_bitmap_len[frag >> 1] + sizeof_b(*aid_tid_info);
00864
00865 if (remaining_len < len)
00866 return -1;
00867
00868
00869 return len;
00870 }
00871
00877 static void txl_he_tb_set_rc_info(void)
00878 {
00879 #if NX_UMAC_PRESENT
00880 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
00881 struct rc_sta_stats *rc_ss = he_tb->sta->pol_tbl.sta_stats;
00882 struct rc_rate_stats *rc_rs = &rc_ss->rate_stats[RC_MAX_N_SAMPLE];
00883
00884 rc_rs->rate_config = (FORMATMOD_HE_MU << FORMAT_MOD_TX_RCX_OFT) |
00885 (he_tb->ul_mcs << VHT_MCS_OFT) | (he_tb->gi_type << HE_GI_TYPE_TX_RCX_OFT) |
00886 (he_tb->ul_bw << BW_TX_RCX_OFT) |(he_tb->ul_nss << VHT_NSS_OFT);
00887 rc_rs->ru_and_length = he_tb->ru_size | (he_tb->ul_length << 3);
00888 #endif
00889 }
00890
00898 static void txl_he_tb_ppdu_chain(struct tx_hd *thd)
00899 {
00900 thd->statinfo &= NUM_MPDU_RETRIES_MSK;
00901 thd->nextfrmexseq_ptr = 0;
00902 thd->policyentryaddr = CPU2HW(&he_tb_desc.tb_pol);
00903 nxmac_tx_tb_head_ptr_set(CPU2HW(thd));
00904 nxmac_dma_cntrl_set(NXMAC_TX_TB_NEW_HEAD_BIT);
00905
00906 txl_he_env.trigger.trig_valid = false;
00907 }
00908
00918 static void txl_he_tb_send_ndp(void)
00919 {
00920 struct tx_hd *thd = &he_tb_desc.ndp.thd;
00921
00922 txl_he_tb_ppdu_chain(thd);
00923 }
00924
00933 static void txl_he_tb_send_qos_null(void)
00934 {
00935 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
00936 struct tx_hd *thd = &he_tb_desc.qos_null.thd;
00937 struct mac_hdr_qos_htc *payl = &he_tb_desc.qos_null.payl;
00938
00939 payl->addr1 = he_tb->ta;
00940 payl->addr2 = txl_he_env.tb_vif->mac_addr;
00941 payl->addr3 = he_tb->ta;
00942 payl->htc = he_tb->uph;
00943
00944 txl_he_tb_ppdu_chain(thd);
00945 }
00946
00954 __INLINE void txl_he_tb_send_bsrp(struct he_trigger_tag *he_tb)
00955 {
00956 struct tx_hd *a_thd = &he_tb_desc.brsp.a_thd;
00957 struct tx_hd *thd_prev = a_thd;
00958 struct mac_hdr *hdr = &he_tb_desc.brsp.hdr;
00959 uint8_t tid, queue_size;
00960 uint16_t nb_delims, subfrm_len;
00961 uint32_t buffered;
00962 uint32_t whichdesc = WHICHDESC_AMPDU_FIRST;
00963
00964 a_thd->frmlen = 0;
00965
00966 hdr->addr1 = he_tb->sta->mac_addr;
00967 hdr->addr2 = txl_he_env.tb_vif->mac_addr;
00968 hdr->addr3 = he_tb->sta->mac_addr;
00969
00970
00971 nb_delims = txl_agg_mpdu_nb_delims(&he_tb_desc.brsp.qos_null[0].thd, he_tb->mmss);
00972 subfrm_len = txl_mpdu_subframe_len(&he_tb_desc.brsp.qos_null[0].thd) + nb_delims * DELIMITER_LEN;
00973
00974 for (tid = 0; tid < TID_MAX; tid++)
00975 {
00976 struct tx_hd *thd = &he_tb_desc.brsp.qos_null[tid].thd;
00977 uint16_t *qos = &he_tb_desc.brsp.qos_null[tid].qos_ctrl;
00978
00979 buffered = macif_buffered_get(he_tb->sta->staid, tid);
00980 if (!buffered)
00981 continue;
00982
00983
00984 if ((a_thd->frmlen + subfrm_len) > he_tb->max_len)
00985 break;
00986
00987 queue_size = txl_he_get_queue_size(buffered);
00988
00989 *qos = MAC_QOSCTRL_QUEUE_SIZE_PRESENT | MAC_QOSCTRL_ACK_NOACK;
00990
00991 *qos |= queue_size << MAC_QOSCTRL_AMSDU_OFT;
00992
00993 *qos |= tid << MAC_QOSCTRL_UP_OFT;
00994
00995 thd->policyentryaddr = 0;
00996 thd->statinfo = 0;
00997 thd->macctrlinfo2 = whichdesc | (nb_delims << NB_BLANK_DELIM_OFT);
00998 whichdesc = WHICHDESC_AMPDU_INT;
00999 thd_prev->nextmpdudesc_ptr = CPU2HW(thd);
01000
01001 a_thd->frmlen += subfrm_len;
01002
01003 thd_prev = thd;
01004 }
01005
01006 if (a_thd->frmlen)
01007 {
01008 thd_prev->nextmpdudesc_ptr = 0;
01009 if ((thd_prev->macctrlinfo2 & WHICHDESC_MSK) == WHICHDESC_AMPDU_FIRST)
01010 {
01011
01012 thd_prev->macctrlinfo2 = WHICHDESC_UNFRAGMENTED_MSDU;
01013 txl_he_tb_ppdu_chain(thd_prev);
01014 }
01015 else
01016 {
01017 thd_prev->macctrlinfo2 &= ~WHICHDESC_MSK;
01018 thd_prev->macctrlinfo2 |= WHICHDESC_AMPDU_LAST;
01019 txl_he_tb_ppdu_chain(a_thd);
01020 }
01021 }
01022 else
01023 {
01024 struct tx_hd *thd = &he_tb_desc.brsp.qos_null[0].thd;
01025 uint16_t *qos = &he_tb_desc.brsp.qos_null[0].qos_ctrl;
01026
01027
01028
01029 *qos = MAC_QOSCTRL_QUEUE_SIZE_PRESENT | MAC_QOSCTRL_ACK_NOACK;
01030 thd->macctrlinfo2 = WHICHDESC_UNFRAGMENTED_MSDU;
01031 thd->nextmpdudesc_ptr = 0;
01032
01033 txl_he_tb_ppdu_chain(thd);
01034 }
01035 }
01043 static void txl_he_tb_send_data(struct tx_hd *thd)
01044 {
01045 #if NX_PROFILING_ON
01046 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01047 #endif
01048
01049 PROF_TX_AC_IRQ_SET(he_tb->ac);
01050
01051
01052 txl_he_tb_timer_start();
01053
01054 txl_he_tb_ppdu_chain(thd);
01055 }
01056
01066 static void txl_he_tb_free_done(struct txdesc *txdesc, uint8_t access_category)
01067 {
01068 struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
01069 struct tx_hd *txhd = &txdesc->lmac.hw_desc->thd;
01070
01071
01072 co_list_pop_front(&(txlist->transmitting[0]));
01073
01074
01075 txlist->ppdu_cnt--;
01076
01077 #if NX_TX_FRAME
01078
01079 if (is_int_frame(txdesc))
01080 {
01081
01082 txl_frame_cfm(txdesc);
01083 }
01084 else
01085 #endif
01086 {
01087
01088 txl_cfm_push(txdesc, txhd->statinfo, access_category);
01089 }
01090 }
01091
01105 static struct tx_hd *txl_he_tb_ppdu_get(struct txdesc **txdesc_next)
01106 {
01107 struct txdesc *txdesc = NULL;
01108 int access_category;
01109 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01110
01111 *txdesc_next = NULL;
01112
01113
01114 if (txl_he_env.tb_ongoing)
01115 return NULL;
01116
01117
01118 for (access_category = AC_VO; access_category >= he_tb->pref_ac; access_category--)
01119 {
01120 struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
01121
01122 he_tb->ac = access_category;
01123
01124
01125
01126
01127 if (txlist->chk_state == BAR_THD_CHK_STATE)
01128 return NULL;
01129
01130 while (1)
01131 {
01132 struct tx_hd *thd;
01133 struct tx_agg_desc *agg_desc;
01134
01135
01136 txdesc = (struct txdesc *)co_list_pick(&(txlist->transmitting[0]));
01137
01138
01139 if (txdesc == NULL)
01140 break;
01141
01142
01143 if (!is_mpdu_agg(txdesc) && (txdesc->lmac.hw_desc->thd.statinfo & DESC_DONE_TX_BIT))
01144 {
01145 txl_he_tb_free_done(txdesc, access_category);
01146 continue;
01147 }
01148
01149 thd = txl_agg_he_tb_prep(txdesc, txdesc_next, he_tb->max_len, he_tb->mmss,
01150 he_tb->ac);
01151
01152 if (!thd)
01153 break;
01154
01155 agg_desc = txdesc->lmac.agg_desc;
01156
01157
01158 ASSERT_ERR(agg_desc != NULL);
01159
01160
01161
01162
01163 agg_desc->status |= AGG_TB;
01164 return thd;
01165 }
01166 }
01167
01168 return NULL;
01169 }
01170
01180 static void txl_he_tb_ac_reconfig(struct txdesc *txdesc)
01181 {
01182 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01183 struct mu_edca_param_tag *mu_edca_param = &txl_he_env.mu_edca.params[he_tb->ac];
01184 struct txl_list *txlist = &txl_cntrl_env.txlist[he_tb->ac];
01185 struct tx_hd *last_thd = NULL;
01186 struct tx_hd *next_thd = NULL;
01187
01188
01189 txl_cntrl_halt_ac(he_tb->ac);
01190
01191
01192 txl_agg_check_saved_agg_desc(he_tb->ac);
01193
01194 do
01195 {
01196
01197
01198 if (!txdesc)
01199 break;
01200
01201 if (is_mpdu_agg(txdesc))
01202 {
01203 struct tx_agg_desc *agg_desc = txdesc->lmac.agg_desc;
01204
01205
01206
01207 if (is_mpdu_last(txdesc))
01208 {
01209
01210
01211
01212 next_thd = last_thd = txl_agg_change_to_singleton(txdesc, false);
01213
01214 if (next_thd)
01215 next_thd->nextfrmexseq_ptr = agg_desc->bar_thd.nextfrmexseq_ptr;
01216
01217 txl_agg_desc_free(agg_desc);
01218 }
01219 else if (is_mpdu_interm(txdesc))
01220 {
01221
01222
01223
01224 next_thd = txl_agg_set_new_ampdu_head(txdesc, &last_thd);
01225 }
01226
01227
01228 else if ((agg_desc->status & (AGG_FORMATTED | AGG_DOWNLOADED)) ==
01229 (AGG_FORMATTED | AGG_DOWNLOADED))
01230 {
01231 next_thd = &agg_desc->a_thd;
01232 last_thd = &agg_desc->bar_thd;
01233 }
01234 }
01235 else
01236 {
01237 if (txl_buffer_get(txdesc) == NULL)
01238 break;
01239
01240 next_thd = last_thd = &txdesc->lmac.hw_desc->thd;
01241
01242
01243 if (!is_htc_sglt_allowed(txdesc))
01244 txl_buffer_remove_htc(next_thd);
01245 }
01246
01247
01248 if (next_thd == NULL)
01249 break;
01250
01251
01252 mu_edca_param->first_frame_exch = next_thd;
01253 if (last_thd->nextfrmexseq_ptr == 0)
01254 txlist->last_frame_exch = last_thd;
01255
01256
01257 return;
01258 } while(0);
01259
01260
01261 txlist->last_frame_exch = NULL;
01262 mu_edca_param->first_frame_exch = NULL;
01263 }
01264
01271 static void txl_he_tb_ppdu_send(void)
01272 {
01273 struct txdesc *txdesc = NULL;
01274 struct tx_hd *thd = NULL;
01275 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01276
01277
01278 if (!he_tb->trig_valid)
01279 {
01280
01281
01282 txl_he_tb_send_ndp();
01283 return;
01284 }
01285
01286
01287 if (he_tb->trig_type == HE_TRIG_TYPE_BSRP)
01288 {
01289 txl_he_tb_send_bsrp(he_tb);
01290 return;
01291 }
01292
01293
01294 thd = txl_he_tb_ppdu_get(&txdesc);
01295
01296 if (thd == NULL)
01297 {
01298 txl_he_tb_send_qos_null();
01299 return;
01300 }
01301
01302
01303 txl_he_tb_send_data(thd);
01304
01305
01306 txl_he_tb_ac_reconfig(txdesc);
01307 }
01308
01314 static void txl_he_tb_desc_init(void)
01315 {
01316 struct tx_hd *thd;
01317 struct mac_hdr_qos *payl;
01318 struct mac_hdr *hdr;
01319 struct tx_policy_tbl *pol = &he_tb_desc.tb_pol;
01320 uint8_t tid;
01321
01322
01323 memset(&he_tb_desc, 0, sizeof(he_tb_desc));
01324
01325
01326
01327
01328
01329
01330 pol->upatterntx = POLICY_TABLE_PATTERN;
01331
01332
01333
01334
01335
01336
01337 payl = (struct mac_hdr_qos *)&he_tb_desc.qos_null.payl;
01338 thd = &he_tb_desc.qos_null.thd;
01339
01340
01341 payl->fctl = MAC_FCTRL_QOS_NULL | MAC_FCTRL_TODS;
01342 payl->qos = MAC_QOSCTRL_ACK_NOACK | MAC_QOSCTRL_HE_QUEUE_SIZE;
01343
01344
01345 thd->upatterntx = TX_HEADER_DESC_PATTERN;
01346 thd->policyentryaddr = CPU2HW(pol);
01347 thd->frmlen = MAC_QOS_NULL_FRAME_SIZE + MAC_HTC_LEN + MAC_FCS_LEN;
01348 thd->datastartptr = CPU2HW(payl);
01349 thd->dataendptr = (uint32_t)thd->datastartptr + thd->frmlen - 1;
01350 thd->first_pbd_ptr = 0;
01351 thd->macctrlinfo1 = EXPECTED_ACK_NO_ACK;
01352
01353
01354
01355
01356
01357
01358 thd = &he_tb_desc.ndp.thd;
01359 thd->upatterntx = TX_HEADER_DESC_PATTERN;
01360 thd->macctrlinfo1 = EXPECTED_ACK_NO_ACK;
01361 thd->policyentryaddr = CPU2HW(pol);
01362
01363
01364
01365
01366
01367
01368 thd = &he_tb_desc.brsp.a_thd;
01369 thd->upatterntx = TX_HEADER_DESC_PATTERN;
01370 thd->macctrlinfo2 = WHICHDESC_AMPDU_EXTRA;
01371 thd->policyentryaddr = CPU2HW(pol);
01372 hdr = &he_tb_desc.brsp.hdr;
01373 hdr->fctl = MAC_FCTRL_QOS_NULL | MAC_FCTRL_TODS;
01374 for (tid = 0; tid < TID_MAX; tid++)
01375 {
01376 struct tx_pbd *pbd = &he_tb_desc.brsp.qos_null[tid].pbd;
01377 thd = &he_tb_desc.brsp.qos_null[tid].thd;
01378
01379 thd->upatterntx = TX_HEADER_DESC_PATTERN;
01380 thd->frmlen = MAC_QOS_NULL_FRAME_SIZE + MAC_FCS_LEN;
01381 thd->datastartptr = CPU2HW(hdr);
01382 thd->dataendptr = (uint32_t)thd->datastartptr + sizeof_b(*hdr) - 1;
01383 thd->first_pbd_ptr = CPU2HW(pbd);
01384 thd->macctrlinfo1 = EXPECTED_ACK_NO_ACK;
01385 pbd->upatterntx = TX_PAYLOAD_DESC_PATTERN;
01386 pbd->datastartptr = CPU2HW(&he_tb_desc.brsp.qos_null[tid].qos_ctrl);
01387 pbd->dataendptr = (uint32_t)pbd->datastartptr + 1;
01388 }
01389 }
01390
01402 static void txl_he_tb_mpdu_transmit_trigger(struct txdesc *txdesc,
01403 uint32_t txstatus)
01404 {
01405 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01406 uint8_t access_category = he_tb->ac;
01407 struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
01408 struct mu_edca_param_tag *mu_edca_param = &txl_he_env.mu_edca.params[access_category];
01409 struct tx_agg_desc *agg_desc = txdesc->lmac.agg_desc;
01410 struct tx_hd *txhd = &txdesc->lmac.hw_desc->thd;
01411
01412
01413
01414
01415
01416
01417
01418 if (txstatus & FRAME_SUCCESSFUL_TX_BIT)
01419 {
01420 if (he_tb->uora)
01421
01422 nxmac_e_ocw_setf(txl_he_env.uora.eocw_min);
01423 else
01424
01425 txl_he_mu_edca_start(he_tb->ac);
01426
01427
01428 rxl_immediate_frame_get();
01429 }
01430 else
01431 {
01432 if (he_tb->uora)
01433 {
01434
01435 uint8_t new_eocw = nxmac_e_ocw_getf();
01436 new_eocw = new_eocw + 1;
01437
01438 if (new_eocw > txl_he_env.uora.eocw_max)
01439 new_eocw = txl_he_env.uora.eocw_max;
01440
01441 nxmac_e_ocw_setf(new_eocw);
01442 }
01443 }
01444
01445
01446 if (!(agg_desc->status & AGG_BA_RECEIVED))
01447 {
01448
01449 co_list_pop_front(&txlist->aggregates);
01450 }
01451 else if (!(agg_desc->status & AGG_BA_VALID))
01452 {
01453
01454 txhd->statinfo &= ~FRAME_SUCCESSFUL_TX_BIT;
01455 txstatus &= ~FRAME_SUCCESSFUL_TX_BIT;
01456 }
01457
01458
01459
01460 txl_agg_release(agg_desc);
01461 txdesc->lmac.agg_desc = NULL;
01462
01463
01464 if (!(txstatus & FRAME_SUCCESSFUL_TX_BIT))
01465 {
01466 uint32_t nb_retry = (txstatus & NUM_MPDU_RETRIES_MSK) >> NUM_MPDU_RETRIES_OFT;
01467 bool amsdu = false;
01468
01469 #if NX_AMSDU_TX
01470
01471
01472
01473
01474
01475 if (txl_buffer_is_amsdu_multi_buf(txdesc))
01476 amsdu = true;
01477 #endif
01478
01479 if (!amsdu && (nb_retry < 5))
01480 {
01481 struct txl_buffer_control *bufctrl = txl_buffer_control_get(txdesc);
01482
01483
01484
01485
01486 if (!nb_retry)
01487 {
01488 #if NX_UMAC_PRESENT
01489
01490 txl_buffer_control_copy(txdesc, txl_buffer_get(txdesc));
01491 #endif
01492
01493
01494 txl_he_txop_dur_rtscts_thres_mpdu_check(txdesc);
01495 }
01496
01497 nb_retry++;
01498 txhd->macctrlinfo1 = bufctrl->mac_control_info;
01499 txhd->phyctrlinfo = bufctrl->phy_control_info;
01500 txhd->policyentryaddr = CPU2HW(&bufctrl->policy_tbl);
01501 txhd->statinfo = nb_retry << NUM_MPDU_RETRIES_OFT;
01502
01503
01504
01505
01506 if (mu_edca_param->first_frame_exch)
01507 txhd->nextfrmexseq_ptr = CPU2HW(mu_edca_param->first_frame_exch);
01508 else
01509 txlist->last_frame_exch = txhd;
01510 mu_edca_param->first_frame_exch = txhd;
01511
01512
01513
01514 txlist->ppdu_cnt++;
01515 return;
01516 }
01517 else
01518 {
01519
01520 txhd->statinfo |= RETRY_LIMIT_REACHED_BIT;
01521 }
01522 }
01523
01524 #if !NX_FULLY_HOSTED
01525
01526 txl_free_done_mpdu(txdesc, access_category, 0);
01527 #endif
01528
01529
01530 co_list_pop_front(&(txlist->transmitting[0]));
01531
01532 #if NX_TX_FRAME
01533
01534 if (is_int_frame(txdesc))
01535 {
01536
01537 txl_frame_cfm(txdesc);
01538 }
01539 else
01540 #endif
01541 {
01542
01543 txl_cfm_push(txdesc, txstatus, access_category);
01544 }
01545 }
01546
01555 static void txl_he_tb_ampdu_mpdu_transmit_trigger(struct txdesc *txdesc,
01556 uint32_t txstatus)
01557 {
01558 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01559 uint8_t access_category = he_tb->ac;
01560 struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
01561
01562 #if !NX_FULLY_HOSTED
01563
01564 txl_free_done_mpdu(txdesc, access_category, 0);
01565 #endif
01566
01567
01568 co_list_pop_front(&(txlist->transmitting[0]));
01569
01570
01571 txl_cfm_push(txdesc, txstatus, access_category);
01572
01573
01574
01575 if (is_mpdu_last(txdesc))
01576 {
01577 txlist->agg_desc = txdesc->lmac.agg_desc;
01578 txlist->chk_state = ATHD_CHK_STATE;
01579 }
01580 }
01581
01582 void txl_he_bsr_compute(struct vif_info_tag *vif)
01583 {
01584 #if NX_UMAC_PRESENT
01585 uint32_t bsr, buffered, buffered_all = 0, buffered_aci_high = 0;
01586 uint8_t aci_bitmap = 0, delta_tid = 0, tids_nb = 0;
01587 uint8_t aci_bitmap_set = 0, aci_high = 0, tid;
01588 uint8_t qs_high = 0, qs_all, sf;
01589 uint32_t buffered_per_aci[AC_MAX];
01590 struct sta_info_tag *sta;
01591
01592
01593 if ((vif->type != VIF_STA) || !vif->active)
01594 return;
01595
01596
01597 sta = &sta_info_tab[vif->u.sta.ap_id];
01598 if (!sta->valid || !STA_CAPA(sta, HE))
01599 return;
01600
01601
01602 bsr = MAC_HTC_TYPE_HE | (MAC_HTC_HE_CTRL_ID_BSR << MAC_HTC_HE_A_CONTROL_OFT);
01603
01604 memset(buffered_per_aci, 0, sizeof(buffered_per_aci));
01605 for (tid = 0; tid < TID_MGT; tid++)
01606 {
01607 uint8_t aci = mac_ac2aci[mac_tid2ac[tid]];
01608 buffered = macif_buffered_get(sta->staid, tid);
01609 if (!buffered)
01610 continue;
01611
01612 tids_nb++;
01613
01614
01615
01616
01617
01618 if (buffered > BSR_BUFFERED_MAX)
01619 buffered = BSR_BUFFERED_MAX;
01620
01621 buffered_all += buffered;
01622 buffered_per_aci[aci] += buffered;
01623
01624
01625 if (buffered_per_aci[aci] > buffered_aci_high)
01626 {
01627 buffered_aci_high = buffered_per_aci[aci];
01628 aci_high = aci;
01629 }
01630
01631
01632 if (CO_BIT(aci) & aci_bitmap)
01633 continue;
01634
01635
01636 aci_bitmap |= CO_BIT(aci);
01637 aci_bitmap_set++;
01638 }
01639
01640 if (tids_nb == TID_MGT)
01641 {
01642 aci_bitmap = 0;
01643 delta_tid = 3;
01644 }
01645 else
01646 delta_tid = tids_nb - aci_bitmap_set;
01647
01648 sf = txl_he_bsr_get_sf_and_qsize(buffered_all, buffered_aci_high, &qs_all, &qs_high);
01649
01650 bsr |= aci_bitmap << (MAC_HTC_HE_BSR_ACI_BMP_OFT + MAC_HTC_HE_A_CONTROL_OFT);
01651 bsr |= delta_tid << (MAC_HTC_HE_BSR_DELTA_TID_OFT + MAC_HTC_HE_A_CONTROL_OFT);
01652 bsr |= aci_high << (MAC_HTC_HE_BSR_ACI_HIGH_OFT + MAC_HTC_HE_A_CONTROL_OFT);
01653 bsr |= sf << (MAC_HTC_HE_BSR_SCALING_FAC_OFT + MAC_HTC_HE_A_CONTROL_OFT);
01654 bsr |= qs_high << (MAC_HTC_HE_BSR_QSIZE_HIGH_OFT + MAC_HTC_HE_A_CONTROL_OFT);
01655 bsr |= qs_all << (MAC_HTC_HE_BSR_QSIZE_ALL_OFT + MAC_HTC_HE_A_CONTROL_OFT);
01656
01657 sta->bsr = bsr;
01658 #endif
01659 }
01660
01661 void txl_he_tb_transmit_cancelled(void)
01662 {
01663 uint8_t access_category;
01664 struct txl_list *txlist;
01665 struct txdesc *txdesc;
01666 struct tx_agg_desc *agg_desc;
01667 struct mu_edca_param_tag *mu_edca_param;
01668
01669
01670
01671 txl_he_tb_halt_queue();
01672
01673
01674 if (!txl_he_env.tb_ongoing)
01675 return;
01676
01677 access_category = txl_he_env.trigger.ac;
01678 txlist = &txl_cntrl_env.txlist[access_category];
01679 mu_edca_param = &txl_he_env.mu_edca.params[access_category];
01680
01681 PROF_TX_MAC_IRQ_SET();
01682 PROF_TX_AC_IRQ_SET(access_category);
01683
01684
01685 txdesc = (struct txdesc *)co_list_pick(&(txlist->transmitting[0]));
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695 if (txlist->chk_state == THD_CHK_STATE)
01696 {
01697 agg_desc = txdesc->lmac.agg_desc;
01698 if (is_mpdu_agg(txdesc) && (txlist->first_to_download[0]->lmac.agg_desc == agg_desc))
01699 {
01700 txlist->first_to_download[0] = tx_desc_next(agg_desc->txdesc_last);
01701 }
01702 }
01703
01704
01705 while (1)
01706 {
01707
01708
01709
01710 if (txlist->chk_state == THD_CHK_STATE)
01711 {
01712 struct tx_hd *txhd;
01713 uint32_t txstatus;
01714
01715
01716
01717 ASSERT_ERR(txdesc != NULL);
01718
01719 txhd = &txdesc->lmac.hw_desc->thd;
01720
01721
01722
01723 txhd->statinfo |= HE_TB_TX_BIT | DESC_DONE_TX_BIT;
01724 txstatus = txhd->statinfo;
01725
01726
01727 if (!is_mpdu_agg(txdesc))
01728 {
01729 txl_he_tb_mpdu_transmit_trigger(txdesc, txstatus);
01730 break;
01731 }
01732
01733
01734 txl_he_tb_ampdu_mpdu_transmit_trigger(txdesc, txstatus);
01735
01736
01737 txdesc = (struct txdesc *)co_list_pick(&(txlist->transmitting[0]));
01738
01739 }
01740
01741
01742
01743 else
01744 {
01745
01746 struct tx_agg_desc *agg_desc = txlist->agg_desc;
01747
01748
01749 PROF_AGG_BAR_DONETX_SET();
01750
01751
01752 agg_desc->status |= AGG_DONE;
01753
01754
01755 co_list_pop_front(&txlist->aggregates);
01756
01757
01758 ke_evt_set(txl_cfm_evt_bit[access_category]);
01759
01760
01761 txlist->chk_state = THD_CHK_STATE;
01762 txlist->agg_desc = NULL;
01763
01764
01765 PROF_AGG_BAR_DONETX_CLR();
01766 break;
01767 }
01768 }
01769
01770
01771 if (!txl_he_is_edca_off(access_category) && (mu_edca_param->first_frame_exch != NULL))
01772 {
01773 txl_cntrl_newhead(CPU2HW(mu_edca_param->first_frame_exch), access_category);
01774 }
01775
01776
01777 txl_he_tb_timer_clear();
01778
01779
01780 txlist->ppdu_cnt--;
01781
01782
01783 txl_agg_check(access_category);
01784
01785 PROF_TX_MAC_IRQ_CLR();
01786 }
01787
01788 void txl_he_tb_transmit_trigger(void)
01789 {
01790 uint8_t access_category = txl_he_env.trigger.ac;
01791 struct txl_list *txlist = &txl_cntrl_env.txlist[access_category];
01792 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
01793 struct mu_edca_param_tag *mu_edca_param = &txl_he_env.mu_edca.params[access_category];
01794
01795 PROF_TX_MAC_IRQ_SET();
01796 PROF_TX_AC_IRQ_SET(access_category);
01797
01798
01799 while (1)
01800 {
01801 struct txdesc * txdesc = NULL;
01802
01803
01804
01805
01806 if (txlist->chk_state == THD_CHK_STATE)
01807 {
01808 struct tx_hd *txhd;
01809 uint32_t txstatus;
01810
01811
01812 txdesc = (struct txdesc *)co_list_pick(&(txlist->transmitting[0]));
01813
01814
01815
01816 ASSERT_ERR(txdesc != NULL);
01817
01818 txhd = &txdesc->lmac.hw_desc->thd;
01819
01820
01821 if (!(txhd->statinfo & DESC_DONE_TX_BIT))
01822 {
01823 #if !NX_FULLY_HOSTED && NX_AMSDU_TX
01824
01825 txl_check_done_amsdu_subframe(txdesc, access_category, 0);
01826 #endif
01827
01828 PROF_TX_MAC_IRQ_CLR();
01829 return;
01830 }
01831
01832
01833 txhd->statinfo |= HE_TB_TX_BIT;
01834 txstatus = txhd->statinfo;
01835
01836
01837 if (!is_mpdu_agg(txdesc))
01838 {
01839 txl_he_tb_mpdu_transmit_trigger(txdesc, txstatus);
01840 break;
01841 }
01842
01843
01844 txl_he_tb_ampdu_mpdu_transmit_trigger(txdesc, txstatus);
01845 }
01846
01847
01848
01849 else
01850 {
01851
01852 struct tx_agg_desc *agg_desc = txlist->agg_desc;
01853 struct tx_hd *thd;
01854 uint32_t thd_status;
01855
01856 if (txlist->chk_state == ATHD_CHK_STATE)
01857
01858 thd = &agg_desc->a_thd;
01859 else
01860
01861 thd = &agg_desc->bar_thd;
01862
01863 thd_status = thd->statinfo;
01864
01865 if (!(thd_status & DESC_DONE_TX_BIT))
01866 {
01867 PROF_TX_MAC_IRQ_CLR();
01868 return;
01869 }
01870
01871
01872 PROF_AGG_BAR_DONETX_SET();
01873
01874 if (thd_status & FRAME_SUCCESSFUL_TX_BIT)
01875 {
01876
01877 if (!(agg_desc->status & AGG_BA_RECEIVED))
01878 {
01879 int i = 0;
01880
01881
01882 do
01883 {
01884 rxl_immediate_frame_get();
01885 i++;
01886 } while ((i < 5) && (!(agg_desc->status & AGG_BA_RECEIVED)));
01887 }
01888
01889
01890 ASSERT_REC(agg_desc->status & AGG_BA_RECEIVED);
01891
01892 if (he_tb->uora)
01893
01894 nxmac_e_ocw_setf(txl_he_env.uora.eocw_min);
01895 else
01896
01897 txl_he_mu_edca_start(txl_he_env.trigger.ac);
01898 }
01899 else
01900 {
01901
01902 co_list_pop_front(&txlist->aggregates);
01903
01904 if (he_tb->uora)
01905 {
01906
01907 uint8_t new_eocw = nxmac_e_ocw_getf();
01908 new_eocw = new_eocw + 1;
01909
01910 if (new_eocw > txl_he_env.uora.eocw_max)
01911 new_eocw = txl_he_env.uora.eocw_max;
01912
01913 nxmac_e_ocw_setf(new_eocw);
01914 }
01915 }
01916
01917
01918 agg_desc->status |= AGG_DONE;
01919
01920
01921 ke_evt_set(txl_cfm_evt_bit[access_category]);
01922
01923
01924
01925 txlist->chk_state = THD_CHK_STATE;
01926 txlist->agg_desc = NULL;
01927
01928
01929 PROF_AGG_BAR_DONETX_CLR();
01930 break;
01931 }
01932 }
01933
01934
01935 if (!txl_he_is_edca_off(access_category) && (mu_edca_param->first_frame_exch != NULL))
01936 {
01937 txl_cntrl_newhead(CPU2HW(mu_edca_param->first_frame_exch), access_category);
01938 }
01939
01940
01941 txl_he_tb_timer_clear();
01942
01943
01944 txlist->ppdu_cnt--;
01945
01946
01947 txl_agg_check(access_category);
01948
01949 PROF_TX_MAC_IRQ_CLR();
01950 }
01951
01952 void txl_he_init(void)
01953 {
01954 memset(&txl_he_env, 0, sizeof(txl_he_env));
01955
01956 txl_he_tb_desc_init();
01957
01958
01959 txl_he_env.trigger.uph = MAC_HTC_HE(HTC_HE_UPH_DEF);
01960
01961 #if NX_MAC_VER > 20
01962
01963 if (phy_ldpc_tx_supported())
01964 nxmac_max_mcs_in_hetb_setf(11);
01965 else
01966 nxmac_max_mcs_in_hetb_setf(9);
01967 #endif
01968 }
01969
01970 void txl_he_reset(void)
01971 {
01972 struct mu_edca_tag mu_edca;
01973 struct vif_info_tag *tb_vif;
01974
01975 #if NX_UMAC_PRESENT && NX_BEACONING
01976 struct sta_info_tag *trigged_sta;
01977 bool trig_started = (txl_he_env.trig_timer.cb != NULL);
01978
01979
01980 if (trig_started)
01981 {
01982
01983 trigged_sta = txl_he_env.trig_timer.env;
01984
01985 mm_timer_clear(&txl_he_env.trig_timer);
01986 trig_started = true;
01987 }
01988 #endif // NX_UMAC_PRESENT && NX_BEACONING
01989
01990
01991 tb_vif = txl_he_env.tb_vif;
01992
01993
01994 if (tb_vif)
01995 {
01996 mu_edca = txl_he_env.mu_edca;
01997
01998 if (mu_edca.timer.cb != NULL)
01999
02000 mm_timer_clear(&txl_he_env.mu_edca.timer);
02001 }
02002
02003
02004 txl_he_init();
02005
02006
02007 txl_he_env.tb_vif = tb_vif;
02008
02009
02010 if (tb_vif)
02011 {
02012
02013 txl_he_env.mu_edca.valid = mu_edca.valid;
02014 for (int i = 0; i < AC_MAX; i++)
02015 {
02016 txl_he_env.mu_edca.params[i].edca = mu_edca.params[i].edca;
02017 txl_he_env.mu_edca.params[i].timeout = mu_edca.params[i].timeout;
02018 }
02019 }
02020
02021 #if NX_UMAC_PRESENT && NX_BEACONING
02022
02023 if (trig_started)
02024 {
02025
02026 txl_he_start_trigger_scheduler(trigged_sta);
02027 }
02028 #endif // NX_UMAC_PRESENT && NX_BEACONING
02029 }
02030
02031 bool txl_he_decode_m_ba(struct rxdesc *badesc, struct tx_agg_desc *agg_desc)
02032 {
02033 struct sta_info_tag *sta = &sta_info_tab[agg_desc->sta_idx];
02034 struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(badesc);
02035 struct rx_hd *hdrdesc = &dma_hdrdesc->hd;
02036 struct rx_pbd *pd = HW2CPU(hdrdesc->first_pbd_ptr);
02037 struct ba_base *ba_payl = (struct ba_base *)HW2CPU(pd->datastartptr);
02038 struct ba_msta_aid_tid_info *aid_tid_info;
02039 int remaining_len = hdrdesc->frmlen;
02040 bool addr1_match = (hdrdesc->statinfo & RX_HD_ADDRMIS) == 0;
02041 bool addr1_group = (hdrdesc->statinfo & RX_HD_GA_FRAME) != 0;
02042
02043
02044 if (!addr1_match && !addr1_group)
02045 return false;
02046
02047 aid_tid_info = (struct ba_msta_aid_tid_info *)(ba_payl + 1);
02048 remaining_len -= sizeof_b(struct ba_base);
02049
02050
02051 while (remaining_len >= 2)
02052 {
02053 uint16_t aid = (aid_tid_info->aid_tid & BA_MULTI_STA_AID_MSK) >> BA_MULTI_STA_AID_OFT;
02054 int aid_tid_len = txl_he_m_ba_aid_tid_len(aid_tid_info, remaining_len);
02055
02056 if (aid_tid_len < 0)
02057 return false;
02058
02059
02060 if (aid == sta->aid)
02061 {
02062 uint8_t tid;
02063
02064 if (aid_tid_info->aid_tid & BA_MULTI_STA_ACK_BIT)
02065 {
02066 agg_desc->ssc_bitmap = NULL;
02067 return true;
02068 }
02069
02070 tid = (aid_tid_info->aid_tid & BA_MULTI_STA_TID_MSK) >> BA_MULTI_STA_TID_OFT;
02071
02072
02073 if (tid != agg_desc->tid)
02074
02075 return false;
02076
02077 memcpy(&agg_desc->ssc_bitmap_tab, &aid_tid_info->ssc_bitmap,
02078 aid_tid_len - sizeof_b(aid_tid_info->aid_tid));
02079 agg_desc->ssc_bitmap = (struct ba_ssc_bitmap *)(&agg_desc->ssc_bitmap_tab);
02080 return true;
02081 }
02082
02083
02084 aid_tid_info = HW2CPU(CPU2HW(aid_tid_info) + aid_tid_len);
02085 remaining_len -= aid_tid_len;
02086 };
02087
02088
02089 return false;
02090 }
02091
02092 void txl_he_trigger_push(struct rxdesc *rxdesc)
02093 {
02094 uint8_t sta_idx;
02095 uint16_t key_idx_hw;
02096 struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
02097 struct rx_hd *hdrdesc = &dma_hdrdesc->hd;
02098 struct rx_pbd *pd = HW2CPU(hdrdesc->first_pbd_ptr);
02099 uint32_t statinfo = hdrdesc->statinfo;
02100 struct he_trigger_tag *he_tb = &txl_he_env.trigger;
02101 struct sta_info_tag *sta;
02102 struct vif_info_tag *vif;
02103
02104
02105 he_tb->trig_valid = false;
02106
02107
02108
02109 ASSERT_REC(hdrdesc->frmlen >= HE_TRIG_FRM_MIN_LEN);
02110
02111
02112 if (!(statinfo & KEY_IDX_VALID_BIT))
02113 {
02114 MAC_ADDR_CPY(&he_tb->ta, HW2CPU(pd->datastartptr + MAC_HEAD_ADDR2_OFT));
02115 return;
02116 }
02117
02118
02119 key_idx_hw = (uint16_t)((statinfo & KEY_IDX_MSK) >> KEY_IDX_OFT);
02120
02121
02122 ASSERT_REC(key_idx_hw >= MM_SEC_DEFAULT_KEY_COUNT);
02123
02124
02125 sta_idx = (uint8_t)(key_idx_hw - MM_SEC_DEFAULT_KEY_COUNT);
02126 sta = &sta_info_tab[sta_idx];
02127 if (sta->valid)
02128 {
02129 he_tb->ta = sta->mac_addr;
02130 }
02131 else
02132 {
02133 MAC_ADDR_CPY(&he_tb->ta, HW2CPU(pd->datastartptr + MAC_HEAD_ADDR2_OFT));
02134 return;
02135 }
02136
02137
02138 vif = &vif_info_tab[sta->inst_nbr];
02139 if (vif != txl_he_env.tb_vif)
02140 return;
02141
02142
02143 if (nxmac_tx_hetb_rem_dur_getf() < TX_HE_TB_PROG_MIN_TIME)
02144 return;
02145
02146
02147 txl_he_tb_params_compute();
02148
02149
02150
02151 he_tb->trig_valid = (he_tb->max_len >= TX_HE_TB_MIN_PSDU_LEN)?true:false;
02152
02153
02154 he_tb->sta = sta;
02155
02156
02157 txl_he_tb_set_rc_info();
02158 }
02159
02160 void txl_he_tb_prot_trigger(void)
02161 {
02162
02163 PROF_TX_HE_TRIG_IRQ_SET();
02164
02165
02166 rxl_immediate_frame_get();
02167
02168
02169 txl_he_tb_ppdu_send();
02170
02171
02172 PROF_TX_HE_TRIG_IRQ_CLR();
02173 }
02174
02175 void txl_he_tb_config(void)
02176 {
02177 struct vif_info_tag *vif = vif_mgmt_get_single_sta_vif();
02178
02179
02180 if (hal_machw_he_support() && (vif != NULL))
02181 {
02182
02183 txl_he_env.tb_vif = vif;
02184
02185
02186 txl_he_tb_enable();
02187 }
02188 else
02189 {
02190
02191 txl_he_tb_disable();
02192
02193
02194 txl_he_env.tb_vif = NULL;
02195 }
02196 }
02197
02198 void txl_he_tb_enable(void)
02199 {
02200 struct tx_policy_tbl *pol;
02201 uint8_t hw_key_idx;
02202
02203 if (txl_he_env.tb_vif == NULL || !txl_he_env.tb_vif->active)
02204 return;
02205
02206
02207 pol = &he_tb_desc.tb_pol;
02208 hw_key_idx = MM_STA_TO_KEY(txl_he_env.tb_vif->u.sta.ap_id);
02209 pol->maccntrlinfo1 = (hw_key_idx << KEYSRAM_INDEX_RA_OFT) | hw_key_idx;
02210 pol->maccntrlinfo2 = 0xFFFF0704;
02211
02212
02213 nxmac_enable_tb_prot_trigger_setf(1);
02214 nxmac_enable_tb_tx_trigger_setf(1);
02215 nxmac_enable_tb_tx_cancelled_setf(1);
02216 #if NX_AMSDU_TX
02217 nxmac_enable_tb_tx_buf_trigger_setf(1);
02218 #endif
02219 nxmac_accept_trigger_sw_frames_setf(1);
02220 nxmac_ra_ru_enable_setf(1);
02221 nxmac_ra_ru_type_setf(0);
02222
02223 }
02224
02225 void txl_he_tb_disable(void)
02226 {
02227 if (txl_he_env.tb_vif != NULL)
02228
02229 txl_he_mu_edca_stop();
02230
02231
02232 nxmac_accept_trigger_sw_frames_setf(0);
02233 nxmac_enable_tb_prot_trigger_setf(0);
02234 nxmac_enable_tb_tx_trigger_setf(0);
02235 nxmac_enable_tb_tx_cancelled_setf(0);
02236 #if NX_AMSDU_TX
02237 nxmac_enable_tb_tx_buf_trigger_setf(0);
02238 #endif
02239 nxmac_ra_ru_enable_setf(0);
02240 }
02241
02242 #if NX_UMAC_PRESENT
02243 uint32_t txl_he_htc_get(struct txdesc *txdesc, struct sta_info_tag *sta)
02244 {
02245 struct tx_agg_desc *agg_desc = txdesc->lmac.agg_desc;
02246
02247
02248 if (agg_desc && ((agg_desc->status & AGG_TB) != 0))
02249
02250 return txl_he_env.trigger.uph;
02251
02252
02253 return sta->bsr;
02254 }
02255 #endif
02256
02257 uint32_t txl_he_idx_to_32us_len_get(int base_idx, uint8_t bw)
02258 {
02259 int idx = base_idx + 3 * (bw >> 1);
02260 int shift = bw & 0x01;
02261 return (((uint32_t)TX_HE_RATE_TO_32US_LEN[idx]) << shift);
02262 }
02263
02264 uint16_t txl_he_idx_to_1us_len_get(int base_idx, uint8_t bw)
02265 {
02266 int idx = base_idx + 3 * (bw >> 1);
02267 int shift = bw & 0x01;
02268 return (((uint32_t)TX_HE_RATE_TO_MIN_SEP[idx]) << shift);
02269 }
02270
02271 int txl_he_ampdu_param_get(struct txdesc *txdesc,
02272 uint8_t format_mod,
02273 uint32_t *max_len_sta,
02274 uint32_t *nss)
02275 {
02276 uint32_t phy_flags = txdesc->umac.phy_flags;
02277 uint32_t mcs_idx = (phy_flags & MCS_INDEX_TX_RCX_MASK) >> MCS_INDEX_TX_RCX_OFT;
02278 uint32_t gi = (phy_flags & HE_GI_TYPE_TX_RCX_MASK) >> HE_GI_TYPE_TX_RCX_OFT;
02279 struct sta_info_tag *sta = &sta_info_tab[txdesc->host.staid];
02280
02281
02282 ASSERT_ERR(format_mod == FORMATMOD_HE_SU);
02283
02284
02285 *nss = ((mcs_idx & VHT_NSS_MASK) >> VHT_NSS_OFT) + 1;
02286
02287
02288 mcs_idx = (mcs_idx & VHT_MCS_MASK) >> VHT_MCS_OFT;
02289
02290
02291 ASSERT_ERR((*nss > 0) && (*nss <= 4));
02292 ASSERT_ERR(mcs_idx <= 11);
02293
02294
02295 *max_len_sta = sta->ampdu_size_max_he;
02296
02297
02298
02299
02300 return (mcs_idx * 6 + gi);
02301 }
02302
02303 void txl_he_mu_edca_param_set(struct mm_set_mu_edca_req const *param)
02304 {
02305 struct mu_edca_tag *mu_edca = &txl_he_env.mu_edca;
02306
02307
02308 for (int i = 0; i < AC_MAX; i++)
02309 {
02310 uint8_t aifsn = param->param[i] & 0x0000000F;
02311 uint8_t timeout = (param->param[i] & 0x00FF0000) >> 16;
02312 uint16_t cw = (param->param[i] & 0x0000FF00) >> 4;
02313
02314 mu_edca->params[i].timeout = timeout;
02315 mu_edca->params[i].edca = cw | aifsn;
02316
02317 if (txl_he_env.tb_vif)
02318 {
02319
02320 mu_edca->params[i].edca |= txl_he_env.tb_vif->txq_params[i] & 0xFFFFF000;
02321 }
02322 }
02323
02324
02325 mu_edca->valid = true;
02326 }
02327
02328 void txl_he_uora_param_set(struct mm_set_uora_req const *param)
02329 {
02330 struct uora_tag *uora = &txl_he_env.uora;
02331
02332 uora->eocw_min = param->eocw_min;
02333 uora->eocw_max = param->eocw_max;
02334 }
02335
02336 void txl_he_mu_edca_blocked(struct tx_hd *thd, uint8_t ac)
02337 {
02338 struct mu_edca_tag *mu_edca = &txl_he_env.mu_edca;
02339 struct mu_edca_param_tag *mu_edca_param = &txl_he_env.mu_edca.params[ac];
02340
02341
02342 if (mu_edca->timer.cb)
02343 {
02344
02345 if (txl_he_is_edca_off(ac))
02346 mu_edca_param->first_frame_exch = thd;
02347
02348
02349 mu_edca_param->timer = 1;
02350 }
02351 }
02352
02353 #if NX_UMAC_PRESENT && NX_BEACONING
02354 void txl_he_start_trigger_scheduler(struct sta_info_tag *sta)
02355 {
02356 txl_he_env.trig_timer.cb = txl_he_trig_time;
02357 txl_he_env.trig_timer.env = sta;
02358 mm_timer_set(&txl_he_env.trig_timer, hal_machw_time() + TX_HE_TRIG_PERIOD);
02359 }
02360 #endif // NX_UMAC_PRESENT && NX_BEACONING
02361
02362 void txl_he_txop_dur_rtscts_thres_ampdu_check(struct txdesc *txdesc)
02363 {
02364 struct vif_info_tag *vif = &vif_info_tab[txdesc->host.vif_idx];
02365 struct tx_agg_desc *agg_desc = txdesc->lmac.agg_desc;
02366
02367 if (vif->txop_dur_rts_thres != MAC_HE_OPER_TXOP_DUR_RTS_THRES_DISABLED)
02368 {
02369 txl_he_txop_dur_rtscts_thres_apply(&txdesc->umac.phy_flags, agg_desc->a_thd.frmlen,
02370 vif->txop_dur_rts_thres);
02371 }
02372 }
02373
02374 void txl_he_txop_dur_rtscts_thres_mpdu_check(struct txdesc *txdesc)
02375 {
02376 struct vif_info_tag *vif = &vif_info_tab[txdesc->host.vif_idx];
02377 struct txl_buffer_control *bufctrl = txl_buffer_control_get(txdesc);
02378 struct tx_hd *txhd = &txdesc->lmac.hw_desc->thd;
02379 struct tx_policy_tbl *pt = &bufctrl->policy_tbl;
02380
02381 if (vif->txop_dur_rts_thres != MAC_HE_OPER_TXOP_DUR_RTS_THRES_DISABLED)
02382 {
02383 for (int i = 0; i < RATE_CONTROL_STEPS; i++)
02384 {
02385 txl_he_txop_dur_rtscts_thres_apply(&pt->ratecntrlinfo[i], txhd->frmlen,
02386 vif->txop_dur_rts_thres);
02387 }
02388 }
02389 }
02390
02391 #endif // NX_MAC_HE
02392