aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/util.c129
1 files changed, 73 insertions, 56 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index e5872ff2c27c..46f404df35e3 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1268,6 +1268,76 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
1268 return res; 1268 return res;
1269} 1269}
1270 1270
1271int cfg80211_check_combinations(struct wiphy *wiphy,
1272 const int num_different_channels,
1273 const u8 radar_detect,
1274 const int iftype_num[NUM_NL80211_IFTYPES])
1275{
1276 int i, j, iftype;
1277 int num_interfaces = 0;
1278 u32 used_iftypes = 0;
1279
1280 for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
1281 num_interfaces += iftype_num[iftype];
1282 if (iftype_num[iftype] > 0 &&
1283 !(wiphy->software_iftypes & BIT(iftype)))
1284 used_iftypes |= BIT(iftype);
1285 }
1286
1287 for (i = 0; i < wiphy->n_iface_combinations; i++) {
1288 const struct ieee80211_iface_combination *c;
1289 struct ieee80211_iface_limit *limits;
1290 u32 all_iftypes = 0;
1291
1292 c = &wiphy->iface_combinations[i];
1293
1294 if (num_interfaces > c->max_interfaces)
1295 continue;
1296 if (num_different_channels > c->num_different_channels)
1297 continue;
1298
1299 limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
1300 GFP_KERNEL);
1301 if (!limits)
1302 return -ENOMEM;
1303
1304 for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
1305 if (wiphy->software_iftypes & BIT(iftype))
1306 continue;
1307 for (j = 0; j < c->n_limits; j++) {
1308 all_iftypes |= limits[j].types;
1309 if (!(limits[j].types & BIT(iftype)))
1310 continue;
1311 if (limits[j].max < iftype_num[iftype])
1312 goto cont;
1313 limits[j].max -= iftype_num[iftype];
1314 }
1315 }
1316
1317 if (radar_detect && !(c->radar_detect_widths & radar_detect))
1318 goto cont;
1319
1320 /* Finally check that all iftypes that we're currently
1321 * using are actually part of this combination. If they
1322 * aren't then we can't use this combination and have
1323 * to continue to the next.
1324 */
1325 if ((all_iftypes & used_iftypes) != used_iftypes)
1326 goto cont;
1327
1328 /* This combination covered all interface types and
1329 * supported the requested numbers, so we're good.
1330 */
1331 kfree(limits);
1332 return 0;
1333 cont:
1334 kfree(limits);
1335 }
1336
1337 return -EBUSY;
1338}
1339EXPORT_SYMBOL(cfg80211_check_combinations);
1340
1271int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, 1341int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1272 struct wireless_dev *wdev, 1342 struct wireless_dev *wdev,
1273 enum nl80211_iftype iftype, 1343 enum nl80211_iftype iftype,
@@ -1276,7 +1346,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1276 u8 radar_detect) 1346 u8 radar_detect)
1277{ 1347{
1278 struct wireless_dev *wdev_iter; 1348 struct wireless_dev *wdev_iter;
1279 u32 used_iftypes = BIT(iftype);
1280 int num[NUM_NL80211_IFTYPES]; 1349 int num[NUM_NL80211_IFTYPES];
1281 struct ieee80211_channel 1350 struct ieee80211_channel
1282 *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS]; 1351 *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
@@ -1284,7 +1353,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1284 enum cfg80211_chan_mode chmode; 1353 enum cfg80211_chan_mode chmode;
1285 int num_different_channels = 0; 1354 int num_different_channels = 0;
1286 int total = 1; 1355 int total = 1;
1287 int i, j; 1356 int i;
1288 1357
1289 ASSERT_RTNL(); 1358 ASSERT_RTNL();
1290 1359
@@ -1369,65 +1438,13 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1369 1438
1370 num[wdev_iter->iftype]++; 1439 num[wdev_iter->iftype]++;
1371 total++; 1440 total++;
1372 used_iftypes |= BIT(wdev_iter->iftype);
1373 } 1441 }
1374 1442
1375 if (total == 1 && !radar_detect) 1443 if (total == 1 && !radar_detect)
1376 return 0; 1444 return 0;
1377 1445
1378 for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { 1446 return cfg80211_check_combinations(&rdev->wiphy, num_different_channels,
1379 const struct ieee80211_iface_combination *c; 1447 radar_detect, num);
1380 struct ieee80211_iface_limit *limits;
1381 u32 all_iftypes = 0;
1382
1383 c = &rdev->wiphy.iface_combinations[i];
1384
1385 if (total > c->max_interfaces)
1386 continue;
1387 if (num_different_channels > c->num_different_channels)
1388 continue;
1389
1390 limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
1391 GFP_KERNEL);
1392 if (!limits)
1393 return -ENOMEM;
1394
1395 for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
1396 if (rdev->wiphy.software_iftypes & BIT(iftype))
1397 continue;
1398 for (j = 0; j < c->n_limits; j++) {
1399 all_iftypes |= limits[j].types;
1400 if (!(limits[j].types & BIT(iftype)))
1401 continue;
1402 if (limits[j].max < num[iftype])
1403 goto cont;
1404 limits[j].max -= num[iftype];
1405 }
1406 }
1407
1408 if (radar_detect && !(c->radar_detect_widths & radar_detect))
1409 goto cont;
1410
1411 /*
1412 * Finally check that all iftypes that we're currently
1413 * using are actually part of this combination. If they
1414 * aren't then we can't use this combination and have
1415 * to continue to the next.
1416 */
1417 if ((all_iftypes & used_iftypes) != used_iftypes)
1418 goto cont;
1419
1420 /*
1421 * This combination covered all interface types and
1422 * supported the requested numbers, so we're good.
1423 */
1424 kfree(limits);
1425 return 0;
1426 cont:
1427 kfree(limits);
1428 }
1429
1430 return -EBUSY;
1431} 1448}
1432 1449
1433int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, 1450int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,