diff options
author | Ilan Peer <ilan.peer@intel.com> | 2019-03-15 11:39:00 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2019-03-29 06:20:58 -0400 |
commit | 08a75a887ee46828b54600f4bb7068d872a5edd5 (patch) | |
tree | 48e36ca08a9dcf77587ba8e55240e8b98f83d93a /net/wireless | |
parent | 78be2d21cc1cd3069c6138dcfecec62583130171 (diff) |
cfg80211: Handle WMM rules in regulatory domain intersection
The support added for regulatory WMM rules did not handle
the case of regulatory domain intersections. Fix it.
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Fixes: 230ebaa189af ("cfg80211: read wmm rules from regulatory database")
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/reg.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2f1bf91eb226..0ba778f371cb 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1309,6 +1309,16 @@ reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1, | |||
1309 | return dfs_region1; | 1309 | return dfs_region1; |
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | static void reg_wmm_rules_intersect(const struct ieee80211_wmm_ac *wmm_ac1, | ||
1313 | const struct ieee80211_wmm_ac *wmm_ac2, | ||
1314 | struct ieee80211_wmm_ac *intersect) | ||
1315 | { | ||
1316 | intersect->cw_min = max_t(u16, wmm_ac1->cw_min, wmm_ac2->cw_min); | ||
1317 | intersect->cw_max = max_t(u16, wmm_ac1->cw_max, wmm_ac2->cw_max); | ||
1318 | intersect->cot = min_t(u16, wmm_ac1->cot, wmm_ac2->cot); | ||
1319 | intersect->aifsn = max_t(u8, wmm_ac1->aifsn, wmm_ac2->aifsn); | ||
1320 | } | ||
1321 | |||
1312 | /* | 1322 | /* |
1313 | * Helper for regdom_intersect(), this does the real | 1323 | * Helper for regdom_intersect(), this does the real |
1314 | * mathematical intersection fun | 1324 | * mathematical intersection fun |
@@ -1323,6 +1333,8 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, | |||
1323 | struct ieee80211_freq_range *freq_range; | 1333 | struct ieee80211_freq_range *freq_range; |
1324 | const struct ieee80211_power_rule *power_rule1, *power_rule2; | 1334 | const struct ieee80211_power_rule *power_rule1, *power_rule2; |
1325 | struct ieee80211_power_rule *power_rule; | 1335 | struct ieee80211_power_rule *power_rule; |
1336 | const struct ieee80211_wmm_rule *wmm_rule1, *wmm_rule2; | ||
1337 | struct ieee80211_wmm_rule *wmm_rule; | ||
1326 | u32 freq_diff, max_bandwidth1, max_bandwidth2; | 1338 | u32 freq_diff, max_bandwidth1, max_bandwidth2; |
1327 | 1339 | ||
1328 | freq_range1 = &rule1->freq_range; | 1340 | freq_range1 = &rule1->freq_range; |
@@ -1333,6 +1345,10 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, | |||
1333 | power_rule2 = &rule2->power_rule; | 1345 | power_rule2 = &rule2->power_rule; |
1334 | power_rule = &intersected_rule->power_rule; | 1346 | power_rule = &intersected_rule->power_rule; |
1335 | 1347 | ||
1348 | wmm_rule1 = &rule1->wmm_rule; | ||
1349 | wmm_rule2 = &rule2->wmm_rule; | ||
1350 | wmm_rule = &intersected_rule->wmm_rule; | ||
1351 | |||
1336 | freq_range->start_freq_khz = max(freq_range1->start_freq_khz, | 1352 | freq_range->start_freq_khz = max(freq_range1->start_freq_khz, |
1337 | freq_range2->start_freq_khz); | 1353 | freq_range2->start_freq_khz); |
1338 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, | 1354 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, |
@@ -1376,6 +1392,29 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, | |||
1376 | intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms, | 1392 | intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms, |
1377 | rule2->dfs_cac_ms); | 1393 | rule2->dfs_cac_ms); |
1378 | 1394 | ||
1395 | if (rule1->has_wmm && rule2->has_wmm) { | ||
1396 | u8 ac; | ||
1397 | |||
1398 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
1399 | reg_wmm_rules_intersect(&wmm_rule1->client[ac], | ||
1400 | &wmm_rule2->client[ac], | ||
1401 | &wmm_rule->client[ac]); | ||
1402 | reg_wmm_rules_intersect(&wmm_rule1->ap[ac], | ||
1403 | &wmm_rule2->ap[ac], | ||
1404 | &wmm_rule->ap[ac]); | ||
1405 | } | ||
1406 | |||
1407 | intersected_rule->has_wmm = true; | ||
1408 | } else if (rule1->has_wmm) { | ||
1409 | *wmm_rule = *wmm_rule1; | ||
1410 | intersected_rule->has_wmm = true; | ||
1411 | } else if (rule2->has_wmm) { | ||
1412 | *wmm_rule = *wmm_rule2; | ||
1413 | intersected_rule->has_wmm = true; | ||
1414 | } else { | ||
1415 | intersected_rule->has_wmm = false; | ||
1416 | } | ||
1417 | |||
1379 | if (!is_valid_reg_rule(intersected_rule)) | 1418 | if (!is_valid_reg_rule(intersected_rule)) |
1380 | return -EINVAL; | 1419 | return -EINVAL; |
1381 | 1420 | ||