- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/tx/txl/txl_cfm.c

Go to the documentation of this file.

    00001
    00013 /*
    00014  ****************************************************************************************
    00015  * @addtogroup TX_CFM
    00016  * @{
    00017  ****************************************************************************************
    00018  */
    00019
    00020 /*
    00021  * INCLUDE FILES
    00022  ****************************************************************************************
    00023  */
    00024 #include <stddef.h>
    00025 #include "txl_cntrl.h"
    00026 #include "txl_cfm.h"
    00027 #include "ke_event.h"
    00028 #include "mac_frame.h"
    00029 #include "dbg.h"
    00030 #include "txl_agg.h"
    00031 #include "txl_buffer.h"
    00032 #include "txl_frame.h"
    00033 #include "co_utils.h"
    00034 #include "ps.h"
    00035
    00036 #if NX_AMPDU_TX
    00037 //for key count
    00038 #include "mm.h"
    00039 //for rx frame release
    00040 #include "rxl_hwdesc.h"
    00041 #endif
    00042 // For LMAC to UMAC communication interface
    00043 #include "macif.h"
    00044 #if NX_UMAC_PRESENT
    00045 #include "me_utils.h"
    00046 #include "txu_cntrl.h"
    00047 #endif
    00048 #if (RW_BFMER_EN)
    00049 #include "bfr.h"
    00050 #endif //(RW_BFMER_EN)
    00051
    00052 /*
    00053  * GLOBAL VARIABLE DEFINITION
    00054  ****************************************************************************************
    00055  */
    00056 struct txl_cfm_env_tag txl_cfm_env;
    00057
    00058 const uint32_t txl_cfm_evt_bit[NX_TXQ_CNT] =
    00059 {
    00060     #if NX_BEACONING
    00061     [AC_BCN] = KE_EVT_TXCFM_BCN_BIT,
    00062     #endif
    00063     [AC_VO] = KE_EVT_TXCFM_AC3_BIT,
    00064     [AC_VI] = KE_EVT_TXCFM_AC2_BIT,
    00065     [AC_BE] = KE_EVT_TXCFM_AC1_BIT,
    00066     [AC_BK] = KE_EVT_TXCFM_AC0_BIT,
    00067 };
    00068
    00069 #if NX_AMPDU_TX
    00070
    00080 static uint8_t txl_ba_ac_get(struct rxdesc *rxdesc)
    00081 {
    00082     #if NX_MAC_HE
    00083     uint8_t ac;
    00084
    00085     if (txl_he_tb_ongoing(&ac))
    00086     {
    00087         return ac;
    00088     }
    00089     else
    00090     #endif
    00091     {
    00092         struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    00093         // Get the status information from the RX header descriptor
    00094         uint32_t statinfo = dma_hdrdesc->hd.statinfo;
    00095
    00096         // And extract the access category from it
    00097         return (uint8_t)((statinfo & IMM_RSP_AC_MSK) >> IMM_RSP_AC_OFT);
    00098     }
    00099 }
    00100
    00114 static bool txl_decode_compressed_ba(struct rxdesc *badesc, struct tx_agg_desc *agg_desc)
    00115 {
    00116     uint8_t tid;
    00117     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(badesc);
    00118     struct rx_hd *hdrdesc = &dma_hdrdesc->hd;
    00119     struct rx_pbd *pd = HW2CPU(hdrdesc->first_pbd_ptr);
    00120     struct ba_comp_frame *ba_payl = (struct ba_comp_frame *)HW2CPU(pd->datastartptr);
    00121
    00122     // Compressed BA shall be unicast to our device
    00123     if (hdrdesc->statinfo & RX_HD_ADDRMIS)
    00124         return false;
    00125
    00126     // Check if BA frame length is correct
    00127     if (hdrdesc->frmlen != BA_COMPRESSED_LEN)
    00128         // Length not correct
    00129         return false;
    00130
    00131     // Extract the TID
    00132     // Byte 1 is MSB of BA Control field, its upper 4 bits = TID
    00133     tid = (ba_payl->ba_cntrl & BA_PAYL_TID_BIT_MSK) >> BA_PAYL_TID_BIT_OFT;
    00134
    00135     // Check if both TID match
    00136     if (tid != agg_desc->tid)
    00137         // No match, we consider BA as invalid
    00138         return false;
    00139
    00140     memcpy(&agg_desc->ssc_bitmap_tab, &ba_payl->ssc_bitmap, sizeof(ba_payl->ssc_bitmap));
    00141     agg_desc->ssc_bitmap = (struct ba_ssc_bitmap *)(&agg_desc->ssc_bitmap_tab);
    00142
    00143     // All checks passed, BA is valid
    00144     return true;
    00145 }
    00146
    00159 static bool txl_is_ba_valid(struct tx_agg_desc *agg_desc, struct rxdesc *badesc)
    00160 {
    00161     uint16_t key_idx_hw;
    00162     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(badesc);
    00163     struct rx_hd *hdrdesc = &dma_hdrdesc->hd;
    00164     uint32_t statinfo = hdrdesc->statinfo;
    00165     #if NX_MAC_HE
    00166     struct rx_pbd *pd = HW2CPU(hdrdesc->first_pbd_ptr);
    00167     struct ba_base *ba_payl = (struct ba_base *)HW2CPU(pd->datastartptr);
    00168     uint16_t ba_type;
    00169     #endif
    00170
    00171     // Check if the Key index is valid, i.e. if the TA is known
    00172     if (!(statinfo & KEY_IDX_VALID_BIT))
    00173         // TA not known, we consider the BA as invalid
    00174         return false;
    00175
    00176     // Get the key index
    00177     key_idx_hw = (uint16_t)((statinfo & KEY_IDX_MSK) >> KEY_IDX_OFT);
    00178
    00179     // Sanity check
    00180     ASSERT_REC_VAL(key_idx_hw >= MM_SEC_DEFAULT_KEY_COUNT, false);
    00181
    00182     // Check if both STA indexes match
    00183     if (MM_KEY_TO_STA(key_idx_hw) != agg_desc->sta_idx)
    00184         // No match, we consider BA as invalid
    00185         return false;
    00186
    00187     #if NX_MAC_HE
    00188     // Get BA type
    00189     ba_type = ba_payl->ba_cntrl & BA_PAYL_TYPE_MSK;
    00190
    00191     if (ba_type == BA_MULTI_STA_TYPE)
    00192         return txl_he_decode_m_ba(badesc, agg_desc);
    00193     #endif
    00194
    00195     // By default we support only compressed BlockAck
    00196     return txl_decode_compressed_ba(badesc, agg_desc);
    00197 }
    00198
    00209 static bool txl_comp_sn(uint16_t sn1, uint16_t sn2)
    00210 {
    00211     if (((uint16_t)((sn1 - sn2) & 0x0FFF)) < 0x07FF)
    00212         return false;
    00213     else
    00214         return true;
    00215 }
    00216
    00226 static uint32_t txl_ba_extract_ack(struct txdesc *txdesc, struct tx_agg_desc *agg_desc,
    00227                                    int *agg_ok)
    00228 {
    00229     struct ba_ssc_bitmap *ssc_bitmap = agg_desc->ssc_bitmap;
    00230     uint16_t ssn;
    00231
    00232     #if NX_MAC_HE
    00233     // Case of "All Ack" feature - if no ssc_bitmap is present, it means everything was
    00234     // received fine
    00235     if (ssc_bitmap == NULL)
    00236     {
    00237         // Increment the number of MPDUs successfully transmitted
    00238         (*agg_ok)++;
    00239         return (BA_FRAME_RECEIVED_BIT | FRAME_SUCCESSFUL_TX_BIT);
    00240     }
    00241     #endif
    00242
    00243     // byte 2 is LSB of Start Sequence control, at bit 4 the SSN starts
    00244     ssn = ssc_bitmap->ssc >> SN_IN_SSC_BIT_OFT;
    00245
    00246     //txdesc is below the start of the BA window - bad, means we moved the window! can never get an ACK for it
    00247     if (txl_comp_sn(txdesc->host.sn, ssn))
    00248     {
    00249         return BA_FRAME_RECEIVED_BIT;
    00250     }
    00251
    00252     uint16_t bit_pos = (txdesc->host.sn - ssn) & 0xFFF;
    00253     uint8_t word_idx = bit_pos/16;
    00254     uint8_t bit_in_word_pos = bit_pos % 16;
    00255
    00256     //make sure SN is in window - shouldn't be possible
    00257     if (word_idx > 3)
    00258     {
    00259         return BA_FRAME_RECEIVED_BIT;
    00260     }
    00261
    00262     if (((ssc_bitmap->bitmap[word_idx] >> bit_in_word_pos) & 0x01) == 0x01)
    00263     {
    00264         // Increment the number of MPDUs successfully transmitted
    00265         (*agg_ok)++;
    00266         return (BA_FRAME_RECEIVED_BIT | FRAME_SUCCESSFUL_TX_BIT);
    00267     }
    00268     else
    00269     {
    00270         return BA_FRAME_RECEIVED_BIT;
    00271     }
    00272 }
    00273 #endif
    00274
    00275
    00276 void txl_cfm_init(void)
    00277 {
    00278     // Reset the environment
    00279     memset(&txl_cfm_env, 0, sizeof(txl_cfm_env));
    00280
    00281     for (int i = 0; i < NX_TXQ_CNT; i++)
    00282     {
    00283         co_list_init(&txl_cfm_env.cfmlist[i]);
    00284     }
    00285 }
    00286
    00287 void txl_cfm_push(struct txdesc *txdesc, uint32_t status, uint8_t access_category)
    00288 {
    00289     struct tx_cfm_tag *cfm = txl_cfm_tag_get(txdesc);
    00290     cfm->status = status;
    00291
    00292     // Push the descriptor in the confirmation queue
    00293     co_list_push_back(&txl_cfm_env.cfmlist[access_category], (struct co_list_hdr *)txdesc);
    00294
    00295     #if NX_AMPDU_TX
    00296     //call the CFM event only if it is a singleton, for MPDUs in AMPDU CFM event is set when BAR is done
    00297     if (!is_mpdu_agg(txdesc))
    00298     #endif
    00299         // Set an event to handle the confirmation in background
    00300         ke_evt_set(txl_cfm_evt_bit[access_category]);
    00301 }
    00302
    00303 #if NX_AMPDU_TX
    00304 void txl_ba_push(struct rxdesc *rxdesc)
    00305 {
    00306     uint8_t ac;
    00307     struct tx_agg_desc *agg_desc;
    00308
    00309     // For profiling
    00310     PROF_AGG_BA_RXED_SET();
    00311
    00312     // Get the access category value
    00313     ac = txl_ba_ac_get(rxdesc);
    00314
    00315     // Set BA in appropriate aggregate descriptor
    00316     agg_desc = (struct tx_agg_desc *)co_list_pop_front(&(txl_cntrl_env.txlist[ac].aggregates));
    00317     // Sanity check - There shall be an AGG descriptor for this BA, because unexpected
    00318     // BAs are filtered earlier in the RX chain
    00319     ASSERT_REC(agg_desc != NULL);
    00320
    00321     // A BlockAck has been received for this PPDU
    00322     agg_desc->status |= AGG_BA_RECEIVED;
    00323
    00324     // Check if the received BA is valid
    00325     if (txl_is_ba_valid(agg_desc, rxdesc))
    00326         agg_desc->status |= AGG_BA_VALID;
    00327
    00328     // For profiling
    00329     PROF_AGG_BA_RXED_CLR();
    00330 }
    00331 #endif
    00332
    00333 void txl_cfm_evt(int access_category)
    00334 {
    00335     struct txdesc *txdesc;
    00336     uint32_t evt_bit = txl_cfm_evt_bit[access_category];
    00337     struct co_list *cfm_list = &txl_cfm_env.cfmlist[access_category];
    00338     #if NX_AMPDU_TX
    00339     #if NX_UMAC_PRESENT
    00340     struct txdesc *txdesc_first = NULL;
    00341     #endif
    00342     int agg_txed = 0;
    00343     int agg_ok = 0;
    00344     #endif
    00345
    00346     // For profiling
    00347     PROF_TX_CFM_EVT_SET();
    00348
    00349     // Check that the event is correctly set
    00350     ASSERT_ERR(ke_evt_get() & evt_bit);
    00351
    00352     // Clear the event
    00353     ke_evt_clear(evt_bit);
    00354
    00355     // Start the TX confirmation upload procedure
    00356     macif_tx_cfm_start(access_category);
    00357
    00358     while(1)
    00359     {
    00360         // Pick the first desc from the cfm queue (either 1st of AMPDU or singleton)
    00361         txdesc = (struct txdesc *)co_list_pick(cfm_list);
    00362
    00363         if (txdesc != NULL)
    00364         {
    00365             #if NX_AMPDU_TX
    00366             struct tx_cfm_tag *cfm = txl_cfm_tag_get(txdesc);
    00367             struct tx_agg_desc *agg_desc = txdesc->lmac.agg_desc;
    00368             #endif
    00369
    00370             // For profiling
    00371             PROF_TX_AC_BG_SET(access_category);
    00372
    00373             #if NX_UAPSD && NX_UMAC_PRESENT
    00374             ps_check_tx_trigger_sent(&txdesc->host,
    00375                                      txl_cfm_tag_get(txdesc)->status);
    00376             #endif
    00377
    00378             #if NX_AMPDU_TX
    00379             // Check if the packet was part of an A-MPDU
    00380             if (agg_desc)
    00381             {
    00382                 uint8_t status = agg_desc->status;
    00383
    00384                 // Check if the A-MPDU status is ready
    00385                 if (!(status & AGG_DONE))
    00386                     break;
    00387
    00388                 // One more aggregated MPDU was transmitted
    00389                 agg_txed++;
    00390
    00391                 //clear FRM successful bit
    00392                 cfm->status &= ~FRAME_SUCCESSFUL_TX_BIT;
    00393
    00394                 if (status & AGG_BA_VALID)
    00395                 {
    00396                     //set ACK state extracted from BA bitmap in FRM successful bit position
    00397                     cfm->status |= txl_ba_extract_ack(txdesc, agg_desc, &agg_ok);
    00398                 }
    00399
    00400                 #if (RW_BFMER_EN)
    00401                 if (bfr_is_enabled())
    00402                 {
    00403                     // Check if the frame was beamformed
    00404                     bfr_tx_cfm(txdesc);
    00405                 }
    00406                 #endif //(RW_BFMER_EN)
    00407
    00408                 #if NX_UMAC_PRESENT
    00409                 // Indicate the packet status to the upper MAC
    00410                 txu_cntrl_cfm(txdesc);
    00411
    00412                 if (is_mpdu_first(txdesc))
    00413                     txdesc_first = txdesc;
    00414                 #endif
    00415
    00416                 // Protect the access to the lists from interrupt preemption
    00417                 GLOBAL_INT_DISABLE();
    00418
    00419                 // Extract the TX descriptor from the confirmation list
    00420                 co_list_pop_front(cfm_list);
    00421
    00422                 if (is_mpdu_last(txdesc))
    00423                 {
    00424                     #if NX_UMAC_PRESENT
    00425                     ASSERT_ERR(txdesc_first != NULL);
    00426                     // Update the RC about the status
    00427                     rc_cfm_ampdu(txdesc_first, agg_txed, agg_ok);
    00428                     txdesc_first = NULL;
    00429                     #endif
    00430
    00431                     // Reset the packet counters
    00432                     agg_txed = 0;
    00433                     agg_ok = 0;
    00434
    00435                     // Free all aggregation related frames and control (BA, BAR, AGG_CNTRL)
    00436                     txl_agg_release(agg_desc);
    00437                 }
    00438
    00439                 // End of interrupt protection
    00440                 GLOBAL_INT_RESTORE();
    00441
    00442                 // Prepare the confirmation to upper MAC
    00443                 macif_tx_cfm_push(access_category, txdesc);
    00444             }
    00445             //singleton MPDU - confirm directly
    00446             else
    00447             {
    00448             #endif
    00449                 // Protect the access to the list from interrupt preemption
    00450                 GLOBAL_INT_DISABLE();
    00451
    00452                 //only picked it, must pop it now
    00453                 co_list_pop_front(cfm_list);
    00454
    00455                 // End of interrupt protection
    00456                 GLOBAL_INT_RESTORE();
    00457
    00458                 #if (RW_BFMER_EN)
    00459                 if (bfr_is_enabled())
    00460                 {
    00461                     // Check if the frame was beamformed
    00462                     bfr_tx_cfm(txdesc);
    00463                 }
    00464                 #endif //(RW_BFMER_EN)
    00465
    00466                 #if NX_UMAC_PRESENT
    00467                 // Update the RC about the TX status
    00468                 // WARNING!!! Must be done before the call to txu_cntrl_cfm()!!!
    00469                 rc_cfm_singleton(txdesc);
    00470
    00471                 // Indicate the packet status to the upper MAC
    00472                 txu_cntrl_cfm(txdesc);
    00473                 #endif
    00474
    00475                 // Send the confirmation to upper MAC, already has status
    00476                 macif_tx_cfm_push(access_category, txdesc);
    00477
    00478             #if NX_AMPDU_TX
    00479             }
    00480             #endif
    00481         }
    00482         else
    00483         {
    00484             // No more descriptors to confirm, so exit the loop
    00485             break;
    00486         }
    00487     }
    00488
    00489     // Stop the TX confirmation upload procedure
    00490     macif_tx_cfm_done(access_category, false);
    00491
    00492     // For profiling
    00493     PROF_TX_CFM_EVT_CLR();
    00494 }
    00495
    00496 void txl_cfm_flush_desc(uint8_t access_category, struct txdesc *txdesc, uint32_t status)
    00497 {
    00498     struct tx_cfm_tag *cfm = txl_cfm_tag_get(txdesc);
    00499
    00500     // Start the TX confirmation upload procedure
    00501     macif_tx_cfm_start(access_category);
    00502
    00503     // Put the status in the descriptor, only if it was not already done by the HW
    00504     if (txdesc->lmac.agg_desc != NULL)
    00505         cfm->status = status | A_MPDU_LAST;
    00506     else if (!(cfm->status & DESC_DONE_TX_BIT))
    00507         cfm->status = status;
    00508
    00509     #if NX_TX_FRAME
    00510     // Check if the frame was generated internally
    00511     if (is_int_frame(txdesc))
    00512     {
    00513         // Put the descriptor in the CFM queue
    00514         txl_frame_cfm(txdesc);
    00515     }
    00516     else
    00517     #endif
    00518     {
    00519         #if NX_UMAC_PRESENT
    00520         // Indicate the packet status to the upper MAC
    00521         txu_cntrl_cfm(txdesc);
    00522         #endif
    00523
    00524         #if (RW_BFMER_EN)
    00525         if (bfr_is_enabled())
    00526         {
    00527             // Check if the frame was beamformed
    00528             bfr_tx_cfm(txdesc);
    00529         }
    00530         #endif //(RW_BFMER_EN)
    00531
    00532         // Prepare the confirmation to the host
    00533         macif_tx_cfm_push(access_category, txdesc);
    00534
    00535         #if !NX_FULLY_HOSTED
    00536         txl_buffer_free_all(txdesc, access_category);
    00537         #endif
    00538     }
    00539
    00540
    00541     #if NX_TX_FRAME
    00542     // Execute the internal frame confirmation event to complete the flush
    00543     txl_frame_evt(0);
    00544     #endif
    00545
    00546     // Stop the TX confirmation upload procedure
    00547     macif_tx_cfm_done(access_category, true);
    00548 }
    00549
    00550
    00551 void txl_cfm_flush(uint8_t access_category, struct co_list *list, uint32_t status)
    00552 {
    00553     // Start the TX confirmation upload procedure
    00554     macif_tx_cfm_start(access_category);
    00555
    00556     // Go through the descriptors in the list
    00557     while (1)
    00558     {
    00559         // Get the first descriptor from the list
    00560         struct txdesc *txdesc = (struct txdesc *)co_list_pop_front(list);
    00561         struct tx_cfm_tag *cfm;
    00562
    00563         // Check if we reached the end of the list
    00564         if (txdesc == NULL)
    00565             break;
    00566
    00567         // Put the status in the descriptor, only if it was not already done by the HW
    00568         cfm = txl_cfm_tag_get(txdesc);
    00569         if (txdesc->lmac.agg_desc != NULL)
    00570             cfm->status = status | A_MPDU_LAST;
    00571         else if (!(cfm->status & DESC_DONE_TX_BIT))
    00572             cfm->status = status;
    00573
    00574         #if NX_TX_FRAME
    00575         // Check if the frame was generated internally
    00576         if (is_int_frame(txdesc))
    00577         {
    00578             // Put the descriptor in the CFM queue
    00579             txl_frame_cfm(txdesc);
    00580         }
    00581         else
    00582         #endif
    00583         {
    00584             #if NX_UMAC_PRESENT
    00585             // Indicate the packet status to the upper MAC
    00586             txu_cntrl_cfm(txdesc);
    00587             #endif
    00588
    00589             #if (RW_BFMER_EN)
    00590             if (bfr_is_enabled())
    00591             {
    00592                 // Check if the frame was beamformed
    00593                 bfr_tx_cfm(txdesc);
    00594             }
    00595             #endif //(RW_BFMER_EN)
    00596
    00597             // Prepare the confirmation to the host
    00598             macif_tx_cfm_push(access_category, txdesc);
    00599
    00600             #if !NX_FULLY_HOSTED
    00601             txl_buffer_free_all(txdesc, access_category);
    00602             #endif
    00603         }
    00604     }
    00605
    00606     #if NX_TX_FRAME
    00607     // Execute the internal frame confirmation event to complete the flush
    00608     txl_frame_evt(0);
    00609     #endif
    00610
    00611     // Stop the TX confirmation upload procedure
    00612     macif_tx_cfm_done(access_category, true);
    00613 }
    00614
    00615
    00617