00001
00017
00018
00019
00020
00021
00022
00023 #include "co_int.h"
00024
00025 #include "co_bool.h"
00026
00027 #include <string.h>
00028
00029 #include "compiler.h"
00030
00031
00032 #include "rxu_cntrl.h"
00033
00034
00035 #include "macif.h"
00036
00037 #include "co_ring.h"
00038
00039 #include "ke_event.h"
00040
00041 #include "ke_task.h"
00042
00043 #include "me_task.h"
00044
00045 #include "mac_frame.h"
00046
00047 #include "rxl_cntrl.h"
00048
00049 #include "sta_mgmt.h"
00050
00051 #include "vif_mgmt.h"
00052
00053 #include "mm.h"
00054
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
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
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
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
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
00169
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
00188 rx_stat_desc->val.status = rx_status;
00189 rx_stat_desc->val.host_id = host_id;
00190
00191
00192 co_list_push_back(&rxu_cntrl_env.rxdesc_ready, list_hdr);
00193
00194
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
00214 uint8_t mac_hdr_len = MAC_SHORT_MAC_HDR_LEN;
00215
00216
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
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
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
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
00410 struct rx_payloaddesc *first_pbd
00411 = (struct rx_payloaddesc *)HW2CPU(dma_hdrdesc->hd.first_pbd_ptr);
00412
00413 struct mac_hdr *machdr = (struct mac_hdr *)HW2CPU(first_pbd->pbd.datastartptr);
00414
00415 struct llc_snap *llc_snap;
00416
00417 struct mac_eth_hdr *eth_hdr;
00418
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
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
00430 memcpy(&machdr_desc->buffer, machdr, machdr_len + LLC_802_2_HDR_LEN);
00431 }
00432 #endif
00433
00434 do
00435 {
00436
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
00471
00472
00473
00474
00475 eth_hdr = (struct mac_eth_hdr *)((uint16_t *)machdr + (machdr_len >> 1) - 7);
00476
00477 llc_snap = (struct llc_snap *)((uint16_t *)machdr + (machdr_len >> 1)
00478 + (rxu_cntrl_env.rx_status.mesh_ctrl_len >> 1));
00479
00480
00481 eth_hdr->len = llc_snap->proto_id;
00482 }
00483 else
00484 #endif //(RW_MESH_EN)
00485 {
00486
00487 llc_snap = (struct llc_snap *)((uint16_t *)machdr + (machdr_len >> 1));
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 if ((!memcmp(llc_snap, &llc_rfc1042_hdr, sizeof(llc_rfc1042_hdr))
00501
00502 && (llc_snap->proto_id != LLC_ETHERTYPE_IPX))
00503 || (!memcmp(llc_snap, &llc_bridge_tunnel_hdr, sizeof(llc_bridge_tunnel_hdr))))
00504 {
00505
00506
00507
00508
00509
00510
00511
00512
00513 eth_hdr = (struct mac_eth_hdr *)((uint16_t *)&(llc_snap->proto_id) - 6);
00514
00515
00516 payl_offset += 8;
00517
00518 rxu_cntrl_env.rx_status.eth_len_present = false;
00519 }
00520 else
00521 {
00522
00523
00524
00525
00526
00527
00528
00529
00530 eth_hdr = (struct mac_eth_hdr *)((uint16_t *)llc_snap - 7);
00531
00532
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
00540 MAC_ADDR_CPY(ð_hdr->da, &rxu_cntrl_env.rx_status.da);
00541 MAC_ADDR_CPY(ð_hdr->sa, &rxu_cntrl_env.rx_status.sa);
00542
00543 } while(0);
00544
00545
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
00555 machdr_desc->buf_len = payl_offset + sizeof_b(struct mac_eth_hdr);
00556 }
00557 #endif
00558
00559
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
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
00583 rxu_cntrl_mac2eth_update(rxdesc);
00584
00585 rxl_mpdu_transfer(rxdesc);
00586
00587 #if NX_MON_DATA
00588 if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
00589 {
00590
00591 rx_status |= RX_STAT_MONITOR;
00592 }
00593 #endif
00594
00595
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
00615 if (vif_mgmt_env.monitor_vif != INVALID_VIF_IDX)
00616 {
00617
00618 if (rx_stat->vif_idx == INVALID_VIF_IDX)
00619 {
00620
00621 rx_status = RX_STAT_MONITOR;
00622 }
00623 else
00624 {
00625 rx_status |= RX_STAT_MONITOR;
00626 }
00627 }
00628
00629
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
00642 rxu_cntrl_env.rx_status.payl_offset = 0;
00643
00644 if (statinfo & RX_HD_SUCCESS)
00645
00646 rxu_cntrl_remove_sec_hdr_mgmt_frame(rxdesc, rx_stat);
00647
00648 rxl_mpdu_transfer(rxdesc);
00649
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
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
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
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
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
00736 rxu_cntrl_env.rx_status.tid = (*qos & MAC_QOSCTRL_UP_MSK);
00737
00738 #if (RW_MESH_EN)
00739
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
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
00772 co_copy8p(mic_buffer, mic_p1_addr, mic_p1_len);
00773 mic_buffer += mic_p1_len;
00774
00775
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
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
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
00845
00846
00847 if (first_frag)
00848 {
00849 struct key_info_tag *key = rx_status->key;
00850
00851
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
00859 struct rx_payloaddesc *pd = HW2CPU(dma_hdrdesc->hd.first_pbd_ptr);
00860
00861
00862
00863 uint16_t data_tot_len = dma_hdrdesc->hd.frmlen - rx_status->machdr_len;
00864
00865
00866
00867 uint16_t remaining_len;
00868 uint16_t comp_len;
00869 uint16_t payl_offset;
00870
00871
00872
00873
00874
00875 if (!first_frag)
00876 {
00877 uint32_t last_bytes_addr = CPU2HW(mic->last_bytes);
00878
00879
00880
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
00888 me_mic_calc(mic_calc_ptr, last_bytes_addr, data_tot_len);
00889
00890
00891 rxu_cntrl_mic_rd_concat(CPU2HW(&rx_mic[0]), data_len,
00892 last_bytes_addr + data_tot_len,
00893 data_ptr);
00894
00895
00896 break;
00897 }
00898
00899
00900 me_mic_calc(mic_calc_ptr, last_bytes_addr, MIC_LEN);
00901 }
00902
00903
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
00912 if ((remaining_len + payl_offset) <= payl_len)
00913 {
00914
00915 comp_len = remaining_len;
00916 }
00917 else
00918 {
00919
00920 comp_len = payl_len - payl_offset;
00921 }
00922
00923
00924 remaining_len -= comp_len;
00925
00926
00927 me_mic_calc(mic_calc_ptr, comp_addr, comp_len);
00928
00929
00930 if (remaining_len == 0)
00931 break;
00932
00933
00934 payl_offset = 0;
00935
00936
00937 pd = HW2CPU(pd->pbd.next);
00938
00939
00940 ASSERT_REC_VAL(pd != NULL, false);
00941 }
00942
00943
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
00953 if ((remaining_len + payl_offset) <= payl_len)
00954 {
00955
00956 mic_len = remaining_len;
00957 }
00958 else
00959 {
00960
00961 mic_len = payl_len - payl_offset;
00962 }
00963
00964
00965 co_copy8p(rx_mic_addr, mic_addr, mic_len);
00966
00967
00968 remaining_len -= mic_len;
00969 rx_mic_addr += mic_len;
00970
00971
00972 if (remaining_len == 0)
00973 break;
00974
00975
00976 payl_offset = 0;
00977
00978
00979 pd = HW2CPU(pd->pbd.next);
00980
00981
00982 ASSERT_REC_VAL(pd != NULL, false);
00983 }
00984 } while (0);
00985
00986 if (last_frag)
00987 {
00988
00989 me_mic_end(mic_calc_ptr);
00990
00991
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
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
01023 rxl_mpdu_partial_transfer(rxdesc, cpy_len, defrag->dma_addr, defrag->mac_hdr_len,
01024 NULL, NULL);
01025
01026
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
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
01052 if ((defrag->sta_idx == sta_idx)
01053 && (defrag->tid == tid)
01054 && (defrag->sn == sn))
01055 {
01056
01057 break;
01058 }
01059
01060 defrag = (struct rxu_cntrl_defrag *)defrag->list_hdr.next;
01061 }
01062
01063
01064 return (defrag);
01065 }
01066
01076 static struct rxu_cntrl_defrag *rxu_cntrl_defrag_alloc(void)
01077 {
01078
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
01085 defrag = (struct rxu_cntrl_defrag *)co_list_pop_front(&rxu_cntrl_env.rxu_defrag_used);
01086
01087
01088 ASSERT_ERR(defrag != NULL);
01089
01090
01091 rxu_cntrl_desc_prepare(NULL, RX_STAT_DELETE, defrag->host_id);
01092 }
01093
01094
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
01113 status = defrag->eth_len_present?RX_STAT_LEN_UPDATE|RX_STAT_ETH_LEN_UPDATE:RX_STAT_LEN_UPDATE;
01114
01115
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
01136 rxu_cntrl_desc_prepare(NULL, RX_STAT_DELETE, defrag->host_id);
01137
01138
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
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
01162 bool upload = false;
01163
01164 uint8_t tid = (qos) ? rxu_cntrl_env.rx_status.tid : 0;
01165
01166 struct rx_cntrl_rx_status *rx_status = &rxu_cntrl_env.rx_status;
01167
01168 uint16_t mf = rx_status->frame_cntl & MAC_FCTRL_MOREFRAG;
01169
01170 struct rxu_cntrl_defrag *defrag;
01171 struct rx_dmadesc *dma_hdrdesc = rxl_dmadesc_get(rxdesc);
01172
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
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
01190 rhd->frmlen -= MIC_LEN;
01191 }
01192
01193
01194 rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
01195 upload = true;
01196 break;
01197 }
01198
01199
01200 defrag = rxu_cntrl_defrag_get(sta_idx, rxu_cntrl_env.rx_status.sn, tid);
01201
01202 if (!defrag)
01203 {
01204
01205 if (rx_status->fn)
01206 break;
01207
01208
01209 defrag = rxu_cntrl_defrag_alloc();
01210
01211
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
01218 defrag->dma_addr = 0;
01219
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
01226 if (rx_status->frame_info & RXU_CNTRL_MIC_CHECK_NEEDED)
01227 rxu_cntrl_mic_check(rxdesc, &defrag->mic, true, false);
01228
01229
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
01235
01236 defrag->frame_len = rhd->frmlen;
01237
01238
01239 co_list_push_back(&rxu_cntrl_env.rxu_defrag_used, &defrag->list_hdr);
01240
01241
01242 upload = true;
01243 }
01244 else
01245 {
01246 uint16_t status;
01247 uint16_t cpy_len;
01248
01249
01250 if (defrag->next_fn != rx_status->fn)
01251
01252 break;
01253
01254
01255 cpy_len = rhd->frmlen - (uint16_t)defrag->mac_hdr_len;
01256 defrag->frame_len += cpy_len;
01257
01258
01259 defrag->next_fn++;
01260
01261
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
01269 defrag->frame_len -= MIC_LEN;
01270 }
01271
01272
01273 rxu_cntrl_defrag_mpdu_transfer(rxdesc, defrag, cpy_len);
01274
01275 if (!mf)
01276 {
01277
01278 rxu_cntrl_defrag_len_update(defrag);
01279
01280
01281 rxu_cntrl_desc_prepare(NULL, status, defrag->host_id);
01282
01283
01284 mm_timer_clear(&defrag->timer);
01285
01286
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
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
01317 bool upload = false;
01318
01319 PROF_RX_DUPLI_NSTA_CHECK_SET();
01320
01321 do
01322 {
01323
01324 struct mac_hdr *machdr = (struct mac_hdr *)frame;
01325
01326
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
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
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
01380 if ((frame_cntrl & MAC_FCTRL_RETRY) &&
01381 (*last_seq_cntl == rxu_cntrl_env.rx_status.seq_cntl))
01382 {
01383
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
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
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
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
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
01487 if (rxu_cntrl_desc_prepare(NULL, status, elt->host_id) == NULL)
01488 {
01489 PROF_REORD_FWD_CLR();
01490 break;
01491 }
01492
01493
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
01514 struct bar_frame *bar = (struct bar_frame *)frame;
01515
01516 uint8_t tid = (bar->bar_cntrl & BAR_CNTL_TID_MSK) >> BAR_CNTL_TID_OFT;
01517
01518 struct rxu_cntrl_reord *reord = sta_info_tab[sta_idx].ba_agmts_rx[tid];
01519
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
01532 if ((ssn == reord->win_start) ||
01533 (((ssn - reord->win_start) & MAC_SEQCTRL_NUM_MAX) > (MAC_SEQCTRL_NUM_MAX >> 1)))
01534 {
01535
01536 break;
01537 }
01538
01539
01540
01541
01542
01543
01544 rxu_cntrl_reord_flush(reord, (ssn - reord->win_start) & MAC_SEQCTRL_NUM_MAX);
01545
01546
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
01572 bool upload = true;
01573
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
01585 if (rx_status->sn == reord->win_start)
01586 {
01587
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
01592 if (upload)
01593 {
01594 rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
01595 }
01596
01597
01598
01599 reord->active = true;
01600
01601
01602 reord->sn_rx_time = hal_machw_time();
01603
01604
01605 rxu_cntrl_reord_update(reord);
01606
01607
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
01619 rxu_cntrl_reord_flush(reord, sn_pos - RX_CNTRL_REORD_WIN_SIZE + 1);
01620
01621
01622 sn_pos = (rx_status->sn - reord->win_start) & MAC_SEQCTRL_NUM_MAX;
01623 }
01624
01625
01626
01627
01628
01629
01630 else if (!reord->active)
01631 {
01632
01633 upload = rxu_cntrl_duplicate_check(rx_status->frame_cntl, sta_idx, 1);
01634
01635
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
01640 if (upload)
01641 rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_FORWARD | RX_STAT_ALLOC);
01642
01643
01644 bam_rx_active(sta_idx, rx_status->tid);
01645 break;
01646 }
01647 else
01648 {
01649
01650 upload = false;
01651 break;
01652 }
01653 }
01654
01655
01656
01657 reord->active = true;
01658
01659 sn_pos = (sn_pos + reord->rx_status_pos) % RX_CNTRL_REORD_WIN_SIZE;
01660
01661
01662 if (reord->elt[sn_pos].host_id)
01663 {
01664
01665 upload = false;
01666 break;
01667 }
01668
01669
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
01682 rxu_msdu_upload_and_indicate(rxdesc, RX_STAT_ALLOC);
01683
01684
01685 reord->elt[sn_pos].host_id = rxu_cntrl_env.hostid_current;
01686
01687 reord->ooo_pkt_cnt++;
01688 }
01689
01690
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
01713 mm_timer_set(&reord->timer, ke_time() + RX_CNTRL_REORD_MAX_WAIT);
01714
01715 do
01716 {
01717
01718 if (!reord->ooo_pkt_cnt)
01719 break;
01720
01721
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
01728 rxu_cntrl_reord_update(reord);
01729 }
01730
01731 rxu_cntrl_reord_fwd(reord);
01732
01733
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
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
01791 struct mac_hdr *hdr = (struct mac_hdr *)frame;
01792
01793 do
01794 {
01795
01796 if (!rxu_cntrl_env.pm_mon.mon)
01797 break;
01798
01799
01800 if (statinfo & RX_HD_ADDRMIS)
01801 break;
01802
01803
01804 if (!MAC_ADDR_CMP(&rxu_cntrl_env.pm_mon.addr, &hdr->addr2))
01805 break;
01806
01807
01808 if ((hdr->fctl & (MAC_FCTRL_PWRMGT | MAC_FCTRL_MOREFRAG)) == MAC_FCTRL_PWRMGT)
01809
01810 rxu_cntrl_env.pm_mon.pm_state = PS_MODE_ON;
01811 else
01812
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
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
01844 if (sta_idx == INVALID_STA_IDX)
01845 {
01846 #if (RW_MESH_EN)
01847
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
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
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
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
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
01915 if (STA_CAPA(sta, HT) && (chwidth <= BW_40MHZ))
01916
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
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
01930 me_sta_bw_nss_max_upd(sta_idx, 0xFF, 0);
01931 else
01932
01933 me_sta_bw_nss_max_upd(sta_idx, 0xFF, 0xFF);
01934 }
01935 } break;
01936
01937 default:
01938 {
01939
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
01982 struct mesh_vif_info_tag *mvif;
01983
01984 if (*vif_idx == INVALID_VIF_IDX)
01985 {
01986
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
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
02008 upload = true;
02009 break;
02010 }
02011 }
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
02024 upload = true;
02025 } break;
02026 }
02027
02028
02029 if (*task_id != TASK_NONE)
02030 {
02031
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
02070 if (*vif_idx != INVALID_VIF_IDX)
02071 {
02072 vif = &vif_info_tab[*vif_idx];
02073 mode = vif->type;
02074 }
02075
02076
02077 switch (framectrl & MAC_FCTRL_TYPESUBTYPE_MASK)
02078 {
02079
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
02090 if (vif)
02091 {
02092 *need_machdr = true;
02093 *task_id = TASK_SCANU;
02094 }
02095 break;
02096
02097 case MAC_FCTRL_BEACON:
02098 {
02099
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
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
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
02140 *need_machdr = true;
02141 *task_id = TASK_MESH;
02142 }
02143 else
02144 {
02145 if (sta_idx == INVALID_STA_IDX)
02146 {
02147
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
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
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
02184 if (mode == VIF_STA)
02185 {
02186 *task_id = TASK_SM;
02187 }
02188 break;
02189
02190 case MAC_FCTRL_ACTION:
02191
02192
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
02232 upload = rxu_mgt_route(framectrl, length, machdr_length, sta_idx, vif_idx, payload,
02233 &dest_id, ©_mac_hdr);
02234
02235
02236 if (dest_id != TASK_NONE)
02237 {
02238
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
02244 phy_get_channel(&info, PHY_PRIM);
02245
02246
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
02264 ke_msg_send(rx);
02265
02266
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
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
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
02337 if ((hdr->fctl & MAC_FCTRL_MOREFRAG) ||
02338 (hdr->seq & MAC_SEQCTRL_FRAG_MSK))
02339 {
02340 upload = false;
02341 break;
02342 }
02343
02344
02345 rssi = hal_desc_get_rssi(&rhd->rx_vec_1, rx_rssi);
02346
02347
02348
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
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
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
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
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
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
02486 rxu_cntrl_machdr_read(frame);
02487
02488 if (!(statinfo & RX_HD_KEYIDV))
02489 {
02490
02491 rxu_cntrl_pm_mon_check(frame, statinfo);
02492
02493
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
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
02516 key_idx_hw = (uint16_t)RX_HD_KEYID_GET(statinfo);
02517
02518
02519 sta_idx = (uint8_t)(key_idx_hw - MM_SEC_DEFAULT_KEY_COUNT);
02520
02521
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
02529 rx_status->statinfo = statinfo;
02530
02531 #if NX_BEACONING
02532
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
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
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
02558 rxu_cntrl_reord_bar_check(sta_idx, frame);
02559 }
02560 #endif //(NX_REORD)
02561 break;
02562
02563 case MAC_FCTRL_MGT_T:
02564
02565 if (!rxu_cntrl_duplicate_check(frame_cntl, sta_idx, false))
02566 break;
02567
02568
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
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
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
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
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
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
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
02622 if (qos && !(rx_status->frame_info & RXU_CNTRL_GROUP_ADDRESSED) &&
02623 mm_ba_agmt_rx_exists(sta_idx, rx_status->tid))
02624 {
02625
02626
02627 upload = rxu_cntrl_reord_check(rxdesc, sta_idx);
02628 }
02629
02630
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
02639 if (!rxu_cntrl_duplicate_check(frame_cntl, sta_idx, qos))
02640 break;
02641
02642
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
02649
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
02661 upload = rxu_upload_monitor(rxdesc, upload);
02662
02663
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
02675 if (sta->ba_agmts_rx[tid] != NULL)
02676 return false;
02677
02678
02679 reord = (struct rxu_cntrl_reord *) co_list_pop_front(&rxu_cntrl_env.rxu_reord_free);
02680 if (!reord)
02681 return false;
02682
02683
02684 memset(reord, 0, sizeof(struct rxu_cntrl_reord));
02685
02686
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
02695 sta->ba_agmts_rx[tid] = reord;
02696
02697
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
02708 ASSERT_ERR(reord != NULL);
02709
02710
02711 mm_timer_clear(&reord->timer);
02712
02713
02714 co_list_push_back(&rxu_cntrl_env.rxu_reord_free,
02715 &reord->list_hdr);
02716
02717
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
02725 if (rxu_cntrl_env.pm_mon.mon)
02726 return;
02727
02728
02729 MAC_ADDR_CPY(&rxu_cntrl_env.pm_mon.addr, addr);
02730
02731 rxu_cntrl_env.pm_mon.pm_state = PS_MODE_OFF;
02732
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
02741 rxu_cntrl_env.pm_mon.mon = false;
02742
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
02751 RX_CNTRL_EVT_SET();
02752
02753
02754 ke_evt_clear(KE_EVT_RXUREADY_BIT);
02755
02756
02757 macif_rx_desc_upload(&rxu_cntrl_env.rxdesc_ready);
02758
02759
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