aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-02-17 09:52:35 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-04-09 04:55:39 -0400
commitcb2d956dd329caa11b5ece454dc52253aa038e73 (patch)
treee1f03836ab1dc2bd10e2249972c42534b0c08101 /net/wireless
parentc8866e55a94fb02b83b13f289e5e470fc928703a (diff)
cfg80211: refactor cfg80211_can_use_iftype_chan()
Separate the code that counts the interface types and channels from the code that check the interface combinations. The new function that checks for combinations is exported so it can be called by the drivers. This is done in preparation for moving the interface combinations checks out of cfg80211. Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
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,