@@ -799,6 +799,13 @@ enum mac80211_rate_control_flags {
};
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
/* there are 40 bytes if you don't need the rateset to be kept */
#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
@@ -1534,6 +1534,47 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
return RX_CONTINUE;
}
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+ struct sta_info *sta = rx->sta;
+ struct ieee80211_bss_conf *bss_conf =
+ &rx->sdata->vif.bss_conf;
+ int sig, last_event, thold;
+
+ if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+ NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+ return;
+
+ sta->count_rx_signal++;
+ if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+ return;
+
+ if (!bss_conf->cqm_rssi_thold || !bss_conf->enable_beacon) {
+ sta->count_rx_signal = 0;
+ return;
+ }
+
+ sig = -ewma_signal_read(&sta->rx_stats_avg.signal);
+ last_event = sta->last_cqm_event_signal;
+ thold = bss_conf->cqm_rssi_thold;
+
+ if (sig < thold && last_event == 0) {
+ sta->last_cqm_event_signal = sig;
+ cfg80211_ap_sta_cqm_rssi_notify(
+ rx->sdata->dev, sta->addr,
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+ sig, GFP_ATOMIC);
+ sta->count_rx_signal = 0;
+ } else if (last_event && sig > thold) {
+ sta->last_cqm_event_signal = 0;
+ cfg80211_ap_sta_cqm_rssi_notify(
+ rx->sdata->dev, sta->addr,
+ NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+ sig, GFP_ATOMIC);
+ sta->count_rx_signal = 0;
+ }
+}
+
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
{
@@ -1589,6 +1630,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal);
+ ieee80211_sta_rx_signal_thold_check(rx);
}
if (status->chains) {
@@ -3981,9 +4023,11 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
- if (!fast_rx->uses_rss)
+ if (!fast_rx->uses_rss) {
ewma_signal_add(&sta->rx_stats_avg.signal,
-status->signal);
+ ieee80211_sta_rx_signal_thold_check(rx);
+ }
}
if (status->chains) {
@@ -579,6 +579,9 @@ struct sta_info {
struct cfg80211_chan_def tdls_chandef;
+ int last_cqm_event_signal;
+ unsigned int count_rx_signal;
+
/* keep last! */
struct ieee80211_sta sta;
};