Changeset 24028


Ignore:
Timestamp:
2010-11-18T11:06:08+01:00 (7 years ago)
Author:
nbd
Message:

mac80211: merge pending cfg80211 patches to fix a race condition with setting the regdomain for multiple cards

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/mac80211/patches/310-pending_work.patch

    r24017 r24028  
    113113 } 
    114114  
     115--- a/include/net/regulatory.h 
     116+++ b/include/net/regulatory.h 
     117@@ -43,6 +43,12 @@ enum environment_cap { 
     118  * @intersect: indicates whether the wireless core should intersect 
     119  *     the requested regulatory domain with the presently set regulatory 
     120  *     domain. 
     121+ * @processed: indicates whether or not this requests has already been 
     122+ *     processed. When the last request is processed it means that the 
     123+ *     currently regulatory domain set on cfg80211 is updated from 
     124+ *     CRDA and can be used by other regulatory requests. When a 
     125+ *     the last request is not yet processed we must yield until it 
     126+ *     is processed before processing any new requests. 
     127  * @country_ie_checksum: checksum of the last processed and accepted 
     128  *     country IE 
     129  * @country_ie_env: lets us know if the AP is telling us we are outdoor, 
     130@@ -54,6 +60,7 @@ struct regulatory_request { 
     131        enum nl80211_reg_initiator initiator; 
     132        char alpha2[2]; 
     133        bool intersect; 
     134+       bool processed; 
     135        enum environment_cap country_ie_env; 
     136        struct list_head list; 
     137 }; 
     138--- a/net/wireless/reg.c 
     139+++ b/net/wireless/reg.c 
     140@@ -96,6 +96,9 @@ struct reg_beacon { 
     141        struct ieee80211_channel chan; 
     142 }; 
     143  
     144+static void reg_todo(struct work_struct *work); 
     145+static DECLARE_WORK(reg_work, reg_todo); 
     146+ 
     147 /* We keep a static world regulatory domain in case of the absence of CRDA */ 
     148 static const struct ieee80211_regdomain world_regdom = { 
     149        .n_reg_rules = 5, 
     150@@ -1317,6 +1320,21 @@ static int ignore_request(struct wiphy * 
     151        return -EINVAL; 
     152 } 
     153  
     154+static void reg_set_request_processed(void) 
     155+{ 
     156+       bool need_more_processing = false; 
     157+ 
     158+       last_request->processed = true; 
     159+ 
     160+       spin_lock(&reg_requests_lock); 
     161+       if (!list_empty(&reg_requests_list)) 
     162+               need_more_processing = true; 
     163+       spin_unlock(&reg_requests_lock); 
     164+ 
     165+       if (need_more_processing) 
     166+               schedule_work(&reg_work); 
     167+} 
     168+ 
     169 /** 
     170  * __regulatory_hint - hint to the wireless core a regulatory domain 
     171  * @wiphy: if the hint comes from country information from an AP, this 
     172@@ -1392,8 +1410,10 @@ new_request: 
     173                 * have applied the requested regulatory domain before we just 
     174                 * inform userspace we have processed the request 
     175                 */ 
     176-               if (r == -EALREADY) 
     177+               if (r == -EALREADY) { 
     178                        nl80211_send_reg_change_event(last_request); 
     179+                       reg_set_request_processed(); 
     180+               } 
     181                return r; 
     182        } 
     183  
     184@@ -1409,16 +1429,13 @@ static void reg_process_hint(struct regu 
     185  
     186        BUG_ON(!reg_request->alpha2); 
     187  
     188-       mutex_lock(&cfg80211_mutex); 
     189-       mutex_lock(&reg_mutex); 
     190- 
     191        if (wiphy_idx_valid(reg_request->wiphy_idx)) 
     192                wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); 
     193  
     194        if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && 
     195            !wiphy) { 
     196                kfree(reg_request); 
     197-               goto out; 
     198+               return; 
     199        } 
     200  
     201        r = __regulatory_hint(wiphy, reg_request); 
     202@@ -1426,28 +1443,46 @@ static void reg_process_hint(struct regu 
     203        if (r == -EALREADY && wiphy && 
     204            wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) 
     205                wiphy_update_regulatory(wiphy, initiator); 
     206-out: 
     207-       mutex_unlock(&reg_mutex); 
     208-       mutex_unlock(&cfg80211_mutex); 
     209 } 
     210  
     211-/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ 
     212+/* 
     213+ * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* 
     214+ * Regulatory hints come on a first come first serve basis and we 
     215+ * must process each one atomically. 
     216+ */ 
     217 static void reg_process_pending_hints(void) 
     218-       { 
     219+{ 
     220        struct regulatory_request *reg_request; 
     221  
     222+       mutex_lock(&cfg80211_mutex); 
     223+       mutex_lock(&reg_mutex); 
     224+ 
     225+       /* When last_request->processed becomes true this will be rescheduled */ 
     226+       if (last_request && !last_request->processed) { 
     227+               REG_DBG_PRINT("Pending regulatory request, waiting " 
     228+                             "for it to be processed..."); 
     229+               goto out; 
     230+       } 
     231+ 
     232        spin_lock(&reg_requests_lock); 
     233-       while (!list_empty(&reg_requests_list)) { 
     234-               reg_request = list_first_entry(&reg_requests_list, 
     235-                                              struct regulatory_request, 
     236-                                              list); 
     237-               list_del_init(&reg_request->list); 
     238  
     239+       if (list_empty(&reg_requests_list)) { 
     240                spin_unlock(&reg_requests_lock); 
     241-               reg_process_hint(reg_request); 
     242-               spin_lock(&reg_requests_lock); 
     243+               goto out; 
     244        } 
     245+ 
     246+       reg_request = list_first_entry(&reg_requests_list, 
     247+                                      struct regulatory_request, 
     248+                                      list); 
     249+       list_del_init(&reg_request->list); 
     250+ 
     251        spin_unlock(&reg_requests_lock); 
     252+ 
     253+       reg_process_hint(reg_request); 
     254+ 
     255+out: 
     256+       mutex_unlock(&reg_mutex); 
     257+       mutex_unlock(&cfg80211_mutex); 
     258 } 
     259  
     260 /* Processes beacon hints -- this has nothing to do with country IEs */ 
     261@@ -1494,8 +1529,6 @@ static void reg_todo(struct work_struct  
     262        reg_process_pending_beacon_hints(); 
     263 } 
     264  
     265-static DECLARE_WORK(reg_work, reg_todo); 
     266- 
     267 static void queue_regulatory_request(struct regulatory_request *request) 
     268 { 
     269        if (isalpha(request->alpha2[0])) 
     270@@ -1530,12 +1563,7 @@ static int regulatory_hint_core(const ch 
     271        request->alpha2[1] = alpha2[1]; 
     272        request->initiator = NL80211_REGDOM_SET_BY_CORE; 
     273  
     274-       /* 
     275-        * This ensures last_request is populated once modules 
     276-        * come swinging in and calling regulatory hints and 
     277-        * wiphy_apply_custom_regulatory(). 
     278-        */ 
     279-       reg_process_hint(request); 
     280+       queue_regulatory_request(request); 
     281  
     282        return 0; 
     283 } 
     284@@ -2061,6 +2089,8 @@ int set_regdom(const struct ieee80211_re 
     285  
     286        nl80211_send_reg_change_event(last_request); 
     287  
     288+       reg_set_request_processed(); 
     289+ 
     290        mutex_unlock(&reg_mutex); 
     291  
     292        return r; 
Note: See TracChangeset for help on using the changeset viewer.