aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/wireless/reg.c114
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
1443static 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 */
1488static enum reg_request_treatment
1489reg_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(&reg_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(&reg_timeout,
1606 msecs_to_jiffies(3142));
1607 break; 1655 break;
1608 } 1656 }
1609} 1657}