@@ -3831,12 +3831,51 @@ static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
sta->rssi_thold = rssi_thold;
sta->rssi_hyst = rssi_hyst;
+ sta->rssi_low = 0;
+ sta->rssi_high = 0;
sta->last_sta_mon_event_signal = 0;
unlock:
mutex_unlock(&sdata->local->sta_mtx);
return 0;
}
+static int ieee80211_set_sta_mon_rssi_range_cfg(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ s32 rssi_low, s32 rssi_high)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct sta_info *sta;
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ (!sdata->vif.bss_conf.enable_beacon ||
+ !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+ NL80211_EXT_FEATURE_STA_MON_RSSI_LIST)))
+ return -EOPNOTSUPP;
+
+ mutex_lock(&sdata->local->sta_mtx);
+
+ sta = sta_info_get_bss(sdata, peer);
+ if (!sta) {
+ mutex_unlock(&sdata->local->sta_mtx);
+ return -ENOENT;
+ }
+
+ if (sta->rssi_low == rssi_low &&
+ sta->rssi_high == rssi_high)
+ goto unlock;
+
+ sta->rssi_thold = 0;
+ sta->rssi_hyst = 0;
+ sta->rssi_low = rssi_low;
+ sta->rssi_high = rssi_high;
+ sta->last_sta_mon_event_signal = 0;
+
+unlock:
+ mutex_unlock(&sdata->local->sta_mtx);
+ return 0;
+}
+
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3932,4 +3971,5 @@ static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
.tx_control_port = ieee80211_tx_control_port,
.get_txq_stats = ieee80211_get_txq_stats,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
+ .set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_cfg,
};
@@ -1569,6 +1569,29 @@ static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
sig, GFP_ATOMIC);
}
}
+
+ if (sta->rssi_low) {
+ int last_event = sta->last_sta_mon_event_signal;
+ int sig = -ewma_signal_read(&sta->rx_stats_avg.signal);
+ int low = sta->rssi_low;
+ int high = sta->rssi_high;
+
+ if (sig < low &&
+ (last_event == 0 || last_event >= low)) {
+ sta->last_sta_mon_event_signal = sig;
+ cfg80211_sta_mon_rssi_notify(
+ rx->sdata->dev, sta->addr,
+ NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+ sig, GFP_ATOMIC);
+ } else if (sig > high &&
+ (last_event == 0 || last_event <= high)) {
+ sta->last_sta_mon_event_signal = sig;
+ cfg80211_sta_mon_rssi_notify(
+ rx->sdata->dev, sta->addr,
+ NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+ sig, GFP_ATOMIC);
+ }
+ }
}
static ieee80211_rx_result debug_noinline
@@ -487,6 +487,10 @@ struct ieee80211_sta_rx_stats {
* should cause an event to be sent indicating where the current value
* is in relation to the newly configured threshold
* @rssi_hyst: Station's RSSI hysteresis
+ * @rssi_low: RSSI lower threshold to monitor station's signal strength, a zero
+ * value implies disabled. This is an alternative mechanism to the single
+ * threshold event and can't be enabled simultaneously with it
+ * @rssi_high: RSSI upper threshold for station
* @last_sta_mon_event_signal: Last signal strength average for a station
* that triggered a sta_mon event. 0 indicates that no event has been
* generated for the current association
@@ -596,6 +600,8 @@ struct sta_info {
s32 rssi_thold;
u32 rssi_hyst;
+ s32 rssi_low;
+ s32 rssi_high;
int last_sta_mon_event_signal;
unsigned int count_rx_signal;
Add set_sta_mon_rssi_range_config api to support configuring low and high RSSI threshold values for a connected station. And trigger an event if a station's signal strength goes out of configured range. Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org> --- net/mac80211/cfg.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/mac80211/rx.c | 23 +++++++++++++++++++++++ net/mac80211/sta_info.h | 6 ++++++ 3 files changed, 69 insertions(+)