Exemplo n.º 1
0
static bool ieee80211_assoc_state_run_event(void *ctx, u_int16_t event, u_int16_t event_data_len, void *event_data) 
{
    wlan_assoc_sm_t sm = (wlan_assoc_sm_t) ctx;
    wlan_if_t vap = sm->vap_handle;
    u_int32_t time_elapsed;

    switch(event) {
    case IEEE80211_ASSOC_EVENT_BEACON_MISS:
        sm->last_failure = WLAN_ASSOC_SM_REASON_BEACON_MISS;    /* beacon miss */ 
        ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); 
        return true;
        break;
    case IEEE80211_ASSOC_EVENT_DISASSOC:
        time_elapsed = CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP() - sm->last_connected_time);
        if ((sm->last_reason == IEEE80211_REASON_AUTH_EXPIRE || sm->last_reason == IEEE80211_REASON_ASSOC_EXPIRE) &&
            (vap->auto_assoc)) {
            ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DISASSOC);
            ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_JOIN); 
#if ATH_SUPPORT_WPA_SUPPLICANT_CHECK_TIME
        } else if(sm->cur_rejoin_attempts < vap->iv_rejoint_attemp_time ) {
            sm->cur_rejoin_attempts++;
            ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DISASSOC);
            ieee80211_sm_transition_to(sm->hsm_handle, IEEE80211_ASSOC_STATE_JOIN); 
        } else {
#else
        } else if(sm->cur_rejoin_attempts < REJOIN_ATTEMP_TIME && time_elapsed < REJOIN_CHECKING_TIME) {
            sm->cur_rejoin_attempts++;
            ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DISASSOC);
            ieee80211_sm_transition_to(sm->hsm_handle, IEEE80211_ASSOC_STATE_JOIN); 
        } else {
#endif 
            ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); 
        }
        return true;
        break;

    case IEEE80211_ASSOC_EVENT_DEAUTH:
        time_elapsed = CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP() - sm->last_connected_time);
        if ((sm->last_reason == IEEE80211_REASON_AUTH_EXPIRE || sm->last_reason == IEEE80211_REASON_ASSOC_EXPIRE) &&
            (vap->auto_assoc)) {
            ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DEAUTH);
           ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_JOIN); 
#if ATH_SUPPORT_WPA_SUPPLICANT_CHECK_TIME
        } else if(sm->cur_rejoin_attempts < vap->iv_rejoint_attemp_time ) {
            sm->cur_rejoin_attempts++;
            ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DEAUTH);
            ieee80211_sm_transition_to(sm->hsm_handle, IEEE80211_ASSOC_STATE_JOIN);
        } else {
#else
        } else if(sm->cur_rejoin_attempts < REJOIN_ATTEMP_TIME && time_elapsed < REJOIN_CHECKING_TIME) {
Exemplo n.º 2
0
/**
 * @brief noise histogrm response 
 *
 * @param rrm
 * @param ie
 *
 * @return 
 */
u_int8_t *ieee80211_rrm_send_nhist_resp(ieee80211_rrm_t rrm,u_int8_t *ie)
{
    struct ieee80211_nhistrsp *rsp=NULL;
    struct ieee80211_measrsp_ie *measrsp=NULL;
    struct ieee80211_rrmreq_info *params=NULL;
    unsigned long tsf;
#if UMAC_SUPPORT_RRM_DEBUG 
    wlan_if_t vap = rrm->rrm_vap;
#endif        

    RRM_FUNCTION_ENTER;

    params = (struct ieee80211_rrmreq_info *)(rrm->rrmcb);
    measrsp = (struct ieee80211_measrsp_ie *)ie;
    measrsp->id = IEEE80211_ELEMID_MEASREP;
    measrsp->token=params->rep_dialogtoken;
    measrsp->rspmode = 0x00; /* Need to validate */
    measrsp->rsptype = IEEE80211_MEASRSP_NOISE_HISTOGRAM_REPORT;
    rsp = (struct ieee80211_nhistrsp *)(&measrsp->rsp[0]);
    rsp->mduration = params->duration;
    rsp->regclass = params->regclass;
    rsp->chnum = params->chnum;
    rsp->anpi = (u_int8_t)rrm->rrm_noisefloor[rsp->chnum];
    OS_GET_RANDOM_BYTES(&rsp->antid,sizeof(rsp->antid));
    OS_GET_RANDOM_BYTES(rsp->ipi,sizeof(rsp->ipi));
    tsf = OS_GET_TIMESTAMP();
    OS_MEMCPY(rsp->tsf,&tsf,4);
    ie = &rsp->rsp[0];
    measrsp->len = (ie - &measrsp->token);

    RRM_FUNCTION_EXIT;
    return ie;
}
Exemplo n.º 3
0
void ieee80211_inact_timeout_sta(struct ieee80211vap *vap)
{

    struct ieee80211_mlme_priv    *mlme_priv = vap->iv_mlme_priv;

    if (!mlme_priv->im_connection_up) {
        return;
    }
    /*
     * if there was an activity in the last IEEE80211_INACT_WAIT period.
     * then reset the counter.
     */
    if (CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP() - vap->iv_last_directed_frame) < (IEEE80211_INACT_WAIT * 1000)) {
        vap->iv_inact_count = (vap->iv_keep_alive_timeout + IEEE80211_INACT_WAIT -1)/IEEE80211_INACT_WAIT;
    }
    if (vap->iv_inact_count) {
        --vap->iv_inact_count;
        if (vap->iv_inact_count == 0) {
            if (ieee80211_sta_power_send_keepalive(vap->iv_pwrsave_sta) == ENXIO) {
                ieee80211_send_nulldata(vap->iv_bss,false); 
            }
            if (vap->iv_keep_alive_timeout) {
                vap->iv_inact_count =  (vap->iv_keep_alive_timeout + IEEE80211_INACT_WAIT -1)/IEEE80211_INACT_WAIT;
            }
        }
    }
} 
Exemplo n.º 4
0
void ieee80211_prdperfstat_thrput_update_hist(struct ieee80211com *ic)
{
    struct ieee80211_prdperfstat_thrput *thrput = &ic->ic_thrput;

    if (thrput->is_histogram_full) {
        thrput->histogram_bytecount -=
            thrput->histogram[thrput->histogram_tail]; 
        
        /* We do not use modulo since it is expensive */
        if (thrput->histogram_tail == (thrput->histogram_size - 1))
        {    
            thrput->histogram_tail = 0;
        } else {
            thrput->histogram_tail++;
        }
    }

    thrput->histogram_bytecount += thrput->curr_bytecount;
    thrput->histogram[thrput->histogram_head] = thrput->curr_bytecount; 
    thrput->curr_bytecount = 0;
     
    thrput->last_save_ms  = OS_GET_TIMESTAMP();

    /* Slide ahead */
    if (thrput->histogram_head == (thrput->histogram_size - 1)) {
        thrput->is_histogram_full = 1;
        thrput->histogram_head = 0;
    } else {
        thrput->histogram_head++;
    }
}
Exemplo n.º 5
0
/* Return throughput in kbps */
u_int32_t ieee80211_prdperfstat_thrput_get(struct ieee80211com *ic)
{
    struct ieee80211_prdperfstat_thrput *thrput = &ic->ic_thrput;
    u_int32_t total_bytes          = 0;
    u_int32_t elapsed_time_ms      = 0;
    u_int32_t thrput_kbps          = 0;
    int num_histogram_entries      = 0;

    if (!thrput->is_started) {
        return 0;
    }
    
    if (unlikely(!thrput->is_histogram_full)) {
        num_histogram_entries =
            thrput->histogram_head - thrput->histogram_tail;
    } else {
        num_histogram_entries = thrput->histogram_size;
    } 
    
    total_bytes = (thrput->histogram_bytecount + thrput->curr_bytecount);

    elapsed_time_ms = (num_histogram_entries * PRDPERFSTAT_THRPUT_INTERVAL_MS) +
                      (OS_GET_TIMESTAMP() - thrput->last_save_ms);

    thrput_kbps = (total_bytes * 8)/ elapsed_time_ms;

    return thrput_kbps;
}
Exemplo n.º 6
0
/**
 * @brief 
 *
 * @param vap
 * @param mode
 *
 * @return 
 * @return on success return 0.
 *         on failure returns -ve value.
 */
int ieee80211_rrm_scan(wlan_if_t vap, u_int8_t mode)
{
    int retval = 0;

    RRM_FUNCTION_ENTER;

    if ((mode == 0) || (mode == 1))
    {
        /* Active mode */
        wlan_scan_table_flush(vap);
        retval = ieee80211_rrm_scan_start(vap, (mode == 1)?true:false);
        if ((retval != 0) && vap->rrm->pending_report)
        {
            ieee80211_rrm_free_report(vap->rrm);
            return -EBUSY;
        }
        else
        {
             vap->rrm->rrm_last_scan = OS_GET_TIMESTAMP();
        }
    }
    else
    {
        /* Send last Beacon Table as report */
        if(vap->rrm->pending_report)
        {
            ieee80211_send_report(vap->rrm);
            return EOK;
        }
    }

    RRM_FUNCTION_EXIT;

    return EOK;
}
Exemplo n.º 7
0
static void
pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg)
{
    struct ath_pktlog_buf *log_buf;
    int32_t buf_size;
    struct ath_pktlog_hdr *log_hdr;
    int32_t cur_wr_offset;
    char *log_ptr;
    struct ath_pktlog_info *pl_info = plarg->pl_info;
    u_int16_t log_type = plarg->log_type;
    size_t log_size = plarg->log_size;
    u_int32_t flags = plarg->flags;

    log_buf = pl_info->buf;
    buf_size = pl_info->buf_size;

    cur_wr_offset = log_buf->wr_offset;
    /* Move read offset to the next entry if there is a buffer overlap */
    if (log_buf->rd_offset >= 0) {
        if ((cur_wr_offset <= log_buf->rd_offset)
            && (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) >
            log_buf->rd_offset)
            PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size);
    } else {
        log_buf->rd_offset = cur_wr_offset;
    }

    log_hdr =
        (struct ath_pktlog_hdr *) (log_buf->log_data + cur_wr_offset);
    log_hdr->log_type = log_type;
    log_hdr->flags = flags;
    log_hdr->timestamp = (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP());
    log_hdr->size = (u_int16_t)log_size;

    cur_wr_offset += sizeof(*log_hdr);

    if ((buf_size - cur_wr_offset) < log_size) {
        while ((cur_wr_offset <= log_buf->rd_offset)
               && (log_buf->rd_offset < buf_size))
            PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size);
        cur_wr_offset = 0;
    }

    while ((cur_wr_offset <= log_buf->rd_offset)
           && (cur_wr_offset + log_size) > log_buf->rd_offset)
        PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size);

    log_ptr = &(log_buf->log_data[cur_wr_offset]);

    cur_wr_offset += log_hdr->size;

    log_buf->wr_offset =
        ((buf_size - cur_wr_offset) >=
         sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset : 0;

    plarg->buf = log_ptr;
}
Exemplo n.º 8
0
/*
 * set vap pause in progress flag .
 */
static inline void 
ath_vap_pause_set_in_progress(struct ath_softc *sc)
{
    int iter_count=0;
    systime_t           start_timestamp  = OS_GET_TIMESTAMP(); 
    systime_t           cur_timestamp ; 
    
    while(atomic_read(&sc->sc_txq_use_cnt)) {
        OS_DELAY(10);                            
        ++ iter_count;                           
        if ((iter_count % 1000) == 0) {          
            cur_timestamp  = OS_GET_TIMESTAMP();    
            if (CONVERT_SYSTEM_TIME_TO_MS(cur_timestamp - start_timestamp) >= VAP_PAUSE_SYNCHRONIZATION_TIMEOUT) { 
                ASSERT(0);                         
            }                                      
        }                                        
    }
    atomic_set(&sc->sc_vap_pause_in_progress, 1);
}
Exemplo n.º 9
0
/**
 * @brief 
 *
 * @param vap
 * @param ni
 * @param req
 * @param rm_token
 *
 * @return 
 * @return on success return 0.
 *         on failure returns -ve value.
 */
int ieee80211_rrm_recv_beacon_req(wlan_if_t vap, wlan_node_t ni, 
                struct ieee80211_measreq_ie *req,u_int8_t rm_token)
{
    struct ieee80211_rrmreq_info *params=NULL;
    struct ieee80211_beaconreq *bcnreq=NULL;

    RRM_FUNCTION_ENTER;


    bcnreq = (struct ieee80211_beaconreq *)(&(req->req[0]));
    params = (struct ieee80211_rrmreq_info *)
           OS_MALLOC(vap->rrm->rrm_osdev, sizeof(struct ieee80211_rrmreq_info), 0);

    if(NULL == params)
        return -EBUSY;
    params->rm_dialogtoken = rm_token;
    params->rep_dialogtoken= req->token;
    params->duration=bcnreq->duration;
    params->chnum = bcnreq->channum;
 
    RRM_DEBUG(vap, RRM_DEBUG_INFO, 
              "%s : duration %d chnum %d regclass %d\n", __func__,  
               params->duration, params->chnum, params->regclass);

    IEEE80211_ADDR_COPY(params->bssid,bcnreq->bssid);
    ieee80211_rrm_set_report_pending(vap,IEEE80211_MEASREQ_BR_TYPE,(void *)params);

    if(vap->rrm->rrm_last_scan == 0)
    {
        ieee80211_rrm_scan(vap, bcnreq->mode);
        return EOK;
    }
    else 
    {
        u_int32_t last_scan_time=0,msec_current_time = 0;
        last_scan_time = (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(vap->rrm->rrm_last_scan);
        msec_current_time = (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(OS_GET_TIMESTAMP());
        msec_current_time -= last_scan_time;
    
        if(msec_current_time <  60*1000)
        {
            if(vap->rrm->pending_report)
                ieee80211_send_report(vap->rrm);
        }
        else
        {
            ieee80211_rrm_scan(vap, bcnreq->mode);
        }
    }

    RRM_FUNCTION_EXIT;
    return EOK;
}
Exemplo n.º 10
0
/*
 * set vap pause in progress flag .
 */
static inline void 
ath_vap_pause_set_in_progress(struct ath_softc *sc)
{
    int iter_count=0;
    systime_t           start_timestamp  = OS_GET_TIMESTAMP(); 
    systime_t           cur_timestamp ; 
    spin_lock(&(sc)->sc_vap_pause_lock);
    while(sc->sc_txq_use_cnt) {
        spin_unlock(&(sc)->sc_vap_pause_lock);
        OS_DELAY(10);                            
        ++ iter_count;                           
        if ((iter_count % 1000) == 0) {          
            cur_timestamp  = OS_GET_TIMESTAMP();    
            if (CONVERT_SYSTEM_TIME_TO_MS(cur_timestamp - start_timestamp) >= VAP_PAUSE_SYNCHRONIZATION_TIMEOUT) { 
                ASSERT(0);                         
            }                                      
        }                                        
        spin_lock(&(sc)->sc_vap_pause_lock);
    }
    sc->sc_vap_pause_in_progress=1;
    spin_unlock(&(sc)->sc_vap_pause_lock);
}
Exemplo n.º 11
0
static void ol_ath_node_collect_stats(struct ieee80211_node *ni)
{
	u_int32_t old_phyerr, new_phyerr;
	u_int32_t old_ostime, new_ostime;
	u_int32_t phyerr_rate;
	u_int32_t msdu_size, max_msdu_size;
    old_phyerr = ni->ni_vap->iv_ald->ald_phyerr;
    old_ostime = ni->ni_vap->iv_ald->ald_ostime;
    new_phyerr = (OL_ATH_NODE_NET80211(ni))->an_phy_err_cnt;
    new_ostime = CONVERT_SYSTEM_TIME_TO_SEC(OS_GET_TIMESTAMP());

    if((new_ostime > old_ostime) && (old_ostime > 0))
	    phyerr_rate = (new_phyerr - old_phyerr)/(new_ostime - old_ostime);
    else
        phyerr_rate = 0;
    ni->ni_vap->iv_ald->ald_phyerr = new_phyerr;
    ni->ni_vap->iv_ald->ald_ostime = new_ostime;

	ni->ni_ald.ald_capacity = (OL_ATH_NODE_NET80211(ni))->an_tx_cnt ?
					((OL_ATH_NODE_NET80211(ni))->an_tx_rates_used/ (OL_ATH_NODE_NET80211(ni))->an_tx_cnt) : 0;

	if(ni->ni_ald.ald_capacity == 0)
		ni->ni_ald.ald_capacity = (OL_ATH_NODE_NET80211(ni))->an_ni_tx_rate/1000;


	if((OL_ATH_NODE_NET80211(ni))->an_tx_bytes == 0)
		msdu_size = ALD_MSDU_SIZE;
	else
		msdu_size = (OL_ATH_NODE_NET80211(ni))->an_tx_bytes/ni->ni_ald.ald_txcount;

	if (msdu_size < DEFAULT_MSDU_SIZE)
		ni->ni_ald.ald_msdusize = ALD_MSDU_SIZE;
	else
		ni->ni_ald.ald_msdusize = msdu_size;
	max_msdu_size = (msdu_size > ALD_MSDU_SIZE) ? msdu_size : ALD_MSDU_SIZE;
	if ((OL_ATH_NODE_NET80211(ni))->an_tx_ratecount > 0)
	    ni->ni_ald.ald_avgmax4msaggr = ni->ni_ald.ald_max4msframelen / ((OL_ATH_NODE_NET80211(ni))->an_tx_ratecount * max_msdu_size);

    if(ni->ni_ald.ald_avgmax4msaggr > 192)
	    ni->ni_ald.ald_avgmax4msaggr = 192;

	if(ni->ni_ald.ald_avgmax4msaggr > 0)
		ni->ni_ald.ald_aggr = ni->ni_ald.ald_avgmax4msaggr/2;
	else
		ni->ni_ald.ald_aggr = 96; //Max aggr 192/2

	/* Avg Aggr should be atleast 1 */
	ni->ni_ald.ald_aggr = ni->ni_ald.ald_aggr > 1 ? ni->ni_ald.ald_aggr : 1;

}
Exemplo n.º 12
0
void ieee80211_prdperfstat_thrput_start(struct ieee80211com *ic)
{
    struct ieee80211_prdperfstat_thrput *thrput = &ic->ic_thrput;
    
    OS_MEMSET(thrput->histogram, 0, thrput->histogram_size * sizeof(u_int32_t));

    thrput->histogram_head          = 0;
    thrput->histogram_tail          = 0;
    thrput->is_histogram_full       = 0;
    thrput->histogram_bytecount     = 0;
    thrput->curr_bytecount          = 0;
    thrput->last_save_ms            = OS_GET_TIMESTAMP();
    
    thrput->timer_count             = 0;
    thrput->is_started              = 1;
}
Exemplo n.º 13
0
static bool ieee80211_assoc_state_assoc_event(void *ctx, u_int16_t event, u_int16_t event_data_len, void *event_data) 
{
    wlan_assoc_sm_t sm = (wlan_assoc_sm_t) ctx;

    switch(event) {
    case IEEE80211_ASSOC_EVENT_ASSOC_SUCCESS:
        sm->last_connected_time = OS_GET_TIMESTAMP();
        ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_RUN); 
        return true;
        break;

    case IEEE80211_ASSOC_EVENT_ASSOC_FAIL:
    case IEEE80211_ASSOC_EVENT_TIMEOUT:
        if (sm->cur_assoc_attempts >= sm->max_assoc_attempts) {
            IEEE80211_DPRINTF(sm->vap_handle,IEEE80211_MSG_STATE,"%s: max assoc attempts reached \n",__func__);
            if (sm->scan_entry) wlan_scan_entry_set_assoc_state(sm->scan_entry, AP_ASSOC_STATE_NONE);
            ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); 
            return true;
        }
        sm->last_failure = WLAN_ASSOC_SM_REASON_ASSOC_FAILED;
        ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_ASSOC); 
        return true;
        break;

    case IEEE80211_ASSOC_EVENT_DISCONNECT_REQUEST:
    case IEEE80211_ASSOC_EVENT_DISASSOC_REQUEST:
        if (sm->scan_entry) wlan_scan_entry_set_assoc_state(sm->scan_entry, AP_ASSOC_STATE_NONE);
        /* cancel pending mlme operation */
        wlan_mlme_cancel(sm->vap_handle);
        if (wlan_mlme_operation_in_progress(sm->vap_handle)) {
            ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_MLME_WAIT); 
        } else {
            ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_INIT); 
        }
        break;

    case IEEE80211_ASSOC_EVENT_DEAUTH:
        ieee80211_send_event(sm, WLAN_ASSOC_SM_EVENT_REJOINING, WLAN_ASSOC_SM_REASON_DEAUTH);
        ieee80211_sm_transition_to(sm->hsm_handle,IEEE80211_ASSOC_STATE_AUTH); 
        return true;
        break;

    default:
        return false;
    }
    return false;
}
Exemplo n.º 14
0
int
pktlog_enable(ath_generic_softc_handle scn, int32_t log_state)
{
    struct pktlog_handle_t *pl_dev = get_pl_handle(scn);
    struct ath_pktlog_info *pl_info = (pl_dev) ?
                                        pl_dev->pl_info : g_pktlog_info;
    int error;

    if (!pl_info) {
        return 0;
    }

    pl_info->log_state = 0;

    if (log_state != 0) {
        if (!pl_dev) {
            if (g_pktlog_mode == PKTLOG_MODE_ADAPTER) {
                pktlog_disable_adapter_logging();
                g_pktlog_mode = PKTLOG_MODE_SYSTEM;
            }
        } else {
            if (g_pktlog_mode == PKTLOG_MODE_SYSTEM) {
                /* Currently the system wide logging is disabled */
                g_pktlog_info->log_state = 0; 
                g_pktlog_mode = PKTLOG_MODE_ADAPTER;
            }
        }

        if (pl_info->buf == NULL) {
            error = pktlog_alloc_buf(scn ,pl_info);
            if (error != 0)
                return error;
                
            pl_info->buf->bufhdr.version = CUR_PKTLOG_VER;
            pl_info->buf->bufhdr.magic_num = PKTLOG_MAGIC_NUM;
            pl_info->buf->wr_offset = 0;
            pl_info->buf->rd_offset = -1;
        }
	    pl_info->start_time_thruput = OS_GET_TIMESTAMP();
	    pl_info->start_time_per = pl_info->start_time_thruput;
    }
    pl_info->log_state = log_state;
    return 0;
}
Exemplo n.º 15
0
/*
 * count PER and stop pktlog if it's over a threshold. Clear the count per an interval.
 */
static void pktlog_trigger_thruput(HAL_BOOL pkt_good, u_int32_t pktlen, struct ath_pktlog_info *pl_info)
{
    static u_int32_t total = 0; // in bytes
	u_int32_t now;

	if (pkt_good)
		total += pktlen;
	now = OS_GET_TIMESTAMP();
	if (CONVERT_SYSTEM_TIME_TO_MS(now - pl_info->start_time_thruput) > pl_info->trigger_interval) {
		if (total < pl_info->thruput_thresh) {
			//trigger stop
	        DPRINTF(pl_info->pl_sc, ATH_DEBUG_ANY, "pktlog stopped: only %d bytes thruput in past %dms\n", total, pl_info->trigger_interval);
			if (pl_info->log_state) {
			    pl_info->saved_state = pl_info->log_state;
			    pl_info->log_state = 0;
			}
		}
		total = 0;
		pl_info->start_time_thruput = now;
	}
}
Exemplo n.º 16
0
/*
 * count PER and stop pktlog if it's over a threshold. Clear the count per an interval.
 */
static void pktlog_trigger_per(HAL_BOOL pkt_good, struct ath_pktlog_info *pl_info, int failcount, int nframes, int nbad)
{
    static u_int32_t pkt_err = 0, pkt_cnt = 0;
	u_int32_t now;

	if(nframes > 1) {
		/* 
		 * this is a tx aggregate packet 
		 * failcount: number of tx retries due to not seeing Block ACK
		 * nframes:   number of subframes in an aggregate
		 */
		pkt_cnt += failcount * nframes;
		pkt_err += failcount * nframes;
		if (pkt_good) {
			pkt_cnt += nframes;
		    pkt_err += nbad;
		}
	} else {
	    pkt_cnt += failcount;
	    pkt_err += failcount;
	    if (pkt_good)
		    pkt_cnt++;
	}
	now = OS_GET_TIMESTAMP();
	if (CONVERT_SYSTEM_TIME_TO_MS(now - pl_info->start_time_per) > pl_info->trigger_interval) {
		if (pkt_err * 100 > pkt_cnt * pl_info->per_thresh) {
			//trigger stop
	        DPRINTF(pl_info->pl_sc, ATH_DEBUG_ANY, "pktlog stopped: seen %d bad packets out of %d in past %dms\n",
				pkt_err, pkt_cnt, pl_info->trigger_interval);
			if (pl_info->log_state) {
			    pl_info->saved_state = pl_info->log_state;
			    pl_info->log_state = 0;
			}
		}
		pkt_err = 0;
		pkt_cnt = 0;
		pl_info->start_time_per = now;
	}
}
Exemplo n.º 17
0
/*
 * Calculate maximum allowed scan_entry age, in ms.
 * Reference_time specifies the timestamp of the oldest accepted entry.
 */
u_int32_t ieee80211_mlme_maximum_scan_entry_age(wlan_if_t vaphandle, 
                                                systime_t reference_time)
{
#define IEEE80211_SCAN_LATENCY_TIME                 1000
    u_int32_t    maximum_age  = 0;
    systime_t    current_time = OS_GET_TIMESTAMP();

    if (reference_time == 0) {
        /* Make all entries old if there's no record of the last scan */
        maximum_age = 0;
    }
    else {
        maximum_age = CONVERT_SYSTEM_TIME_TO_MS(current_time - reference_time);

        /* 
         * Make all entries in the table "old" by setting the maximum age
         * to 0 if last scan occurred too long ago. This can happen when 
         * system is resuming from S3/S4.
         */
        if (maximum_age > IEEE80211_SCAN_ENTRY_EXPIRE_TIME) {
            maximum_age = IEEE80211_SCAN_ENTRY_EXPIRE_TIME;
        }
    }
    
    /* 
     * Add a latency time to account for the delay from the time the
     * maximum age is calculated to the time it's actually used.
     * Failing to account for this latency time can cause the oldest
     * entries in the scan list to be skipped.
     */
    if (maximum_age > 0) {
        maximum_age += IEEE80211_SCAN_LATENCY_TIME;
    }

    return maximum_age;
#undef IEEE80211_SCAN_LATENCY_TIME
}
Exemplo n.º 18
0
void ieee80211_recv_beacon_ibss(struct ieee80211_node *ni, wbuf_t wbuf, int subtype, 
                                struct ieee80211_rx_status *rs, ieee80211_scan_entry_t  scan_entry)
{
    struct ieee80211vap                          *vap = ni->ni_vap;
    struct ieee80211com                          *ic = ni->ni_ic;
    u_int16_t                                    capinfo;
    int                                          ibssmerge = 0;
    struct ieee80211_channelswitch_ie            *chanie = NULL;
    struct ieee80211_extendedchannelswitch_ie    *echanie = NULL;
    struct ieee80211_frame                       *wh;
    u_int64_t                                    tsf;
    u_int8_t                                     *quiet_elm = NULL; 
    bool                                         free_node = FALSE;
#if ATH_SUPPORT_IBSS_DFS
    struct ieee80211_ibssdfs_ie                  *ibssdfsie = NULL;
#endif /* ATH_SUPPORT_IBSS_DFS */

    wh = (struct ieee80211_frame *)wbuf_header(wbuf);
    capinfo = ieee80211_scan_entry_capinfo(scan_entry);

    if (!(capinfo & IEEE80211_CAPINFO_IBSS))
        return;

    OS_MEMCPY((u_int8_t *)&tsf, ieee80211_scan_entry_tsf(scan_entry), sizeof(tsf));
    if (ni != ni->ni_bss_node) {
        OS_MEMCPY(ni->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp));
        /* update activity indication */
        ni->ni_beacon_rstamp = OS_GET_TIMESTAMP();
        ni->ni_probe_ticks   = 0;
    }

    /*
     * Check BBSID before updating our beacon configuration to make 
     * sure the received beacon really belongs to our Adhoc network.
     */
    if ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) &&
        ieee80211_vap_ready_is_set(vap) &&
        (IEEE80211_ADDR_EQ(wh->i_addr3, ieee80211_node_get_bssid(vap->iv_bss)))) {
        /*
         * if the neighbor is not in the list, add it to the list.
         */
        if (ni == ni->ni_bss_node) {
            ni = ieee80211_add_neighbor(ni, scan_entry);
            if (ni == NULL) {
                return;
            }
            OS_MEMCPY(ni->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp));
            free_node = TRUE;
        }
        ni->ni_rssi = rs->rs_rssi;

        /*
         * record tsf of last beacon into bss node
         */
        OS_MEMCPY(ni->ni_bss_node->ni_tstamp.data, &tsf, sizeof(ni->ni_tstamp));

        /*
         * record absolute time of last beacon
         */
        vap->iv_last_beacon_time = OS_GET_TIMESTAMP();

        ic->ic_beacon_update(ni, rs->rs_rssi);

#if ATH_SUPPORT_IBSS_WMM
        /*
         * check for WMM parameters
         */
        if ((ieee80211_scan_entry_wmeparam_ie(scan_entry) != NULL) ||
            (ieee80211_scan_entry_wmeinfo_ie(scan_entry)  != NULL)) {

            /* Node is WMM-capable if WME IE (either subtype) is present */
            ni->ni_ext_caps |= IEEE80211_NODE_C_QOS;

            /* QOS-enable */
            ieee80211node_set_flag(ni, IEEE80211_NODE_QOS);
        } else {
            /* If WME IE not present node is not WMM capable */
            ni->ni_ext_caps &= ~IEEE80211_NODE_C_QOS;
            
            ieee80211node_clear_flag(ni, IEEE80211_NODE_QOS);
        }
#endif  
#if ATH_SUPPORT_IBSS_DFS

        if (ic->ic_curchan->ic_flagext & IEEE80211_CHAN_DFS) {
            //check and see if we need to update other info for ibss_dfsie
            ibssdfsie = (struct ieee80211_ibssdfs_ie *)ieee80211_scan_entry_ibssdfs_ie(scan_entry);
            if(ibssdfsie) {
               if (ieee80211_check_and_update_ibss_dfs(vap, ibssdfsie)) {
                   ieee80211_ibss_beacon_update_start(ic);
               }
            }

            /* update info from DFS owner */
            if(ibssdfsie){
                if(IEEE80211_ADDR_EQ(wh->i_addr2, ibssdfsie->owner)) {
                    if(OS_MEMCMP(ibssdfsie, &vap->iv_ibssdfs_ie_data, MIN_IBSS_DFS_IE_CONTENT_SIZE)) {
                        if(le64_to_cpu(tsf) >= rs->rs_tstamp.tsf){
                            IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, ibssdfsie->owner);
                            vap->iv_ibssdfs_ie_data.rec_interval = ibssdfsie->rec_interval;
                            ieee80211_ibss_beacon_update_start(ic);
                        }
                    }
                }
            }
            /* check if owner and it is not transmitting ibssIE */
            else if(IEEE80211_ADDR_EQ(wh->i_addr2, vap->iv_ibssdfs_ie_data.owner)){
                IEEE80211_ADDR_COPY(vap->iv_ibssdfs_ie_data.owner, vap->iv_myaddr);
                vap->iv_ibssdfs_state = IEEE80211_IBSSDFS_OWNER;
                ieee80211_ibss_beacon_update_start(ic);            
            } 
        }
   
#endif /* ATH_SUPPORT_IBSS_DFS */

        /*
         * check for spectrum management
         */
        if (capinfo & IEEE80211_CAPINFO_SPECTRUM_MGMT) {
            chanie  = (struct ieee80211_channelswitch_ie *)         ieee80211_scan_entry_csa(scan_entry);
#if ATH_SUPPORT_IBSS_DFS
            if(chanie)
            {
                 OS_MEMCPY(&vap->iv_channelswitch_ie_data, chanie, sizeof(struct ieee80211_channelswitch_ie));
                 ieee80211_ibss_beacon_update_start(ic);
            }
#endif /* ATH_SUPPORT_IBSS_DFS */
            echanie = (struct ieee80211_extendedchannelswitch_ie *) ieee80211_scan_entry_xcsa(scan_entry);
            if ((!chanie) && (!echanie)) {
                quiet_elm = ieee80211_scan_entry_quiet(scan_entry);
            }
        }
    }

    /*
     * Handle ibss merge as needed; check the tsf on the
     * frame before attempting the merge.  The 802.11 spec
     * says the station should change its bssid to match
     * the oldest station with the same ssid, where oldest
     * is determined by the tsf.  Note that hardware
     * reconfiguration happens through callback to
     * ath as the state machine will go from
     * RUN -> RUN when this happens.
     */
    if (ieee80211_vap_ready_is_set(vap) &&
        (le64_to_cpu(tsf) >= rs->rs_tstamp.tsf)) {
        ibssmerge = ieee80211_ibss_merge(ni,scan_entry);
    }

    if (ibssmerge) {
        ieee80211_mlme_adhoc_merge_start(ni);
    }

    /*
     * RNWF-specific: indicate to NDIS about the potential association.
     * It should be done after IBSS merge, which is called from ath_beacon_update().
     */
    if (IEEE80211_ADDR_EQ(wh->i_addr3, ieee80211_node_get_bssid(ni))) {
        /* Indicate node joined IBSS */
    if ((capinfo & IEEE80211_CAPINFO_RADIOMEAS)
         && ieee80211_vap_rrm_is_set(vap)) {
        if(ni->ni_assoc_state != IEEE80211_NODE_ADHOC_STATE_AUTH_ASSOC)
            ieee80211_set_node_rrm(ni,TRUE);
    } else {
        ieee80211_set_node_rrm(ni,FALSE);
    } 
        ieee80211_mlme_adhoc_join_indication(ni, wbuf);

        /* notify mlme of beacon reception */
        ieee80211_mlme_join_complete_adhoc(ni);
    }

    if (ibssmerge) {
        ieee80211_mlme_adhoc_merge_completion(ni);
    }

    if (quiet_elm) {
        ic->ic_set_quiet(ni, quiet_elm);
    }

    if (free_node == TRUE) {
        ieee80211_free_node(ni);
    }

}
Exemplo n.º 19
0
void
ieee80211_vap_iter_beacon_miss(void *arg, wlan_if_t vap) 
{
    systime_t              tstamp;
    systime_t              last_link_time;
    systime_t              last_traffic_time;
    struct ieee80211com    *ic = vap->iv_ic;    
    struct ieee80211_mlme_priv    *mlme_priv = vap->iv_mlme_priv;
    ieee80211_mlme_event   event;

    IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
                      "%s: %s iv_bmiss_count=%d reset=%d max=%d arg=%08p swbmiss=%d\n",
                      __func__,
                      (arg != NULL) ? "SW" : "HW",
                      vap->iv_bmiss_count,
                      vap->iv_bmiss_count_for_reset,
                      vap->iv_bmiss_count_max,
                      arg,
                      mlme_sta_swbmiss_active(vap));

    /*
     * Our handling is only meaningful for stations that are
     * associated; any other conditions else will be handled
     * through different means (e.g. the tx timeout on mgt frames).
     */
    if ((vap->iv_opmode != IEEE80211_M_STA) ||
        !ieee80211_vap_ready_is_set(vap)) {
        mlme_sta_swbmiss_timer_print_status(vap); /* print the status of sw bmiss */
        return;
    }

    /* 
     * ignore HW beacon miss if SW beacon miss is enabled.
     * and completely rely on SW beacon miss.
     */
    if ((arg == NULL) && mlme_sta_swbmiss_active(vap)) {
        return;
    }

    /*
     * WAR for excessive beacon miss problem on SoC.
     * Consider a beacon miss only when we have two consecutive
     * beacon misses and there are no rx activities in between.
     *
     * Count beacon misses only if we gave the AP a chance by sending a
     * directed Probe Request.
     *
     * Don't do anything if we are scanning a foreign channel.
     * Trying to transmit a frame (Probe Request) during a channel change 
     * (which includes a channel reset) can cause a NMI due to invalid HW 
     * addresses. 
     * Trying to transmit a Probe Request while in a foreign channel 
     * wouldn't do us any good either.
     *
     * Query current time only after retrieving LastLinkTime. This avoids 
     * possible negative values if this routine is preempted by reception of 
     * a beacon or directed frame which would update the fields used to 
     * calculate LastLinkTime.
     */

    last_traffic_time = ieee80211_get_directed_frame_timestamp(vap);
    last_link_time = (vap->iv_last_beacon_time > last_traffic_time) ? 
        vap->iv_last_beacon_time : last_traffic_time;
    tstamp = OS_GET_TIMESTAMP();

    {
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
            "%d.%03d | %s: count=%d probe=%d beacon:%lums directed:%lums data:%lums ap_frame:%lums traffic_ind:%lums\n",
            ((u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp)) / 1000,
            ((u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp)) % 1000,
            __func__, vap->iv_bmiss_count,
            ieee80211_scan_can_transmit(ic->ic_scanner),
            (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_last_beacon_time),
            (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - last_traffic_time),
            (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_lastdata),
            (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_last_ap_frame),
            (u_int32_t) CONVERT_SYSTEM_TIME_TO_MS(tstamp - vap->iv_last_traffic_indication));
    }

    /*
     * Do not count beacon misses received when we're off-channel, or
     * within IEEE80211_MINIMUM_BMISS_TIME ms of the last valid beacon.
     */ 
    if ((! ieee80211_scan_in_home_channel(ic->ic_scanner)) || 
        (CONVERT_SYSTEM_TIME_TO_MS(tstamp - last_link_time) < IEEE80211_MINIMUM_BMISS_TIME)) {
        mlme_sta_swbmiss_timer_start(vap); /* restart beacon miss timer */
        return;
    }

    vap->iv_bmiss_count++;
    
  
    event.u.event_bmiss.cur_bmiss_count = vap->iv_bmiss_count;
    event.u.event_bmiss.max_bmiss_count = vap->iv_bmiss_count_for_reset;
    event.type = IEEE80211_MLME_EVENT_BEACON_MISS;

    ieee80211_mlme_deliver_event(mlme_priv,&event);

    if (vap->iv_bmiss_count < vap->iv_bmiss_count_for_reset) {
#ifdef ATH_SWRETRY
        /* Turn off the sw retry mechanism until we receive
         * any data frame or probe response for the BSS we are
         * associated to.
         */
        ic->ic_set_swretrystate(vap->iv_bss, FALSE);
#endif                        

        /*
         * It is possible that the hardware gets into
         * deaf mode. Reset the hardware to see if it can recover
         * from the condition.
         */

        /* indicate device error */
        IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: Beacon miss, do internal reset!!\n", __func__);
        IEEE80211_DELIVER_EVENT_DEVICE_ERROR(vap);
                
        mlme_sta_swbmiss_timer_start(vap); /* restart beacon miss timer */
        return;
    }

    /*  max bmiss count reached */

    vap->iv_bmiss_count = 0;    /* reset bmiss counter */

    IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY, "%s: Beacon miss, will indicate to OS!!\n", __func__);
    /* indicate beacon miss */
    IEEE80211_DELIVER_EVENT_BEACON_MISS(vap);
}
Exemplo n.º 20
0
static int 
ol_vdev_wmi_event_handler(ol_scn_t scn, u_int8_t *data, u_int16_t datalen, void *context)
{
    ieee80211_resmgr_t resmgr = (ieee80211_resmgr_t )context;
    wmi_vdev_start_response_event *wmi_vdev_start_resp_ev =
                                                (wmi_vdev_start_response_event *)data;
    wlan_if_t vaphandle;
    struct ieee80211com  *ic = resmgr->ic;
    struct ieee80211_channel *chan = NULL;
    struct ieee80211_node *ni;
    u_int8_t numvaps, actidx = 0;
    struct ol_ath_vap_net80211 *avn;
    bool do_notify = true;
    vaphandle = ol_ath_vap_get(scn, wmi_vdev_start_resp_ev->vdev_id);

    if (NULL == vaphandle) {
        printk("Event received for Invalid/Deleted vap handle\n");
        return 0;
    }

    avn = OL_ATH_VAP_NET80211(vaphandle);

    printk("ol_vdev_start_resp_ev for vap %d (%p)\n", wmi_vdev_start_resp_ev->vdev_id, scn->wmi_handle);

    spin_lock(&vaphandle->init_lock);

    switch (vaphandle->iv_opmode) {

        case IEEE80211_M_MONITOR:
               /* Handle same as HOSTAP */
        case IEEE80211_M_HOSTAP:
            /* If vap is not waiting for the WMI event from target
               return here
             */
            if(avn->av_ol_resmgr_wait == FALSE) {
                spin_unlock(&vaphandle->init_lock);
                return 0;
            }
             /* Resetting the ol_resmgr_wait flag*/
            avn->av_ol_resmgr_wait = FALSE;

            numvaps = ieee80211_vaps_active(ic);

            chan =  vaphandle->iv_des_chan[vaphandle->iv_des_mode];

            /* 
             * if there is a vap already running.
             * ignore the desired channel and use the
             * operating channel of the other vap.
             */
            /* so that cwm can do its own crap. need to untie from state */
            /* vap join is called here to wake up the chip if it is in sleep state */
            ieee80211_vap_join(vaphandle);
            
            if (numvaps == 0) {
                //AP_DFS: ieee80211_set_channel(ic, chan);
                if (wmi_vdev_start_resp_ev->resp_type != WMI_VDEV_RESTART_RESP_EVENT) {
                     /* 20/40 Mhz coexistence  handler */
                    if ((avn->av_ol_resmgr_chan != NULL) && (chan != avn->av_ol_resmgr_chan)) {
                        chan = avn->av_ol_resmgr_chan;
                    }

                    ic->ic_prevchan = ic->ic_curchan;
                    ic->ic_curchan = chan;
                    /*update channel history*/
                    actidx = ic->ic_chanidx;
                    ic->ic_chanhist[actidx].chanid = (ic->ic_curchan)->ic_ieee;
                    ic->ic_chanhist[actidx].chanjiffies = OS_GET_TIMESTAMP();
                    ic->ic_chanidx == (IEEE80211_CHAN_MAXHIST - 1) ? ic->ic_chanidx = 0 : ++(ic->ic_chanidx);
                    /* update max channel power to max regpower of current channel */
                    ieee80211com_set_curchanmaxpwr(ic, chan->ic_maxregpower);
                    ieee80211_wme_initparams(vaphandle);
                }

                /* ieee80211 Layer - Default Configuration */
                vaphandle->iv_bsschan = ic->ic_curchan;
                /* XXX reset erp state */
                ieee80211_reset_erp(ic, ic->ic_curmode, vaphandle->iv_opmode);
            } else {
                /* ieee80211 Layer - Default Configuration */
                vaphandle->iv_bsschan = ic->ic_curchan;
            }
            /* use the vap bsschan for dfs configure */
            if ( IEEE80211_IS_CHAN_DFS(vaphandle->iv_bsschan)) {
                   extern void ol_if_dfs_configure(struct ieee80211com *ic);
                   ol_if_dfs_configure(ic);
            }
            break;
        case IEEE80211_M_STA:

            ni = vaphandle->iv_bss;

            chan = ni->ni_chan;

            vaphandle->iv_bsschan = chan;
            
            ic->ic_prevchan = ic->ic_curchan;
            ic->ic_curchan = chan;
            /* update max channel power to max regpower of current channel */
            ieee80211com_set_curchanmaxpwr(ic, chan->ic_maxregpower);

            /* ieee80211 Layer - Default Configuration */
            vaphandle->iv_bsschan = ic->ic_curchan;

            /* XXX reset erp state */
            ieee80211_reset_erp(ic, ic->ic_curmode, vaphandle->iv_opmode);
            ieee80211_wme_initparams(vaphandle);
            if (wmi_vdev_start_resp_ev->resp_type == WMI_VDEV_RESTART_RESP_EVENT) {
                do_notify = false;
            }
            
            break;
        default:
            break;
    }

    vaphandle->init_in_progress = false;
    spin_unlock(&vaphandle->init_lock);

    /* Intimate start completion to VAP module */
    /* if STA, bypass notification for RESTERT EVENT */
    if (do_notify)
    ieee80211_notify_vap_start_complete(resmgr, vaphandle, IEEE80211_RESMGR_STATUS_SUCCESS);

    return 0;
}
Exemplo n.º 21
0
int ath_ald_collect_data(ath_dev_t dev, ath_ald_t ald_data)
{
    u_int32_t cu = 0; /* cu: channel utilization; cc: channel capacity */
    u_int32_t msdu_size=0, load=0;
    u_int32_t rxclear=0, rxframe=0, txframe=0;
    u_int32_t new_phyerr=0, new_ostime=0;
    u_int32_t old_phyerr=0, old_ostime=0;
    u_int32_t phyerr_rate=0;
    u_int32_t tmp = 0;
    u_int8_t good;
    struct ath_softc *sc = ATH_DEV_TO_SC(dev);

    spin_lock(ald_data->ald_lock);

    good = ath_hal_getMibCycleCountsPct(sc->sc_ah, &rxclear, &rxframe, &txframe);

    if(good) {
        cu = rxclear;
    }
    old_phyerr = ald_data->ald_phyerr;
    old_ostime = ald_data->ald_ostime;
    new_phyerr = sc->sc_phy_stats[sc->sc_curmode].ast_rx_phyerr;
    new_ostime = OS_GET_TIMESTAMP()/1000;
    if((new_ostime > old_ostime) && (old_ostime > 0))
        phyerr_rate = (new_phyerr - old_phyerr)/(new_ostime - old_ostime);
    else
        phyerr_rate = 0;

    ald_data->ald_phyerr = new_phyerr;
    ald_data->ald_ostime = new_ostime;

    if(ald_data->ald_unicast_tx_packets != 0 ){
        msdu_size = ald_data->ald_unicast_tx_bytes/ald_data->ald_unicast_tx_packets;
    }else{
        msdu_size = ALD_MSDU_SIZE;
    }

    ald_data->phyerr_rate = phyerr_rate;
    ald_data->msdu_size = msdu_size;

    /* currently not in use, the value is not accurate somehow */ 
    if((sc->sc_ald.sc_ald_tbuf != 0) && (sc->sc_ald.sc_ald_tnum != 0)){
        tmp = sc->sc_ald.sc_ald_tbuf/sc->sc_ald.sc_ald_tnum;
        if (tmp > 0) {
            load = sc->sc_txbuf_free*msdu_size/(tmp*1000);
        }
    }else
        load = ALD_MAX_DEV_LOAD;

    if (sc->sc_ald.sc_ald_cunum > 0) {
        cu = sc->sc_ald.sc_ald_cu / sc->sc_ald.sc_ald_cunum;
    }
    sc->sc_ald.sc_ald_cu = 0;
    sc->sc_ald.sc_ald_cunum = 0;
    ald_data->ald_unicast_tx_bytes = 0;
    ald_data->ald_unicast_tx_packets = 0;
   
    ald_data->ald_chan_util = cu;
    ald_data->ald_dev_load = load;
    spin_unlock(ald_data->ald_lock);

    sc->sc_ald.sc_ald_tbuf = 0;
    sc->sc_ald.sc_ald_tnum = 0;
    return 0;
}