00001
00020
00021
00022
00023
00024 #include "ps.h"
00025 #include "mac_ie.h"
00026 #include "sta_mgmt.h"
00027 #include "vif_mgmt.h"
00028 #include "mm.h"
00029 #include "co_utils.h"
00030 #include "co_status.h"
00031 #include "dbg.h"
00032 #include "txl_frame.h"
00033 #include "phy.h"
00034 #include "tpc.h"
00035
00036 #if (NX_DPSM)
00037 #include "td.h"
00038 #endif //(NX_DPSM)
00039
00040 #if NX_POWERSAVE
00041
00042
00043
00044
00045
00046
00048 #define PS_TX_ERROR_MAX (3)
00049
00050
00051
00052
00053
00055 struct ps_env_tag ps_env;
00056
00057
00058
00059
00060
00072 static uint8_t ps_send_pspoll(struct vif_info_tag *vif)
00073 {
00074 struct txl_frame_desc_tag *frame;
00075 struct mac_hdr_ctrl *buf;
00076 struct tx_hd *thd;
00077 struct sta_info_tag *sta = &sta_info_tab[vif->u.sta.ap_id];
00078 int txtype;
00079
00080
00081 txtype = vif_mgmt_get_txtype(vif);
00082 frame = txl_frame_get(txtype, MAC_PSPOLL_FRAME_SIZE);
00083 if (frame == NULL)
00084 return CO_FAIL;
00085
00086
00087 tpc_update_frame_tx_power(vif, frame);
00088
00089
00090 buf = txl_buffer_payload_get(&frame->txdesc);
00091
00092
00093 buf->fctl = MAC_FCTRL_PSPOLL;
00094 buf->durid = (0x3 << 14) | sta->aid;
00095 buf->addr1 = sta->mac_addr;
00096 buf->addr2 = vif->mac_addr;
00097
00098
00099 thd = &frame->txdesc.lmac.hw_desc->thd;
00100 thd->macctrlinfo2 |= DONT_TOUCH_DUR | TS_VALID_BIT | (MAC_FCTRL_PSPOLL >> 1);
00101
00102 #if (NX_CHNL_CTXT || NX_P2P)
00103
00104 frame->txdesc.host.vif_idx = sta->inst_nbr;
00105 frame->txdesc.host.staid = sta->staid;
00106 #endif //(NX_CHNL_CTXT || NX_P2P)
00107
00108
00109 txl_frame_push(frame, AC_VO);
00110
00111 return CO_OK;
00112 }
00113
00130 static bool ps_check_tx_status(struct vif_info_tag *vif, uint32_t status,
00131 cfm_func_ptr cfm)
00132 {
00133
00134 bool handle_cfm = true;
00135
00136
00137 if (!(status & FRAME_SUCCESSFUL_TX_BIT))
00138 {
00139
00140 vif->u.sta.ps_retry++;
00141
00142
00143 if (vif->u.sta.ps_retry == PS_TX_ERROR_MAX)
00144 {
00145 #if (NX_CONNECTION_MONITOR)
00146
00147 mm_send_connection_loss_ind(vif);
00148 #endif //(NX_CONNECTION_MONITOR)
00149
00150 }
00151 else
00152 {
00153
00154 txl_frame_send_null_frame(vif->u.sta.ap_id, cfm, vif);
00155
00156
00157 handle_cfm = false;
00158 }
00159 }
00160
00161 return (handle_cfm);
00162 }
00163
00177 static void ps_enable_cfm(void *env, uint32_t status)
00178 {
00179
00180 if (!ps_check_tx_status((struct vif_info_tag *)env, status, ps_enable_cfm))
00181 {
00182 return;
00183 }
00184
00185 if (ps_env.cfm_cnt)
00186 {
00187
00188 ps_env.cfm_cnt--;
00189 }
00190
00191
00192 if (ps_env.cfm_cnt == 0)
00193 {
00194 #if NX_UAPSD
00195
00196 if (ps_env.uapsd_on)
00197 {
00198 struct vif_info_tag *vif =
00199 (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00200
00201 mm_timer_set(&ps_env.uapsd_timer, ke_time() + ps_env.uapsd_timeout);
00202 ps_env.uapsd_tmr_on = true;
00203 while (vif != NULL)
00204 {
00205 if ((vif->type == VIF_STA) && vif->active && vif->u.sta.uapsd_queues)
00206 vif->prevent_sleep &= ~PS_VIF_WAITING_EOSP;
00207
00208
00209 vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
00210 }
00211 }
00212 #endif
00213
00214 #if (NX_DPSM)
00215 if (PS_DPSM_STATE_GET(ON) && PS_DPSM_STATE_GET(RESUMING))
00216 {
00217
00218 PS_DPSM_STATE_CLEAR(RESUMING);
00219
00220 PS_DPSM_STATE_CLEAR(PAUSE);
00221 TRACE_STA(PS, "{VIF-%d} PS mode resumed", ((struct vif_info_tag *)env)->index);
00222 }
00223 else
00224 #endif //(NX_DPSM)
00225 {
00226
00227 ps_env.ps_on = true;
00228 TRACE_STA(PS, "{VIF-%d} PS mode enabled", ((struct vif_info_tag *)env)->index);
00229
00230
00231 ke_msg_send_basic(MM_SET_PS_MODE_CFM, ps_env.taskid, TASK_MM);
00232 }
00233
00234 #if (NX_DPSM)
00235 if (PS_DPSM_STATE_GET(SET_MODE_REQ))
00236 {
00237
00238 PS_DPSM_STATE_CLEAR(SET_MODE_REQ);
00239
00240 ps_set_mode(ps_env.next_mode, ps_env.taskid);
00241 }
00242 #endif //(NX_DPSM)
00243 }
00244 }
00245
00259 static void ps_disable_cfm(void *env, uint32_t status)
00260 {
00261
00262 if (!ps_check_tx_status((struct vif_info_tag *)env, status, ps_disable_cfm))
00263 {
00264 return;
00265 }
00266
00267 if (ps_env.cfm_cnt)
00268 {
00269
00270 ps_env.cfm_cnt--;
00271 }
00272
00273
00274 if (ps_env.cfm_cnt == 0)
00275 {
00276 struct vif_info_tag *vif =
00277 (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00278
00279 #if NX_UAPSD
00280
00281 mm_timer_clear(&ps_env.uapsd_timer);
00282 ps_env.uapsd_tmr_on = false;
00283 #endif
00284
00285 while (vif != NULL)
00286 {
00287 if ((vif->type == VIF_STA) && vif->active)
00288 {
00289 vif->prevent_sleep &= ~(PS_VIF_WAITING_BCMC | PS_VIF_WAITING_UC | PS_VIF_WAITING_EOSP);
00290 }
00291
00292
00293 vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
00294 }
00295
00296 #if (NX_DPSM)
00297
00298 if (PS_DPSM_STATE_GET(ON) && PS_DPSM_STATE_GET(PAUSING))
00299 {
00300
00301 PS_DPSM_STATE_CLEAR(PAUSING);
00302
00303 PS_DPSM_STATE_SET(PAUSE);
00304 TRACE_STA(PS, "{VIF-%d} PS mode paused", ((struct vif_info_tag *)env)->index);
00305 }
00306 else
00307 #endif //(NX_DPSM)
00308 {
00309
00310 ps_env.ps_on = false;
00311 TRACE_STA(PS, "{VIF-%d} PS mode disabled", ((struct vif_info_tag *)env)->index);
00312
00313
00314 ke_msg_send_basic(MM_SET_PS_MODE_CFM, ps_env.taskid, TASK_MM);
00315 }
00316
00317 #if (NX_DPSM)
00318 if (PS_DPSM_STATE_GET(SET_MODE_REQ))
00319 {
00320
00321 PS_DPSM_STATE_CLEAR(SET_MODE_REQ);
00322
00323 ps_set_mode(ps_env.next_mode, ps_env.taskid);
00324 }
00325 #endif //(NX_DPSM)
00326 }
00327 }
00328
00329 #if (NX_DPSM)
00330
00340 static void ps_dpsm_update(bool pause)
00341 {
00342
00343 struct vif_info_tag *vif;
00344
00345 cfm_func_ptr cfm ;
00346
00347 PROF_PS_DPSM_UPDATE_SET();
00348
00349
00350 if (pause)
00351 {
00352 cfm = ps_disable_cfm;
00353
00354
00355 PS_DPSM_STATE_SET(PAUSING);
00356
00357
00358 ps_env.prevent_sleep |= PS_PSM_PAUSED;
00359
00360 PROF_PS_PAUSE_SET();
00361 }
00362
00363 else
00364 {
00365 cfm = ps_enable_cfm;
00366
00367
00368 PS_DPSM_STATE_SET(RESUMING);
00369
00370
00371 ps_env.prevent_sleep &= ~PS_PSM_PAUSED;
00372
00373 PROF_PS_PAUSE_CLR();
00374 }
00375
00376
00377 nxmac_pwr_mgt_setf((uint8_t)(pause == false));
00378
00379
00380 ps_env.cfm_cnt = 0;
00381
00382
00383 vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00384
00385 while (vif)
00386 {
00387 if ((vif->type == VIF_STA) && vif->active
00388 #if (NX_CHNL_CTXT)
00389 && chan_is_tx_allowed(vif)
00390 #endif //(NX_CHNL_CTXT)
00391 )
00392 {
00393
00394 vif->u.sta.ps_retry = 0;
00395
00396 ps_env.cfm_cnt++;
00397
00398
00399 txl_frame_send_null_frame(vif->u.sta.ap_id, cfm, vif);
00400 }
00401
00402
00403 vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
00404 }
00405
00406
00407 if (ps_env.cfm_cnt == 0)
00408 {
00409 cfm(NULL, FRAME_SUCCESSFUL_TX_BIT);
00410 }
00411
00412 PROF_PS_DPSM_UPDATE_CLR();
00413 }
00414 #endif //(NX_DPSM)
00415
00416 #if (NX_UAPSD)
00417
00426 static void ps_uapsd_timer_handle(void *env)
00427 {
00428 bool sta_active = false;
00429
00430 struct vif_info_tag *vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00431
00432 while (vif != NULL)
00433 {
00434 if ((vif->type == VIF_STA) && vif->active && vif->u.sta.uapsd_queues
00435 #if NX_CHNL_CTXT
00436 && chan_is_tx_allowed(vif)
00437 #endif
00438 )
00439 {
00440
00441 sta_active = true;
00442
00443
00444 if (ke_time_past(vif->u.sta.uapsd_last_rxtx + ps_env.uapsd_timeout/2))
00445 {
00446 #if (NX_P2P)
00447 if (vif->p2p && !p2p_is_present(vif->p2p_index))
00448 {
00449
00450
00451
00452 vif->u.sta.sp_paused = true;
00453 }
00454 else
00455 #endif //(NX_P2P)
00456 if (txl_frame_send_qosnull_frame(vif->u.sta.ap_id,
00457 vif->u.sta.uapsd_tid << MAC_QOSCTRL_UP_OFT,
00458 NULL, NULL) == CO_OK)
00459 {
00460 TRACE_STA(PS, "{VIF-%d} start periodic UAPSD Service Period",
00461 vif->index);
00462 vif->prevent_sleep |= PS_VIF_WAITING_EOSP;
00463 vif->u.sta.uapsd_last_rxtx = ke_time();
00464 }
00465 }
00466 }
00467
00468
00469 vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
00470 }
00471
00472
00473 if (sta_active)
00474 {
00475
00476 mm_timer_set(&ps_env.uapsd_timer, ke_time() + ps_env.uapsd_timeout);
00477 }
00478 else
00479 {
00480
00481 ps_env.uapsd_tmr_on = false;
00482 }
00483 }
00484 #endif //(NX_UAPSD)
00485
00486 void ps_init(void)
00487 {
00488
00489 memset(&ps_env, 0, sizeof(ps_env));
00490
00491 #if (NX_UAPSD)
00492
00493 ps_env.uapsd_timer.cb = ps_uapsd_timer_handle;
00494 #endif //(NX_UAPSD)
00495 }
00496
00497 void ps_set_mode(uint8_t mode, ke_task_id_t taskid)
00498 {
00499 struct vif_info_tag *vif;
00500 cfm_func_ptr cfm;
00501
00502
00503 ps_env.taskid = taskid;
00504
00505 #if (NX_DPSM)
00506
00507 if (PS_DPSM_STATE_GET(ON) && (PS_DPSM_STATE_GET(PAUSING) || PS_DPSM_STATE_GET(RESUMING)))
00508 {
00509
00510 ps_env.next_mode = mode;
00511
00512 PS_DPSM_STATE_SET(SET_MODE_REQ);
00513
00514 return;
00515 }
00516 #endif //(NX_DPSM)
00517
00518 if (mode == PS_MODE_OFF)
00519 {
00520
00521 cfm = ps_disable_cfm;
00522
00523 #if (NX_DPSM)
00524
00525 ps_env.dpsm_state = 0;
00526 #endif //(NX_DPSM)
00527
00528
00529
00530 nxmac_pwr_mgt_setf(0);
00531 }
00532 else
00533 {
00534
00535 cfm = ps_enable_cfm;
00536
00537 #if (NX_DPSM)
00538
00539 if (mode == PS_MODE_ON_DYN)
00540 {
00541
00542 PS_DPSM_STATE_SET(ON);
00543 }
00544 #endif //(NX_DPSM)
00545
00546
00547
00548 nxmac_pwr_mgt_setf(1);
00549 }
00550
00551
00552 ps_env.cfm_cnt = 0;
00553 #if NX_UAPSD
00555 ps_env.uapsd_on = false;
00556 #endif
00557
00558
00559 vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00560
00561 while (vif != NULL)
00562 {
00563 if ((vif->type == VIF_STA) && vif->active
00564 #if NX_CHNL_CTXT
00565 && chan_is_tx_allowed(vif)
00566 #endif
00567 )
00568 {
00569
00570 vif->u.sta.ps_retry = 0;
00571
00572 ps_env.cfm_cnt++;
00573
00574 #if NX_UAPSD
00575
00576 if (vif->u.sta.uapsd_queues)
00577 ps_env.uapsd_on = true;
00578 #endif
00579
00580
00581 txl_frame_send_null_frame(vif->u.sta.ap_id, cfm, vif);
00582 }
00583
00584
00585 vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
00586 }
00587
00588
00589 if (ps_env.cfm_cnt == 0)
00590 {
00591
00592 cfm(NULL, FRAME_SUCCESSFUL_TX_BIT);
00593 }
00594 }
00595
00607 #if (!RW_MESH_EN)
00608 __INLINE
00609 #endif //(!RW_MESH_EN)
00610 bool ps_check_tim(uint32_t a_tim, uint16_t aid)
00611 {
00612
00613 uint8_t mask;
00614 unsigned int n, n1, n2;
00615
00616
00617
00618 n = aid / 8;
00619
00620
00621 mask = CO_BIT(aid & 0x7);
00622
00623
00624 n1 = co_read8p(a_tim + MAC_TIM_BMPC_OFT) & 0xFE;
00625 n2 = co_read8p(a_tim + MAC_TIM_LEN_OFT) + n1 - 4;
00626
00627
00628 if ((n < n1) || (n > n2))
00629 {
00630 return false;
00631 }
00632
00633
00634 n -= n1;
00635
00636 if (co_read8p(a_tim + MAC_TIM_BMP_OFT + n) & mask)
00637 {
00638 return true;
00639 }
00640
00641 return false;
00642 }
00643
00644 void ps_check_beacon(uint32_t tim, uint16_t len, struct vif_info_tag *vif)
00645 {
00646 uint16_t aid = sta_info_tab[vif->u.sta.ap_id].aid;
00647
00648
00649 vif->prevent_sleep &= ~PS_VIF_WAITING_BCN;
00650
00651
00652 if (!ps_env.ps_on)
00653 return;
00654
00655 #if (NX_DPSM)
00656 if (PS_DPSM_STATE_GET(PAUSE))
00657 return;
00658 #endif //(NX_DPSM)
00659
00660
00661 if (tim == 0)
00662 return;
00663
00664 PROF_PS_CHECK_BCN_SET();
00665
00666
00667 if (!vif->u.sta.dont_wait_bcmc)
00668 {
00669 int bcmc_octet = vif->u.sta.bssid_index / 8;
00670 int bcmc_bit = vif->u.sta.bssid_index % 8;
00671 if (co_read8p(tim + MAC_TIM_BMPC_OFT + bcmc_octet) & CO_BIT(bcmc_bit))
00672 {
00673 vif->prevent_sleep |= PS_VIF_WAITING_BCMC;
00674 TRACE_STA(PS, "{VIF-%d} AP has BroadCast/Multicast traffic buffered",
00675 vif->index);
00676 }
00677 else
00678 vif->prevent_sleep &= ~PS_VIF_WAITING_BCMC;
00679 }
00680
00681
00682 if (ps_check_tim(tim, aid))
00683 {
00684 TRACE_STA(PS, "{VIF-%d} AP has traffic buffered for us", vif->index);
00685
00686 #if NX_UAPSD
00687 if ((vif->u.sta.uapsd_queues & PS_ALL_UAPSD_ACS) == PS_ALL_UAPSD_ACS)
00688 {
00689
00690 if (txl_frame_send_qosnull_frame(vif->u.sta.ap_id,
00691 TID_7 << MAC_QOSCTRL_UP_OFT,
00692 NULL, NULL) == CO_OK)
00693 {
00694 vif->prevent_sleep |= PS_VIF_WAITING_EOSP;
00695 TRACE_STA(PS, "Start UAPSD Service Period");
00696 }
00697 }
00698 else
00699 #endif
00700 {
00701
00702
00703 if (ps_send_pspoll(vif) == CO_OK)
00704 {
00705 vif->prevent_sleep |= PS_VIF_WAITING_UC;
00706 TRACE_STA(PS, "Send PS-POLL");
00707 }
00708 }
00709 }
00710 else
00711 {
00712 #if NX_UAPSD
00713 if ((vif->u.sta.uapsd_queues & PS_ALL_UAPSD_ACS) == PS_ALL_UAPSD_ACS)
00714 {
00715 vif->prevent_sleep &= ~PS_VIF_WAITING_EOSP;
00716 }
00717 else
00718 #endif
00719 vif->prevent_sleep &= ~PS_VIF_WAITING_UC;
00720 }
00721
00722 PROF_PS_CHECK_BCN_CLR();
00723 }
00724
00725 void ps_check_frame(uint8_t *frame, uint32_t statinfo, struct vif_info_tag *vif)
00726 {
00727 struct mac_hdr *machdr = (struct mac_hdr *)frame;
00728 uint16_t framectrl = machdr->fctl;
00729
00730
00731 if (!ps_env.ps_on)
00732 return;
00733
00734
00735 if (MAC_ADDR_GROUP(&machdr->addr1))
00736 {
00737
00738 if (!(framectrl & MAC_FCTRL_MOREDATA) || vif->u.sta.dont_wait_bcmc)
00739
00740 vif->prevent_sleep &= ~PS_VIF_WAITING_BCMC;
00741 }
00742 else
00743 {
00744 #if (NX_UAPSD)
00745 bool uapsd_frame = false;
00746 #endif
00747
00748
00749 if (statinfo & RX_HD_ADDRMIS)
00750 return;
00751
00752 PROF_PS_CHECK_RX_SET();
00753
00754 #if (NX_UAPSD)
00755 if (ps_env.uapsd_on)
00756 {
00757
00758 if ((framectrl & MAC_FCTRL_QOS_DATA) == MAC_FCTRL_QOS_DATA)
00759 {
00760 uint16_t qos;
00761 uint8_t tid;
00762
00763
00764 if ((framectrl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_TODS_FROMDS)
00765 {
00766 struct mac_hdr_long_qos *hdr = (struct mac_hdr_long_qos *)machdr;
00767 qos = hdr->qos;
00768 }
00769 else
00770 {
00771 struct mac_hdr_qos *hdr = (struct mac_hdr_qos *)machdr;
00772 qos = hdr->qos;
00773 }
00774
00775
00776 tid = (qos & MAC_QOSCTRL_UP_MSK) >> MAC_QOSCTRL_UP_OFT;
00777
00778
00779 if (vif->u.sta.uapsd_queues & CO_BIT(mac_tid2ac[tid]))
00780 {
00781
00782 uapsd_frame = true;
00783
00784
00785 vif->u.sta.uapsd_last_rxtx = ke_time();
00786
00787
00788 if (qos & MAC_QOSCTRL_EOSP)
00789 {
00790
00791 vif->prevent_sleep &= ~PS_VIF_WAITING_EOSP;
00792 TRACE_STA(PS, "{VIF-%d} EOSP received", vif->index);
00793 }
00794 }
00795 }
00796 else if ((framectrl & MAC_FCTRL_TYPE_MASK) == MAC_FCTRL_MGT_T)
00797 {
00798
00799
00800
00801 if (vif->u.sta.uapsd_queues & CO_BIT(AC_VO))
00802 {
00803
00804 uapsd_frame = true;
00805
00806
00807 vif->u.sta.uapsd_last_rxtx = ke_time();
00808 }
00809 }
00810 }
00811
00812
00813
00814
00815 if (!uapsd_frame)
00816 #endif //(NX_UAPSD)
00817 {
00818 #if (NX_DPSM)
00819
00820 td_pck_ps_ind(vif->index, true);
00821 #endif //(NX_DPSM)
00822
00823 TRACE_STA(PS, "{VIF-%d} received PS frame. (more data = %d)",
00824 vif->index, (framectrl & MAC_FCTRL_MOREDATA));
00825
00826 if (framectrl & MAC_FCTRL_MOREDATA)
00827 {
00828 #if (NX_DPSM)
00829 if (!PS_DPSM_STATE_GET(PAUSE))
00830 #endif //(NX_DPSM)
00831 {
00832 if (ps_send_pspoll(vif) != CO_OK)
00833 {
00834
00835 vif->prevent_sleep &= ~PS_VIF_WAITING_UC;
00836 }
00837 }
00838 }
00839 else
00840 {
00841
00842 vif->prevent_sleep &= ~PS_VIF_WAITING_UC;
00843 }
00844 }
00845
00846 PROF_PS_CHECK_RX_CLR();
00847 }
00848 }
00849
00850 #if (NX_UAPSD || NX_DPSM)
00851 bool ps_check_tx_frame(uint8_t staid, uint8_t tid)
00852 {
00853 struct sta_info_tag *sta;
00854 struct vif_info_tag *vif;
00855 bool is_trigger = false;
00856 #if (NX_DPSM)
00857 bool skip_stat = false;
00858 #endif
00859
00860
00861 if (!ps_env.ps_on)
00862 return false;
00863
00864
00865 if (staid == 0xFF)
00866 return false;
00867
00868
00869 if (tid == 0xFF)
00870 return false;
00871
00872
00873 sta = &sta_info_tab[staid];
00874 vif = &vif_info_tab[sta->inst_nbr];
00875
00876
00877 if ((vif->type != VIF_STA) || !vif->active)
00878 return false;
00879
00880 PROF_PS_CHECK_TX_SET();
00881
00882 #if (NX_UAPSD)
00883
00884 if (vif->u.sta.uapsd_queues & CO_BIT(mac_tid2ac[tid]))
00885 {
00886
00887 vif->prevent_sleep |= PS_VIF_WAITING_EOSP;
00888 is_trigger = true;
00889
00890
00891 vif->u.sta.uapsd_last_rxtx = ke_time();
00892
00893 #if NX_DPSM
00894
00895
00896 if ((vif->u.sta.uapsd_queues & PS_ALL_UAPSD_ACS) != PS_ALL_UAPSD_ACS)
00897 skip_stat = true;
00898 #endif
00899 }
00900 #endif //(NX_UAPSD)
00901
00902 #if (NX_DPSM)
00903 if (!skip_stat)
00904
00905 td_pck_ps_ind(vif->index, false);
00906 #endif //(NX_DPSM)
00907
00908 PROF_PS_CHECK_TX_CLR();
00909 return is_trigger;
00910 }
00911 #endif //(NX_UAPSD || NX_DPSM)
00912
00913 #if (NX_UAPSD)
00914 void ps_uapsd_set(struct vif_info_tag *vif, uint8_t hw_queue, bool uapsd)
00915 {
00916 if (uapsd)
00917 {
00918
00919 vif->u.sta.uapsd_queues |= CO_BIT(hw_queue);
00920
00921
00922 if (ps_env.ps_on && !ps_env.uapsd_tmr_on)
00923 {
00924
00925 ps_env.uapsd_on = true;
00926
00927 mm_timer_set(&ps_env.uapsd_timer, ke_time() + ps_env.uapsd_timeout);
00928 ps_env.uapsd_tmr_on = true;
00929 }
00930 }
00931 else
00932 {
00933 vif->u.sta.uapsd_queues &= ~CO_BIT(hw_queue);
00934 }
00935
00936
00937 if (vif->u.sta.uapsd_queues)
00938 {
00939 uint8_t ac2tid[AC_MAX] = {TID_2, TID_0, TID_5, TID_7};
00940 uint8_t ac_highest = 31 - co_clz(vif->u.sta.uapsd_queues);
00941 vif->u.sta.uapsd_tid = ac2tid[ac_highest];
00942 }
00943 }
00944 #endif //(NX_UAPSD)
00945
00946 #if (NX_DPSM)
00947 void ps_traffic_status_update(uint8_t vif_index, uint8_t new_status)
00948 {
00949
00950 struct vif_info_tag *vif;
00951
00952 bool has_traffic = (new_status != 0);
00953
00954 bool is_ps_paused;
00955
00956
00957 if (!ps_env.ps_on || !PS_DPSM_STATE_GET(ON))
00958 return;
00959
00960
00961 if (PS_DPSM_STATE_GET(PAUSING) || PS_DPSM_STATE_GET(RESUMING))
00962 return;
00963
00964 if (!has_traffic)
00965 {
00966
00967 vif = (struct vif_info_tag *)co_list_pick(&vif_mgmt_env.used_list);
00968
00969 while (vif)
00970 {
00971
00972 if (vif->index != vif_index)
00973 {
00974
00975 if (vif->active && (vif->type == VIF_STA))
00976 {
00977 if (td_get_ps_status(vif->index))
00978 {
00979 has_traffic = true;
00980 break;
00981 }
00982 }
00983 }
00984
00985
00986 vif = (struct vif_info_tag *)co_list_next(&vif->list_hdr);
00987 };
00988 }
00989
00990
00991 is_ps_paused = PS_DPSM_STATE_GET(PAUSE);
00992
00993
00994 if (has_traffic)
00995 {
00996
00997 if (!is_ps_paused)
00998 {
00999 ps_dpsm_update(true);
01000 }
01001 }
01002 else
01003 {
01004
01005 if (is_ps_paused)
01006 {
01007 ps_dpsm_update(false);
01008 }
01009 }
01010 }
01011 #endif //(NX_DPSM)
01012
01013 #if (NX_P2P && NX_UAPSD)
01014 void ps_p2p_absence_update(struct vif_info_tag *vif, bool absent)
01015 {
01016 if (!vif->active)
01017 return;
01018
01019 if (vif->type == VIF_STA)
01020 {
01021 if (absent)
01022 {
01023 if (vif->prevent_sleep & PS_VIF_WAITING_EOSP)
01024 {
01025
01026 vif->u.sta.sp_paused = true;
01027 vif->prevent_sleep &= ~PS_VIF_WAITING_EOSP;
01028 }
01029 }
01030 else
01031 {
01032
01033
01034 if (vif->u.sta.sp_paused)
01035 {
01036
01037 vif->u.sta.sp_paused = false;
01038 if (txl_frame_send_qosnull_frame(vif->u.sta.ap_id,
01039 vif->u.sta.uapsd_tid << MAC_QOSCTRL_UP_OFT,
01040 NULL, NULL) == CO_OK)
01041 {
01042 vif->prevent_sleep |= PS_VIF_WAITING_EOSP;
01043 vif->u.sta.uapsd_last_rxtx = ke_time();
01044 }
01045 }
01046 }
01047 }
01048 #if NX_UMAC_PRESENT && NX_P2P_GO
01049 else if ((vif->type == VIF_AP) && absent)
01050 {
01051
01052 struct sta_info_tag *sta = (struct sta_info_tag *)co_list_pick(&vif->sta_list);
01053
01054 while (sta != NULL)
01055 {
01056 if (sta->ps_service_period & UAPSD_SERVICE_PERIOD)
01057 {
01058 if (sta->ps_service_period & UAPSD_SERVICE_PERIOD_HOST)
01059 mm_traffic_req_ind(sta->staid, PS_SP_INTERRUPTED, true);
01060 sta->ps_service_period = NO_SERVICE_PERIOD;
01061 }
01062 sta = (struct sta_info_tag *)sta->list_hdr.next;
01063 }
01064 }
01065 #endif // NX_P2P_GO
01066 }
01067 #endif //(NX_P2P && NX_UAPSD)
01068
01069 #if (NX_UAPSD && NX_UMAC_PRESENT)
01070 void ps_check_tx_trigger_sent(struct hostdesc *hostdesc, uint32_t tx_status)
01071 {
01072 struct vif_info_tag *vif;
01073
01074 if (!(hostdesc->flags & TXU_CNTRL_UASPD_TRIGGER) ||
01075 !(tx_status & FRAME_SUCCESSFUL_TX_BIT))
01076 return;
01077
01078 vif = &vif_info_tab[hostdesc->vif_idx];
01079 vif->prevent_sleep |= PS_VIF_WAITING_EOSP;
01080 }
01081
01082 #endif //(NX_UAPSD && NX_UMAC_PRESENT)
01083
01084 #endif
01085