diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5162233..72d2b07 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3849,6 +3849,96 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
 	return drv_get_ftm_responder_stats(local, sdata, ftm_stats);
 }
 
+void sta_mon_rssi_config_free(struct sta_info *sta)
+{
+	kfree(sta->rssi_tholds);
+	sta->rssi_tholds = NULL;
+	sta->n_rssi_tholds = 0;
+}
+
+static void ieee80211_update_rssi_config(struct sta_info *sta)
+{
+	s32 last;
+	u32 hyst;
+	int i, n;
+
+	if (!sta->n_rssi_tholds)
+		return;
+
+	if (!sta->last_rssi_event_value)
+		sta->last_rssi_event_value =
+			-ewma_signal_read(&sta->rx_stats_avg.signal);
+
+	last = sta->last_rssi_event_value;
+	hyst = sta->rssi_hyst;
+	n = sta->n_rssi_tholds;
+
+	for (i = 0; i < n; i++)
+		if (last < sta->rssi_tholds[i])
+			break;
+
+	sta->rssi_low = i > 0 ? (sta->rssi_tholds[i - 1] - hyst) : S32_MIN;
+	sta->rssi_high = i < n ? (sta->rssi_tholds[i] + hyst - 1) : S32_MAX;
+}
+
+static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+					     struct net_device *dev,
+					     const u8 *mac_addr,
+					     const s32 *rssi_tholds,
+					     u32 rssi_hyst, int n_rssi_tholds,
+					     bool fixed_thold)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct sta_info *sta;
+	int ret = 0;
+
+	mutex_lock(&local->sta_mtx);
+
+	if (mac_addr) {
+		sta = sta_info_get_bss(sdata, mac_addr);
+		if (!sta) {
+			ret = -ENOENT;
+			goto out;
+		}
+
+		sta_mon_rssi_config_free(sta);
+		sta->rssi_hyst = rssi_hyst;
+		if (fixed_thold) {
+			if (n_rssi_tholds > 2) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			if (n_rssi_tholds == 1) {
+				sta->rssi_low = rssi_tholds[0];
+				sta->rssi_high = rssi_tholds[0];
+			} else {
+				sta->rssi_low = rssi_tholds[0];
+				sta->rssi_high = rssi_tholds[1];
+			}
+		} else {
+			const s32 *rssi_tholds;
+
+			rssi_tholds = kmemdup(rssi_tholds,
+					      n_rssi_tholds * sizeof(s32),
+					      GFP_KERNEL);
+			if (!rssi_tholds) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			sta->rssi_tholds = rssi_tholds;
+			sta->n_rssi_tholds = n_rssi_tholds;
+			ieee80211_update_rssi_config(sta);
+		}
+	}
+
+out:
+	mutex_unlock(&local->sta_mtx);
+	return ret;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -3944,4 +4034,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
 	.tx_control_port = ieee80211_tx_control_port,
 	.get_txq_stats = ieee80211_get_txq_stats,
 	.get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
+	.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
 };
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index fb8c225..28e9a6b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1020,6 +1020,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
 
 	rate_control_remove_sta_debugfs(sta);
 	ieee80211_sta_debugfs_remove(sta);
+	sta_mon_rssi_config_free(sta);
 
 	cleanup_single_sta(sta);
 }
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9a04327..acbad98 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -411,6 +411,9 @@ struct ieee80211_sta_rx_stats {
 	u64 msdu[IEEE80211_NUM_TIDS + 1];
 };
 
+struct sta_mon_rssi_config {
+};
+
 /*
  * The bandwidth threshold below which the per-station CoDel parameters will be
  * scaled to be more lenient (to prevent starvation of slow stations). This
@@ -482,6 +485,14 @@ struct ieee80211_sta_rx_stats {
  * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
  *	this (by advertising the USES_RSS hw flag)
  * @status_stats: TX status statistics
+ * @n_rssi_tholds: Number of thresholds passed by user
+ * @rssi_tholds: RSSI threshold limit passed by the user
+ * @rssi_low: RSSI lower threshold for this station, a zero value implies
+ *	disabled
+ * @rssi_high: RSSI upper threshold for this station
+ * @rssi_hyst: RSSI hysteresis for this station
+ * @last_rssi_event_value: Last RSSI value for this station triggered the
+ *	RSSI cross event.
  */
 struct sta_info {
 	/* General information, mostly static */
@@ -583,6 +594,13 @@ struct sta_info {
 
 	struct cfg80211_chan_def tdls_chandef;
 
+	int n_rssi_tholds;
+	const s32 *rssi_tholds;
+	s32 rssi_low;
+	s32 rssi_high;
+	u32 rssi_hyst;
+	s32 last_rssi_event_value;
+
 	/* keep last! */
 	struct ieee80211_sta sta;
 };
@@ -720,6 +738,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
 			  const u8 *addr);
 int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
 			      const u8 *addr);
+void sta_mon_rssi_config_free(struct sta_info *sta);
 
 void sta_info_recalc_tim(struct sta_info *sta);
 
