diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c686d1b..de7519e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -46,6 +46,13 @@ */ #define IEEE80211_PROBE_WAIT (HZ / 2) +/* + * Weight given to the latest Beacon frame when calculating average signal + * strength for Beacon frames received in the current BSS. This must be + * between 1 and 15. + */ +#define IEEE80211_SIGNAL_AVE_WEIGHT 3 + #define TMR_RUNNING_TIMER 0 #define TMR_RUNNING_CHANSW 1 @@ -732,6 +739,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.associated = cbss; memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); + sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; + /* just to be sure */ sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | IEEE80211_STA_BEACON_POLL); @@ -1347,6 +1356,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_rx_status *rx_status) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; size_t baselen; struct ieee802_11_elems elems; struct ieee80211_local *local = sdata->local; @@ -1382,6 +1392,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) return; + /* Track average RSSI from the Beacon frames of the current AP */ + ifmgd->last_beacon_signal = rx_status->signal; + if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { + ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; + ifmgd->ave_beacon_signal = rx_status->signal; + ifmgd->last_cqm_event_signal = 0; + } else { + ifmgd->ave_beacon_signal = + (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + + (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * + ifmgd->ave_beacon_signal) / 16; + } + if (bss_conf->cqm_rssi_thold && + !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { + int sig = ifmgd->ave_beacon_signal / 16; + int last_event = ifmgd->last_cqm_event_signal; + int thold = bss_conf->cqm_rssi_thold; + int hyst = bss_conf->cqm_rssi_hyst; + if (sig < thold && + (last_event == 0 || sig < last_event - hyst)) { + ifmgd->last_cqm_event_signal = sig; + ieee80211_cqm_rssi_notify( + &sdata->vif, + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + GFP_KERNEL); + } else if (sig > thold && + (last_event == 0 || sig > last_event + hyst)) { + ifmgd->last_cqm_event_signal = sig; + ieee80211_cqm_rssi_notify( + &sdata->vif, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + GFP_KERNEL); + } + } + if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) { |