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); }
systime_t wlan_get_directed_frame_timestamp(wlan_if_t vaphandle) { return ieee80211_get_directed_frame_timestamp(vaphandle); }