00001
00013 #include "apm.h"
00014 #include "apm_task.h"
00015 #include "mac_frame.h"
00016 #include "vif_mgmt.h"
00017 #include "me_utils.h"
00018 #include "me_task.h"
00019 #include "ps.h"
00020 #include "txu_cntrl.h"
00021
00022 #if NX_BEACONING
00023
00028
00029 struct apm apm_env;
00030
00031
00032
00033
00034
00035
00041 static void apm_bss_config_init(void)
00042 {
00043
00044 ASSERT_ERR(co_list_is_empty(&apm_env.bss_config));
00045
00046
00047 co_list_init(&apm_env.bss_config);
00048 }
00049
00057 static void apm_bss_config_push(void *param)
00058 {
00059 struct ke_msg *msg = ke_param2msg(param);
00060
00061 co_list_push_back(&apm_env.bss_config, &msg->hdr);
00062 }
00063
00064 void apm_init(void)
00065 {
00066
00067 memset(&apm_env, 0, sizeof(apm_env));
00068 apm_env.aging_sta_idx = 0;
00069
00070
00071 ke_state_set(TASK_APM, APM_IDLE);
00072 }
00073
00074 void apm_start_cfm(uint8_t status)
00075 {
00076 struct apm_start_req const *param = apm_env.param;
00077 struct apm_start_cfm *cfm = KE_MSG_ALLOC(APM_START_CFM, TASK_API, TASK_APM, apm_start_cfm);
00078
00079
00080 if (status == CO_OK)
00081 {
00082 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00083 struct sta_info_tag *sta = &sta_info_tab[VIF_TO_BCMC_IDX(param->vif_idx)];
00084 struct mm_set_vif_state_req *req = KE_MSG_ALLOC(MM_SET_VIF_STATE_REQ, TASK_MM,
00085 TASK_APM, mm_set_vif_state_req);
00086
00087
00088 req->active = true;
00089 req->inst_nbr = vif->index;
00090
00091
00092 ke_msg_send(req);
00093
00094 vif->flags = param->flags;
00095 vif->u.ap.ctrl_port_ethertype = param->ctrl_port_ethertype;
00096 vif->u.ap.ps_sta_cnt = 0;
00097 cfm->ch_idx = vif->chan_ctxt->idx;
00098 cfm->bcmc_idx = VIF_TO_BCMC_IDX(param->vif_idx);
00099
00100
00101 sta->info.rate_set = param->basic_rates;
00102
00103 sta->ctrl_port_state = PORT_OPEN;
00104
00105
00106 me_init_bcmc_rate(sta);
00107
00108
00109 sta->pol_tbl.upd_field |= CO_BIT(STA_MGMT_POL_UPD_TX_POWER);
00110
00111
00112 sta->mac_addr.array[0] = 0x1;
00113 sta->staid = VIF_TO_BCMC_IDX(param->vif_idx);
00114 }
00115
00116
00117 cfm->status = status;
00118 cfm->vif_idx = param->vif_idx;
00119
00120
00121 ke_msg_send(cfm);
00122
00123
00124 ke_msg_free(ke_param2msg(param));
00125 apm_env.param = NULL;
00126
00127
00128 ke_state_set(TASK_APM, APM_IDLE);
00129 }
00130
00131
00132 void apm_set_bss_param(void)
00133 {
00134 struct apm_start_req const *param = apm_env.param;
00135 struct vif_info_tag *vif = &vif_info_tab[param->vif_idx];
00136 struct me_set_ps_disable_req *ps = KE_MSG_ALLOC(ME_SET_PS_DISABLE_REQ, TASK_ME, TASK_APM,
00137 me_set_ps_disable_req);
00138 struct mm_set_bssid_req *bssid = KE_MSG_ALLOC(MM_SET_BSSID_REQ, TASK_MM, TASK_APM,
00139 mm_set_bssid_req);
00140 struct mm_set_basic_rates_req *brates = KE_MSG_ALLOC(MM_SET_BASIC_RATES_REQ, TASK_MM,
00141 TASK_APM, mm_set_basic_rates_req);
00142 struct mm_set_beacon_int_req *bint = KE_MSG_ALLOC(MM_SET_BEACON_INT_REQ, TASK_MM,
00143 TASK_APM, mm_set_beacon_int_req);
00144 struct me_set_active_req *active = KE_MSG_ALLOC(ME_SET_ACTIVE_REQ, TASK_ME,
00145 TASK_APM, me_set_active_req);
00146
00147
00148 apm_bss_config_init();
00149
00150
00151 #if (NX_P2P_GO)
00152 if ( vif->p2p )
00153 {
00154
00155
00156 nxmac_pwr_mgt_setf(0);
00157 #if NX_POWERSAVE
00158 vif->prevent_sleep |= PS_VIF_P2P_GO_PRESENT;
00159 #endif
00160 }
00161 else
00162 #endif //(NX_P2P_GO)
00163 {
00164 ps->ps_disable = true;
00165 ps->vif_idx = vif->index;
00166 apm_bss_config_push(ps);
00167 }
00168
00169
00170 bssid->bssid = vif->mac_addr;
00171 bssid->inst_nbr = param->vif_idx;
00172 apm_bss_config_push(bssid);
00173
00174
00175 brates->band = param->chan.band;
00176 brates->rates = me_legacy_rate_bitfield_build(¶m->basic_rates, true);
00177 brates->inst_nbr = param->vif_idx;
00178 apm_bss_config_push(brates);
00179
00180
00181 bint->beacon_int = param->bcn_int;
00182 bint->inst_nbr = param->vif_idx;
00183 apm_bss_config_push(bint);
00184
00185
00186 active->active = true;
00187 active->vif_idx = param->vif_idx;
00188 apm_bss_config_push(active);
00189
00190
00191 apm_bss_config_send();
00192
00193
00194 ke_state_set(TASK_APM, APM_BSS_PARAM_SETTING);
00195 }
00196
00197 void apm_bss_config_send(void)
00198 {
00199 struct ke_msg *msg = (struct ke_msg *)co_list_pop_front(&apm_env.bss_config);
00200
00201
00202 ASSERT_ERR(msg != NULL);
00203
00204
00205 ke_msg_send(ke_msg2param(msg));
00206 }
00207
00208 void apm_bcn_set(void)
00209 {
00210 struct apm_start_req const *param = apm_env.param;
00211 struct mm_bcn_change_req *bcn = KE_MSG_ALLOC(MM_BCN_CHANGE_REQ, TASK_MM,
00212 TASK_APM, mm_bcn_change_req);
00213
00214 bcn->bcn_ptr = param->bcn_addr;
00215 bcn->bcn_len = param->bcn_len;
00216 bcn->tim_oft = param->tim_oft;
00217 bcn->tim_len = param->tim_len;
00218 bcn->inst_nbr = param->vif_idx;
00219
00220
00221 ke_msg_send(bcn);
00222
00223 ke_state_set(TASK_APM, APM_BCN_SETTING);
00224 }
00225
00226 void apm_stop(struct vif_info_tag *vif)
00227 {
00228 struct me_set_ps_disable_req *ps = KE_MSG_ALLOC(ME_SET_PS_DISABLE_REQ, TASK_ME, TASK_APM,
00229 me_set_ps_disable_req);
00230 struct me_set_active_req *idle = KE_MSG_ALLOC(ME_SET_ACTIVE_REQ, TASK_ME,
00231 TASK_APM, me_set_active_req);
00232
00233
00234 apm_bss_config_init();
00235
00236
00237 ps->ps_disable = false;
00238 ps->vif_idx = vif->index;
00239 apm_bss_config_push(ps);
00240
00241
00242 if (vif->active)
00243 {
00244 struct mm_set_vif_state_req *state = KE_MSG_ALLOC(MM_SET_VIF_STATE_REQ, TASK_MM,
00245 TASK_APM, mm_set_vif_state_req);
00246 state->active = false;
00247 state->inst_nbr = vif->index;
00248 apm_bss_config_push(state);
00249 }
00250
00251
00252 if (vif->chan_ctxt != NULL)
00253 {
00254 struct mm_chan_ctxt_unlink_req *unlk = KE_MSG_ALLOC(MM_CHAN_CTXT_UNLINK_REQ,TASK_MM,
00255 TASK_APM, mm_chan_ctxt_unlink_req);
00256 unlk->vif_index = vif->index;
00257 apm_bss_config_push(unlk);
00258 }
00259
00260 idle->active = false;
00261 idle->vif_idx = vif->index;
00262 apm_bss_config_push(idle);
00263
00264
00265 apm_bss_config_send();
00266
00267 ke_state_set(TASK_APM, APM_STOPPING);
00268 }
00269
00270 bool apm_tx_int_ps_check(struct txdesc *txdesc)
00271 {
00272 struct vif_info_tag *vif = &vif_info_tab[txdesc->host.vif_idx];
00273
00274
00275 if ((vif->type == VIF_AP) &&
00276 (txdesc->host.staid < STA_MAX) &&
00277 ((sta_info_tab[txdesc->host.staid].ps_state == PS_MODE_ON) &&
00278 !(sta_info_tab[txdesc->host.staid].ps_service_period & ANY_SERVICE_PERIOD_INT)))
00279 {
00280
00281 txdesc->host.flags |= TXU_CNTRL_POSTPONE_PS;
00282 return false;
00283 }
00284
00285 return true;
00286 }
00287
00288 void apm_tx_int_ps_postpone(struct txdesc *txdesc, struct sta_info_tag *sta)
00289 {
00290 if (txdesc->host.flags & TXU_CNTRL_POSTPONE_PS)
00291 {
00292 bool new_traffic = true;
00293
00294 if (sta->info.uapsd_queues & mac_ac2uapsd[txdesc->host.tid])
00295 {
00296 if (sta->traffic_avail & UAPSD_TRAFFIC_INT)
00297 new_traffic = false;
00298 else
00299 sta->traffic_avail |= UAPSD_TRAFFIC_INT;
00300 }
00301 else
00302 {
00303 if (sta->traffic_avail & PS_TRAFFIC_INT)
00304 new_traffic = false;
00305 else
00306 sta->traffic_avail |= PS_TRAFFIC_INT;
00307 }
00308
00309 if (new_traffic &&
00310 (!(sta->info.uapsd_queues & mac_ac2uapsd[txdesc->host.tid]) ||
00311 (sta->info.uapsd_queues == MAC_QOS_INFO_STA_UAPSD_ENABLED_ALL)))
00312 {
00313 struct mm_tim_update_req *tim = KE_MSG_ALLOC(MM_TIM_UPDATE_REQ, TASK_MM,
00314 TASK_ME, mm_tim_update_req);
00315
00316 tim->aid = sta->aid;
00317 tim->inst_nbr = sta->inst_nbr;
00318 tim->tx_avail = true;
00319
00320 ke_msg_send(tim);
00321 }
00322 }
00323 }
00324
00325 struct txdesc *apm_tx_int_ps_get_postpone(struct vif_info_tag *vif,
00326 struct sta_info_tag *sta,
00327 int *stop)
00328 {
00329 struct txdesc *txdesc, *txdesc_prev = NULL;
00330 enum sta_ps_traffic traffic_int, traffic_host;
00331 bool more = false;
00332
00333 if ((vif->type != VIF_AP) ||
00334 (sta->ps_service_period == NO_SERVICE_PERIOD))
00335 {
00336 *stop = 0;
00337 return NULL;
00338 }
00339
00340
00341 if (sta->ps_service_period & PS_SERVICE_PERIOD)
00342 {
00343 traffic_int = PS_TRAFFIC_INT;
00344 traffic_host = PS_TRAFFIC_HOST;
00345 }
00346 else
00347 {
00348 traffic_int = UAPSD_TRAFFIC_INT;
00349 traffic_host = UAPSD_TRAFFIC_HOST;
00350 }
00351
00352 if (!(sta->traffic_avail & traffic_int))
00353 {
00354 *stop = 1;
00355 return NULL;
00356 }
00357
00358
00359 txdesc = (struct txdesc *)co_list_pick(&sta->tx_desc_post);
00360 while (txdesc)
00361 {
00362 if (!!(sta->info.uapsd_queues & mac_ac2uapsd[txdesc->host.tid]) ==
00363 (sta->ps_service_period == UAPSD_SERVICE_PERIOD_INT))
00364 {
00365 break;
00366 }
00367
00368 txdesc_prev = txdesc;
00369 txdesc = tx_desc_next(txdesc);
00370 }
00371
00372 if (!txdesc)
00373 {
00374 ASSERT_WARN(0);
00375 *stop = 1;
00376 return NULL;
00377 }
00378
00379 co_list_remove(&sta->tx_desc_post, &txdesc_prev->list_hdr, &txdesc->list_hdr);
00380
00381 if (sta->ps_service_period & BCN_SERVICE_PERIOD)
00382 {
00383 txdesc->host.tid = AC_BCN;
00384 }
00385 else
00386 {
00387
00388
00389 txdesc->host.tid = AC_VO;
00390 }
00391
00392
00393 if (txdesc_prev)
00394 txdesc_prev = tx_desc_next(txdesc_prev);
00395 else
00396 txdesc_prev = (struct txdesc *)co_list_pick(&sta->tx_desc_post);
00397 while (txdesc_prev)
00398 {
00399 if (!!(sta->info.uapsd_queues & mac_ac2uapsd[txdesc_prev->host.tid]) ==
00400 (sta->ps_service_period == UAPSD_SERVICE_PERIOD_INT))
00401 {
00402 more = true;
00403 break;
00404 }
00405
00406 txdesc_prev = tx_desc_next(txdesc_prev);
00407 }
00408
00409
00410 if (!more)
00411 {
00412 sta->traffic_avail &= ~traffic_int;
00413 more = (sta->traffic_avail & traffic_host);
00414 }
00415
00416 if (more)
00417 {
00418 struct mac_hdr *mac_hdr = txl_buffer_payload_get(txdesc);
00419 mac_hdr->fctl |= MAC_FCTRL_MOREDATA;
00420 }
00421 else
00422 {
00423 struct mm_tim_update_req *tim = KE_MSG_ALLOC(MM_TIM_UPDATE_REQ, TASK_MM,
00424 TASK_ME, mm_tim_update_req);
00425 tim->aid = sta->aid;
00426 tim->inst_nbr = sta->inst_nbr;
00427 tim->tx_avail = false;
00428 ke_msg_send(tim);
00429 }
00430
00431 return txdesc;
00432 }
00433
00434 void apm_tx_int_ps_clear(struct vif_info_tag *vif, uint8_t sta_idx)
00435 {
00436 struct sta_info_tag *sta = &sta_info_tab[sta_idx];
00437
00438 if (vif->type != VIF_AP)
00439 return;
00440
00441
00442 sta_mgmt_send_postponed_frame(vif, sta, 0);
00443
00444 if (sta->traffic_avail & (UAPSD_TRAFFIC_INT | PS_TRAFFIC_INT))
00445 {
00446 sta->traffic_avail &= ~(UAPSD_TRAFFIC_INT | PS_TRAFFIC_INT);
00447
00448
00449 if (!sta->traffic_avail)
00450 {
00451 struct mm_tim_update_req *tim = KE_MSG_ALLOC(MM_TIM_UPDATE_REQ, TASK_MM,
00452 TASK_ME, mm_tim_update_req);
00453 tim->aid = sta->aid;
00454 tim->inst_nbr = sta->inst_nbr;
00455 tim->tx_avail = false;
00456 ke_msg_send(tim);
00457 }
00458 }
00459 }
00460
00462
00463 #endif
00464