@@ -62,6 +62,7 @@ struct regulatory_request {
bool intersect;
bool processed;
enum environment_cap country_ie_env;
+ struct completion *completion;
struct list_head list;
};
@@ -2535,6 +2535,7 @@ static int parse_reg_rule(struct nlattr *tb[],
static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
{
+ DECLARE_COMPLETION_ONSTACK(completion);
int r;
char *data = NULL;
@@ -2556,7 +2557,9 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
- r = regulatory_hint_user(data);
+ r = regulatory_hint_user(data, &completion);
+
+ wait_for_completion_interruptible(&completion);
return r;
}
@@ -1428,6 +1428,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
int r = 0;
struct wiphy *wiphy = NULL;
enum nl80211_reg_initiator initiator = reg_request->initiator;
+ struct completion *completion = reg_request->completion;
BUG_ON(!reg_request->alpha2);
@@ -1437,7 +1438,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
!wiphy) {
kfree(reg_request);
- return;
+ goto out;
}
r = __regulatory_hint(wiphy, reg_request);
@@ -1445,6 +1446,11 @@ static void reg_process_hint(struct regulatory_request *reg_request)
if (r == -EALREADY && wiphy &&
wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
wiphy_update_regulatory(wiphy, initiator);
+
+out:
+ /* Mark this reg request done */
+ if (completion)
+ complete_all(completion);
}
/*
@@ -1571,7 +1577,7 @@ static int regulatory_hint_core(const char *alpha2)
}
/* User hints */
-int regulatory_hint_user(const char *alpha2)
+int regulatory_hint_user(const char *alpha2, struct completion *completion)
{
struct regulatory_request *request;
@@ -1585,6 +1591,7 @@ int regulatory_hint_user(const char *alpha2)
request->alpha2[0] = alpha2[0];
request->alpha2[1] = alpha2[1];
request->initiator = NL80211_REGDOM_SET_BY_USER;
+ request->completion = completion;
queue_regulatory_request(request);
@@ -1787,7 +1794,7 @@ static void restore_regulatory_settings(bool reset_user)
* settings, user regulatory settings takes precedence.
*/
if (is_an_alpha2(alpha2))
- regulatory_hint_user(user_alpha2);
+ regulatory_hint_user(user_alpha2, NULL);
}
@@ -2149,7 +2156,7 @@ int __init regulatory_init(void)
* as a user hint.
*/
if (!is_world_regdom(ieee80211_regdom))
- regulatory_hint_user(ieee80211_regdom);
+ regulatory_hint_user(ieee80211_regdom, NULL);
return 0;
}
@@ -6,7 +6,7 @@ extern const struct ieee80211_regdomain *cfg80211_regdomain;
bool is_world_regdom(const char *alpha2);
bool reg_is_valid_request(const char *alpha2);
-int regulatory_hint_user(const char *alpha2);
+int regulatory_hint_user(const char *alpha2, struct completion *completion);
void reg_device_remove(struct wiphy *wiphy);