diff options
-rw-r--r-- | net/wireless/reg.c | 114 |
1 files changed, 81 insertions, 33 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2b7ab01b2616..1bd590c2ed7f 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1337,6 +1337,7 @@ get_reg_request_treatment(struct wiphy *wiphy, | |||
1337 | 1337 | ||
1338 | switch (pending_request->initiator) { | 1338 | switch (pending_request->initiator) { |
1339 | case NL80211_REGDOM_SET_BY_CORE: | 1339 | case NL80211_REGDOM_SET_BY_CORE: |
1340 | case NL80211_REGDOM_SET_BY_USER: | ||
1340 | return REG_REQ_IGNORE; | 1341 | return REG_REQ_IGNORE; |
1341 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1342 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1342 | if (reg_request_cell_base(lr)) { | 1343 | if (reg_request_cell_base(lr)) { |
@@ -1388,36 +1389,6 @@ get_reg_request_treatment(struct wiphy *wiphy, | |||
1388 | return REG_REQ_ALREADY_SET; | 1389 | return REG_REQ_ALREADY_SET; |
1389 | 1390 | ||
1390 | return REG_REQ_INTERSECT; | 1391 | return REG_REQ_INTERSECT; |
1391 | case NL80211_REGDOM_SET_BY_USER: | ||
1392 | if (reg_request_cell_base(pending_request)) | ||
1393 | return reg_ignore_cell_hint(pending_request); | ||
1394 | |||
1395 | if (reg_request_cell_base(lr)) | ||
1396 | return REG_REQ_IGNORE; | ||
1397 | |||
1398 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
1399 | return REG_REQ_INTERSECT; | ||
1400 | /* | ||
1401 | * If the user knows better the user should set the regdom | ||
1402 | * to their country before the IE is picked up | ||
1403 | */ | ||
1404 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER && | ||
1405 | lr->intersect) | ||
1406 | return REG_REQ_IGNORE; | ||
1407 | /* | ||
1408 | * Process user requests only after previous user/driver/core | ||
1409 | * requests have been processed | ||
1410 | */ | ||
1411 | if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || | ||
1412 | lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || | ||
1413 | lr->initiator == NL80211_REGDOM_SET_BY_USER) && | ||
1414 | regdom_changes(lr->alpha2)) | ||
1415 | return REG_REQ_IGNORE; | ||
1416 | |||
1417 | if (!regdom_changes(pending_request->alpha2)) | ||
1418 | return REG_REQ_ALREADY_SET; | ||
1419 | |||
1420 | return REG_REQ_OK; | ||
1421 | } | 1392 | } |
1422 | 1393 | ||
1423 | return REG_REQ_IGNORE; | 1394 | return REG_REQ_IGNORE; |
@@ -1469,6 +1440,80 @@ reg_process_hint_core(struct regulatory_request *core_request) | |||
1469 | return REG_REQ_OK; | 1440 | return REG_REQ_OK; |
1470 | } | 1441 | } |
1471 | 1442 | ||
1443 | static enum reg_request_treatment | ||
1444 | __reg_process_hint_user(struct regulatory_request *user_request) | ||
1445 | { | ||
1446 | struct regulatory_request *lr = get_last_request(); | ||
1447 | |||
1448 | if (reg_request_cell_base(user_request)) | ||
1449 | return reg_ignore_cell_hint(user_request); | ||
1450 | |||
1451 | if (reg_request_cell_base(lr)) | ||
1452 | return REG_REQ_IGNORE; | ||
1453 | |||
1454 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
1455 | return REG_REQ_INTERSECT; | ||
1456 | /* | ||
1457 | * If the user knows better the user should set the regdom | ||
1458 | * to their country before the IE is picked up | ||
1459 | */ | ||
1460 | if (lr->initiator == NL80211_REGDOM_SET_BY_USER && | ||
1461 | lr->intersect) | ||
1462 | return REG_REQ_IGNORE; | ||
1463 | /* | ||
1464 | * Process user requests only after previous user/driver/core | ||
1465 | * requests have been processed | ||
1466 | */ | ||
1467 | if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || | ||
1468 | lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || | ||
1469 | lr->initiator == NL80211_REGDOM_SET_BY_USER) && | ||
1470 | regdom_changes(lr->alpha2)) | ||
1471 | return REG_REQ_IGNORE; | ||
1472 | |||
1473 | if (!regdom_changes(user_request->alpha2)) | ||
1474 | return REG_REQ_ALREADY_SET; | ||
1475 | |||
1476 | return REG_REQ_OK; | ||
1477 | } | ||
1478 | |||
1479 | /** | ||
1480 | * reg_process_hint_user - process user regulatory requests | ||
1481 | * @user_request: a pending user regulatory request | ||
1482 | * | ||
1483 | * The wireless subsystem can use this function to process | ||
1484 | * a regulatory request initiated by userspace. | ||
1485 | * | ||
1486 | * Returns one of the different reg request treatment values. | ||
1487 | */ | ||
1488 | static enum reg_request_treatment | ||
1489 | reg_process_hint_user(struct regulatory_request *user_request) | ||
1490 | { | ||
1491 | enum reg_request_treatment treatment; | ||
1492 | struct regulatory_request *lr; | ||
1493 | |||
1494 | treatment = __reg_process_hint_user(user_request); | ||
1495 | if (treatment == REG_REQ_IGNORE || | ||
1496 | treatment == REG_REQ_ALREADY_SET) { | ||
1497 | kfree(user_request); | ||
1498 | return treatment; | ||
1499 | } | ||
1500 | |||
1501 | lr = get_last_request(); | ||
1502 | if (lr != &core_request_world && lr) | ||
1503 | kfree_rcu(lr, rcu_head); | ||
1504 | |||
1505 | user_request->intersect = treatment == REG_REQ_INTERSECT; | ||
1506 | user_request->processed = false; | ||
1507 | rcu_assign_pointer(last_request, user_request); | ||
1508 | |||
1509 | user_alpha2[0] = user_request->alpha2[0]; | ||
1510 | user_alpha2[1] = user_request->alpha2[1]; | ||
1511 | |||
1512 | if (call_crda(user_request->alpha2)) | ||
1513 | return REG_REQ_IGNORE; | ||
1514 | return REG_REQ_OK; | ||
1515 | } | ||
1516 | |||
1472 | /** | 1517 | /** |
1473 | * __regulatory_hint - hint to the wireless core a regulatory domain | 1518 | * __regulatory_hint - hint to the wireless core a regulatory domain |
1474 | * @wiphy: if the hint comes from country information from an AP, this | 1519 | * @wiphy: if the hint comes from country information from an AP, this |
@@ -1585,6 +1630,12 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1585 | reg_process_hint_core(reg_request); | 1630 | reg_process_hint_core(reg_request); |
1586 | return; | 1631 | return; |
1587 | case NL80211_REGDOM_SET_BY_USER: | 1632 | case NL80211_REGDOM_SET_BY_USER: |
1633 | treatment = reg_process_hint_user(reg_request); | ||
1634 | if (treatment == REG_REQ_OK || | ||
1635 | treatment == REG_REQ_ALREADY_SET) | ||
1636 | return; | ||
1637 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | ||
1638 | return; | ||
1588 | case NL80211_REGDOM_SET_BY_DRIVER: | 1639 | case NL80211_REGDOM_SET_BY_DRIVER: |
1589 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1640 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1590 | treatment = __regulatory_hint(wiphy, reg_request); | 1641 | treatment = __regulatory_hint(wiphy, reg_request); |
@@ -1601,9 +1652,6 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1601 | wiphy_update_regulatory(wiphy, reg_request->initiator); | 1652 | wiphy_update_regulatory(wiphy, reg_request->initiator); |
1602 | break; | 1653 | break; |
1603 | default: | 1654 | default: |
1604 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) | ||
1605 | schedule_delayed_work(®_timeout, | ||
1606 | msecs_to_jiffies(3142)); | ||
1607 | break; | 1655 | break; |
1608 | } | 1656 | } |
1609 | } | 1657 | } |