summaryrefslogtreecommitdiff
path: root/net/wireless/util.c
diff options
context:
space:
mode:
authorPurushottam Kushwaha <pkushwah@qti.qualcomm.com>2016-10-27 17:32:05 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-02 04:22:03 -0700
commitbe04d39c8b866850f6b2f0a8516bd74450fa6635 (patch)
tree35ca9db731d833b6465db4039700e3a90b91453f /net/wireless/util.c
parentb67bb93f565e831efbcdea58a6751737064d3fc6 (diff)
cfg80211: support virtual interfaces with different beacon intervals
This commit provides a mechanism for the host drivers to advertise the support for different beacon intervals among the respective interface combinations in a group, through NL80211_IFACE_COMB_BI_MIN_GCD (u32). This value will be compared against GCD of all beaconing interfaces of matching combinations. If the driver doesn't advertise this value, the old behaviour where all beacon intervals must be identical is retained. If it is specified, then any beacon interval for an interface in the interface combination as well as the GCD of all active beacon intervals in the combination must be greater or equal to this value. Signed-off-by: Purushottam Kushwaha <pkushwah@qti.qualcomm.com> [change commit message, some variable names, small other things] Signed-off-by: Johannes Berg <johannes.berg@intel.com> Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git Git-commit: 0c317a02ca982ca093e71bf07cb562265ba40032 CRs-fixed: 1025311 Change-Id: Ie432af1fefc79f88ec67d212f8b9880355c4266d Signed-off-by: Purushottam Kushwaha <pkushwah@codeaurora.org> [pkushwah@codeaurora.org: This commit also includes fix for memory leak which was introduced by 0c317a02ca982ca093e71bf07cb562265ba40032 320c975f180b19296f0fd6c5bf2144e633aaba5e: cfg80211: fix possible memory leak in cfg80211_iter_combinations()]
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 6822b4e57fad..acff02fcc281 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1483,24 +1483,46 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int)
+ enum nl80211_iftype iftype, u32 beacon_int)
{
struct wireless_dev *wdev;
- int res = 0;
+ struct iface_combination_params params = {
+ .beacon_int_gcd = beacon_int, /* GCD(n) = n */
+ };
if (!beacon_int)
return -EINVAL;
+ params.iftype_num[iftype] = 1;
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
- if (wdev->beacon_interval != beacon_int) {
- res = -EINVAL;
- break;
+
+ params.iftype_num[wdev->iftype]++;
+ }
+
+ list_for_each_entry(wdev, &rdev->wdev_list, list) {
+ u32 bi_prev = wdev->beacon_interval;
+
+ if (!wdev->beacon_interval)
+ continue;
+
+ /* slight optimisation - skip identical BIs */
+ if (wdev->beacon_interval == beacon_int)
+ continue;
+
+ params.beacon_int_different = true;
+
+ /* Get the GCD */
+ while (bi_prev != 0) {
+ u32 tmp_bi = bi_prev;
+
+ bi_prev = params.beacon_int_gcd % bi_prev;
+ params.beacon_int_gcd = tmp_bi;
}
}
- return res;
+ return cfg80211_check_combinations(&rdev->wiphy, &params);
}
int cfg80211_iter_combinations(struct wiphy *wiphy,
@@ -1576,6 +1598,17 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;
+ if (params->beacon_int_gcd) {
+ if (c->beacon_int_min_gcd &&
+ params->beacon_int_gcd < c->beacon_int_min_gcd) {
+ kfree(limits);
+ return -EINVAL;
+ }
+ if (!c->beacon_int_min_gcd &&
+ params->beacon_int_different)
+ goto cont;
+ }
+
/* This combination covered all interface types and
* supported the requested numbers, so we're good.
*/