ath9k: fix key search for a-mpdu on ar9300
[openwrt.git] / package / mac80211 / patches / 310-pending_cfg80211_fixes.patch
1 --- a/include/net/regulatory.h
2 +++ b/include/net/regulatory.h
3 @@ -43,6 +43,12 @@ enum environment_cap {
4   * @intersect: indicates whether the wireless core should intersect
5   *     the requested regulatory domain with the presently set regulatory
6   *     domain.
7 + * @processed: indicates whether or not this requests has already been
8 + *     processed. When the last request is processed it means that the
9 + *     currently regulatory domain set on cfg80211 is updated from
10 + *     CRDA and can be used by other regulatory requests. When a
11 + *     the last request is not yet processed we must yield until it
12 + *     is processed before processing any new requests.
13   * @country_ie_checksum: checksum of the last processed and accepted
14   *     country IE
15   * @country_ie_env: lets us know if the AP is telling us we are outdoor,
16 @@ -54,6 +60,7 @@ struct regulatory_request {
17         enum nl80211_reg_initiator initiator;
18         char alpha2[2];
19         bool intersect;
20 +       bool processed;
21         enum environment_cap country_ie_env;
22         struct list_head list;
23  };
24 --- a/net/wireless/reg.c
25 +++ b/net/wireless/reg.c
26 @@ -96,6 +96,9 @@ struct reg_beacon {
27         struct ieee80211_channel chan;
28  };
29  
30 +static void reg_todo(struct work_struct *work);
31 +static DECLARE_WORK(reg_work, reg_todo);
32 +
33  /* We keep a static world regulatory domain in case of the absence of CRDA */
34  static const struct ieee80211_regdomain world_regdom = {
35         .n_reg_rules = 5,
36 @@ -1317,6 +1320,21 @@ static int ignore_request(struct wiphy *
37         return -EINVAL;
38  }
39  
40 +static void reg_set_request_processed(void)
41 +{
42 +       bool need_more_processing = false;
43 +
44 +       last_request->processed = true;
45 +
46 +       spin_lock(&reg_requests_lock);
47 +       if (!list_empty(&reg_requests_list))
48 +               need_more_processing = true;
49 +       spin_unlock(&reg_requests_lock);
50 +
51 +       if (need_more_processing)
52 +               schedule_work(&reg_work);
53 +}
54 +
55  /**
56   * __regulatory_hint - hint to the wireless core a regulatory domain
57   * @wiphy: if the hint comes from country information from an AP, this
58 @@ -1392,8 +1410,10 @@ new_request:
59                  * have applied the requested regulatory domain before we just
60                  * inform userspace we have processed the request
61                  */
62 -               if (r == -EALREADY)
63 +               if (r == -EALREADY) {
64                         nl80211_send_reg_change_event(last_request);
65 +                       reg_set_request_processed();
66 +               }
67                 return r;
68         }
69  
70 @@ -1409,16 +1429,13 @@ static void reg_process_hint(struct regu
71  
72         BUG_ON(!reg_request->alpha2);
73  
74 -       mutex_lock(&cfg80211_mutex);
75 -       mutex_lock(&reg_mutex);
76 -
77         if (wiphy_idx_valid(reg_request->wiphy_idx))
78                 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
79  
80         if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
81             !wiphy) {
82                 kfree(reg_request);
83 -               goto out;
84 +               return;
85         }
86  
87         r = __regulatory_hint(wiphy, reg_request);
88 @@ -1426,28 +1443,46 @@ static void reg_process_hint(struct regu
89         if (r == -EALREADY && wiphy &&
90             wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
91                 wiphy_update_regulatory(wiphy, initiator);
92 -out:
93 -       mutex_unlock(&reg_mutex);
94 -       mutex_unlock(&cfg80211_mutex);
95  }
96  
97 -/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */
98 +/*
99 + * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
100 + * Regulatory hints come on a first come first serve basis and we
101 + * must process each one atomically.
102 + */
103  static void reg_process_pending_hints(void)
104 -       {
105 +{
106         struct regulatory_request *reg_request;
107  
108 +       mutex_lock(&cfg80211_mutex);
109 +       mutex_lock(&reg_mutex);
110 +
111 +       /* When last_request->processed becomes true this will be rescheduled */
112 +       if (last_request && !last_request->processed) {
113 +               REG_DBG_PRINT("Pending regulatory request, waiting "
114 +                             "for it to be processed...");
115 +               goto out;
116 +       }
117 +
118         spin_lock(&reg_requests_lock);
119 -       while (!list_empty(&reg_requests_list)) {
120 -               reg_request = list_first_entry(&reg_requests_list,
121 -                                              struct regulatory_request,
122 -                                              list);
123 -               list_del_init(&reg_request->list);
124  
125 +       if (list_empty(&reg_requests_list)) {
126                 spin_unlock(&reg_requests_lock);
127 -               reg_process_hint(reg_request);
128 -               spin_lock(&reg_requests_lock);
129 +               goto out;
130         }
131 +
132 +       reg_request = list_first_entry(&reg_requests_list,
133 +                                      struct regulatory_request,
134 +                                      list);
135 +       list_del_init(&reg_request->list);
136 +
137         spin_unlock(&reg_requests_lock);
138 +
139 +       reg_process_hint(reg_request);
140 +
141 +out:
142 +       mutex_unlock(&reg_mutex);
143 +       mutex_unlock(&cfg80211_mutex);
144  }
145  
146  /* Processes beacon hints -- this has nothing to do with country IEs */
147 @@ -1494,8 +1529,6 @@ static void reg_todo(struct work_struct 
148         reg_process_pending_beacon_hints();
149  }
150  
151 -static DECLARE_WORK(reg_work, reg_todo);
152 -
153  static void queue_regulatory_request(struct regulatory_request *request)
154  {
155         if (isalpha(request->alpha2[0]))
156 @@ -1530,12 +1563,7 @@ static int regulatory_hint_core(const ch
157         request->alpha2[1] = alpha2[1];
158         request->initiator = NL80211_REGDOM_SET_BY_CORE;
159  
160 -       /*
161 -        * This ensures last_request is populated once modules
162 -        * come swinging in and calling regulatory hints and
163 -        * wiphy_apply_custom_regulatory().
164 -        */
165 -       reg_process_hint(request);
166 +       queue_regulatory_request(request);
167  
168         return 0;
169  }
170 @@ -2061,6 +2089,8 @@ int set_regdom(const struct ieee80211_re
171  
172         nl80211_send_reg_change_event(last_request);
173  
174 +       reg_set_request_processed();
175 +
176         mutex_unlock(&reg_mutex);
177  
178         return r;