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.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2d9760084b74..c040f8a0f1ed 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1307,6 +1307,9 @@ static bool ignore_reg_update(struct wiphy *wiphy,
1307{ 1307{
1308 struct regulatory_request *lr = get_last_request(); 1308 struct regulatory_request *lr = get_last_request();
1309 1309
1310 if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
1311 return true;
1312
1310 if (!lr) { 1313 if (!lr) {
1311 REG_DBG_PRINT("Ignoring regulatory request set by %s " 1314 REG_DBG_PRINT("Ignoring regulatory request set by %s "
1312 "since last_request is not set\n", 1315 "since last_request is not set\n",
@@ -2147,11 +2150,52 @@ static void reg_process_pending_beacon_hints(void)
2147 spin_unlock_bh(&reg_pending_beacons_lock); 2150 spin_unlock_bh(&reg_pending_beacons_lock);
2148} 2151}
2149 2152
2153static void reg_process_self_managed_hints(void)
2154{
2155 struct cfg80211_registered_device *rdev;
2156 struct wiphy *wiphy;
2157 const struct ieee80211_regdomain *tmp;
2158 const struct ieee80211_regdomain *regd;
2159 enum ieee80211_band band;
2160 struct regulatory_request request = {};
2161
2162 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2163 wiphy = &rdev->wiphy;
2164
2165 spin_lock(&reg_requests_lock);
2166 regd = rdev->requested_regd;
2167 rdev->requested_regd = NULL;
2168 spin_unlock(&reg_requests_lock);
2169
2170 if (regd == NULL)
2171 continue;
2172
2173 tmp = get_wiphy_regdom(wiphy);
2174 rcu_assign_pointer(wiphy->regd, regd);
2175 rcu_free_regdom(tmp);
2176
2177 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
2178 handle_band_custom(wiphy, wiphy->bands[band], regd);
2179
2180 reg_process_ht_flags(wiphy);
2181
2182 request.wiphy_idx = get_wiphy_idx(wiphy);
2183 request.alpha2[0] = regd->alpha2[0];
2184 request.alpha2[1] = regd->alpha2[1];
2185 request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
2186
2187 nl80211_send_wiphy_reg_change_event(&request);
2188 }
2189
2190 reg_check_channels();
2191}
2192
2150static void reg_todo(struct work_struct *work) 2193static void reg_todo(struct work_struct *work)
2151{ 2194{
2152 rtnl_lock(); 2195 rtnl_lock();
2153 reg_process_pending_hints(); 2196 reg_process_pending_hints();
2154 reg_process_pending_beacon_hints(); 2197 reg_process_pending_beacon_hints();
2198 reg_process_self_managed_hints();
2155 rtnl_unlock(); 2199 rtnl_unlock();
2156} 2200}
2157 2201
@@ -2432,6 +2476,8 @@ static void restore_regulatory_settings(bool reset_user)
2432 world_alpha2[1] = cfg80211_world_regdom->alpha2[1]; 2476 world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
2433 2477
2434 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 2478 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2479 if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
2480 continue;
2435 if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG) 2481 if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
2436 restore_custom_reg_settings(&rdev->wiphy); 2482 restore_custom_reg_settings(&rdev->wiphy);
2437 } 2483 }
@@ -2835,10 +2881,52 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2835 return 0; 2881 return 0;
2836} 2882}
2837 2883
2884int regulatory_set_wiphy_regd(struct wiphy *wiphy,
2885 struct ieee80211_regdomain *rd)
2886{
2887 const struct ieee80211_regdomain *regd;
2888 const struct ieee80211_regdomain *prev_regd;
2889 struct cfg80211_registered_device *rdev;
2890
2891 if (WARN_ON(!wiphy || !rd))
2892 return -EINVAL;
2893
2894 if (WARN(!(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED),
2895 "wiphy should have REGULATORY_WIPHY_SELF_MANAGED\n"))
2896 return -EPERM;
2897
2898 if (WARN(!is_valid_rd(rd), "Invalid regulatory domain detected\n")) {
2899 print_regdomain_info(rd);
2900 return -EINVAL;
2901 }
2902
2903 regd = reg_copy_regd(rd);
2904 if (IS_ERR(regd))
2905 return PTR_ERR(regd);
2906
2907 rdev = wiphy_to_rdev(wiphy);
2908
2909 spin_lock(&reg_requests_lock);
2910 prev_regd = rdev->requested_regd;
2911 rdev->requested_regd = regd;
2912 spin_unlock(&reg_requests_lock);
2913
2914 kfree(prev_regd);
2915
2916 schedule_work(&reg_work);
2917 return 0;
2918}
2919EXPORT_SYMBOL(regulatory_set_wiphy_regd);
2920
2838void wiphy_regulatory_register(struct wiphy *wiphy) 2921void wiphy_regulatory_register(struct wiphy *wiphy)
2839{ 2922{
2840 struct regulatory_request *lr; 2923 struct regulatory_request *lr;
2841 2924
2925 /* self-managed devices ignore external hints */
2926 if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
2927 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
2928 REGULATORY_COUNTRY_IE_IGNORE;
2929
2842 if (!reg_dev_ignore_cell_hint(wiphy)) 2930 if (!reg_dev_ignore_cell_hint(wiphy))
2843 reg_num_devs_support_basehint++; 2931 reg_num_devs_support_basehint++;
2844 2932