aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@do-not-panic.com>2013-11-05 12:18:05 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 14:51:10 -0500
commit21636c7faae0a980e73f366e164ffaa77a424786 (patch)
tree090765286c7187cace67aa5436cc763ec7312782 /net/wireless
parent0d97a61917d8c00adb9e445ec23ee09150d720a4 (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.c103
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
1501static 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 */
1533static enum reg_request_treatment
1534reg_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(&reg_timeout, msecs_to_jiffies(3142)); 1704 schedule_delayed_work(&reg_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;