diff options
Diffstat (limited to 'net/wireless/reg.c')
| -rw-r--r-- | net/wireless/reg.c | 49 | 
1 files changed, 33 insertions, 16 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e71f5a66574..3302c56f60d 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -57,8 +57,17 @@  #define REG_DBG_PRINT(args...)  #endif +static struct regulatory_request core_request_world = { +	.initiator = NL80211_REGDOM_SET_BY_CORE, +	.alpha2[0] = '0', +	.alpha2[1] = '0', +	.intersect = false, +	.processed = true, +	.country_ie_env = ENVIRON_ANY, +}; +  /* Receipt of information from last regulatory request */ -static struct regulatory_request *last_request; +static struct regulatory_request *last_request = &core_request_world;  /* To trigger userspace events */  static struct platform_device *reg_pdev; @@ -150,7 +159,7 @@ static char user_alpha2[2];  module_param(ieee80211_regdom, charp, 0444);  MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); -static void reset_regdomains(void) +static void reset_regdomains(bool full_reset)  {  	/* avoid freeing static information or freeing something twice */  	if (cfg80211_regdomain == cfg80211_world_regdom) @@ -165,6 +174,13 @@ static void reset_regdomains(void)  	cfg80211_world_regdom = &world_regdom;  	cfg80211_regdomain = NULL; + +	if (!full_reset) +		return; + +	if (last_request != &core_request_world) +		kfree(last_request); +	last_request = &core_request_world;  }  /* @@ -175,7 +191,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd)  {  	BUG_ON(!last_request); -	reset_regdomains(); +	reset_regdomains(false);  	cfg80211_world_regdom = rd;  	cfg80211_regdomain = rd; @@ -1407,7 +1423,8 @@ static int __regulatory_hint(struct wiphy *wiphy,  	}  new_request: -	kfree(last_request); +	if (last_request != &core_request_world) +		kfree(last_request);  	last_request = pending_request;  	last_request->intersect = intersect; @@ -1577,9 +1594,6 @@ static int regulatory_hint_core(const char *alpha2)  {  	struct regulatory_request *request; -	kfree(last_request); -	last_request = NULL; -  	request = kzalloc(sizeof(struct regulatory_request),  			  GFP_KERNEL);  	if (!request) @@ -1777,7 +1791,7 @@ static void restore_regulatory_settings(bool reset_user)  	mutex_lock(&cfg80211_mutex);  	mutex_lock(®_mutex); -	reset_regdomains(); +	reset_regdomains(true);  	restore_alpha2(alpha2, reset_user);  	/* @@ -2037,12 +2051,18 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)  	}  	request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); +	if (!request_wiphy && +	    (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || +	     last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { +		schedule_delayed_work(®_timeout, 0); +		return -ENODEV; +	}  	if (!last_request->intersect) {  		int r;  		if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { -			reset_regdomains(); +			reset_regdomains(false);  			cfg80211_regdomain = rd;  			return 0;  		} @@ -2063,7 +2083,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)  		if (r)  			return r; -		reset_regdomains(); +		reset_regdomains(false);  		cfg80211_regdomain = rd;  		return 0;  	} @@ -2088,7 +2108,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)  		rd = NULL; -		reset_regdomains(); +		reset_regdomains(false);  		cfg80211_regdomain = intersected_rd;  		return 0; @@ -2108,7 +2128,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)  	kfree(rd);  	rd = NULL; -	reset_regdomains(); +	reset_regdomains(false);  	cfg80211_regdomain = intersected_rd;  	return 0; @@ -2261,11 +2281,8 @@ void /* __init_or_exit */ regulatory_exit(void)  	mutex_lock(&cfg80211_mutex);  	mutex_lock(®_mutex); -	reset_regdomains(); - -	kfree(last_request); +	reset_regdomains(true); -	last_request = NULL;  	dev_set_uevent_suppress(®_pdev->dev, true);  	platform_device_unregister(reg_pdev);  |