cfg80211: make regulatory_hint() remove REGULATORY_CUSTOM_REG
[deliverable/linux.git] / net / wireless / reg.c
index 6ad7b29688629a51853e4dbcb0ed83bb12cf18a2..9b897fca7487dd4fe8d8364368e8516ab8f369c0 100644 (file)
@@ -120,6 +120,48 @@ static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
        return rtnl_dereference(wiphy->regd);
 }
 
+static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
+{
+       switch (dfs_region) {
+       case NL80211_DFS_UNSET:
+               return "unset";
+       case NL80211_DFS_FCC:
+               return "FCC";
+       case NL80211_DFS_ETSI:
+               return "ETSI";
+       case NL80211_DFS_JP:
+               return "JP";
+       }
+       return "Unknown";
+}
+
+enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy)
+{
+       const struct ieee80211_regdomain *regd = NULL;
+       const struct ieee80211_regdomain *wiphy_regd = NULL;
+
+       regd = get_cfg80211_regdom();
+       if (!wiphy)
+               goto out;
+
+       wiphy_regd = get_wiphy_regdom(wiphy);
+       if (!wiphy_regd)
+               goto out;
+
+       if (wiphy_regd->dfs_region == regd->dfs_region)
+               goto out;
+
+       REG_DBG_PRINT("%s: device specific dfs_region "
+                     "(%s) disagrees with cfg80211's "
+                     "central dfs_region (%s)\n",
+                     dev_name(&wiphy->dev),
+                     reg_dfs_region_str(wiphy_regd->dfs_region),
+                     reg_dfs_region_str(regd->dfs_region));
+
+out:
+       return regd->dfs_region;
+}
+
 static void rcu_free_regdom(const struct ieee80211_regdomain *r)
 {
        if (!r)
@@ -212,6 +254,12 @@ static void reg_kfree_last_request(void)
                kfree_rcu(lr, rcu_head);
 }
 
+static void reg_update_last_request(struct regulatory_request *request)
+{
+       reg_kfree_last_request();
+       rcu_assign_pointer(last_request, request);
+}
+
 static void reset_regdomains(bool full_reset,
                             const struct ieee80211_regdomain *new_regdom)
 {
@@ -238,8 +286,7 @@ static void reset_regdomains(bool full_reset,
        if (!full_reset)
                return;
 
-       reg_kfree_last_request();
-       rcu_assign_pointer(last_request, &core_request_world);
+       reg_update_last_request(&core_request_world);
 }
 
 /*
@@ -457,6 +504,14 @@ static int call_crda(const char *alpha2)
        return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
 }
 
+static enum reg_request_treatment
+reg_call_crda(struct regulatory_request *request)
+{
+       if (call_crda(request->alpha2))
+               return REG_REQ_IGNORE;
+       return REG_REQ_OK;
+}
+
 bool reg_is_valid_request(const char *alpha2)
 {
        struct regulatory_request *lr = get_last_request();
@@ -557,6 +612,20 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
 #undef ONE_GHZ_IN_KHZ
 }
 
+/*
+ * Later on we can perhaps use the more restrictive DFS
+ * region but we don't have information for that yet so
+ * for now simply disallow conflicts.
+ */
+static enum nl80211_dfs_regions
+reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
+                        const enum nl80211_dfs_regions dfs_region2)
+{
+       if (dfs_region1 != dfs_region2)
+               return NL80211_DFS_UNSET;
+       return dfs_region1;
+}
+
 /*
  * Helper for regdom_intersect(), this does the real
  * mathematical intersection fun
@@ -688,6 +757,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
        rd->n_reg_rules = num_rules;
        rd->alpha2[0] = '9';
        rd->alpha2[1] = '8';
+       rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,
+                                                 rd2->dfs_region);
 
        return rd;
 }
@@ -855,7 +926,7 @@ static void handle_channel(struct wiphy *wiphy,
 
                if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
                    request_wiphy && request_wiphy == wiphy &&
-                   request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
+                   request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
                        REG_DBG_PRINT("Disabling freq %d MHz for good\n",
                                      chan->center_freq);
                        chan->orig_flags |= IEEE80211_CHAN_DISABLED;
@@ -882,7 +953,7 @@ static void handle_channel(struct wiphy *wiphy,
 
        if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
            request_wiphy && request_wiphy == wiphy &&
-           request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
+           request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
                /*
                 * This guarantees the driver's requested regulatory domain
                 * will always be used as a base for further regulatory
@@ -908,13 +979,11 @@ static void handle_channel(struct wiphy *wiphy,
        chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
        if (chan->orig_mpwr) {
                /*
-                * Devices that have their own custom regulatory domain
-                * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the
-                * passed country IE power settings.
+                * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
+                * will always follow the passed country IE power settings.
                 */
                if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
-                   wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
-                   wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
+                   wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER)
                        chan->max_power = chan->max_reg_power;
                else
                        chan->max_power = min(chan->orig_mpwr,
@@ -984,8 +1053,8 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
 
 static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
 {
-       if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY &&
-           !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY))
+       if (wiphy->regulatory_flags & REGULATORY_STRICT_REG &&
+           !(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG))
                return true;
        return false;
 }
@@ -1003,7 +1072,7 @@ static bool ignore_reg_update(struct wiphy *wiphy,
        }
 
        if (initiator == NL80211_REGDOM_SET_BY_CORE &&
-           wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
+           wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
                REG_DBG_PRINT("Ignoring regulatory request set by %s "
                              "since the driver uses its own custom "
                              "regulatory domain\n",
@@ -1041,7 +1110,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
                return true;
 
        if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
-           wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)
+           wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
                return true;
 
        return false;
@@ -1069,7 +1138,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
        if (!reg_is_world_roaming(wiphy))
                return;
 
-       if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS)
+       if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS)
                return;
 
        chan_before.center_freq = chan->center_freq;
@@ -1209,14 +1278,30 @@ static void reg_process_ht_flags(struct wiphy *wiphy)
                reg_process_ht_flags_band(wiphy, wiphy->bands[band]);
 }
 
+static void reg_call_notifier(struct wiphy *wiphy,
+                             struct regulatory_request *request)
+{
+       if (wiphy->reg_notifier)
+               wiphy->reg_notifier(wiphy, request);
+}
+
 static void wiphy_update_regulatory(struct wiphy *wiphy,
                                    enum nl80211_reg_initiator initiator)
 {
        enum ieee80211_band band;
        struct regulatory_request *lr = get_last_request();
 
-       if (ignore_reg_update(wiphy, initiator))
+       if (ignore_reg_update(wiphy, initiator)) {
+               /*
+                * Regulatory updates set by CORE are ignored for custom
+                * regulatory cards. Let us notify the changes to the driver,
+                * as some drivers used this to restore its orig_* reg domain.
+                */
+               if (initiator == NL80211_REGDOM_SET_BY_CORE &&
+                   wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
+                       reg_call_notifier(wiphy, lr);
                return;
+       }
 
        lr->dfs_region = get_cfg80211_regdom()->dfs_region;
 
@@ -1225,9 +1310,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
 
        reg_process_beacons(wiphy);
        reg_process_ht_flags(wiphy);
-
-       if (wiphy->reg_notifier)
-               wiphy->reg_notifier(wiphy, lr);
+       reg_call_notifier(wiphy, lr);
 }
 
 static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
@@ -1240,15 +1323,6 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                wiphy = &rdev->wiphy;
                wiphy_update_regulatory(wiphy, initiator);
-               /*
-                * Regulatory updates set by CORE are ignored for custom
-                * regulatory cards. Let us notify the changes to the driver,
-                * as some drivers used this to restore its orig_* reg domain.
-                */
-               if (initiator == NL80211_REGDOM_SET_BY_CORE &&
-                   wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
-                   wiphy->reg_notifier)
-                       wiphy->reg_notifier(wiphy, get_last_request());
        }
 }
 
@@ -1310,9 +1384,9 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
        enum ieee80211_band band;
        unsigned int bands_set = 0;
 
-       WARN(!(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY),
-            "wiphy should have WIPHY_FLAG_CUSTOM_REGULATORY\n");
-       wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+       WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG),
+            "wiphy should have REGULATORY_CUSTOM_REG\n");
+       wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
 
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                if (!wiphy->bands[band])
@@ -1364,12 +1438,9 @@ reg_process_hint_core(struct regulatory_request *core_request)
        core_request->intersect = false;
        core_request->processed = false;
 
-       reg_kfree_last_request();
-       rcu_assign_pointer(last_request, core_request);
+       reg_update_last_request(core_request);
 
-       if (call_crda(core_request->alpha2))
-               return REG_REQ_IGNORE;
-       return REG_REQ_OK;
+       return reg_call_crda(core_request);
 }
 
 static enum reg_request_treatment
@@ -1432,15 +1503,12 @@ reg_process_hint_user(struct regulatory_request *user_request)
        user_request->intersect = treatment == REG_REQ_INTERSECT;
        user_request->processed = false;
 
-       reg_kfree_last_request();
-       rcu_assign_pointer(last_request, user_request);
+       reg_update_last_request(user_request);
 
        user_alpha2[0] = user_request->alpha2[0];
        user_alpha2[1] = user_request->alpha2[1];
 
-       if (call_crda(user_request->alpha2))
-               return REG_REQ_IGNORE;
-       return REG_REQ_OK;
+       return reg_call_crda(user_request);
 }
 
 static enum reg_request_treatment
@@ -1505,8 +1573,7 @@ reg_process_hint_driver(struct wiphy *wiphy,
        driver_request->intersect = treatment == REG_REQ_INTERSECT;
        driver_request->processed = false;
 
-       reg_kfree_last_request();
-       rcu_assign_pointer(last_request, driver_request);
+       reg_update_last_request(driver_request);
 
        /*
         * Since CRDA will not be called in this case as we already
@@ -1519,9 +1586,7 @@ reg_process_hint_driver(struct wiphy *wiphy,
                return treatment;
        }
 
-       if (call_crda(driver_request->alpha2))
-               return REG_REQ_IGNORE;
-       return REG_REQ_OK;
+       return reg_call_crda(driver_request);
 }
 
 static enum reg_request_treatment
@@ -1536,6 +1601,9 @@ __reg_process_hint_country_ie(struct wiphy *wiphy,
                if (regdom_changes(country_ie_request->alpha2))
                        return REG_REQ_IGNORE;
                return REG_REQ_ALREADY_SET;
+       } else {
+               if (wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_IGNORE)
+                       return REG_REQ_IGNORE;
        }
 
        if (unlikely(!is_an_alpha2(country_ie_request->alpha2)))
@@ -1604,12 +1672,9 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
        country_ie_request->intersect = false;
        country_ie_request->processed = false;
 
-       reg_kfree_last_request();
-       rcu_assign_pointer(last_request, country_ie_request);
+       reg_update_last_request(country_ie_request);
 
-       if (call_crda(country_ie_request->alpha2))
-               return REG_REQ_IGNORE;
-       return REG_REQ_OK;
+       return reg_call_crda(country_ie_request);
 }
 
 /* This processes *all* regulatory hints */
@@ -1653,7 +1718,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
 
        /* This is required so that the orig_* parameters are saved */
        if (treatment == REG_REQ_ALREADY_SET && wiphy &&
-           wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
+           wiphy->regulatory_flags & REGULATORY_STRICT_REG)
                wiphy_update_regulatory(wiphy, reg_request->initiator);
 }
 
@@ -1788,6 +1853,8 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
        if (WARN_ON(!alpha2 || !wiphy))
                return -EINVAL;
 
+       wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG;
+
        request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
        if (!request)
                return -ENOMEM;
@@ -1980,7 +2047,7 @@ static void restore_regulatory_settings(bool reset_user)
        world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
 
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
-               if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY)
+               if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
                        restore_custom_reg_settings(&rdev->wiphy);
        }
 
@@ -2108,7 +2175,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
        }
 }
 
-bool reg_supported_dfs_region(u8 dfs_region)
+bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
 {
        switch (dfs_region) {
        case NL80211_DFS_UNSET:
@@ -2123,27 +2190,6 @@ bool reg_supported_dfs_region(u8 dfs_region)
        }
 }
 
-static void print_dfs_region(u8 dfs_region)
-{
-       if (!dfs_region)
-               return;
-
-       switch (dfs_region) {
-       case NL80211_DFS_FCC:
-               pr_info(" DFS Master region FCC");
-               break;
-       case NL80211_DFS_ETSI:
-               pr_info(" DFS Master region ETSI");
-               break;
-       case NL80211_DFS_JP:
-               pr_info(" DFS Master region JP");
-               break;
-       default:
-               pr_info(" DFS Master region Unknown");
-               break;
-       }
-}
-
 static void print_regdomain(const struct ieee80211_regdomain *rd)
 {
        struct regulatory_request *lr = get_last_request();
@@ -2175,7 +2221,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
                }
        }
 
-       print_dfs_region(rd->dfs_region);
+       pr_info(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region));
        print_rd_rules(rd);
 }
 
@@ -2185,48 +2231,60 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
        print_rd_rules(rd);
 }
 
-/* Takes ownership of rd only if it doesn't fail */
-static int __set_regdom(const struct ieee80211_regdomain *rd)
+static int reg_set_rd_core(const struct ieee80211_regdomain *rd)
+{
+       if (!is_world_regdom(rd->alpha2))
+               return -EINVAL;
+       update_world_regdomain(rd);
+       return 0;
+}
+
+static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
+                          struct regulatory_request *user_request)
 {
-       const struct ieee80211_regdomain *regd;
        const struct ieee80211_regdomain *intersected_rd = NULL;
-       struct wiphy *request_wiphy;
-       struct regulatory_request *lr = get_last_request();
 
-       /* Some basic sanity checks first */
+       if (is_world_regdom(rd->alpha2))
+               return -EINVAL;
+
+       if (!regdom_changes(rd->alpha2))
+               return -EALREADY;
 
-       if (!reg_is_valid_request(rd->alpha2))
+       if (!is_valid_rd(rd)) {
+               pr_err("Invalid regulatory domain detected:\n");
+               print_regdomain_info(rd);
                return -EINVAL;
+       }
 
-       if (is_world_regdom(rd->alpha2)) {
-               update_world_regdomain(rd);
+       if (!user_request->intersect) {
+               reset_regdomains(false, rd);
                return 0;
        }
 
-       if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
-           !is_unknown_alpha2(rd->alpha2))
+       intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
+       if (!intersected_rd)
                return -EINVAL;
 
-       /*
-        * Lets only bother proceeding on the same alpha2 if the current
-        * rd is non static (it means CRDA was present and was used last)
-        * and the pending request came in from a country IE
-        */
-       if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-               /*
-                * If someone else asked us to change the rd lets only bother
-                * checking if the alpha2 changes if CRDA was already called
-                */
-               if (!regdom_changes(rd->alpha2))
-                       return -EALREADY;
-       }
+       kfree(rd);
+       rd = NULL;
+       reset_regdomains(false, intersected_rd);
 
-       /*
-        * Now lets set the regulatory domain, update all driver channels
-        * and finally inform them of what we have done, in case they want
-        * to review or adjust their own settings based on their own
-        * internal EEPROM data
-        */
+       return 0;
+}
+
+static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
+                            struct regulatory_request *driver_request)
+{
+       const struct ieee80211_regdomain *regd;
+       const struct ieee80211_regdomain *intersected_rd = NULL;
+       const struct ieee80211_regdomain *tmp;
+       struct wiphy *request_wiphy;
+
+       if (is_world_regdom(rd->alpha2))
+               return -EINVAL;
+
+       if (!regdom_changes(rd->alpha2))
+               return -EALREADY;
 
        if (!is_valid_rd(rd)) {
                pr_err("Invalid regulatory domain detected:\n");
@@ -2234,29 +2292,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
                return -EINVAL;
        }
 
-       request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
-       if (!request_wiphy &&
-           (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
-            lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+       request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
+       if (!request_wiphy) {
                schedule_delayed_work(&reg_timeout, 0);
                return -ENODEV;
        }
 
-       if (!lr->intersect) {
-               if (lr->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
-                       reset_regdomains(false, rd);
-                       return 0;
-               }
-
-               /*
-                * For a driver hint, lets copy the regulatory domain the
-                * driver wanted to the wiphy to deal with conflicts
-                */
-
-               /*
-                * Userspace could have sent two replies with only
-                * one kernel request.
-                */
+       if (!driver_request->intersect) {
                if (request_wiphy->regd)
                        return -EALREADY;
 
@@ -2269,38 +2311,59 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
                return 0;
        }
 
-       /* Intersection requires a bit more work */
+       intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
+       if (!intersected_rd)
+               return -EINVAL;
 
-       if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-               intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
-               if (!intersected_rd)
-                       return -EINVAL;
+       /*
+        * We can trash what CRDA provided now.
+        * However if a driver requested this specific regulatory
+        * domain we keep it for its private use
+        */
+       tmp = get_wiphy_regdom(request_wiphy);
+       rcu_assign_pointer(request_wiphy->regd, rd);
+       rcu_free_regdom(tmp);
 
-               /*
-                * We can trash what CRDA provided now.
-                * However if a driver requested this specific regulatory
-                * domain we keep it for its private use
-                */
-               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
-                       const struct ieee80211_regdomain *tmp;
+       rd = NULL;
 
-                       tmp = get_wiphy_regdom(request_wiphy);
-                       rcu_assign_pointer(request_wiphy->regd, rd);
-                       rcu_free_regdom(tmp);
-               } else {
-                       kfree(rd);
-               }
+       reset_regdomains(false, intersected_rd);
+
+       return 0;
+}
 
-               rd = NULL;
+static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
+                                struct regulatory_request *country_ie_request)
+{
+       struct wiphy *request_wiphy;
 
-               reset_regdomains(false, intersected_rd);
+       if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
+           !is_unknown_alpha2(rd->alpha2))
+               return -EINVAL;
 
-               return 0;
+       /*
+        * Lets only bother proceeding on the same alpha2 if the current
+        * rd is non static (it means CRDA was present and was used last)
+        * and the pending request came in from a country IE
+        */
+
+       if (!is_valid_rd(rd)) {
+               pr_err("Invalid regulatory domain detected:\n");
+               print_regdomain_info(rd);
+               return -EINVAL;
        }
 
-       return -EINVAL;
-}
+       request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx);
+       if (!request_wiphy) {
+               schedule_delayed_work(&reg_timeout, 0);
+               return -ENODEV;
+       }
+
+       if (country_ie_request->intersect)
+               return -EINVAL;
 
+       reset_regdomains(false, rd);
+       return 0;
+}
 
 /*
  * Use this call to set the current regulatory domain. Conflicts with
@@ -2312,10 +2375,32 @@ int set_regdom(const struct ieee80211_regdomain *rd)
        struct regulatory_request *lr;
        int r;
 
+       if (!reg_is_valid_request(rd->alpha2)) {
+               kfree(rd);
+               return -EINVAL;
+       }
+
        lr = get_last_request();
 
        /* Note that this doesn't update the wiphys, this is done below */
-       r = __set_regdom(rd);
+       switch (lr->initiator) {
+       case NL80211_REGDOM_SET_BY_CORE:
+               r = reg_set_rd_core(rd);
+               break;
+       case NL80211_REGDOM_SET_BY_USER:
+               r = reg_set_rd_user(rd, lr);
+               break;
+       case NL80211_REGDOM_SET_BY_DRIVER:
+               r = reg_set_rd_driver(rd, lr);
+               break;
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               r = reg_set_rd_country_ie(rd, lr);
+               break;
+       default:
+               WARN(1, "invalid initiator %d\n", lr->initiator);
+               return -EINVAL;
+       }
+
        if (r) {
                if (r == -EALREADY)
                        reg_set_request_processed();
This page took 0.047713 seconds and 5 git commands to generate.