- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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

Go to the documentation of this file.

    00001
    00017 /*
    00018  * INCLUDE FILES
    00019  ****************************************************************************************
    00020  */
    00021
    00022 // standard includes
    00023 #include "co_int.h"
    00024 // for bool
    00025 #include "co_bool.h"
    00026 // for NULL
    00027 #include <string.h>
    00028 // for __INLINE
    00029 #include "compiler.h"
    00030
    00031 // main file include
    00032 #include "rxu_cntrl.h"
    00033
    00034 // Communication with upper layers
    00035 #include "macif.h"
    00036 // for ring element types
    00037 #include "co_ring.h"
    00038 // for event bits
    00039 #include "ke_event.h"
    00040 // for api task
    00041 #include "ke_task.h"
    00042 // for api task
    00043 #include "me_task.h"
    00044 // for MIC header length
    00045 #include "mac_frame.h"
    00046 // LMAC RX Controller
    00047 #include "rxl_cntrl.h"
    00048 // STA Information
    00049 #include "sta_mgmt.h"
    00050 // VIF Information
    00051 #include "vif_mgmt.h"
    00052 // STA Info table
    00053 #include "mm.h"
    00054 // Function prototypes and HW desc macros
    00055 #include "rxl_hwdesc.h"
    00056 #include "ps.h"
    00057
    00058 #include "co_utils.h"
    00059 #include "co_endian.h"
    00060
    00061 #include "hal_desc.h"
    00062
    00063 #include "llc.h"
    00064 #include "bam.h"
    00065 #include "mac_ie.h"
    00066 #include "me_utils.h"
    00067 #include "rxu_task.h"
    00068 #include "scanu_task.h"
    00069 #include "scanu.h"
    00070 #include "sm.h"
    00071 #if NX_MFP
    00072 #include "mfp.h"
    00073 #endif
    00074 #if (RW_MESH_EN)
    00075 #include "mesh_hwmp.h"
    00076 #endif //(RW_MESH_EN)
    00077
    00078 /*
    00079  * MACROS
    00080  ****************************************************************************************
    00081  */
    00082
    00084 #define RXL_CNTRL_IS_DATA(frame_cntrl)                                                   \
    00085            ((frame_cntrl & MAC_FCTRL_TYPE_MASK) == MAC_FCTRL_DATA_T)
    00087 #define RXL_CNTRL_IS_QOS_DATA(frame_cntrl)                                               \
    00088            ((frame_cntrl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_QOS_DATA)
    00090 #define RXL_CNTRL_IS_MGT(frame_cntrl)                                                    \
    00091            ((frame_cntrl & MAC_FCTRL_TYPE_MASK) == MAC_FCTRL_MGT_T)
    00093 #define RXL_CNTRL_IS_CTRL(frame_cntrl)                                                   \
    00094            ((frame_cntrl & MAC_FCTRL_TYPE_MASK) == MAC_FCTRL_CTRL_T)
    00095
    00097 #define RXL_CNTRL_IS_PROTECTED(frame_cntrl)                                              \
    00098            ((frame_cntrl & MAC_FCTRL_PROTECTEDFRAME) == MAC_FCTRL_PROTECTEDFRAME)
    00099
    00100 /*
    00101  * GLOBAL VARIABLE DECLARATIONS
    00102  ****************************************************************************************
    00103  */
    00104
    00106 struct rxu_cntrl_env_tag rxu_cntrl_env;
    00107
    00110 #if NX_FULLY_HOSTED
    00111 #define __RX_STAT_DESC_LOC
    00112 #else
    00113 #define __RX_STAT_DESC_LOC __SHAREDRAM
    00114 #endif
    00116 struct rxu_stat_desc rxu_stat_desc_pool[RX_STAT_DESC_CNT] __RX_STAT_DESC_LOC;
    00117
    00118 #if (NX_REORD)
    00120 struct rxu_cntrl_reord rxu_cntrl_reord_pool[RX_CNTRL_REORD_POOL_SIZE];
    00121 #endif //(NX_REORD)
    00122
    00124 struct rxu_cntrl_defrag rxu_cntrl_defrag_pool[RX_CNTRL_DEFRAG_POOL_SIZE];
    00125
    00126 /*
    00127  * PRIVATE FUNCTION DEFINITIONS
    00128  ****************************************************************************************
    00129  */
    00137 static void rxu_upload_cfm(void *env)
    00138 {
    00139     #if NX_FULLY_HOSTED
    00140     struct rxu_stat_desc *rx_stat_desc = env;
    00141     rx_stat_desc->rxdesc = NULL;
    00142     #else
    00143     struct rxu_stat_val *val = env;
    00144     val->status = 0;
    00145     rxl_host_irq_mitigation_update(env);
    00146     #endif
    00147 }
    00148
    00160 static struct rxu_stat_desc *rxu_cntrl_desc_prepare(struct rxdesc *rxdesc,
    00161                                                     uint16_t rx_status,
    00162                                                     uint32_t host_id)
    00163 {
    00164     // Structure containing the RX descriptor information
    00165     struct rxu_stat_desc *rx_stat_desc = &rxu_stat_desc_pool[rxu_cntrl_env.rxdesc_idx];
    00166     struct co_list_hdr *list_hdr;
    00167
    00168     // Sanity check - the number of internal RX desc is sized to ensure there is always
    00169     // one available
    00170     ASSERT_REC_VAL(rx_stat_desc->val.status == 0, NULL);
    00171
    00172     PROF_IPCDESC_PREPARE_SET();
    00173
    00174     #if NX_FULLY_HOSTED
    00175     list_hdr = &rx_stat_desc->list_hdr;
    00176     rx_stat_desc->rxdesc = rxdesc;
    00177     if (rxdesc)
    00178     {
    00179         rxdesc->upload_cntrl.cb = rxu_upload_cfm;
    00180         rxdesc->upload_cntrl.env = rx_stat_desc;
    00181     }
    00182     #else
    00183     list_hdr = &rx_stat_desc->upload_cntrl.list_hdr;
    00184     rx_stat_desc->upload_cntrl.rxdesc = rxdesc;
    00185     #endif
    00186
    00187     // Fullfil the descriptor value structure
    00188     rx_stat_desc->val.status = rx_status;
    00189     rx_stat_desc->val.host_id = host_id;
    00190
    00191     // Insert the element in the ready list
    00192     co_list_push_back(&rxu_cntrl_env.rxdesc_ready, list_hdr);
    00193
    00194     // Increment the RX Desc index
    00195     rxu_cntrl_env.rxdesc_idx = (rxu_cntrl_env.rxdesc_idx + 1) % RX_STAT_DESC_CNT;
    00196
    00197     PROF_IPCDESC_PREPARE_CLR();
    00198
    00199     return (rx_stat_desc);
    00200 }
    00201
    00211 __INLINE uint8_t rxu_cntrl_machdr_len_get(uint16_t frame_cntl)
    00212 {
    00213     // MAC Header length
    00214     uint8_t mac_hdr_len = MAC_SHORT_MAC_HDR_LEN;
    00215
    00216     // Check if Address 4 field is present (FDS and TDS set to 1)
    00217     if ((frame_cntl & (MAC_FCTRL_TODS | MAC_FCTRL_FROMDS))
    00218                                     == (MAC_FCTRL_TODS | MAC_FCTRL_FROMDS))
    00219     {
    00220         mac_hdr_len += (MAC_LONG_MAC_HDR_LEN - MAC_SHORT_MAC_HDR_LEN);
    00221     }
    00222
    00223     // Check if QoS Control Field is present
    00224     if (RXL_CNTRL_IS_QOS_DATA(frame_cntl))
    00225     {
    00226         mac_hdr_len += (MAC_LONG_QOS_MAC_HDR_LEN - MAC_LONG_MAC_HDR_LEN);
    00227     }
    00228
    00229     // Check if HT Control Field is present (Order bit set to 1)
    00230     if (frame_cntl & MAC_FCTRL_ORDER)
    00231     {
    00232         mac_hdr_len += (MAC_LONG_QOS_HTC_MAC_HDR_LEN - MAC_LONG_QOS_MAC_HDR_LEN);
    00233     }
    00234
    00235     return (mac_hdr_len);
    00236 }
    00237
    00248 static bool rxu_cntrl_protected_handle(uint8_t *frame, uint32_t statinfo)
    00249 {
    00250     uint32_t frame_addr = CPU2HW(frame);
    00251     uint16_t *iv = HW2CPU(frame_addr + rxu_cntrl_env.rx_status.machdr_len);
    00252     bool ga = (statinfo & RX_HD_GA_FRAME) != 0;
    00253     struct key_info_tag *key;
    00254     bool upload = true;
    00255
    00256     switch (statinfo & RX_HD_DECRSTATUS)
    00257     {
    00258         case RX_HD_DECR_CCMP128_SUCCESS:
    00259             if (ga)
    00260             {
    00261                 struct vif_info_tag *vif = &vif_info_tab[rxu_cntrl_env.rx_status.vif_idx];
    00262                 key = &vif->key_info[iv[1] >> 14];
    00263             }
    00264             else
    00265             {
    00266                 struct sta_info_tag *sta = &sta_info_tab[rxu_cntrl_env.rx_status.sta_idx];
    00267                 key = &sta->sta_sec_info.key_info;
    00268             }
    00269             rxu_cntrl_env.rx_status.key = key;
    00270             #if RW_WAPI_EN && !NX_RX_RING
    00271             if (key->cipher == MAC_CIPHER_WPI_SMS4) {
    00272                 rxu_cntrl_env.rx_status.machdr_len += WPI_IV_LEN;
    00273                 rxu_cntrl_env.rx_status.pn = (((uint64_t)iv[4]) << 48) |
    00274                     (((uint64_t)iv[3]) << 32) | (((uint64_t)iv[2]) << 16) | iv[1];
    00275                 rxu_cntrl_env.rx_status.frame_info |= RXU_CNTRL_PN_CHECK_NEEDED;
    00276             } else
    00277             #endif
    00278             {
    00279                 rxu_cntrl_env.rx_status.machdr_len += IV_LEN + EIV_LEN;
    00280                 rxu_cntrl_env.rx_status.pn = (((uint64_t)iv[3]) << 32) |
    00281                     (((uint64_t)iv[2]) << 16) | iv[0];
    00282                 rxu_cntrl_env.rx_status.frame_info |= RXU_CNTRL_PN_CHECK_NEEDED;
    00283             }
    00284             break;
    00285         #if RW_WAPI_EN && NX_RX_RING
    00286         case RX_HD_DECR_WAPI_SUCCESS:
    00287             if (ga)
    00288             {
    00289                 struct vif_info_tag *vif = &vif_info_tab[rxu_cntrl_env.rx_status.vif_idx];
    00290                 key = &vif->key_info[iv[1] >> 14];
    00291             }
    00292             else
    00293             {
    00294                 struct sta_info_tag *sta = &sta_info_tab[rxu_cntrl_env.rx_status.sta_idx];
    00295                 key = &sta->sta_sec_info.key_info;
    00296             }
    00297             rxu_cntrl_env.rx_status.key = key;
    00298             rxu_cntrl_env.rx_status.machdr_len += WPI_IV_LEN;
    00299             rxu_cntrl_env.rx_status.pn = (((uint64_t)iv[4]) << 48) |
    00300                 (((uint64_t)iv[3]) << 32) | (((uint64_t)iv[2]) << 16) | iv[1];
    00301             rxu_cntrl_env.rx_status.frame_info |= RXU_CNTRL_PN_CHECK_NEEDED;
    00302             break;
    00303         #endif // RW_WAPI_EN && NX_RX_RING
    00304         case RX_HD_DECR_WEP_SUCCESS:
    00305             rxu_cntrl_env.rx_status.machdr_len += IV_LEN;
    00306             break;
    00307         case RX_HD_DECR_TKIP_SUCCESS:
    00308             rxu_cntrl_env.rx_status.machdr_len += IV_LEN + EIV_LEN;
    00309             rxu_cntrl_env.rx_status.pn = (((uint64_t)iv[3]) << 32) |
    00310                                          (((uint64_t)iv[2]) << 16) |
    00311                                           ((iv[0] & 0xFF) << 8) | (iv[1] & 0xFF);
    00312             rxu_cntrl_env.rx_status.frame_info |= RXU_CNTRL_PN_CHECK_NEEDED |
    00313                                                   RXU_CNTRL_MIC_CHECK_NEEDED;
    00314             if (ga)
    00315             {
    00316                 struct vif_info_tag *vif = &vif_info_tab[rxu_cntrl_env.rx_status.vif_idx];
    00317                 key = &vif->key_info[iv[1] >> 14];
    00318             }
    00319             else
    00320             {
    00321                 struct sta_info_tag *sta = &sta_info_tab[rxu_cntrl_env.rx_status.sta_idx];
    00322                 key = &sta->sta_sec_info.key_info;
    00323             }
    00324             rxu_cntrl_env.rx_status.key = key;
    00325             break;
    00326         default:
    00327             upload = false;
    00328             break;
    00329     }
    00330
    00331     return upload;
    00332 }
    00333
    00345 static bool rxu_cntrl_check_pn(uint64_t *pn, struct key_info_tag *key, uint8_t tid)
    00346 {
    00347     if (*pn > key->rx_pn[tid])
    00348     {
    00349         key->rx_pn[tid] = *pn;
    00350         return true;
    00351     }
    00352
    00353     return false;
    00354 }
    00355
    00366 static void rxu_cntrl_remove_sec_hdr_mgmt_frame(struct rxdesc *rxdesc,
    00367                                                 struct rx_cntrl_rx_status *rx_status)
    00368 {
    00369     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    00370     struct rx_payloaddesc *payl_d = HW2CPU(dma_hdrdesc->hd.first_pbd_ptr);
    00371     struct mac_hdr *machdr = HW2CPU(payl_d->pbd.datastartptr);
    00372     uint8_t machdr_len = rxu_cntrl_machdr_len_get(machdr->fctl);
    00373     uint8_t payl_offset = rx_status->machdr_len - machdr_len;
    00374     uint16_t *src, *dst, *start;
    00375
    00376     if (payl_offset == 0)
    00377         return;
    00378
    00379     ASSERT_WARN((payl_offset & 0x1) == 0);
    00380
    00381     start = src = dst = (uint16_t *)machdr;
    00382     src  += machdr_len/2 - 1;
    00383     dst  += rx_status->machdr_len/2 - 1;
    00384
    00385     while (src >= start)
    00386     {
    00387         *dst-- = *src--;
    00388     }
    00389
    00390     dma_hdrdesc->hd.frmlen -= payl_offset;
    00391     rx_status->payl_offset = payl_offset;
    00392     rx_status->machdr_len -= payl_offset;
    00393 }
    00394
    00402 static void rxu_cntrl_mac2eth_update(struct rxdesc *rxdesc)
    00403 {
    00404     #if (RW_MESH_EN)
    00405     // Get VIF Information
    00406     struct vif_info_tag *vif = &vif_info_tab[rxu_cntrl_env.rx_status.vif_idx];
    00407     #endif //(RW_MESH_EN)
    00408     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    00409     // First payload descriptor -> Buffer will contain the MAC Header (and IV, EIV if present)
    00410     struct rx_payloaddesc *first_pbd
    00411             = (struct rx_payloaddesc *)HW2CPU(dma_hdrdesc->hd.first_pbd_ptr);
    00412     // Map a MAC Header structure on the frame
    00413     struct mac_hdr *machdr = (struct mac_hdr *)HW2CPU(first_pbd->pbd.datastartptr);
    00414     // LLC/SNAP part of the PDU
    00415     struct llc_snap *llc_snap;
    00416     // Ethernet Header
    00417     struct mac_eth_hdr *eth_hdr;
    00418     // Compute MAC Header Length (will IV length + EIV length if present)
    00419     uint16_t machdr_len = rxu_cntrl_env.rx_status.machdr_len;
    00420     uint8_t payl_offset = machdr_len - sizeof_b(struct mac_eth_hdr);
    00421
    00422 //    PROF_MAC2ETH_UPDATE_SET();
    00423
    00424     #if NX_MON_DATA
    00425     if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
    00426     {
    00427         struct rxu_machdrdesc *machdr_desc = &dma_hdrdesc->mac_hdr_backup;
    00428
    00429         // Copy MAC Header, LLC and SNAP before overriding
    00430         memcpy(&machdr_desc->buffer, machdr, machdr_len + LLC_802_2_HDR_LEN);
    00431     }
    00432     #endif
    00433
    00434     do
    00435     {
    00436         // For QOS frame get User priority and check for A-MSDU
    00437         dma_hdrdesc->flags &= ~(RX_FLAGS_USER_PRIO_INDEX_MSK);
    00438         if (RXL_CNTRL_IS_QOS_DATA(machdr->fctl))
    00439         {
    00440             uint16_t qos;
    00441             uint16_t prio;
    00442
    00443             if ((machdr->fctl & MAC_FCTRL_TODS_FROMDS) ==
    00444                 MAC_FCTRL_TODS_FROMDS)
    00445             {
    00446                 struct mac_hdr_long_qos *qos_hdr = (struct mac_hdr_long_qos *)machdr;
    00447                 qos = qos_hdr->qos;
    00448             }
    00449             else
    00450             {
    00451                 struct mac_hdr_qos *qos_hdr = (struct mac_hdr_qos *)machdr;
    00452                 qos = qos_hdr->qos;
    00453             }
    00454
    00455             prio = ((qos & MAC_QOSCTRL_UP_MSK) >> MAC_QOSCTRL_UP_OFT);
    00456             dma_hdrdesc->flags |= ((prio) << RX_FLAGS_USER_PRIO_INDEX_OFT) & RX_FLAGS_USER_PRIO_INDEX_MSK;
    00457
    00458             if (qos & MAC_QOSCTRL_AMSDU_PRESENT)
    00459             {
    00460                 dma_hdrdesc->flags |= RX_FLAGS_IS_AMSDU_BIT;
    00461                 payl_offset += sizeof_b(struct mac_eth_hdr);
    00462                 break;
    00463             }
    00464         }
    00465
    00466         #if (RW_MESH_EN)
    00467         if ((vif->type == VIF_MESH_POINT)
    00468                 && (rxu_cntrl_env.rx_status.dst_idx != INVALID_STA_IDX))
    00469         {
    00470             // -> Packet becomes
    00471             /********************************************************************
    00472              *  DA  |  SA  |  ETHERTYPE  |  MESH_CONTROL  |  LLC/SNAP  |  DATA  |
    00473              ********************************************************************/
    00474             // Skip MAC Header (Mesh Control not included)
    00475             eth_hdr = (struct mac_eth_hdr *)((uint16_t *)machdr + (machdr_len >> 1) - 7);
    00476             // Pointer to the payload - Skip MAC Header and Mesh Control
    00477             llc_snap = (struct llc_snap *)((uint16_t *)machdr + (machdr_len >> 1)
    00478                                                               + (rxu_cntrl_env.rx_status.mesh_ctrl_len >> 1));
    00479
    00480             // Set Ethertype
    00481             eth_hdr->len = llc_snap->proto_id;
    00482         }
    00483         else
    00484         #endif //(RW_MESH_EN)
    00485         {
    00486             // Pointer to the payload - Skip MAC Header
    00487             llc_snap = (struct llc_snap *)((uint16_t *)machdr + (machdr_len >> 1));
    00488
    00489             /*
    00490              * Ethernet encapsulated packet structure
    00491              ******************************************
    00492              *  MAC HEADER  |  LLC  |  SNAP  |  DATA  |
    00493              ******************************************
    00494              * or
    00495              *************************
    00496              *  MAC HEADER  |  DATA  |
    00497              *************************
    00498              * The type of structure depends on the LLC fields.
    00499              */
    00500             if ((!memcmp(llc_snap, &llc_rfc1042_hdr, sizeof(llc_rfc1042_hdr))
    00501                  //&& (llc_snap->ether_type != LLC_ETHERTYPE_AARP) - Appletalk depracated ?
    00502                  && (llc_snap->proto_id != LLC_ETHERTYPE_IPX))
    00503                 || (!memcmp(llc_snap, &llc_bridge_tunnel_hdr, sizeof(llc_bridge_tunnel_hdr))))
    00504             {
    00505                 // Case 1 -> Packet becomes
    00506                 /********************************************
    00507                  *  DA  |  SA  |  SNAP->ETHERTYPE  |  DATA  |
    00508                  ********************************************/
    00509                 /*
    00510                  * Ethernet Header will start 6 half-words (MAC Address length is 6 bytes) before Ethertag
    00511                  * type
    00512                  */
    00513                 eth_hdr = (struct mac_eth_hdr *)((uint16_t *)&(llc_snap->proto_id) - 6);
    00514
    00515                 // Remove length of LLC/SNAP
    00516                 payl_offset += 8;
    00517
    00518                 rxu_cntrl_env.rx_status.eth_len_present = false;
    00519             }
    00520             else
    00521             {
    00522                 // Case 2 -> Packet becomes
    00523                 /********************************
    00524                  *  DA  |  SA  |  LEN  |  DATA  |
    00525                  ********************************/
    00526                 /*
    00527                  * Ethernet Header will start 7 half-words (MAC Address length is 6 bytes and Length
    00528                  * field is 2 bytes) before LLC Snap
    00529                  */
    00530                 eth_hdr = (struct mac_eth_hdr *)((uint16_t *)llc_snap - 7);
    00531
    00532                 // Set length (Initial length - MAC Header Length)
    00533                 eth_hdr->len = co_htons(dma_hdrdesc->hd.frmlen - machdr_len);
    00534
    00535                 rxu_cntrl_env.rx_status.eth_len_present = true;
    00536             }
    00537         }
    00538
    00539         // Set DA and SA in the Ethernet Header
    00540         MAC_ADDR_CPY(&eth_hdr->da, &rxu_cntrl_env.rx_status.da);
    00541         MAC_ADDR_CPY(&eth_hdr->sa, &rxu_cntrl_env.rx_status.sa);
    00542
    00543     } while(0);
    00544
    00545     // Update Frame Length
    00546     dma_hdrdesc->hd.frmlen -= payl_offset;
    00547     rxu_cntrl_env.rx_status.payl_offset = payl_offset;
    00548
    00549     #if NX_MON_DATA
    00550     if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
    00551     {
    00552         struct rxu_machdrdesc *machdr_desc = &dma_hdrdesc->mac_hdr_backup;
    00553
    00554         //Set length
    00555         machdr_desc->buf_len = payl_offset + sizeof_b(struct mac_eth_hdr);
    00556     }
    00557     #endif
    00558
    00559 //    PROF_MAC2ETH_UPDATE_CLR();
    00560 }
    00561
    00571 static void rxu_msdu_upload_and_indicate(struct rxdesc *rxdesc,
    00572                                          uint16_t rx_status)
    00573 {
    00574     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    00575     struct rx_cntrl_rx_status *rx_stat = &rxu_cntrl_env.rx_status;
    00576
    00577     // Put the VIF and STA information to the RX flags
    00578     dma_hdrdesc->flags |= (rx_stat->sta_idx << RX_FLAGS_STA_INDEX_OFT) |
    00579                           (rx_stat->vif_idx << RX_FLAGS_VIF_INDEX_OFT) |
    00580                           (rx_stat->dst_idx << RX_FLAGS_DST_INDEX_OFT);
    00581
    00582     // Translate the MAC frame to an Ethernet frame
    00583     rxu_cntrl_mac2eth_update(rxdesc);
    00584     // Program the DMA transfer of the MPDU
    00585     rxl_mpdu_transfer(rxdesc);
    00586
    00587     #if NX_MON_DATA
    00588     if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
    00589     {
    00590         // set frame for monitor interface
    00591         rx_status |= RX_STAT_MONITOR;
    00592     }
    00593     #endif
    00594
    00595     // Prepare the descriptor for the last received packet
    00596     rxu_cntrl_desc_prepare(rxdesc, rx_status, rxu_cntrl_env.hostid_current);
    00597 }
    00598
    00607 static void rxu_mpdu_upload_and_indicate(struct rxdesc *rxdesc, uint16_t rx_status)
    00608 {
    00609     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    00610     struct rx_cntrl_rx_status *rx_stat = &rxu_cntrl_env.rx_status;
    00611     struct rx_hd *rhd = &dma_hdrdesc->hd;
    00612     uint32_t statinfo = rhd->statinfo;
    00613
    00614     //Check whether we have a monitor interface
    00615     if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
    00616     {
    00617         // Check if vif is invalid
    00618         if (rx_stat->vif_idx == INVALID_VIF_IDX)
    00619         {
    00620             // Send frame to driver for monitoring only
    00621             rx_status = RX_STAT_MONITOR;
    00622         }
    00623         else
    00624         {
    00625             rx_status |= RX_STAT_MONITOR;
    00626         }
    00627     }
    00628
    00629     // Put the VIF and STA information to the RX flags
    00630     dma_hdrdesc->flags |= (rx_stat->sta_idx << RX_FLAGS_STA_INDEX_OFT) |
    00631                           (rx_stat->vif_idx << RX_FLAGS_VIF_INDEX_OFT) |
    00632                           RX_FLAGS_IS_MPDU_BIT;
    00633
    00634     #if (RW_MESH_EN)
    00635     if (rx_stat->frame_info & RXU_CNTRL_NEW_MESH_PEER)
    00636     {
    00637         dma_hdrdesc->flags |= RX_FLAGS_NEW_MESH_PEER_BIT;
    00638     }
    00639     #endif //(RW_MESH_EN)
    00640
    00641     // MPDU is transfered as-is, so no offset is applied
    00642     rxu_cntrl_env.rx_status.payl_offset = 0;
    00643     // Check whether frame was successfully received
    00644     if (statinfo & RX_HD_SUCCESS)
    00645         // Remove security header in mgmt frame
    00646         rxu_cntrl_remove_sec_hdr_mgmt_frame(rxdesc, rx_stat);
    00647     // Program the DMA transfer of the MPDU
    00648     rxl_mpdu_transfer(rxdesc);
    00649     // Prepare the descriptor for the last received packet
    00650     rxu_cntrl_desc_prepare(rxdesc, rx_status, rxu_cntrl_env.hostid_current);
    00651 }
    00652
    00671 static void rxu_cntrl_get_da_sa(struct mac_hdr_long *machdr_ptr)
    00672 {
    00673     // Get DA
    00674     if (machdr_ptr->fctl & MAC_FCTRL_TODS)
    00675     {
    00676         MAC_ADDR_CPY(&rxu_cntrl_env.rx_status.da, &machdr_ptr->addr3);
    00677     }
    00678     else
    00679     {
    00680         MAC_ADDR_CPY(&rxu_cntrl_env.rx_status.da, &machdr_ptr->addr1);
    00681     }
    00682
    00683     // Get SA
    00684     if (machdr_ptr->fctl & MAC_FCTRL_FROMDS)
    00685     {
    00686         if (machdr_ptr->fctl & MAC_FCTRL_TODS)
    00687         {
    00688             MAC_ADDR_CPY(&rxu_cntrl_env.rx_status.sa, &machdr_ptr->addr4);
    00689         }
    00690         else
    00691         {
    00692             MAC_ADDR_CPY(&rxu_cntrl_env.rx_status.sa, &machdr_ptr->addr3);
    00693         }
    00694     }
    00695     else
    00696     {
    00697         MAC_ADDR_CPY(&rxu_cntrl_env.rx_status.sa, &machdr_ptr->addr2);
    00698     }
    00699 }
    00700
    00709 static void rxu_cntrl_machdr_read(uint8_t *frame)
    00710 {
    00711     // Map a MAC Header structure on the frame
    00712     struct mac_hdr *machdr = (struct mac_hdr *)frame;
    00713     uint16_t *qos;
    00714
    00715     rxu_cntrl_env.rx_status.frame_cntl = machdr->fctl;
    00716     rxu_cntrl_env.rx_status.seq_cntl = machdr->seq;
    00717     rxu_cntrl_env.rx_status.frame_info = 0;
    00718
    00719     rxu_cntrl_env.rx_status.sn = machdr->seq >> MAC_SEQCTRL_NUM_OFT;
    00720     rxu_cntrl_env.rx_status.fn = machdr->seq & MAC_SEQCTRL_FRAG_MSK;
    00721
    00722     if ((machdr->fctl & MAC_FCTRL_QOS_DATA) == MAC_FCTRL_QOS_DATA)
    00723     {
    00724         // Check if Address4 field is present
    00725         if ((machdr->fctl & MAC_FCTRL_TODS_FROMDS)
    00726                                     == MAC_FCTRL_TODS_FROMDS)
    00727         {
    00728             qos = &((struct mac_hdr_long_qos *)machdr)->qos;
    00729         }
    00730         else
    00731         {
    00732             qos = &((struct mac_hdr_qos *)machdr)->qos;
    00733         }
    00734
    00735         // Extract TID from QoS Control Field
    00736         rxu_cntrl_env.rx_status.tid = (*qos & MAC_QOSCTRL_UP_MSK);
    00737
    00738         #if (RW_MESH_EN)
    00739         // Keep address of QoS Control field for later Mesh Control handling
    00740         rxu_cntrl_env.rx_status.a_qos_ctrl = CPU2HW(qos);
    00741         #endif //(RW_MESH_EN)
    00742     }
    00743     else
    00744     {
    00745         rxu_cntrl_env.rx_status.tid = 0;
    00746     }
    00747
    00748     rxu_cntrl_env.rx_status.machdr_len = rxu_cntrl_machdr_len_get(machdr->fctl);
    00749
    00750     if (MAC_ADDR_GROUP(&machdr->addr1))
    00751         rxu_cntrl_env.rx_status.frame_info |= RXU_CNTRL_GROUP_ADDRESSED;
    00752
    00753     // Extract Destination Address and Source Address
    00754     rxu_cntrl_get_da_sa((struct mac_hdr_long *)machdr);
    00755 }
    00756
    00768 static void rxu_cntrl_mic_rd_concat(uint32_t mic_buffer, uint8_t mic_p1_len,
    00769                                     uint32_t mic_p1_addr, uint32_t mic_p2_addr)
    00770 {
    00771     // Copy first part of MIC byte per byte
    00772     co_copy8p(mic_buffer, mic_p1_addr, mic_p1_len);
    00773     mic_buffer += mic_p1_len;
    00774
    00775     // Copy second part of MIC byte per byte
    00776     co_copy8p(mic_buffer, mic_p2_addr, MIC_LEN - mic_p1_len);
    00777 }
    00778
    00789 static bool rxu_cntrl_mic_compare(uint32_t *mic_value1, uint32_t *mic_value2)
    00790 {
    00791     return ((*mic_value1 == *mic_value2) &&
    00792             (*(mic_value1 + 1) == *(mic_value2 + 1)));
    00793 }
    00794
    00801 static void rxu_cntrl_mic_failure(void)
    00802 {
    00803     struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
    00804     struct me_tkip_mic_failure_ind *ind = KE_MSG_ALLOC(ME_TKIP_MIC_FAILURE_IND, TASK_API,
    00805                                                        TASK_ME, me_tkip_mic_failure_ind);
    00806
    00807     // Fill in parameters
    00808     ind->addr = sta_info_tab[rx_status->sta_idx].mac_addr;
    00809     ind->tsc = rx_status->pn;
    00810     ind->ga = (rx_status->statinfo & RX_HD_GA_FRAME) != 0;
    00811     ind->vif_idx = rx_status->vif_idx;
    00812     ind->keyid = rx_status->key->key_idx;
    00813
    00814     // Send the message
    00815     ke_msg_send(ind);
    00816 }
    00817
    00832 static bool rxu_cntrl_mic_check(struct rxdesc *rxdesc, struct rxu_mic_calc *mic,
    00833                                 bool first_frag, bool last_frag)
    00834 {
    00835     struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
    00836     struct mic_calc *mic_calc_ptr = &mic->mic_calc;
    00837     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    00839     uint32_t rx_mic[2];
    00840     uint32_t rx_mic_addr = CPU2HW(rx_mic);
    00841     bool upload = true;
    00842
    00843     /*
    00844      * If first fragment, retrieve the MIC key and initialize the mic_calc structure
    00845      * associated with the provided STAID tuple.
    00846      */
    00847     if (first_frag)
    00848     {
    00849         struct key_info_tag *key = rx_status->key;
    00850
    00851         // Initializing mic_calc structure
    00852         me_mic_init(mic_calc_ptr, key->u.mic.rx_key, &rx_status->da,
    00853                         &rx_status->sa, rx_status->tid);
    00854     }
    00855
    00856     do
    00857     {
    00858         // Payload Descriptor
    00859         struct rx_payloaddesc *pd = HW2CPU(dma_hdrdesc->hd.first_pbd_ptr);
    00860         /*
    00861          * Total payload Length to proceed (excluding MAC Header, IV, EIV)
    00862          */
    00863         uint16_t data_tot_len = dma_hdrdesc->hd.frmlen - rx_status->machdr_len;
    00864         /*
    00865          * Length on which the MIC is computed
    00866          */
    00867         uint16_t remaining_len;
    00868         uint16_t comp_len;
    00869         uint16_t payl_offset;
    00870
    00871         /*
    00872          * If either first_frag or last_frag is False, the packet is part of a fragmented
    00873          * MPDU.
    00874          */
    00875         if (!first_frag)
    00876         {
    00877             uint32_t last_bytes_addr = CPU2HW(mic->last_bytes);
    00878             /*
    00879              * If not first fragment, we should have stored 8 last bytes from the previous
    00880              * received fragment in case these blocks contain a part of the MIC value
    00881              */
    00882             if (last_frag && (data_tot_len < MIC_LEN))
    00883             {
    00884                 uint32_t data_ptr = pd->pbd.datastartptr + rx_status->machdr_len;
    00885                 uint8_t data_len = MIC_LEN - data_tot_len;
    00886
    00887                 // Continue MIC Calculation with stored bytes not part of MIC
    00888                 me_mic_calc(mic_calc_ptr, last_bytes_addr, data_tot_len);
    00889
    00890                 // Extract the MIC from the stored data and the received data
    00891                 rxu_cntrl_mic_rd_concat(CPU2HW(&rx_mic[0]), data_len,
    00892                                         last_bytes_addr + data_tot_len,
    00893                                         data_ptr);
    00894
    00895                 // Go to End MIC Calculation + MIC verification step
    00896                 break;
    00897             }
    00898
    00899             // Continue the MIC Calculation with the 8 stored bytes
    00900             me_mic_calc(mic_calc_ptr, last_bytes_addr, MIC_LEN);
    00901         }
    00902
    00903         // Loop as long as the MPDU still has data on which we need to compute the MIC
    00904         remaining_len = data_tot_len - MIC_LEN;
    00905         payl_offset = rx_status->machdr_len;
    00906         while (1)
    00907         {
    00908             uint32_t comp_addr = pd->pbd.datastartptr + payl_offset;
    00909             uint16_t payl_len = pd->pbd.dataendptr - pd->pbd.datastartptr + 1;
    00910
    00911             // Check if we have reached the last payload buffer containing the MPDU
    00912             if ((remaining_len + payl_offset) <= payl_len)
    00913             {
    00914                 // DMA only the remaining bytes of the payload
    00915                 comp_len = remaining_len;
    00916             }
    00917             else
    00918             {
    00919                 // The complete payload buffer has to be DMA'ed
    00920                 comp_len = payl_len - payl_offset;
    00921             }
    00922
    00923             // Compute remaining length to be computed
    00924             remaining_len -= comp_len;
    00925
    00926             // Compute the MIC on this payload buffer
    00927             me_mic_calc(mic_calc_ptr, comp_addr, comp_len);
    00928
    00929             // Check if we have finished to compute the MIC
    00930             if (remaining_len == 0)
    00931                 break;
    00932
    00933             // Reset the offset
    00934             payl_offset = 0;
    00935
    00936             // Move to the next RBD
    00937             pd = HW2CPU(pd->pbd.next);
    00938
    00939             // Sanity check - There shall be a payload descriptor available
    00940             ASSERT_REC_VAL(pd != NULL, false);
    00941         }
    00942
    00943         // Now read the last 8 bytes
    00944         remaining_len = MIC_LEN;
    00945         payl_offset += comp_len;
    00946         while (1)
    00947         {
    00948             uint16_t payl_len = pd->pbd.dataendptr - pd->pbd.datastartptr + 1;
    00949             uint32_t mic_addr = pd->pbd.datastartptr + payl_offset;
    00950             uint16_t mic_len;
    00951
    00952             // Check if we have reached the last payload buffer containing the MPDU
    00953             if ((remaining_len + payl_offset) <= payl_len)
    00954             {
    00955                 // Copy only the remaining bytes of the MIC
    00956                 mic_len = remaining_len;
    00957             }
    00958             else
    00959             {
    00960                 // The complete payload buffer has to copied
    00961                 mic_len = payl_len - payl_offset;
    00962             }
    00963
    00964             // Copy the MIC chunk
    00965             co_copy8p(rx_mic_addr, mic_addr, mic_len);
    00966
    00967             // Compute the remaining length to be DMA'ed to host
    00968             remaining_len -= mic_len;
    00969             rx_mic_addr += mic_len;
    00970
    00971             // Check if we have finished to compute the MIC
    00972             if (remaining_len == 0)
    00973                 break;
    00974
    00975             // Reset the offset
    00976             payl_offset = 0;
    00977
    00978             // Move to the next RBD
    00979             pd = HW2CPU(pd->pbd.next);
    00980
    00981             // Sanity check - There shall be a payload descriptor available
    00982             ASSERT_REC_VAL(pd != NULL, false);
    00983         }
    00984     } while (0);
    00985
    00986     if (last_frag)
    00987     {
    00988         // Finalizing the MIC calculation; to obtain the final MIC key
    00989         me_mic_end(mic_calc_ptr);
    00990
    00991         // Finally check the computed MIC value
    00992         upload = rxu_cntrl_mic_compare(&rx_mic[0], (uint32_t *)mic_calc_ptr);
    00993         if (!upload)
    00994             rxu_cntrl_mic_failure();
    00995     }
    00996     else
    00997     {
    00998         // Copy the 8 bytes known as MIC in the structure
    00999         mic->last_bytes[0] = rx_mic[0];
    01000         mic->last_bytes[1] = rx_mic[1];
    01001     }
    01002
    01003     return upload;
    01004 }
    01005
    01016 static void rxu_cntrl_defrag_mpdu_transfer(struct rxdesc *rxdesc,
    01017                                            struct rxu_cntrl_defrag *defrag,
    01018                                            uint16_t cpy_len)
    01019 {
    01020     PROF_DEFRAG_TRANSFER_SET();
    01021
    01022     // Program upload of fragment
    01023     rxl_mpdu_partial_transfer(rxdesc, cpy_len, defrag->dma_addr, defrag->mac_hdr_len,
    01024                               NULL, NULL);
    01025
    01026     // Update stored DMA offset
    01027     defrag->dma_addr += cpy_len;
    01028
    01029     PROF_DEFRAG_TRANSFER_CLR();
    01030 }
    01031
    01044 static struct rxu_cntrl_defrag *rxu_cntrl_defrag_get(uint8_t sta_idx, uint16_t sn, uint8_t tid)
    01045 {
    01046     // Get the first element of the list of used Reassembly structures
    01047     struct rxu_cntrl_defrag *defrag = (struct rxu_cntrl_defrag *)co_list_pick(&rxu_cntrl_env.rxu_defrag_used);
    01048
    01049     while (defrag)
    01050     {
    01051         // Compare Station Id and TID
    01052         if ((defrag->sta_idx == sta_idx)
    01053                 && (defrag->tid == tid)
    01054                 && (defrag->sn == sn))
    01055         {
    01056             // We found a matching structure, escape from the loop
    01057             break;
    01058         }
    01059
    01060         defrag = (struct rxu_cntrl_defrag *)defrag->list_hdr.next;
    01061     }
    01062
    01063     // Return found element
    01064     return (defrag);
    01065 }
    01066
    01076 static struct rxu_cntrl_defrag *rxu_cntrl_defrag_alloc(void)
    01077 {
    01078     // Get the first element of the list of used Reassembly structures
    01079     struct rxu_cntrl_defrag *defrag =
    01080            (struct rxu_cntrl_defrag *)co_list_pop_front(&rxu_cntrl_env.rxu_defrag_free);
    01081
    01082     if (!defrag)
    01083     {
    01084         // Get the first element of the list of used Reassembly structures
    01085         defrag = (struct rxu_cntrl_defrag *)co_list_pop_front(&rxu_cntrl_env.rxu_defrag_used);
    01086
    01087         // Sanity check - There shall be an available structure
    01088         ASSERT_ERR(defrag != NULL);
    01089
    01090         // Inform the host that the allocated data buffer can be freed
    01091         rxu_cntrl_desc_prepare(NULL, RX_STAT_DELETE, defrag->host_id);
    01092     }
    01093
    01094     // Return the allocated element
    01095     return (defrag);
    01096 }
    01097
    01106 static void rxu_cntrl_defrag_len_update(struct rxu_cntrl_defrag *defrag)
    01107 {
    01108     uint16_t status;
    01109     struct rxu_stat_desc *rx_stat_desc;
    01110
    01111     PROF_DEFRAG_UPD_LENGTH_SET();
    01112     // Fulfill the descriptor value structure
    01113     status = defrag->eth_len_present?RX_STAT_LEN_UPDATE|RX_STAT_ETH_LEN_UPDATE:RX_STAT_LEN_UPDATE;
    01114
    01115     // Prepare the RX descriptor
    01116     rx_stat_desc = rxu_cntrl_desc_prepare(NULL, status, defrag->host_id);
    01117
    01118     if (rx_stat_desc)
    01119         rx_stat_desc->val.frame_len = defrag->frame_len;
    01120     PROF_DEFRAG_UPD_LENGTH_CLR();
    01121 }
    01122
    01131 static void rxu_cntrl_defrag_timeout_cb(void *env)
    01132 {
    01133     struct rxu_cntrl_defrag *defrag = env;
    01134
    01135     // Inform the host that the allocated data buffer can be freed
    01136     rxu_cntrl_desc_prepare(NULL, RX_STAT_DELETE, defrag->host_id);
    01137
    01138     // Remove the structure from the list
    01139     co_list_extract(&rxu_cntrl_env.rxu_defrag_used, &defrag->list_hdr);
    01140     co_list_push_back(&rxu_cntrl_env.rxu_defrag_free, &defrag->list_hdr);
    01141
    01142     // Start the descriptor transfer
    01143     macif_rx_desc_upload(&rxu_cntrl_env.rxdesc_ready);
    01144 }
    01145
    01158 static bool rxu_cntrl_defrag_check(struct rxdesc *rxdesc,
    01159                                       uint8_t sta_idx, bool qos)
    01160 {
    01161     // IPC status
    01162     bool upload = false;
    01163     // Traffic Index - Use best effort if non-QoS
    01164     uint8_t tid = (qos) ? rxu_cntrl_env.rx_status.tid : 0;
    01165     // RX status structure
    01166     struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
    01167     // More Fragment
    01168     uint16_t mf = rx_status->frame_cntl & MAC_FCTRL_MOREFRAG;
    01169     // Reassembly structure
    01170     struct rxu_cntrl_defrag *defrag;
    01171     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    01172     // Pointer to the RHD of the packet
    01173     struct rx_hd *rhd = &dma_hdrdesc->hd;
    01174
    01175     PROF_DEFRAG_CHECK_SET();
    01176
    01177     do
    01178     {
    01179         if (!mf && !rx_status->fn)
    01180         {
    01181             struct rxu_mic_calc mic;
    01182
    01183             // Perform the MIC check if required
    01184             if (rx_status->frame_info & RXU_CNTRL_MIC_CHECK_NEEDED)
    01185             {
    01186                 if (!rxu_cntrl_mic_check(rxdesc, &mic, true, true))
    01187                     break;
    01188                 else
    01189                     // Adjust the packet length to remove the MIC from the end of the payload
    01190                     rhd->frmlen -= MIC_LEN;
    01191             }
    01192
    01193             // Data is not fragmented, can be forwarded
    01194             rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
    01195             upload = true;
    01196             break;
    01197         }
    01198
    01199         // Check if a reassembly procedure is in progress
    01200         defrag = rxu_cntrl_defrag_get(sta_idx, rxu_cntrl_env.rx_status.sn, tid);
    01201
    01202         if (!defrag)
    01203         {
    01204             // If not first fragment, we can reject the packet
    01205             if (rx_status->fn)
    01206                 break;
    01207
    01208             // Allocate a Reassembly structure
    01209             defrag = rxu_cntrl_defrag_alloc();
    01210
    01211             // Fullfil the Reassembly structure
    01212             defrag->sta_idx     = sta_idx;
    01213             defrag->tid         = tid;
    01214             defrag->sn          = rx_status->sn;
    01215             defrag->all_rcv     = false;
    01216             defrag->next_fn     = 1;
    01217             // Reset buffer DMA Address or offset
    01218             defrag->dma_addr    = 0;
    01219             // Get MAC Header Length
    01220             defrag->mac_hdr_len = rx_status->machdr_len;
    01221             defrag->timer.cb = rxu_cntrl_defrag_timeout_cb;
    01222             defrag->timer.env = defrag;
    01223             mm_timer_set(&defrag->timer, hal_machw_time() + RX_CNTRL_DEFRAG_MAX_WAIT);
    01224
    01225             // Perform the MIC check if required
    01226             if (rx_status->frame_info & RXU_CNTRL_MIC_CHECK_NEEDED)
    01227                 rxu_cntrl_mic_check(rxdesc, &defrag->mic, true, false);
    01228
    01229             // Transfer the frame to the upper layers
    01230             rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_ALLOC);
    01231             defrag->dma_addr = rx_status->host_buf_addr;
    01232             defrag->host_id = rxu_cntrl_env.hostid_current;
    01233             defrag->eth_len_present = rx_status->eth_len_present;
    01234             // Reset total received length - this has to be done after the MSDU upload
    01235             // as the frmlen field is modified in the MAC2ETH conversion
    01236             defrag->frame_len = rhd->frmlen;
    01237
    01238             // Push the reassembly structure at the end of the list of used structures
    01239             co_list_push_back(&rxu_cntrl_env.rxu_defrag_used, &defrag->list_hdr);
    01240
    01241             // Data is uploaded
    01242             upload = true;
    01243         }
    01244         else
    01245         {
    01246             uint16_t status;
    01247             uint16_t cpy_len;
    01248
    01249             // Check the fragment is the one we are waiting for
    01250             if (defrag->next_fn != rx_status->fn)
    01251                 // Packet has already been received
    01252                 break;
    01253
    01254             // Get payload length of fragment
    01255             cpy_len = rhd->frmlen - (uint16_t)defrag->mac_hdr_len;
    01256             defrag->frame_len += cpy_len;
    01257
    01258             // Update number of received fragment
    01259             defrag->next_fn++;
    01260
    01261             // Perform the MIC check if required
    01262             status = RX_STAT_FORWARD;
    01263             if (rx_status->frame_info & RXU_CNTRL_MIC_CHECK_NEEDED)
    01264             {
    01265                 if (!rxu_cntrl_mic_check(rxdesc, &defrag->mic, false, (mf == 0)))
    01266                     status = RX_STAT_DELETE;
    01267                 else if (mf == 0)
    01268                     // Adjust the total frame length to remove the MIC from the end
    01269                     defrag->frame_len -= MIC_LEN;
    01270             }
    01271
    01272             // Data can be copied
    01273             rxu_cntrl_defrag_mpdu_transfer(rxdesc, defrag, cpy_len);
    01274
    01275             if (!mf)
    01276             {
    01277                 // Request for a frame length update before forwarding the packet
    01278                 rxu_cntrl_defrag_len_update(defrag);
    01279
    01280                 // Indicate that the packet can now be transmitted
    01281                 rxu_cntrl_desc_prepare(NULL, status, defrag->host_id);
    01282
    01283                 // Clear the reassembly timer
    01284                 mm_timer_clear(&defrag->timer);
    01285
    01286                 // Free the Reassembly structure
    01287                 co_list_extract(&rxu_cntrl_env.rxu_defrag_used, &defrag->list_hdr);
    01288                 co_list_push_back(&rxu_cntrl_env.rxu_defrag_free, &defrag->list_hdr);
    01289             }
    01290
    01291             upload = true;
    01292         }
    01293
    01294         // Store the current time
    01295         defrag->time = hal_machw_time();
    01296     } while (0);
    01297
    01298     PROF_DEFRAG_CHECK_CLR();
    01299
    01300     return (upload);
    01301 }
    01302
    01314 static bool rxu_cntrl_duplicate_nsta_check(uint8_t *frame)
    01315 {
    01316     // Returned status
    01317     bool upload = false;
    01318
    01319     PROF_RX_DUPLI_NSTA_CHECK_SET();
    01320
    01321     do
    01322     {
    01323         // Map a MAC Header structure on the frame
    01324         struct mac_hdr *machdr = (struct mac_hdr *)frame;
    01325
    01326         // Check retry bit, source address and received sequence control value
    01327         if ((machdr->fctl & MAC_FCTRL_RETRY) &&
    01328             (rxu_cntrl_env.rxu_dupli.last_seq_cntl == machdr->seq) &&
    01329             (!memcmp(&machdr->addr2, &rxu_cntrl_env.rxu_dupli.last_src_addr, sizeof(struct mac_addr))))
    01330         {
    01331             // Reject the packet
    01332             break;
    01333         }
    01334
    01335         rxu_cntrl_env.rxu_dupli.last_seq_cntl = machdr->seq;
    01336         rxu_cntrl_env.rxu_dupli.last_src_addr = machdr->addr2;
    01337
    01338         upload = true;
    01339     } while (0);
    01340
    01341     PROF_RX_DUPLI_NSTA_CHECK_CLR();
    01342
    01343     return (upload);
    01344 }
    01345
    01359 static bool rxu_cntrl_duplicate_check(uint16_t frame_cntrl, uint8_t sta_idx, uint8_t qos)
    01360 {
    01361     // Returned status
    01362     bool upload = false;
    01363
    01364     PROF_RX_DUPLI_CHECK_SET();
    01365
    01366     do
    01367     {
    01368         uint16_t *last_seq_cntl;
    01369
    01370         if (qos)
    01371         {
    01372             last_seq_cntl = &(sta_info_tab[sta_idx].rx_qos_last_seqcntl[rxu_cntrl_env.rx_status.tid]);
    01373         }
    01374         else
    01375         {
    01376             last_seq_cntl = &(sta_info_tab[sta_idx].rx_nqos_last_seqcntl);
    01377         }
    01378
    01379         // Check retry bit and received sequence control value
    01380         if ((frame_cntrl & MAC_FCTRL_RETRY) &&
    01381             (*last_seq_cntl == rxu_cntrl_env.rx_status.seq_cntl))
    01382         {
    01383             // Reject the packet
    01384             break;
    01385         }
    01386
    01387         *last_seq_cntl = rxu_cntrl_env.rx_status.seq_cntl;
    01388
    01389         upload = true;
    01390     } while (0);
    01391
    01392     PROF_RX_DUPLI_CHECK_CLR();
    01393
    01394     return (upload);
    01395 }
    01396
    01397 #if (NX_REORD)
    01398
    01405 static void rxu_cntrl_reord_update(struct rxu_cntrl_reord *rx_reord)
    01406 {
    01407     // Move the windows
    01408     rx_reord->elt[rx_reord->rx_status_pos].host_id = 0;
    01409     rx_reord->win_start     = (rx_reord->win_start + 1) & MAC_SEQCTRL_NUM_MAX;
    01410     rx_reord->rx_status_pos = (rx_reord->rx_status_pos + 1) % RX_CNTRL_REORD_WIN_SIZE;
    01411 }
    01412
    01422 static void rxu_cntrl_reord_flush(struct rxu_cntrl_reord *rx_reord, uint16_t sn_skipped)
    01423 {
    01424     // Forward all packets that have already been received
    01425     for (uint16_t i = 0; (i < sn_skipped) && rx_reord->ooo_pkt_cnt; i++)
    01426     {
    01427         uint8_t index = (rx_reord->rx_status_pos + i) % RX_CNTRL_REORD_WIN_SIZE;
    01428         struct rxu_cntrl_reord_elt *elt = &rx_reord->elt[index];
    01429         uint16_t status = RX_STAT_FORWARD;
    01430
    01431         PROF_REORD_FLUSH_SET();
    01432
    01433         if (elt->host_id)
    01434         {
    01435             if (elt->pn_check)
    01436             {
    01437                 ASSERT_ERR(rx_reord->key);
    01438
    01439                 if (!rxu_cntrl_check_pn(&elt->pn, rx_reord->key, rx_reord->tid))
    01440                     status = RX_STAT_DELETE;
    01441             }
    01442
    01443             // Data has already been copied in host memory and can now be forwarded
    01444             rxu_cntrl_desc_prepare(NULL, status, elt->host_id);
    01445
    01446             elt->host_id = 0;
    01447
    01448             rx_reord->ooo_pkt_cnt--;
    01449         }
    01450
    01451         PROF_REORD_FLUSH_CLR();
    01452     }
    01453
    01454     rx_reord->win_start     = (rx_reord->win_start + sn_skipped) & MAC_SEQCTRL_NUM_MAX;
    01455     rx_reord->rx_status_pos = (rx_reord->rx_status_pos + sn_skipped) % RX_CNTRL_REORD_WIN_SIZE;
    01456 }
    01457
    01466 static void rxu_cntrl_reord_fwd(struct rxu_cntrl_reord *rx_reord)
    01467 {
    01468     while (rx_reord->elt[rx_reord->rx_status_pos].host_id)
    01469     {
    01470         struct rxu_cntrl_reord_elt *elt = &rx_reord->elt[rx_reord->rx_status_pos];
    01471         uint16_t status = RX_STAT_FORWARD;
    01472
    01473         PROF_REORD_FWD_SET();
    01474
    01475         ASSERT_ERR(rx_reord->ooo_pkt_cnt);
    01476
    01477         // Perform PN replay check if required
    01478         if (elt->pn_check)
    01479         {
    01480             ASSERT_ERR(rx_reord->key);
    01481
    01482             if (!rxu_cntrl_check_pn(&elt->pn, rx_reord->key, rx_reord->tid))
    01483                 status = RX_STAT_DELETE;
    01484         }
    01485
    01486         // Data has already been copied in host memory and can now be forwarded
    01487         if (rxu_cntrl_desc_prepare(NULL, status, elt->host_id) == NULL)
    01488         {
    01489             PROF_REORD_FWD_CLR();
    01490             break;
    01491         }
    01492
    01493         // Update the SN status
    01494         rxu_cntrl_reord_update(rx_reord);
    01495
    01496         rx_reord->ooo_pkt_cnt--;
    01497
    01498         PROF_REORD_FWD_CLR();
    01499     }
    01500 }
    01501
    01511 static void rxu_cntrl_reord_bar_check(uint8_t sta_idx, uint8_t *frame)
    01512 {
    01513     // Map the BAR structure on the received frame
    01514     struct bar_frame *bar = (struct bar_frame *)frame;
    01515     // TID for which BA is required
    01516     uint8_t tid = (bar->bar_cntrl & BAR_CNTL_TID_MSK) >> BAR_CNTL_TID_OFT;
    01517     // Get the associated BA Agreement
    01518     struct rxu_cntrl_reord *reord = sta_info_tab[sta_idx].ba_agmts_rx[tid];
    01519     // Extract the Start Sequence Number
    01520     uint16_t ssn = bar->bar_information >> MAC_SEQCTRL_NUM_OFT;
    01521
    01522     PROF_REORD_BAR_CHECK_SET();
    01523
    01524     do
    01525     {
    01526         if (!reord)
    01527         {
    01528             break;
    01529         }
    01530
    01531         // See IEEE 802.11-2012 Section 9.21.7.3 c)
    01532         if ((ssn == reord->win_start) ||
    01533             (((ssn - reord->win_start) & MAC_SEQCTRL_NUM_MAX) > (MAC_SEQCTRL_NUM_MAX >> 1)))
    01534         {
    01535             // Make no change to the record
    01536             break;
    01537         }
    01538
    01539         /*
    01540          * Flush all needed packet so that:
    01541          *      - WinStart = SSN
    01542          *      - WinEnd   = WinStart + WinSize - 1
    01543          */
    01544         rxu_cntrl_reord_flush(reord, (ssn - reord->win_start) & MAC_SEQCTRL_NUM_MAX);
    01545
    01546         // Transfer the descriptors pushed in the ready list
    01547         macif_rx_desc_upload(&rxu_cntrl_env.rxdesc_ready);
    01548     } while (0);
    01549
    01550     PROF_REORD_BAR_CHECK_CLR();
    01551 }
    01552
    01569 static bool rxu_cntrl_reord_check(struct rxdesc *rxdesc, uint8_t sta_idx)
    01570 {
    01571     // Returned status
    01572     bool upload = true;
    01573     // SN position in the sn status bit field
    01574     uint16_t sn_pos;
    01575     struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
    01576
    01577     PROF_REORD_CHECK_SET();
    01578
    01579     do
    01580     {
    01581         struct rxu_cntrl_reord *reord
    01582                     = sta_info_tab[sta_idx].ba_agmts_rx[rx_status->tid];
    01583
    01584         // Check if the received packet had the lowest expected SN
    01585         if (rx_status->sn == reord->win_start)
    01586         {
    01587             // Perform the PN check if required
    01588             if (rx_status->frame_info & RXU_CNTRL_PN_CHECK_NEEDED)
    01589                 upload = rxu_cntrl_check_pn(&rx_status->pn, rx_status->key, rx_status->tid);
    01590
    01591             // Check if we need to upload the frame
    01592             if (upload)
    01593             {
    01594                 rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
    01595             }
    01596
    01597             // Received packet is within the reordering window, the RX agreement can be
    01598             // considered as active
    01599             reord->active = true;
    01600
    01601             // Store current time
    01602             reord->sn_rx_time = hal_machw_time();
    01603
    01604             // Update the RX Window
    01605             rxu_cntrl_reord_update(reord);
    01606
    01607             // And forward any ready frames
    01608             rxu_cntrl_reord_fwd(reord);
    01609         }
    01610         else
    01611         {
    01612             sn_pos = (rx_status->sn - reord->win_start) & MAC_SEQCTRL_NUM_MAX;
    01613
    01614             if (sn_pos >= RX_CNTRL_REORD_WIN_SIZE)
    01615             {
    01616                 if (sn_pos < (MAC_SEQCTRL_NUM_MAX >> 1))
    01617                 {
    01618                     // Move the window
    01619                     rxu_cntrl_reord_flush(reord, sn_pos - RX_CNTRL_REORD_WIN_SIZE + 1);
    01620
    01621                     // Recompute the SN position
    01622                     sn_pos = (rx_status->sn - reord->win_start) & MAC_SEQCTRL_NUM_MAX;
    01623                 }
    01624                 // Received packet is older than expected. Two cases apply:
    01625                 //   - Either the agreement is still not active, and in that case we shall
    01626                 //     just consider the packet as being sent outside the BA agreement,
    01627                 //     i.e not consider it as a old one
    01628                 //   - Or the agreement is active, and in that case the packet has to be
    01629                 //     discarded
    01630                 else if (!reord->active)
    01631                 {
    01632                     // Perform the duplicate check
    01633                     upload = rxu_cntrl_duplicate_check(rx_status->frame_cntl, sta_idx, 1);
    01634
    01635                     // Perform the PN check if required
    01636                     if (upload && (rx_status->frame_info & RXU_CNTRL_PN_CHECK_NEEDED))
    01637                         upload = rxu_cntrl_check_pn(&rx_status->pn, rx_status->key, rx_status->tid);
    01638
    01639                     // Check if we need to upload the frame
    01640                     if (upload)
    01641                         rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
    01642
    01643                     // Indicate the activity on this RX BlockAck agreement
    01644                     bam_rx_active(sta_idx, rx_status->tid);
    01645                     break;
    01646                 }
    01647                 else
    01648                 {
    01649                     // Discard the MPDU
    01650                     upload = false;
    01651                     break;
    01652                 }
    01653             }
    01654
    01655             // Received packet is within the reordering window (or outside but newer than
    01656             // expected), the RX agreement can be considered as active
    01657             reord->active = true;
    01658
    01659             sn_pos = (sn_pos + reord->rx_status_pos) % RX_CNTRL_REORD_WIN_SIZE;
    01660
    01661             // Check if the packet has already been received
    01662             if (reord->elt[sn_pos].host_id)
    01663             {
    01664                 // Discard the MPDU
    01665                 upload = false;
    01666                 break;
    01667             }
    01668
    01669             // Store the PN and keys if required
    01670             if (rx_status->frame_info & RXU_CNTRL_PN_CHECK_NEEDED)
    01671             {
    01672                 reord->key = rx_status->key;
    01673                 reord->elt[sn_pos].pn = rx_status->pn;
    01674                 reord->elt[sn_pos].pn_check = true;
    01675             }
    01676             else
    01677             {
    01678                 reord->elt[sn_pos].pn_check = false;
    01679             }
    01680
    01681             // Data has been received out of order
    01682             rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_ALLOC);
    01683
    01684             // Store the Host ID in the reordering element
    01685             reord->elt[sn_pos].host_id = rxu_cntrl_env.hostid_current;
    01686
    01687             reord->ooo_pkt_cnt++;
    01688         }
    01689
    01690         // Indicate the activity on this RX BlockAck agreement
    01691         bam_rx_active(sta_idx, rx_status->tid);
    01692     } while (0);
    01693
    01694     PROF_REORD_CHECK_CLR();
    01695
    01696     return (upload);
    01697 }
    01698
    01708 static void rxu_cntrl_reord_timeout_cb(void *env)
    01709 {
    01710     struct rxu_cntrl_reord *reord = env;
    01711
    01712     // Restart reordering timer
    01713     mm_timer_set(&reord->timer, ke_time() + RX_CNTRL_REORD_MAX_WAIT);
    01714
    01715     do
    01716     {
    01717         // Check if there is at least a packet waiting
    01718         if (!reord->ooo_pkt_cnt)
    01719             break;
    01720
    01721         // Check if we spent too much time waiting for an SN
    01722         if (!hal_machw_time_past(reord->sn_rx_time + RX_CNTRL_REORD_MAX_WAIT))
    01723             break;
    01724
    01725         if (!reord->elt[reord->rx_status_pos].host_id)
    01726         {
    01727             // Consider the next waited packet as received
    01728             rxu_cntrl_reord_update(reord);
    01729         }
    01730         // Send the data
    01731         rxu_cntrl_reord_fwd(reord);
    01732
    01733         // If list of descriptor ready for upload was empty and now contains some elements, start transfer
    01734         if (co_list_pick(&rxu_cntrl_env.rxdesc_ready))
    01735         {
    01736             macif_rx_desc_upload(&rxu_cntrl_env.rxdesc_ready);
    01737         }
    01738     } while (0);
    01739 }
    01740 #endif //(RX_REORD)
    01741
    01757 static bool rxu_cntrl_spurious_check(uint8_t *frame, struct rxdesc *rxdesc)
    01758 {
    01759     struct mac_hdr *machdr = (struct mac_hdr *)frame;
    01760     int i;
    01761
    01762     for (i = 0 ; i < NX_VIRT_DEV_MAX ; i++) {
    01763         struct vif_info_tag *vif = &vif_info_tab[i];
    01764
    01765         if ((vif->active) && (vif->type == VIF_AP) &&
    01766             MAC_ADDR_CMP_PACKED(&machdr->addr1, &vif->mac_addr)) {
    01767
    01768             rxu_cntrl_env.rx_status.vif_idx = vif->index;
    01769             // upload complete frame as it
    01770             rxu_mpdu_upload_and_indicate(rxdesc, RX_STAT_SPURIOUS);
    01771             return true;
    01772         }
    01773     }
    01774
    01775     return false;
    01776 }
    01777
    01788 static void rxu_cntrl_pm_mon_check(uint8_t *frame, uint32_t statinfo)
    01789 {
    01790     // Map a MAC Header structure on the frame
    01791     struct mac_hdr *hdr = (struct mac_hdr *)frame;
    01792
    01793     do
    01794     {
    01795         // Check if the PM monitoring is enabled
    01796         if (!rxu_cntrl_env.pm_mon.mon)
    01797             break;
    01798
    01799         // Check if the packet is for the local device
    01800         if (statinfo & RX_HD_ADDRMIS)
    01801             break;
    01802
    01803         // Compare the MAC address with the expected one
    01804         if (!MAC_ADDR_CMP(&rxu_cntrl_env.pm_mon.addr, &hdr->addr2))
    01805             break;
    01806
    01807         // Check if the peer device is going to sleep or not
    01808         if ((hdr->fctl & (MAC_FCTRL_PWRMGT | MAC_FCTRL_MOREFRAG)) == MAC_FCTRL_PWRMGT)
    01809             // Device is going to sleep
    01810             rxu_cntrl_env.pm_mon.pm_state = PS_MODE_ON;
    01811         else
    01812             // Device is going to be active
    01813             rxu_cntrl_env.pm_mon.pm_state = PS_MODE_OFF;
    01814     } while(0);
    01815 }
    01816
    01834 static bool rxu_mgt_route_action(uint32_t *payload, uint16_t length, uint8_t sta_idx, uint8_t *vif_idx,
    01835                                  ke_task_id_t *task_id, uint16_t machdr_length, bool *need_machdr)
    01836 {
    01837     // Extract the category and action type from the frame
    01838     uint32_t addr           = CPU2HW(payload) + machdr_length;
    01839     uint8_t action_category = co_read8p(addr + MAC_ACTION_CATEGORY_OFT);
    01840     uint16_t task_idx       = 0xFF;
    01841     bool upload = false;
    01842
    01843     // Handle action frames for known stations only
    01844     if (sta_idx == INVALID_STA_IDX)
    01845     {
    01846         #if (RW_MESH_EN)
    01847         // If Action Category is Self-Protected, authorize frames from unknown STA
    01848         if (action_category != MAC_SELF_PROT_ACTION_CATEGORY)
    01849         #endif //(RW_MESH_EN)
    01850         {
    01851             return true;
    01852         }
    01853     }
    01854
    01855     switch (action_category)
    01856     {
    01857         case MAC_BA_ACTION_CATEGORY:
    01858         {
    01859             *task_id = TASK_BAM;
    01860             task_idx = 0;
    01861         } break;
    01862
    01863         #if NX_VHT || NX_HE
    01864         case MAC_VHT_ACTION_CATEGORY:
    01865         {
    01866             uint8_t vht_action = co_read8p(addr + MAC_ACTION_ACTION_OFT);
    01867             switch (vht_action)
    01868             {
    01869                 case MAC_OP_MODE_NOTIF_VHT_ACTION:
    01870                 {
    01871                     uint8_t opmode = co_read8p(addr + MAC_OP_MODE_NOTIF_OPMODE_OFT);
    01872                     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    01873
    01874                     // This frame is valid if peer device is VHT or HE capable
    01875                     if ((STA_CAPA(sta, VHT) || STA_CAPA(sta, HE)) &&
    01876                         !(opmode & MAC_OPMODE_RXNSS_TYPE_BIT))
    01877                     {
    01878                         uint8_t bw = (opmode & MAC_OPMODE_BW_MSK) >> MAC_OPMODE_BW_OFT;
    01879                         uint8_t nss = (opmode & MAC_OPMODE_RXNSS_MSK) >> MAC_OPMODE_RXNSS_OFT;
    01880
    01881                         // Update maximum supported bandwidth
    01882                         me_sta_bw_nss_max_upd(sta_idx, bw, nss);
    01883                     }
    01884                 } break;
    01885
    01886                 #if RW_MUMIMO_RX_EN
    01887                 case MAC_GROUP_ID_MGMT_VHT_ACTION:
    01888                 {
    01889                     // Set the Membership Status and User Position arrays to the PHY
    01890                     phy_set_group_id_info(addr + MAC_GROUP_ID_MGT_MEMBERSHIP_OFT,
    01891                                           addr + MAC_GROUP_ID_MGT_USER_POS_OFT);
    01892                 } break;
    01893                 #endif
    01894
    01895                 default:
    01896                 {
    01897                     // Other VHT action categories are not supported
    01898                     upload = true;
    01899                 } break;
    01900             }
    01901         } break;
    01902         #endif
    01903
    01904         case MAC_HT_ACTION_CATEGORY:
    01905         {
    01906             uint8_t ht_action = co_read8p(addr + MAC_ACTION_ACTION_OFT);
    01907             switch (ht_action)
    01908             {
    01909                 case MAC_CHAN_WIDTH_HT_ACTION:
    01910                 {
    01911                     uint8_t chwidth = co_read8p(addr + MAC_CHAN_WIDTH_WIDTH_OFT);
    01912                     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    01913
    01914                     // This frame is valid if peer device is HT capable
    01915                     if (STA_CAPA(sta, HT) && (chwidth <= BW_40MHZ))
    01916                         // Update maximum supported bandwidth
    01917                         me_sta_bw_nss_max_upd(sta_idx, chwidth, 0xFF);
    01918                 } break;
    01919
    01920                 case MAC_SMPS_HT_ACTION:
    01921                 {
    01922                     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    01923
    01924                     // This frame is valid if peer device is HT capable
    01925                     if (STA_CAPA(sta, HT))
    01926                     {
    01927                         uint8_t sm_pwr_ctrl = co_read8p(addr + MAC_SM_PRW_CTRL_OFT);
    01928                         if (sm_pwr_ctrl & MAC_SMPS_ENABLE_BIT)
    01929                             // Limit NSS for this station to 1
    01930                             me_sta_bw_nss_max_upd(sta_idx, 0xFF, 0);
    01931                         else
    01932                             // No limit for the NSS to be used
    01933                             me_sta_bw_nss_max_upd(sta_idx, 0xFF, 0xFF);
    01934                     }
    01935                 } break;
    01936
    01937                 default:
    01938                 {
    01939                     // Other HT action categories are not supported
    01940                     upload = true;
    01941                 } break;
    01942             }
    01943         } break;
    01944
    01945         #ifdef NX_MFP
    01946         case MAC_SA_QUERY_ACTION_CATEGORY:
    01947         {
    01948             uint8_t sa_query_action;
    01949             struct vif_info_tag *vif;
    01950
    01951             if ((length - machdr_length) < MAC_SA_QUERY_MIN_LEN)
    01952             {
    01953                 break;
    01954             }
    01955             else if (*vif_idx == INVALID_VIF_IDX)
    01956             {
    01957                 upload = true;
    01958                 break;
    01959             }
    01960
    01961             vif = &vif_info_tab[*vif_idx];
    01962             sa_query_action = co_read8p(addr + MAC_SA_QUERY_ACTION_OFT);
    01963
    01964             if ((vif->type == VIF_STA) &&
    01965                 (sa_query_action == MAC_SA_QUERY_REQUEST))
    01966             {
    01967                 *task_id = TASK_SM;
    01968                 task_idx = 0;
    01969             }
    01970             else
    01971             {
    01972                 upload = true;
    01973                 break;
    01974             }
    01975         } break;
    01976     #endif
    01977
    01978         #if (RW_MESH_EN)
    01979         case (MAC_SELF_PROT_ACTION_CATEGORY):
    01980         {
    01981             // Get Mesh VIF on which action frame has been received
    01982             struct mesh_vif_info_tag *mvif;
    01983
    01984             if (*vif_idx == INVALID_VIF_IDX)
    01985             {
    01986                // Get addressed Mesh VIF based on received Mesh ID
    01987                mvif = mesh_check_mesh_id(CPU2HW(payload) + MAC_SELF_PROT_ACTION_CAPA_LEN,
    01988                                          length - MAC_SELF_PROT_ACTION_CAPA_LEN);
    01989
    01990                if (!mvif)
    01991                {
    01992                    break;
    01993                }
    01994
    01995                // Update the VIF information
    01996                *vif_idx = mvif->vif_idx;
    01997             }
    01998             else
    01999             {
    02000                 struct vif_info_tag *vif = &vif_info_tab[*vif_idx];
    02001
    02002                 mvif = &mesh_vif_info_tab[vif->mvif_idx];
    02003             }
    02004
    02005             if (mvif->user_mpm)
    02006             {
    02007                 // These frames are used for MPM, upload them
    02008                 upload = true;
    02009                 break;
    02010             }
    02011         } // no break
    02012
    02013         case (MAC_MESH_ACTION_CATEGORY):
    02014         {
    02015             *task_id = TASK_MESH;
    02016             task_idx = 0;
    02017             *need_machdr = true;
    02018         } break;
    02019         #endif //(RW_MESH_EN)
    02020
    02021         default:
    02022         {
    02023             // Other action categories are not supported
    02024             upload = true;
    02025         } break;
    02026     }
    02027
    02028     // format the TaskId taking in to account the instance index
    02029     if (*task_id != TASK_NONE)
    02030     {
    02031         // Sanity check
    02032         ASSERT_ERR(task_idx != 0xFF);
    02033         *task_id = KE_BUILD_ID(*task_id, task_idx);
    02034     }
    02035
    02036     return upload;
    02037 }
    02038
    02056 static bool rxu_mgt_route(uint16_t framectrl,
    02057                           uint16_t length,
    02058                           uint16_t machdr_length,
    02059                           uint8_t sta_idx,
    02060                           uint8_t *vif_idx,
    02061                           uint32_t *payload,
    02062                           ke_task_id_t *task_id,
    02063                           bool *need_machdr)
    02064 {
    02065     struct vif_info_tag *vif = NULL;
    02066     uint8_t mode = VIF_UNKNOWN;
    02067     bool upload = true;
    02068
    02069     // Get the VIF entry
    02070     if (*vif_idx != INVALID_VIF_IDX)
    02071     {
    02072         vif = &vif_info_tab[*vif_idx];
    02073         mode = vif->type;
    02074     }
    02075
    02076     // Route the message depending on its type and subtype
    02077     switch (framectrl & MAC_FCTRL_TYPESUBTYPE_MASK)
    02078     {
    02079         // Message arrive to STA in ESS only
    02080         case MAC_FCTRL_ASSOCRSP:
    02081         case MAC_FCTRL_REASSOCRSP:
    02082             if (mode == VIF_STA)
    02083             {
    02084                 *task_id = TASK_SM;
    02085             }
    02086             break;
    02087
    02088         case MAC_FCTRL_PROBERSP:
    02089             // Check if the ProbeRsp was for us
    02090             if (vif)
    02091             {
    02092                 *need_machdr = true;
    02093                 *task_id = TASK_SCANU;
    02094             }
    02095             break;
    02096
    02097         case MAC_FCTRL_BEACON:
    02098         {
    02099             // Only forward beacons to SCANU task if we are in scanning state
    02100             if (ke_state_get(TASK_SCANU) == SCANU_SCANNING)
    02101             {
    02102                 *need_machdr = true;
    02103                 *task_id = TASK_SCANU;
    02104                 *vif_idx = scanu_env.param->vif_idx;
    02105             }
    02106
    02107             #if (RW_MESH_EN)
    02108             do
    02109             {
    02110                 struct mesh_vif_info_tag *mvif;
    02111
    02112                 if (*task_id != TASK_NONE)
    02113                 {
    02114                     break;
    02115                 }
    02116
    02117                 if (*vif_idx == INVALID_VIF_IDX)
    02118                 {
    02119                    // Get addressed Mesh VIF based on received Mesh ID
    02120                    mvif = mesh_check_mesh_id(CPU2HW(payload) + MAC_BEACON_VARIABLE_PART_OFT,
    02121                                              length - MAC_BEACON_VARIABLE_PART_OFT);
    02122
    02123                    if (!mvif)
    02124                    {
    02125                        break;
    02126                    }
    02127
    02128                    // Update the VIF information
    02129                    *vif_idx = mvif->vif_idx;
    02130                    vif = &vif_info_tab[*vif_idx];
    02131                 }
    02132                 else
    02133                 {
    02134                     mvif = &mesh_vif_info_tab[vif->mvif_idx];
    02135                 }
    02136
    02137                 if (!mvif->user_mpm)
    02138                 {
    02139                     // Forward the frame to the mesh task
    02140                     *need_machdr = true;
    02141                     *task_id = TASK_MESH;
    02142                 }
    02143                 else
    02144                 {
    02145                     if (sta_idx == INVALID_STA_IDX)
    02146                     {
    02147                         // Map a MAC Header on the frame
    02148                         struct mac_hdr *mac_hdr = (struct mac_hdr *)payload;
    02149
    02150                         if (mesh_accept_new_peer(&mac_hdr->addr2, *vif_idx,
    02151                                                  CPU2HW(payload) + MAC_BEACON_VARIABLE_PART_OFT,
    02152                                                  length - MAC_BEACON_VARIABLE_PART_OFT))
    02153                         {
    02154                             rxu_cntrl_env.rx_status.frame_info |= RXU_CNTRL_NEW_MESH_PEER;
    02155                         }
    02156                         else
    02157                         {
    02158                             upload = false;
    02159                         }
    02160                     }
    02161                 }
    02162             } while (0);
    02163             #endif //(RW_MESH_EN)
    02164
    02165             // Handle a received beacon if sent by a peer AP
    02166             if (sta_idx != INVALID_STA_IDX)
    02167             {
    02168                 if (vif->active)
    02169                 {
    02170                     me_beacon_check(*vif_idx, length, CPU2HW(payload));
    02171                 }
    02172             }
    02173             // else keep TASK_NONE as destination task
    02174         } break;
    02175
    02176         case MAC_FCTRL_AUTHENT:
    02177             if (sm_external_auth_in_progress())
    02178             {
    02179                 break;
    02180             }
    02181         case MAC_FCTRL_DEAUTHENT:
    02182         case MAC_FCTRL_DISASSOC:
    02183             // routed to SM task (case STA in ESS network)
    02184             if (mode == VIF_STA)
    02185             {
    02186                 *task_id = TASK_SM;
    02187             }
    02188             break;
    02189
    02190         case MAC_FCTRL_ACTION:
    02191             // Route the action frame based on its category and action type
    02192             // in addition to the sta_mode (AP, STA)
    02193             upload = rxu_mgt_route_action(payload, length, sta_idx, vif_idx, task_id, machdr_length, need_machdr);
    02194             break;
    02195         default:
    02196             break;
    02197     }
    02198
    02199     return upload;
    02200 }
    02201
    02218 static bool rxu_mgt_frame_ind(uint16_t framectrl,
    02219                               uint16_t length,
    02220                               uint8_t sta_idx,
    02221                               uint8_t *vif_idx,
    02222                               int8_t rssi,
    02223                               struct rx_pbd *pbd,
    02224                               uint16_t machdr_length)
    02225 {
    02226     ke_task_id_t dest_id = TASK_NONE;
    02227     uint32_t *payload = HW2CPU(pbd->datastartptr);
    02228     bool copy_mac_hdr = false;
    02229     bool upload;
    02230
    02231     // Route the message to the correct task and/or handle it immediately
    02232     upload = rxu_mgt_route(framectrl, length, machdr_length, sta_idx, vif_idx, payload,
    02233                            &dest_id, &copy_mac_hdr);
    02234
    02235     // Check if the message has to be forwarded or not
    02236     if (dest_id != TASK_NONE)
    02237     {
    02238         // Allocate the message
    02239         struct rxu_mgt_ind *rx = KE_MSG_ALLOC_VAR(RXU_MGT_IND, dest_id, TASK_RXU, rxu_mgt_ind, length);
    02240         struct phy_channel_info info;
    02241         uint16_t src_offset = 0;
    02242
    02243         // Get the information on the current channel from the PHY driver
    02244         phy_get_channel(&info, PHY_PRIM);
    02245
    02246         // Fill in the parameter structure fields that can be filled now
    02247         if (!copy_mac_hdr)
    02248         {
    02249             ASSERT_WARN((machdr_length & 0x3) == 0);
    02250             length -= machdr_length;
    02251             src_offset = machdr_length;
    02252         }
    02253         rx->length = length;
    02254         rxl_mpdu_copy(pbd, length, src_offset, rx->payload);
    02255
    02256         rx->inst_nbr = *vif_idx;
    02257         rx->sta_idx = sta_idx;
    02258         rx->framectrl = framectrl;
    02259         rx->rssi = rssi;
    02260         rx->center_freq = (info.info1 >> 16) & 0xFFFF;
    02261         rx->band = info.info1 & 0xFF;
    02262
    02263         // Send the message to the destination task
    02264         ke_msg_send(rx);
    02265
    02266         // The message has been handled internally, no need to upload it
    02267         upload = false;
    02268     }
    02269
    02270     return (upload);
    02271 }
    02272
    02283 static uint8_t rxu_mgt_search_rx_vif(struct mac_hdr *hdr, uint32_t statinfo)
    02284 {
    02285     uint8_t vif_idx = INVALID_VIF_IDX;
    02286
    02287     if (!(statinfo & (RX_HD_ADDRMIS | RX_HD_GA_FRAME)))
    02288     {
    02289         struct vif_info_tag *vif = vif_mgmt_first_used();
    02290
    02291         // Go through the VIF entries to find if one is matching the ADDR1 we got
    02292         while (vif != NULL)
    02293         {
    02294             if (MAC_ADDR_CMP(&vif->mac_addr, &hdr->addr1))
    02295             {
    02296                 vif_idx = vif->index;
    02297                 break;
    02298             }
    02299             vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
    02300         }
    02301     }
    02302     else if (statinfo & RX_HD_GA_FRAME)
    02303     {
    02304         // If ProbeReq look at the address 3 to check if it is ours
    02305     }
    02306
    02307     return (vif_idx);
    02308 }
    02309
    02322 static bool rxu_mgt_frame_check(struct rxdesc* rxdesc, uint8_t sta_idx)
    02323 {
    02324     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    02325     struct rx_hd *rhd = &dma_hdrdesc->hd;
    02326     struct rx_payloaddesc *payl_d = HW2CPU(rhd->first_pbd_ptr);
    02327     struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
    02328     uint32_t *frame = HW2CPU(payl_d->pbd.datastartptr);
    02329     struct mac_hdr *hdr = (struct mac_hdr *)frame;
    02330     int8_t rssi;
    02331     int8_t rx_rssi[2];
    02332     bool upload = true;
    02333
    02334     do
    02335     {
    02336         // Currently no support of fragmented management frames in UMAC
    02337         if ((hdr->fctl & MAC_FCTRL_MOREFRAG) ||
    02338             (hdr->seq & MAC_SEQCTRL_FRAG_MSK))
    02339         {
    02340             upload = false;
    02341             break;
    02342         }
    02343
    02344         // Retrieve the RSSI values from the RX vector
    02345         rssi = hal_desc_get_rssi(&rhd->rx_vec_1, rx_rssi);
    02346
    02347         // Check if the sending STA is known. If not we search the VIF
    02348         // index receiving the frame, if there is one
    02349         if (sta_idx == INVALID_STA_IDX)
    02350         {
    02351             rx_status->vif_idx = rxu_mgt_search_rx_vif(hdr, rhd->statinfo);
    02352         }
    02353         #if NX_MON_DATA
    02354         // Check if the frame is unicast and not for us (only in case of monitor+data interface)
    02355         else if ((vif_mgmt_env.monitor_vif != INVALID_VIF_IDX) &&
    02356                 (!MAC_ADDR_GROUP(&hdr->addr1)) &&
    02357                 (MAC_ADDR_CMP(&vif_info_tab[rx_status->vif_idx].mac_addr, &hdr->addr1)))
    02358         {
    02359             rx_status->vif_idx = INVALID_VIF_IDX;
    02360         }
    02361         #endif
    02362
    02363         #if NX_MFP
    02364         if (!mfp_ignore_mgmt_frame(rx_status, frame, rhd->frmlen, &upload))
    02365         #endif
    02366             upload = rxu_mgt_frame_ind(hdr->fctl, rhd->frmlen, sta_idx, &rx_status->vif_idx,
    02367                                        rssi, &payl_d->pbd, rx_status->machdr_len);
    02368
    02369         if (!upload)
    02370             break;
    02371
    02372         // Upload the received MPDU without any modification
    02373         rxu_mpdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
    02374     } while (0);
    02375
    02376     return (upload);
    02377 }
    02378
    02384 static void rxu_cntrl_desc_init(void)
    02385 {
    02386     uint32_t i;
    02387     // Initialize the DMA descriptor
    02388     for (i = 0; i < RX_STAT_DESC_CNT; i++)
    02389     {
    02390         #if !NX_FULLY_HOSTED
    02391         rxu_stat_desc_pool[i].upload_cntrl.cb = rxu_upload_cfm;
    02392         rxu_stat_desc_pool[i].upload_cntrl.env = &rxu_stat_desc_pool[i].val;
    02393         rxu_stat_desc_pool[i].upload_cntrl.flags = 0;
    02394         // No data buffer directly attached to the RHD
    02395         rxu_stat_desc_pool[i].dma_desc.src    = CPU2HW(&rxu_stat_desc_pool[i].val.host_id);
    02396         rxu_stat_desc_pool[i].dma_desc.length = 9;
    02397         rxu_stat_desc_pool[i].dma_desc.ctrl   = RX_LLICTRL(1);
    02398         #endif
    02399
    02400         rxu_stat_desc_pool[i].val.status = 0;
    02401     }
    02402 }
    02403
    02417 static bool rxu_upload_monitor(struct rxdesc *rxdesc, bool upload)
    02418 {
    02419     if ((vif_mgmt_env.monitor_vif == INVALID_VIF_IDX) || upload)
    02420     {
    02421         return upload;
    02422     }
    02423
    02424     rxu_cntrl_env.rx_status.vif_idx = vif_mgmt_env.monitor_vif;
    02425     rxu_mpdu_upload_and_indicate(rxdesc, RX_STAT_MONITOR);
    02426     return true;
    02427 }
    02428
    02429 /*
    02430  * PUBLIC FUNCTION DEFINITIONS
    02431  ****************************************************************************************
    02432  */
    02433
    02434 void rxu_cntrl_init(void)
    02435 {
    02436     co_list_init(&rxu_cntrl_env.rxdesc_ready);
    02437
    02438     #if (NX_REORD)
    02439     co_list_init(&rxu_cntrl_env.rxu_reord_free);
    02440
    02441     for (uint16_t i = 0; i < RX_CNTRL_REORD_POOL_SIZE; i++)
    02442     {
    02443         co_list_push_back(&rxu_cntrl_env.rxu_reord_free, &rxu_cntrl_reord_pool[i].list_hdr);
    02444     }
    02445     #endif //(NX_REORD)
    02446
    02447     co_list_init(&rxu_cntrl_env.rxu_defrag_free);
    02448     co_list_init(&rxu_cntrl_env.rxu_defrag_used);
    02449
    02450     for (uint16_t i = 0; i < RX_CNTRL_DEFRAG_POOL_SIZE; i++)
    02451     {
    02452         co_list_push_back(&rxu_cntrl_env.rxu_defrag_free, &rxu_cntrl_defrag_pool[i].list_hdr);
    02453     }
    02454
    02455     rxu_cntrl_env.rxu_dupli.last_seq_cntl = 0xFFFF;
    02456
    02457     rxu_cntrl_desc_init();
    02458 }
    02459
    02460 bool rxu_cntrl_frame_handle(struct rxdesc* rxdesc)
    02461 {
    02462     struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
    02463     struct rx_hd *rhd = &dma_hdrdesc->hd;
    02464     struct rx_pbd *pd = HW2CPU(rhd->first_pbd_ptr);
    02465     uint8_t *frame = HW2CPU(pd->datastartptr);
    02466     bool upload = false;
    02467     struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
    02468     uint16_t frame_cntl;
    02469     uint8_t sta_idx;
    02470     uint32_t statinfo = rhd->statinfo;
    02471     uint16_t key_idx_hw;
    02472     bool qos;
    02473
    02474     do
    02475     {
    02476         if (!(statinfo & RX_HD_SUCCESS))
    02477             break;
    02478
    02479         frame_cntl = co_read16(frame);
    02480         dma_hdrdesc->flags = 0;
    02481
    02482         rx_status->sta_idx = INVALID_STA_IDX;
    02483         rx_status->vif_idx = INVALID_VIF_IDX;
    02484
    02485         // Read needed information in the MAC Header
    02486         rxu_cntrl_machdr_read(frame);
    02487
    02488         if (!(statinfo & RX_HD_KEYIDV))
    02489         {
    02490             // Perform the check on the PM bit if required
    02491             rxu_cntrl_pm_mon_check(frame, statinfo);
    02492
    02493             // When the sender is unknown, only management frames are handled here
    02494             if ((frame_cntl & MAC_FCTRL_TYPE_MASK) != MAC_FCTRL_MGT_T)
    02495             {
    02496                 upload = rxu_cntrl_spurious_check(frame, rxdesc);
    02497                 break;
    02498             }
    02499
    02500             if (!rxu_cntrl_duplicate_nsta_check(frame))
    02501                 break;
    02502
    02503             // Authentication can be encrypted (when using SHARED-KEY)
    02504             if (RXL_CNTRL_IS_PROTECTED(rx_status->frame_cntl) &&
    02505                 (((statinfo & RX_HD_DECRSTATUS) != RX_HD_DECR_WEP_SUCCESS) ||
    02506                  !rxu_cntrl_protected_handle(frame, statinfo))) {
    02507                 upload = rxu_cntrl_spurious_check(frame, rxdesc);
    02508                 break;
    02509             }
    02510
    02511             upload = rxu_mgt_frame_check(rxdesc, INVALID_STA_IDX);
    02512             break;
    02513         }
    02514
    02515         // Get the HW key index
    02516         key_idx_hw = (uint16_t)RX_HD_KEYID_GET(statinfo);
    02517
    02518         // Retrieve the station index and instance number
    02519         sta_idx = (uint8_t)(key_idx_hw - MM_SEC_DEFAULT_KEY_COUNT);
    02520
    02521         // Check if the STA is registered
    02522         if (!sta_mgmt_is_valid(sta_idx))
    02523             break;
    02524
    02525         rx_status->sta_idx = sta_idx;
    02526         rx_status->vif_idx = sta_info_tab[sta_idx].inst_nbr;
    02527
    02528         // Save the status information field
    02529         rx_status->statinfo = statinfo;
    02530
    02531         #if NX_BEACONING
    02532         // In AP mode, check if the destination address is part of our known addresses
    02533         if ((vif_info_tab[rx_status->vif_idx].type == VIF_AP) &&
    02534             (!MAC_ADDR_GROUP(&rx_status->da)))
    02535         {
    02536             rx_status->dst_idx = hal_machw_search_addr(&rx_status->da);
    02537         }
    02538         #endif
    02539
    02540         // Check 4 addresses
    02541         if ((frame_cntl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_TODS_FROMDS)
    02542         {
    02543             dma_hdrdesc->flags |= RX_FLAGS_4_ADDR_BIT;
    02544         }
    02545
    02546         // Check if received frame was encrypted
    02547         if (RXL_CNTRL_IS_PROTECTED(rx_status->frame_cntl) &&
    02548             !rxu_cntrl_protected_handle(frame, rx_status->statinfo))
    02549             break;
    02550
    02551         switch (frame_cntl & MAC_FCTRL_TYPE_MASK)
    02552         {
    02553             case MAC_FCTRL_CTRL_T:
    02554                 #if (NX_REORD)
    02555                 if ((frame_cntl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_BAR)
    02556                 {
    02557                     // Check the Start Sequence Numbers contained by the receive Block Ack Request PDU
    02558                     rxu_cntrl_reord_bar_check(sta_idx, frame);
    02559                 }
    02560                 #endif //(NX_REORD)
    02561                 break;
    02562
    02563             case MAC_FCTRL_MGT_T:
    02564                 // Perform the duplicate check
    02565                 if (!rxu_cntrl_duplicate_check(frame_cntl, sta_idx, false))
    02566                     break;
    02567
    02568                 // Perform the PN check if required
    02569                 if ((rx_status->frame_info & RXU_CNTRL_PN_CHECK_NEEDED) &&
    02570                     !rxu_cntrl_check_pn(&rx_status->pn, rx_status->key, TID_MGT))
    02571                      break;
    02572
    02573                 // Now check if the management is of interest for us
    02574                 upload = rxu_mgt_frame_check(rxdesc, rx_status->sta_idx);
    02575                 break;
    02576
    02577             case MAC_FCTRL_DATA_T:
    02578             {
    02579                 #if (RW_MESH_EN)
    02580                 // Get VIF information
    02581                 struct vif_info_tag *vif = &vif_info_tab[rx_status->vif_idx];
    02582
    02583                 if (vif->type == VIF_MESH_POINT)
    02584                 {
    02585                     if (!mesh_accept_frame(sta_idx))
    02586                     {
    02587                         break;
    02588                     }
    02589
    02590                     // Extract the Mesh PS status from the received header
    02591                     mesh_ps_rx_data_handle(rx_status->vif_idx, rx_status->sta_idx, (uint32_t)frame);
    02592                 }
    02593                 #endif //(RW_MESH_EN)
    02594
    02595                 // Check if the received frame is a NULL frame
    02596                 if (frame_cntl & MAC_NODATA_ST_BIT)
    02597                     break;
    02598
    02599                 qos = ((frame_cntl & MAC_QOS_ST_BIT) != 0);
    02600
    02601                 #if (RW_MESH_EN)
    02602                 if (vif->type == VIF_MESH_POINT)
    02603                 {
    02604                     // Check if this frame is for us or if it has to be forwarded to another Mesh STA
    02605                     if (!mesh_hwmp_check_data_dest(vif, sta_idx, (uint32_t)frame, rx_status))
    02606                     {
    02607                         break;
    02608                     }
    02609
    02610                     rx_status->mesh_ctrl_len = mesh_rx_get_machdr_add_len(vif, rx_status->a_qos_ctrl);
    02611
    02612                     // If frame has to be forwarded to another Mesh Point, keep Mesh Control as is
    02613                     if (rx_status->dst_idx == INVALID_STA_IDX)
    02614                     {
    02615                         rx_status->machdr_len += rx_status->mesh_ctrl_len;
    02616                     }
    02617                 }
    02618                 #endif //(RW_MESH_EN)
    02619
    02620                 #if (NX_REORD)
    02621                 // Check if a BA Agreement exists for the STAID
    02622                 if (qos && !(rx_status->frame_info & RXU_CNTRL_GROUP_ADDRESSED) &&
    02623                     mm_ba_agmt_rx_exists(sta_idx, rx_status->tid))
    02624                 {
    02625                     // Check if received packet was expected
    02626                     // If yes, the packet can be uploaded in host memory
    02627                     upload = rxu_cntrl_reord_check(rxdesc, sta_idx);
    02628                 }
    02629                 // Check if MPDU is part of an A-MPDU by checking its position inside
    02630                 // of the A-MPDU.
    02631                 else if (RX_AMPDU_MPDUCNT(rhd->ampdu_stat_info) == 1)
    02632                 {
    02633                     bam_send_del_ba_agg(sta_idx, rx_status->tid);
    02634                 }
    02635                 else
    02636                 #endif //(NX_REORD)
    02637                 {
    02638                     // Perform the duplicate check
    02639                     if (!rxu_cntrl_duplicate_check(frame_cntl, sta_idx, qos))
    02640                         break;
    02641
    02642                     // Perform the PN check if required
    02643                     if ((rx_status->frame_info & RXU_CNTRL_PN_CHECK_NEEDED) &&
    02644                         !rxu_cntrl_check_pn(&rx_status->pn, rx_status->key, rx_status->tid))
    02645                          break;
    02646
    02647                     /*
    02648                      * Packet has not been detected as a duplicate one. Check if reassembly procedure
    02649                      * has to be used
    02650                      */
    02651                     upload = rxu_cntrl_defrag_check(rxdesc, sta_idx, qos);
    02652                 }
    02653             } break;
    02654
    02655             default:
    02656                 break;
    02657         }
    02658     } while (0);
    02659
    02660     //Upload for monitor interface (if any)
    02661     upload = rxu_upload_monitor(rxdesc, upload);
    02662
    02663     // Transfer the pending descriptors
    02664     macif_rx_desc_upload(&rxu_cntrl_env.rxdesc_ready);
    02665
    02666     return (upload);
    02667 }
    02668
    02669 #if (NX_REORD)
    02670 bool rxu_cntrl_reord_create(struct sta_info_tag *sta, uint8_t tid, uint16_t ssn)
    02671 {
    02672     struct rxu_cntrl_reord *reord;
    02673
    02674     // Check if we already have a reordering structure allocated for this STA/TID pair
    02675     if (sta->ba_agmts_rx[tid] != NULL)
    02676         return false;
    02677
    02678     // Get a free reordering structure
    02679     reord = (struct rxu_cntrl_reord *) co_list_pop_front(&rxu_cntrl_env.rxu_reord_free);
    02680     if (!reord)
    02681         return false;
    02682
    02683     // Reset the content
    02684     memset(reord, 0, sizeof(struct rxu_cntrl_reord));
    02685
    02686     // Configure the RX SN Window
    02687     reord->tid = tid;
    02688     reord->win_start = ssn;
    02689     reord->rx_status_pos = ssn % RX_CNTRL_REORD_WIN_SIZE;
    02690     reord->sn_rx_time = hal_machw_time();
    02691     reord->timer.cb = rxu_cntrl_reord_timeout_cb;
    02692     reord->timer.env = reord;
    02693
    02694     // Save the pointer to the reordering structure
    02695     sta->ba_agmts_rx[tid] = reord;
    02696
    02697     // Start the reordering timer
    02698     mm_timer_set(&reord->timer, reord->sn_rx_time + RX_CNTRL_REORD_MAX_WAIT);
    02699
    02700     return true;
    02701 }
    02702
    02703 void rxu_cntrl_reord_delete(struct sta_info_tag *sta, uint8_t tid)
    02704 {
    02705     struct rxu_cntrl_reord *reord = sta->ba_agmts_rx[tid];
    02706
    02707     // Sanity check - The element shall exist
    02708     ASSERT_ERR(reord != NULL);
    02709
    02710     // Stop the reordering timer
    02711     mm_timer_clear(&reord->timer);
    02712
    02713     // Push back the reordering structure to the free list
    02714     co_list_push_back(&rxu_cntrl_env.rxu_reord_free,
    02715                       &reord->list_hdr);
    02716
    02717     // Delete the pointer to the reordering structure
    02718     sta->ba_agmts_rx[tid] = NULL;
    02719 }
    02720 #endif //(NX_REORD)
    02721
    02722 void rxu_cntrl_monitor_pm(struct mac_addr *addr)
    02723 {
    02724     // Only one address can be monitored at a time
    02725     if (rxu_cntrl_env.pm_mon.mon)
    02726         return;
    02727
    02728     // Copy the MAC address
    02729     MAC_ADDR_CPY(&rxu_cntrl_env.pm_mon.addr, addr);
    02730     // Set the PM state to active
    02731     rxu_cntrl_env.pm_mon.pm_state = PS_MODE_OFF;
    02732     // Enable the PM monitoring
    02733     rxu_cntrl_env.pm_mon.mon = true;
    02734 }
    02735
    02736 uint8_t rxu_cntrl_get_pm(void)
    02737 {
    02738     uint8_t pm_state = rxu_cntrl_env.pm_mon.pm_state;
    02739
    02740     // Disable the PM monitoring
    02741     rxu_cntrl_env.pm_mon.mon = false;
    02742     // Set the PM state to active
    02743     rxu_cntrl_env.pm_mon.pm_state = PS_MODE_OFF;
    02744
    02745     return (pm_state);
    02746 }
    02747
    02748 void rxu_cntrl_evt(int dummy)
    02749 {
    02750     // for profiling
    02751     RX_CNTRL_EVT_SET();
    02752
    02753     // Clear the kernel event
    02754     ke_evt_clear(KE_EVT_RXUREADY_BIT);
    02755
    02756     // Transfer the pending descriptor list
    02757     macif_rx_desc_upload(&rxu_cntrl_env.rxdesc_ready);
    02758
    02759     // for profiling
    02760     RX_CNTRL_EVT_CLR();
    02761 }
    02762
    02763 bool rxu_cntrl_desc_check(void)
    02764 {
    02765     return (rxu_stat_desc_pool[rxu_cntrl_env.rxdesc_idx].val.status == 0);
    02766 }
    02767
    02768
    02770