aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index ab801a1097b2..58d69959ab28 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -106,6 +106,9 @@ struct reg_beacon {
106static void reg_todo(struct work_struct *work); 106static void reg_todo(struct work_struct *work);
107static DECLARE_WORK(reg_work, reg_todo); 107static DECLARE_WORK(reg_work, reg_todo);
108 108
109static void reg_timeout_work(struct work_struct *work);
110static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work);
111
109/* We keep a static world regulatory domain in case of the absence of CRDA */ 112/* We keep a static world regulatory domain in case of the absence of CRDA */
110static const struct ieee80211_regdomain world_regdom = { 113static const struct ieee80211_regdomain world_regdom = {
111 .n_reg_rules = 5, 114 .n_reg_rules = 5,
@@ -1330,6 +1333,9 @@ static void reg_set_request_processed(void)
1330 need_more_processing = true; 1333 need_more_processing = true;
1331 spin_unlock(&reg_requests_lock); 1334 spin_unlock(&reg_requests_lock);
1332 1335
1336 if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
1337 cancel_delayed_work_sync(&reg_timeout);
1338
1333 if (need_more_processing) 1339 if (need_more_processing)
1334 schedule_work(&reg_work); 1340 schedule_work(&reg_work);
1335} 1341}
@@ -1440,8 +1446,17 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1440 r = __regulatory_hint(wiphy, reg_request); 1446 r = __regulatory_hint(wiphy, reg_request);
1441 /* This is required so that the orig_* parameters are saved */ 1447 /* This is required so that the orig_* parameters are saved */
1442 if (r == -EALREADY && wiphy && 1448 if (r == -EALREADY && wiphy &&
1443 wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) 1449 wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
1444 wiphy_update_regulatory(wiphy, initiator); 1450 wiphy_update_regulatory(wiphy, initiator);
1451 return;
1452 }
1453
1454 /*
1455 * We only time out user hints, given that they should be the only
1456 * source of bogus requests.
1457 */
1458 if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER)
1459 schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
1445} 1460}
1446 1461
1447/* 1462/*
@@ -1744,6 +1759,8 @@ static void restore_regulatory_settings(bool reset_user)
1744{ 1759{
1745 char alpha2[2]; 1760 char alpha2[2];
1746 struct reg_beacon *reg_beacon, *btmp; 1761 struct reg_beacon *reg_beacon, *btmp;
1762 struct regulatory_request *reg_request, *tmp;
1763 LIST_HEAD(tmp_reg_req_list);
1747 1764
1748 mutex_lock(&cfg80211_mutex); 1765 mutex_lock(&cfg80211_mutex);
1749 mutex_lock(&reg_mutex); 1766 mutex_lock(&reg_mutex);
@@ -1751,6 +1768,25 @@ static void restore_regulatory_settings(bool reset_user)
1751 reset_regdomains(); 1768 reset_regdomains();
1752 restore_alpha2(alpha2, reset_user); 1769 restore_alpha2(alpha2, reset_user);
1753 1770
1771 /*
1772 * If there's any pending requests we simply
1773 * stash them to a temporary pending queue and
1774 * add then after we've restored regulatory
1775 * settings.
1776 */
1777 spin_lock(&reg_requests_lock);
1778 if (!list_empty(&reg_requests_list)) {
1779 list_for_each_entry_safe(reg_request, tmp,
1780 &reg_requests_list, list) {
1781 if (reg_request->initiator !=
1782 NL80211_REGDOM_SET_BY_USER)
1783 continue;
1784 list_del(&reg_request->list);
1785 list_add_tail(&reg_request->list, &tmp_reg_req_list);
1786 }
1787 }
1788 spin_unlock(&reg_requests_lock);
1789
1754 /* Clear beacon hints */ 1790 /* Clear beacon hints */
1755 spin_lock_bh(&reg_pending_beacons_lock); 1791 spin_lock_bh(&reg_pending_beacons_lock);
1756 if (!list_empty(&reg_pending_beacons)) { 1792 if (!list_empty(&reg_pending_beacons)) {
@@ -1785,8 +1821,31 @@ static void restore_regulatory_settings(bool reset_user)
1785 */ 1821 */
1786 if (is_an_alpha2(alpha2)) 1822 if (is_an_alpha2(alpha2))
1787 regulatory_hint_user(user_alpha2); 1823 regulatory_hint_user(user_alpha2);
1788}
1789 1824
1825 if (list_empty(&tmp_reg_req_list))
1826 return;
1827
1828 mutex_lock(&cfg80211_mutex);
1829 mutex_lock(&reg_mutex);
1830
1831 spin_lock(&reg_requests_lock);
1832 list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) {
1833 REG_DBG_PRINT("Adding request for country %c%c back "
1834 "into the queue\n",
1835 reg_request->alpha2[0],
1836 reg_request->alpha2[1]);
1837 list_del(&reg_request->list);
1838 list_add_tail(&reg_request->list, &reg_requests_list);
1839 }
1840 spin_unlock(&reg_requests_lock);
1841
1842 mutex_unlock(&reg_mutex);
1843 mutex_unlock(&cfg80211_mutex);
1844
1845 REG_DBG_PRINT("Kicking the queue\n");
1846
1847 schedule_work(&reg_work);
1848}
1790 1849
1791void regulatory_hint_disconnect(void) 1850void regulatory_hint_disconnect(void)
1792{ 1851{
@@ -2125,6 +2184,13 @@ out:
2125 mutex_unlock(&reg_mutex); 2184 mutex_unlock(&reg_mutex);
2126} 2185}
2127 2186
2187static void reg_timeout_work(struct work_struct *work)
2188{
2189 REG_DBG_PRINT("Timeout while waiting for CRDA to reply, "
2190 "restoring regulatory settings");
2191 restore_regulatory_settings(true);
2192}
2193
2128int __init regulatory_init(void) 2194int __init regulatory_init(void)
2129{ 2195{
2130 int err = 0; 2196 int err = 0;
@@ -2178,6 +2244,7 @@ void /* __init_or_exit */ regulatory_exit(void)
2178 struct reg_beacon *reg_beacon, *btmp; 2244 struct reg_beacon *reg_beacon, *btmp;
2179 2245
2180 cancel_work_sync(&reg_work); 2246 cancel_work_sync(&reg_work);
2247 cancel_delayed_work_sync(&reg_timeout);
2181 2248
2182 mutex_lock(&cfg80211_mutex); 2249 mutex_lock(&cfg80211_mutex);
2183 mutex_lock(&reg_mutex); 2250 mutex_lock(&reg_mutex);