diff options
author | Ilan peer <ilan.peer@intel.com> | 2015-03-30 08:15:49 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-04-01 05:22:38 -0400 |
commit | c37722bd1972118142ee54c0e1a727142d944068 (patch) | |
tree | 6f07eb73e85fdc58258044610586726138f3a5ee /net/wireless | |
parent | 7bedd0cfad4e122bc0ddaf3fc955a38c88c95d35 (diff) |
cfg80211: Stop calling crda if it is not responsive
Patch eeca9fce1d71a4955855ceb0c3b13c1eb9db27c1 (cfg80211: Schedule
timeout for all CRDA call) introduced a regression, where in case
that crda is not installed (or not configured properly etc.), the
regulatory core will needlessly continue to call it, polluting the
log with the following log:
"cfg80211: Calling CRDA to update world regulatory domain"
Fix this by limiting the number of continuous CRDA request failures.
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 2 | ||||
-rw-r--r-- | net/wireless/reg.c | 34 | ||||
-rw-r--r-- | net/wireless/reg.h | 9 |
3 files changed, 38 insertions, 7 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6dd1ab3b10ea..dd78445c7d50 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5664,7 +5664,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5664 | } | 5664 | } |
5665 | } | 5665 | } |
5666 | 5666 | ||
5667 | r = set_regdom(rd); | 5667 | r = set_regdom(rd, REGD_SOURCE_CRDA); |
5668 | /* set_regdom took ownership */ | 5668 | /* set_regdom took ownership */ |
5669 | rd = NULL; | 5669 | rd = NULL; |
5670 | 5670 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index be5f81caa488..0e347f888fe9 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -135,6 +135,11 @@ static spinlock_t reg_indoor_lock; | |||
135 | /* Used to track the userspace process controlling the indoor setting */ | 135 | /* Used to track the userspace process controlling the indoor setting */ |
136 | static u32 reg_is_indoor_portid; | 136 | static u32 reg_is_indoor_portid; |
137 | 137 | ||
138 | /* Max number of consecutive attempts to communicate with CRDA */ | ||
139 | #define REG_MAX_CRDA_TIMEOUTS 10 | ||
140 | |||
141 | static u32 reg_crda_timeouts; | ||
142 | |||
138 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | 143 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) |
139 | { | 144 | { |
140 | return rtnl_dereference(cfg80211_regdomain); | 145 | return rtnl_dereference(cfg80211_regdomain); |
@@ -485,7 +490,7 @@ static void reg_regdb_search(struct work_struct *work) | |||
485 | mutex_unlock(®_regdb_search_mutex); | 490 | mutex_unlock(®_regdb_search_mutex); |
486 | 491 | ||
487 | if (!IS_ERR_OR_NULL(regdom)) | 492 | if (!IS_ERR_OR_NULL(regdom)) |
488 | set_regdom(regdom); | 493 | set_regdom(regdom, REGD_SOURCE_INTERNAL_DB); |
489 | 494 | ||
490 | rtnl_unlock(); | 495 | rtnl_unlock(); |
491 | } | 496 | } |
@@ -535,15 +540,20 @@ static int call_crda(const char *alpha2) | |||
535 | snprintf(country, sizeof(country), "COUNTRY=%c%c", | 540 | snprintf(country, sizeof(country), "COUNTRY=%c%c", |
536 | alpha2[0], alpha2[1]); | 541 | alpha2[0], alpha2[1]); |
537 | 542 | ||
543 | /* query internal regulatory database (if it exists) */ | ||
544 | reg_regdb_query(alpha2); | ||
545 | |||
546 | if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { | ||
547 | pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n"); | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | |||
538 | if (!is_world_regdom((char *) alpha2)) | 551 | if (!is_world_regdom((char *) alpha2)) |
539 | pr_info("Calling CRDA for country: %c%c\n", | 552 | pr_info("Calling CRDA for country: %c%c\n", |
540 | alpha2[0], alpha2[1]); | 553 | alpha2[0], alpha2[1]); |
541 | else | 554 | else |
542 | pr_info("Calling CRDA to update world regulatory domain\n"); | 555 | pr_info("Calling CRDA to update world regulatory domain\n"); |
543 | 556 | ||
544 | /* query internal regulatory database (if it exists) */ | ||
545 | reg_regdb_query(alpha2); | ||
546 | |||
547 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); | 557 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); |
548 | } | 558 | } |
549 | 559 | ||
@@ -2293,6 +2303,9 @@ int regulatory_hint_user(const char *alpha2, | |||
2293 | request->initiator = NL80211_REGDOM_SET_BY_USER; | 2303 | request->initiator = NL80211_REGDOM_SET_BY_USER; |
2294 | request->user_reg_hint_type = user_reg_hint_type; | 2304 | request->user_reg_hint_type = user_reg_hint_type; |
2295 | 2305 | ||
2306 | /* Allow calling CRDA again */ | ||
2307 | reg_crda_timeouts = 0; | ||
2308 | |||
2296 | queue_regulatory_request(request); | 2309 | queue_regulatory_request(request); |
2297 | 2310 | ||
2298 | return 0; | 2311 | return 0; |
@@ -2362,6 +2375,9 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
2362 | request->alpha2[1] = alpha2[1]; | 2375 | request->alpha2[1] = alpha2[1]; |
2363 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; | 2376 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; |
2364 | 2377 | ||
2378 | /* Allow calling CRDA again */ | ||
2379 | reg_crda_timeouts = 0; | ||
2380 | |||
2365 | queue_regulatory_request(request); | 2381 | queue_regulatory_request(request); |
2366 | 2382 | ||
2367 | return 0; | 2383 | return 0; |
@@ -2415,6 +2431,9 @@ void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band, | |||
2415 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; | 2431 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; |
2416 | request->country_ie_env = env; | 2432 | request->country_ie_env = env; |
2417 | 2433 | ||
2434 | /* Allow calling CRDA again */ | ||
2435 | reg_crda_timeouts = 0; | ||
2436 | |||
2418 | queue_regulatory_request(request); | 2437 | queue_regulatory_request(request); |
2419 | request = NULL; | 2438 | request = NULL; |
2420 | out: | 2439 | out: |
@@ -2893,7 +2912,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
2893 | * multiple drivers can be ironed out later. Caller must've already | 2912 | * multiple drivers can be ironed out later. Caller must've already |
2894 | * kmalloc'd the rd structure. | 2913 | * kmalloc'd the rd structure. |
2895 | */ | 2914 | */ |
2896 | int set_regdom(const struct ieee80211_regdomain *rd) | 2915 | int set_regdom(const struct ieee80211_regdomain *rd, |
2916 | enum ieee80211_regd_source regd_src) | ||
2897 | { | 2917 | { |
2898 | struct regulatory_request *lr; | 2918 | struct regulatory_request *lr; |
2899 | bool user_reset = false; | 2919 | bool user_reset = false; |
@@ -2904,6 +2924,9 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2904 | return -EINVAL; | 2924 | return -EINVAL; |
2905 | } | 2925 | } |
2906 | 2926 | ||
2927 | if (regd_src == REGD_SOURCE_CRDA) | ||
2928 | reg_crda_timeouts = 0; | ||
2929 | |||
2907 | lr = get_last_request(); | 2930 | lr = get_last_request(); |
2908 | 2931 | ||
2909 | /* Note that this doesn't update the wiphys, this is done below */ | 2932 | /* Note that this doesn't update the wiphys, this is done below */ |
@@ -3063,6 +3086,7 @@ static void reg_timeout_work(struct work_struct *work) | |||
3063 | { | 3086 | { |
3064 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); | 3087 | REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); |
3065 | rtnl_lock(); | 3088 | rtnl_lock(); |
3089 | reg_crda_timeouts++; | ||
3066 | restore_regulatory_settings(true); | 3090 | restore_regulatory_settings(true); |
3067 | rtnl_unlock(); | 3091 | rtnl_unlock(); |
3068 | } | 3092 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index a2c4e16459da..9f495d76eca0 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -16,6 +16,11 @@ | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | enum ieee80211_regd_source { | ||
20 | REGD_SOURCE_INTERNAL_DB, | ||
21 | REGD_SOURCE_CRDA, | ||
22 | }; | ||
23 | |||
19 | extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; | 24 | extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain; |
20 | 25 | ||
21 | bool reg_is_valid_request(const char *alpha2); | 26 | bool reg_is_valid_request(const char *alpha2); |
@@ -46,7 +51,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy); | |||
46 | int __init regulatory_init(void); | 51 | int __init regulatory_init(void); |
47 | void regulatory_exit(void); | 52 | void regulatory_exit(void); |
48 | 53 | ||
49 | int set_regdom(const struct ieee80211_regdomain *rd); | 54 | int set_regdom(const struct ieee80211_regdomain *rd, |
55 | enum ieee80211_regd_source regd_src); | ||
56 | |||
50 | unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, | 57 | unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, |
51 | const struct ieee80211_reg_rule *rule); | 58 | const struct ieee80211_reg_rule *rule); |
52 | 59 | ||