/** * @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; }
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) {
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; } } } }
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; }
/* * 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); }
/* * 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; } }
/* * 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; } }
/* * 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); }
/* * 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 }
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); }