- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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

Go to the documentation of this file.

    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  * FUNCTION IMPLEMENTATIONS
    00033  ****************************************************************************************
    00034  */
    00035
    00041 static void apm_bss_config_init(void)
    00042 {
    00043     // Sanity check - No BSS config should be ongoing
    00044     ASSERT_ERR(co_list_is_empty(&apm_env.bss_config));
    00045
    00046     // Initialize the BSS configuration list
    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     // Reset the environment
    00067     memset(&apm_env, 0, sizeof(apm_env));
    00068     apm_env.aging_sta_idx = 0;
    00069
    00070     // Set state as Idle
    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     // Check if the status is OK
    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         // Fill the message parameters
    00088         req->active = true;
    00089         req->inst_nbr = vif->index;
    00090
    00091         // Send the message to the task
    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         // Copy the rate set to the station entry
    00101         sta->info.rate_set = param->basic_rates;
    00102         // Open the control port for this station
    00103         sta->ctrl_port_state = PORT_OPEN;
    00104
    00105         // Initialize the policy table
    00106         me_init_bcmc_rate(sta);
    00107
    00108         // Initialize tx power on first transmit
    00109         sta->pol_tbl.upd_field |= CO_BIT(STA_MGMT_POL_UPD_TX_POWER);
    00110
    00111         // Initialize MAC address with muticast bit set
    00112         sta->mac_addr.array[0] = 0x1;
    00113         sta->staid = VIF_TO_BCMC_IDX(param->vif_idx);
    00114     }
    00115
    00116     // Fill-in the message parameters
    00117     cfm->status = status;
    00118     cfm->vif_idx = param->vif_idx;
    00119
    00120     // Send the message
    00121     ke_msg_send(cfm);
    00122
    00123     // Free the parameters
    00124     ke_msg_free(ke_param2msg(param));
    00125     apm_env.param = NULL;
    00126
    00127     // We are now waiting for the channel addition confirmation
    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     // Initialize the BSS configuration list
    00148     apm_bss_config_init();
    00149
    00150     // Disable PS mode when an AP is started
    00151     #if (NX_P2P_GO)
    00152     if ( vif->p2p )
    00153     {
    00154         // P2P GO interface may enter sleep mode once NOA and/or Opportunistic PS
    00155         // are enabled but not until then.
    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     // BSSID
    00170     bssid->bssid = vif->mac_addr;
    00171     bssid->inst_nbr = param->vif_idx;
    00172     apm_bss_config_push(bssid);
    00173
    00174     // Basic rates
    00175     brates->band = param->chan.band;
    00176     brates->rates = me_legacy_rate_bitfield_build(&param->basic_rates, true);
    00177     brates->inst_nbr = param->vif_idx;
    00178     apm_bss_config_push(brates);
    00179
    00180     // Beacon interval
    00181     bint->beacon_int = param->bcn_int;
    00182     bint->inst_nbr = param->vif_idx;
    00183     apm_bss_config_push(bint);
    00184
    00185     // Go back to ACTIVE after setting the BSS parameters
    00186     active->active = true;
    00187     active->vif_idx = param->vif_idx;
    00188     apm_bss_config_push(active);
    00189
    00190     // Send the first BSS configuration message
    00191     apm_bss_config_send();
    00192
    00193     // We are now waiting for the channel addition confirmation
    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     // Sanity check - We shall have a message available
    00202     ASSERT_ERR(msg != NULL);
    00203
    00204     // Send the message
    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     // Fill-in the parameters
    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     // Send the beacon information to the LMAC
    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     // Initialize the BSS configuration list
    00234     apm_bss_config_init();
    00235
    00236     // Re-allow PS mode in case it was disallowed
    00237     ps->ps_disable = false;
    00238     ps->vif_idx = vif->index;
    00239     apm_bss_config_push(ps);
    00240
    00241     // VIF state
    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     // Unlink the VIF from the channel context
    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     // Send the first BSS configuration message
    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     /* Don't push frame to connected STA in PS */
    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         /* For now all possible internally generated frame are bufferable */
    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     /* Check that there is still requested traffic in queue */
    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     /* Get first txdesc that match the service period (i.e. legacy or uapsd) */
    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         /* To avoid disorder with EOSP, alwasy sent in AC_VO */
    00388         /* In practice most of internally generated frames are already on AC_VO */
    00389         txdesc->host.tid = AC_VO;
    00390     }
    00391
    00392     /* Check if more txdesc is present for the same kind of service period */
    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     /* If no more internal traffic, check host status */
    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     /* push all postponed frame */
    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         /* If there is still HOST traffic wait for host to update TIM */
    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 /* NX_BEACONING */
    00464