regulatory: use RCU in regulatory_hint_11d()
authorJohannes Berg <johannes.berg@intel.com>
Fri, 10 May 2013 17:07:52 +0000 (19:07 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 24 May 2013 22:02:18 +0000 (00:02 +0200)
Since it just does a quick check of the last regulatory
request, the function doesn't have to hold the reg mutex
but can use RCU instead.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/reg.c

index e76559618588cd6ae919ff38406d6d75c5d2495a..17e5eccb42c84b51f102d28d4cbfa07d95370ff4 100644 (file)
@@ -1715,20 +1715,18 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
 {
        char alpha2[2];
        enum environment_cap env = ENVIRON_ANY;
-       struct regulatory_request *request, *lr;
-
-       mutex_lock(&reg_mutex);
-       lr = get_last_request();
-
-       if (unlikely(!lr))
-               goto out;
+       struct regulatory_request *request = NULL, *lr;
 
        /* IE len must be evenly divisible by 2 */
        if (country_ie_len & 0x01)
-               goto out;
+               return;
 
        if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
-               goto out;
+               return;
+
+       request = kzalloc(sizeof(*request), GFP_KERNEL);
+       if (!request)
+               return;
 
        alpha2[0] = country_ie[0];
        alpha2[1] = country_ie[1];
@@ -1738,6 +1736,12 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
        else if (country_ie[2] == 'O')
                env = ENVIRON_OUTDOOR;
 
+       rcu_read_lock();
+       lr = get_last_request();
+
+       if (unlikely(!lr))
+               goto out;
+
        /*
         * We will run this only upon a successful connection on cfg80211.
         * We leave conflict resolution to the workqueue, where can hold
@@ -1747,10 +1751,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
            lr->wiphy_idx != WIPHY_IDX_INVALID)
                goto out;
 
-       request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
-       if (!request)
-               goto out;
-
        request->wiphy_idx = get_wiphy_idx(wiphy);
        request->alpha2[0] = alpha2[0];
        request->alpha2[1] = alpha2[1];
@@ -1758,8 +1758,10 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
        request->country_ie_env = env;
 
        queue_regulatory_request(request);
+       request = NULL;
 out:
-       mutex_unlock(&reg_mutex);
+       kfree(request);
+       rcu_read_unlock();
 }
 
 static void restore_alpha2(char *alpha2, bool reset_user)