|
@@ -1268,6 +1268,76 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int cfg80211_check_combinations(struct wiphy *wiphy,
|
|
|
|
+ const int num_different_channels,
|
|
|
|
+ const u8 radar_detect,
|
|
|
|
+ const int iftype_num[NUM_NL80211_IFTYPES])
|
|
|
|
+{
|
|
|
|
+ int i, j, iftype;
|
|
|
|
+ int num_interfaces = 0;
|
|
|
|
+ u32 used_iftypes = 0;
|
|
|
|
+
|
|
|
|
+ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
|
|
|
|
+ num_interfaces += iftype_num[iftype];
|
|
|
|
+ if (iftype_num[iftype] > 0 &&
|
|
|
|
+ !(wiphy->software_iftypes & BIT(iftype)))
|
|
|
|
+ used_iftypes |= BIT(iftype);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < wiphy->n_iface_combinations; i++) {
|
|
|
|
+ const struct ieee80211_iface_combination *c;
|
|
|
|
+ struct ieee80211_iface_limit *limits;
|
|
|
|
+ u32 all_iftypes = 0;
|
|
|
|
+
|
|
|
|
+ c = &wiphy->iface_combinations[i];
|
|
|
|
+
|
|
|
|
+ if (num_interfaces > c->max_interfaces)
|
|
|
|
+ continue;
|
|
|
|
+ if (num_different_channels > c->num_different_channels)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (!limits)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
|
|
|
|
+ if (wiphy->software_iftypes & BIT(iftype))
|
|
|
|
+ continue;
|
|
|
|
+ for (j = 0; j < c->n_limits; j++) {
|
|
|
|
+ all_iftypes |= limits[j].types;
|
|
|
|
+ if (!(limits[j].types & BIT(iftype)))
|
|
|
|
+ continue;
|
|
|
|
+ if (limits[j].max < iftype_num[iftype])
|
|
|
|
+ goto cont;
|
|
|
|
+ limits[j].max -= iftype_num[iftype];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (radar_detect && !(c->radar_detect_widths & radar_detect))
|
|
|
|
+ goto cont;
|
|
|
|
+
|
|
|
|
+ /* Finally check that all iftypes that we're currently
|
|
|
|
+ * using are actually part of this combination. If they
|
|
|
|
+ * aren't then we can't use this combination and have
|
|
|
|
+ * to continue to the next.
|
|
|
|
+ */
|
|
|
|
+ if ((all_iftypes & used_iftypes) != used_iftypes)
|
|
|
|
+ goto cont;
|
|
|
|
+
|
|
|
|
+ /* This combination covered all interface types and
|
|
|
|
+ * supported the requested numbers, so we're good.
|
|
|
|
+ */
|
|
|
|
+ kfree(limits);
|
|
|
|
+ return 0;
|
|
|
|
+ cont:
|
|
|
|
+ kfree(limits);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return -EBUSY;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(cfg80211_check_combinations);
|
|
|
|
+
|
|
int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|
int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|
struct wireless_dev *wdev,
|
|
struct wireless_dev *wdev,
|
|
enum nl80211_iftype iftype,
|
|
enum nl80211_iftype iftype,
|
|
@@ -1276,7 +1346,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|
u8 radar_detect)
|
|
u8 radar_detect)
|
|
{
|
|
{
|
|
struct wireless_dev *wdev_iter;
|
|
struct wireless_dev *wdev_iter;
|
|
- u32 used_iftypes = BIT(iftype);
|
|
|
|
int num[NUM_NL80211_IFTYPES];
|
|
int num[NUM_NL80211_IFTYPES];
|
|
struct ieee80211_channel
|
|
struct ieee80211_channel
|
|
*used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
|
|
*used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
|
|
@@ -1284,7 +1353,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|
enum cfg80211_chan_mode chmode;
|
|
enum cfg80211_chan_mode chmode;
|
|
int num_different_channels = 0;
|
|
int num_different_channels = 0;
|
|
int total = 1;
|
|
int total = 1;
|
|
- int i, j;
|
|
|
|
|
|
+ int i;
|
|
|
|
|
|
ASSERT_RTNL();
|
|
ASSERT_RTNL();
|
|
|
|
|
|
@@ -1369,65 +1438,13 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
|
|
|
|
|
|
num[wdev_iter->iftype]++;
|
|
num[wdev_iter->iftype]++;
|
|
total++;
|
|
total++;
|
|
- used_iftypes |= BIT(wdev_iter->iftype);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (total == 1 && !radar_detect)
|
|
if (total == 1 && !radar_detect)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
|
|
|
|
- const struct ieee80211_iface_combination *c;
|
|
|
|
- struct ieee80211_iface_limit *limits;
|
|
|
|
- u32 all_iftypes = 0;
|
|
|
|
-
|
|
|
|
- c = &rdev->wiphy.iface_combinations[i];
|
|
|
|
-
|
|
|
|
- if (total > c->max_interfaces)
|
|
|
|
- continue;
|
|
|
|
- if (num_different_channels > c->num_different_channels)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
|
|
|
|
- GFP_KERNEL);
|
|
|
|
- if (!limits)
|
|
|
|
- return -ENOMEM;
|
|
|
|
-
|
|
|
|
- for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
|
|
|
|
- if (rdev->wiphy.software_iftypes & BIT(iftype))
|
|
|
|
- continue;
|
|
|
|
- for (j = 0; j < c->n_limits; j++) {
|
|
|
|
- all_iftypes |= limits[j].types;
|
|
|
|
- if (!(limits[j].types & BIT(iftype)))
|
|
|
|
- continue;
|
|
|
|
- if (limits[j].max < num[iftype])
|
|
|
|
- goto cont;
|
|
|
|
- limits[j].max -= num[iftype];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (radar_detect && !(c->radar_detect_widths & radar_detect))
|
|
|
|
- goto cont;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Finally check that all iftypes that we're currently
|
|
|
|
- * using are actually part of this combination. If they
|
|
|
|
- * aren't then we can't use this combination and have
|
|
|
|
- * to continue to the next.
|
|
|
|
- */
|
|
|
|
- if ((all_iftypes & used_iftypes) != used_iftypes)
|
|
|
|
- goto cont;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * This combination covered all interface types and
|
|
|
|
- * supported the requested numbers, so we're good.
|
|
|
|
- */
|
|
|
|
- kfree(limits);
|
|
|
|
- return 0;
|
|
|
|
- cont:
|
|
|
|
- kfree(limits);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
+ return cfg80211_check_combinations(&rdev->wiphy, num_different_channels,
|
|
|
|
+ radar_detect, num);
|
|
}
|
|
}
|
|
|
|
|
|
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
|
|
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
|