diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/util.c | 129 |
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 | ||
1271 | int 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 | } | ||
1339 | EXPORT_SYMBOL(cfg80211_check_combinations); | ||
1340 | |||
1271 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | 1341 | int 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 | ||
1433 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | 1450 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, |