diff options
author | Luis R. Rodriguez <mcgrof@do-not-panic.com> | 2013-11-05 12:18:05 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-11-25 14:51:10 -0500 |
commit | 21636c7faae0a980e73f366e164ffaa77a424786 (patch) | |
tree | 090765286c7187cace67aa5436cc763ec7312782 /net/wireless | |
parent | 0d97a61917d8c00adb9e445ec23ee09150d720a4 (diff) |
cfg80211: process driver regulatory requests on its own
This makes the code easier to read and follow.
Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/reg.c | 103 |
1 files changed, 86 insertions, 17 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1bd590c2ed7f..7188ef9f07b6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1338,6 +1338,7 @@ get_reg_request_treatment(struct wiphy *wiphy, | |||
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 | case NL80211_REGDOM_SET_BY_USER: |
1341 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
1341 | return REG_REQ_IGNORE; | 1342 | return REG_REQ_IGNORE; |
1342 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1343 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1343 | if (reg_request_cell_base(lr)) { | 1344 | if (reg_request_cell_base(lr)) { |
@@ -1372,23 +1373,6 @@ get_reg_request_treatment(struct wiphy *wiphy, | |||
1372 | return REG_REQ_ALREADY_SET; | 1373 | return REG_REQ_ALREADY_SET; |
1373 | } | 1374 | } |
1374 | return REG_REQ_OK; | 1375 | return REG_REQ_OK; |
1375 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
1376 | if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { | ||
1377 | if (regdom_changes(pending_request->alpha2)) | ||
1378 | return REG_REQ_OK; | ||
1379 | return REG_REQ_ALREADY_SET; | ||
1380 | } | ||
1381 | |||
1382 | /* | ||
1383 | * This would happen if you unplug and plug your card | ||
1384 | * back in or if you add a new device for which the previously | ||
1385 | * loaded card also agrees on the regulatory domain. | ||
1386 | */ | ||
1387 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | ||
1388 | !regdom_changes(pending_request->alpha2)) | ||
1389 | return REG_REQ_ALREADY_SET; | ||
1390 | |||
1391 | return REG_REQ_INTERSECT; | ||
1392 | } | 1376 | } |
1393 | 1377 | ||
1394 | return REG_REQ_IGNORE; | 1378 | return REG_REQ_IGNORE; |
@@ -1514,6 +1498,89 @@ reg_process_hint_user(struct regulatory_request *user_request) | |||
1514 | return REG_REQ_OK; | 1498 | return REG_REQ_OK; |
1515 | } | 1499 | } |
1516 | 1500 | ||
1501 | static enum reg_request_treatment | ||
1502 | __reg_process_hint_driver(struct regulatory_request *driver_request) | ||
1503 | { | ||
1504 | struct regulatory_request *lr = get_last_request(); | ||
1505 | |||
1506 | if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { | ||
1507 | if (regdom_changes(driver_request->alpha2)) | ||
1508 | return REG_REQ_OK; | ||
1509 | return REG_REQ_ALREADY_SET; | ||
1510 | } | ||
1511 | |||
1512 | /* | ||
1513 | * This would happen if you unplug and plug your card | ||
1514 | * back in or if you add a new device for which the previously | ||
1515 | * loaded card also agrees on the regulatory domain. | ||
1516 | */ | ||
1517 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | ||
1518 | !regdom_changes(driver_request->alpha2)) | ||
1519 | return REG_REQ_ALREADY_SET; | ||
1520 | |||
1521 | return REG_REQ_INTERSECT; | ||
1522 | } | ||
1523 | |||
1524 | /** | ||
1525 | * reg_process_hint_driver - process driver regulatory requests | ||
1526 | * @driver_request: a pending driver regulatory request | ||
1527 | * | ||
1528 | * The wireless subsystem can use this function to process | ||
1529 | * a regulatory request issued by an 802.11 driver. | ||
1530 | * | ||
1531 | * Returns one of the different reg request treatment values. | ||
1532 | */ | ||
1533 | static enum reg_request_treatment | ||
1534 | reg_process_hint_driver(struct wiphy *wiphy, | ||
1535 | struct regulatory_request *driver_request) | ||
1536 | { | ||
1537 | const struct ieee80211_regdomain *regd; | ||
1538 | enum reg_request_treatment treatment; | ||
1539 | struct regulatory_request *lr; | ||
1540 | |||
1541 | treatment = __reg_process_hint_driver(driver_request); | ||
1542 | |||
1543 | switch (treatment) { | ||
1544 | case REG_REQ_OK: | ||
1545 | break; | ||
1546 | case REG_REQ_IGNORE: | ||
1547 | kfree(driver_request); | ||
1548 | return treatment; | ||
1549 | case REG_REQ_INTERSECT: | ||
1550 | /* fall through */ | ||
1551 | case REG_REQ_ALREADY_SET: | ||
1552 | regd = reg_copy_regd(get_cfg80211_regdom()); | ||
1553 | if (IS_ERR(regd)) { | ||
1554 | kfree(driver_request); | ||
1555 | return REG_REQ_IGNORE; | ||
1556 | } | ||
1557 | rcu_assign_pointer(wiphy->regd, regd); | ||
1558 | } | ||
1559 | |||
1560 | lr = get_last_request(); | ||
1561 | if (lr != &core_request_world && lr) | ||
1562 | kfree_rcu(lr, rcu_head); | ||
1563 | |||
1564 | driver_request->intersect = treatment == REG_REQ_INTERSECT; | ||
1565 | driver_request->processed = false; | ||
1566 | rcu_assign_pointer(last_request, driver_request); | ||
1567 | |||
1568 | /* | ||
1569 | * Since CRDA will not be called in this case as we already | ||
1570 | * have applied the requested regulatory domain before we just | ||
1571 | * inform userspace we have processed the request | ||
1572 | */ | ||
1573 | if (treatment == REG_REQ_ALREADY_SET) { | ||
1574 | nl80211_send_reg_change_event(driver_request); | ||
1575 | reg_set_request_processed(); | ||
1576 | return treatment; | ||
1577 | } | ||
1578 | |||
1579 | if (call_crda(driver_request->alpha2)) | ||
1580 | return REG_REQ_IGNORE; | ||
1581 | return REG_REQ_OK; | ||
1582 | } | ||
1583 | |||
1517 | /** | 1584 | /** |
1518 | * __regulatory_hint - hint to the wireless core a regulatory domain | 1585 | * __regulatory_hint - hint to the wireless core a regulatory domain |
1519 | * @wiphy: if the hint comes from country information from an AP, this | 1586 | * @wiphy: if the hint comes from country information from an AP, this |
@@ -1637,6 +1704,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1637 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | 1704 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); |
1638 | return; | 1705 | return; |
1639 | case NL80211_REGDOM_SET_BY_DRIVER: | 1706 | case NL80211_REGDOM_SET_BY_DRIVER: |
1707 | treatment = reg_process_hint_driver(wiphy, reg_request); | ||
1708 | break; | ||
1640 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1709 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1641 | treatment = __regulatory_hint(wiphy, reg_request); | 1710 | treatment = __regulatory_hint(wiphy, reg_request); |
1642 | break; | 1711 | break; |