@@ -4139,7 +4139,7 @@ static inline struct wiphy *wiphy_new(const struct cfg80211_ops *ops,
struct cfg80211_conn;
struct cfg80211_internal_bss;
struct cfg80211_cached_keys;
-struct cfg80211_cqm_config;
+struct cfg80211_rssi_config;
/**
* struct wireless_dev - wireless device state
@@ -4204,7 +4204,7 @@ static inline struct wiphy *wiphy_new(const struct cfg80211_ops *ops,
* @event_lock: (private) lock for event list
* @owner_nlportid: (private) owner socket port ID
* @nl_owner_dead: (private) owner socket went away
- * @cqm_config: (private) nl80211 RSSI monitor state
+ * @rssi_config: (private) nl80211 RSSI monitor state
*/
struct wireless_dev {
struct wiphy *wiphy;
@@ -4275,7 +4275,8 @@ struct wireless_dev {
} wext;
#endif
- struct cfg80211_cqm_config *cqm_config;
+ struct cfg80211_rssi_config *rssi_config;
+ struct list_head rssi_config_list;
};
static inline u8 *wdev_address(struct wireless_dev *wdev)
@@ -994,10 +994,28 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
}
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
-void cfg80211_cqm_config_free(struct wireless_dev *wdev)
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 *peer)
{
- kfree(wdev->cqm_config);
- wdev->cqm_config = NULL;
+ struct cfg80211_rssi_config *rssi_config, *tmp;
+
+ if (list_empty(&wdev->rssi_config_list))
+ goto free;
+
+ list_for_each_entry_safe(rssi_config, tmp, &wdev->rssi_config_list,
+ list) {
+ if (peer && memcmp(rssi_config->addr, peer, ETH_ALEN))
+ continue;
+
+ list_del(&rssi_config->list);
+ kfree(rssi_config);
+ if (list_empty(&wdev->rssi_config_list) || peer)
+ goto out;
+ }
+
+free:
+ kfree(wdev->rssi_config);
+out:
+ wdev->rssi_config = NULL;
}
void cfg80211_unregister_wdev(struct wireless_dev *wdev)
@@ -1027,7 +1045,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
break;
}
- cfg80211_cqm_config_free(wdev);
+ cfg80211_rssi_config_free(wdev, NULL);
}
EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -1163,6 +1181,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
+ INIT_LIST_HEAD(&wdev->rssi_config_list);
/*
* We get here also when the interface changes network namespaces,
@@ -1292,7 +1311,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
kzfree(wdev->wext.keys);
#endif
flush_work(&wdev->disconnect_wk);
- cfg80211_cqm_config_free(wdev);
+ cfg80211_rssi_config_free(wdev, NULL);
}
/*
* synchronise (so that we won't find this netdev
@@ -260,10 +260,12 @@ struct cfg80211_beacon_registration {
u32 nlportid;
};
-struct cfg80211_cqm_config {
+struct cfg80211_rssi_config {
+ struct list_head list;
u32 rssi_hyst;
s32 last_rssi_event_value;
int n_rssi_thresholds;
+ u8 addr[ETH_ALEN];
s32 rssi_thresholds[0];
};
@@ -514,6 +516,6 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
#define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; })
#endif
-void cfg80211_cqm_config_free(struct wireless_dev *wdev);
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 *peer);
#endif /* __NET_WIRELESS_CORE_H */
@@ -3200,6 +3200,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
+ INIT_LIST_HEAD(&wdev->rssi_config_list);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
@@ -10140,7 +10141,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
int err;
/* RSSI reporting disabled? */
- if (!wdev->cqm_config)
+ if (!wdev->rssi_config)
return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
/*
@@ -10149,7 +10150,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
* connection is established and enough beacons received to calculate
* the average.
*/
- if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss &&
+ if (!wdev->rssi_config->last_rssi_event_value && wdev->current_bss &&
rdev->ops->get_station) {
struct station_info sinfo = {};
u8 *mac_addr;
@@ -10161,26 +10162,56 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
return err;
if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
- wdev->cqm_config->last_rssi_event_value =
+ wdev->rssi_config->last_rssi_event_value =
(s8) sinfo.rx_beacon_signal_avg;
}
- last = wdev->cqm_config->last_rssi_event_value;
- hyst = wdev->cqm_config->rssi_hyst;
- n = wdev->cqm_config->n_rssi_thresholds;
+ last = wdev->rssi_config->last_rssi_event_value;
+ hyst = wdev->rssi_config->rssi_hyst;
+ n = wdev->rssi_config->n_rssi_thresholds;
for (i = 0; i < n; i++)
- if (last < wdev->cqm_config->rssi_thresholds[i])
+ if (last < wdev->rssi_config->rssi_thresholds[i])
break;
low = i > 0 ?
- (wdev->cqm_config->rssi_thresholds[i - 1] - hyst) : S32_MIN;
+ (wdev->rssi_config->rssi_thresholds[i - 1] - hyst) : S32_MIN;
high = i < n ?
- (wdev->cqm_config->rssi_thresholds[i] + hyst - 1) : S32_MAX;
+ (wdev->rssi_config->rssi_thresholds[i] + hyst - 1) : S32_MAX;
return rdev_set_cqm_rssi_range_config(rdev, dev, low, high);
}
+static struct cfg80211_rssi_config *
+cfg80211_get_rssi_config(struct wireless_dev *wdev, const s32 *thresholds,
+ int n_thresholds, u32 hysteresis, const u8 *peer)
+{
+ struct cfg80211_rssi_config *rssi_config;
+
+ if (!peer)
+ return NULL;
+
+ if (list_empty(&wdev->rssi_config_list))
+ goto new;
+
+ list_for_each_entry(rssi_config, &wdev->rssi_config_list, list) {
+ if (!memcmp(rssi_config->addr, peer, ETH_ALEN))
+ goto found;
+ }
+
+new:
+ rssi_config = kzalloc(sizeof(struct cfg80211_rssi_config) +
+ n_thresholds * sizeof(s32), GFP_KERNEL);
+ list_add(&rssi_config->list, &wdev->rssi_config_list);
+found:
+ rssi_config->rssi_hyst = hysteresis;
+ rssi_config->n_rssi_thresholds = n_thresholds;
+ memcpy(rssi_config->addr, peer, ETH_ALEN);
+ memcpy(rssi_config->rssi_thresholds, thresholds,
+ n_thresholds * sizeof(s32));
+ return rssi_config;
+}
+
static int nl80211_set_cqm_rssi(struct genl_info *info,
const s32 *thresholds, int n_thresholds,
u32 hysteresis)
@@ -10204,7 +10235,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
return -EOPNOTSUPP;
wdev_lock(wdev);
- cfg80211_cqm_config_free(wdev);
+ cfg80211_rssi_config_free(wdev, NULL);
wdev_unlock(wdev);
if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
@@ -10224,21 +10255,14 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
wdev_lock(wdev);
if (n_thresholds) {
- struct cfg80211_cqm_config *cqm_config;
-
- cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) +
- n_thresholds * sizeof(s32), GFP_KERNEL);
- if (!cqm_config) {
+ wdev->rssi_config = cfg80211_get_rssi_config(
+ wdev, thresholds,
+ n_thresholds, hysteresis,
+ wdev->current_bss->pub.bssid);
+ if (!wdev->rssi_config) {
err = -ENOMEM;
goto unlock;
}
-
- cqm_config->rssi_hyst = hysteresis;
- cqm_config->n_rssi_thresholds = n_thresholds;
- memcpy(cqm_config->rssi_thresholds, thresholds,
- n_thresholds * sizeof(s32));
-
- wdev->cqm_config = cqm_config;
}
err = cfg80211_cqm_rssi_update(rdev, dev);
@@ -15053,13 +15077,13 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
return;
- if (wdev->cqm_config) {
- wdev->cqm_config->last_rssi_event_value = rssi_level;
+ if (wdev->rssi_config) {
+ wdev->rssi_config->last_rssi_event_value = rssi_level;
cfg80211_cqm_rssi_update(rdev, dev);
if (rssi_level == 0)
- rssi_level = wdev->cqm_config->last_rssi_event_value;
+ rssi_level = wdev->rssi_config->last_rssi_event_value;
}
msg = cfg80211_prepare_cqm(dev, NULL, gfp);
This patch changes single cqm_config into mac address based rssi config list. This way the same structure can be utilized by AP mode as well. Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org> --- include/net/cfg80211.h | 7 +++-- net/wireless/core.c | 29 ++++++++++++++++---- net/wireless/core.h | 6 ++-- net/wireless/nl80211.c | 74 +++++++++++++++++++++++++++++++++----------------- 4 files changed, 81 insertions(+), 35 deletions(-)