cfg80211: Stop calling crda if it is not responsive
Patch eeca9fce1d
(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>
This commit is contained in:
parent
7bedd0cfad
commit
c37722bd19
3 changed files with 38 additions and 7 deletions
|
@ -5664,7 +5664,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = set_regdom(rd);
|
r = set_regdom(rd, REGD_SOURCE_CRDA);
|
||||||
/* set_regdom took ownership */
|
/* set_regdom took ownership */
|
||||||
rd = NULL;
|
rd = NULL;
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,11 @@ static spinlock_t reg_indoor_lock;
|
||||||
/* Used to track the userspace process controlling the indoor setting */
|
/* Used to track the userspace process controlling the indoor setting */
|
||||||
static u32 reg_is_indoor_portid;
|
static u32 reg_is_indoor_portid;
|
||||||
|
|
||||||
|
/* Max number of consecutive attempts to communicate with CRDA */
|
||||||
|
#define REG_MAX_CRDA_TIMEOUTS 10
|
||||||
|
|
||||||
|
static u32 reg_crda_timeouts;
|
||||||
|
|
||||||
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
|
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
|
||||||
{
|
{
|
||||||
return rtnl_dereference(cfg80211_regdomain);
|
return rtnl_dereference(cfg80211_regdomain);
|
||||||
|
@ -485,7 +490,7 @@ static void reg_regdb_search(struct work_struct *work)
|
||||||
mutex_unlock(®_regdb_search_mutex);
|
mutex_unlock(®_regdb_search_mutex);
|
||||||
|
|
||||||
if (!IS_ERR_OR_NULL(regdom))
|
if (!IS_ERR_OR_NULL(regdom))
|
||||||
set_regdom(regdom);
|
set_regdom(regdom, REGD_SOURCE_INTERNAL_DB);
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
@ -535,15 +540,20 @@ static int call_crda(const char *alpha2)
|
||||||
snprintf(country, sizeof(country), "COUNTRY=%c%c",
|
snprintf(country, sizeof(country), "COUNTRY=%c%c",
|
||||||
alpha2[0], alpha2[1]);
|
alpha2[0], alpha2[1]);
|
||||||
|
|
||||||
|
/* query internal regulatory database (if it exists) */
|
||||||
|
reg_regdb_query(alpha2);
|
||||||
|
|
||||||
|
if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
|
||||||
|
pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_world_regdom((char *) alpha2))
|
if (!is_world_regdom((char *) alpha2))
|
||||||
pr_info("Calling CRDA for country: %c%c\n",
|
pr_info("Calling CRDA for country: %c%c\n",
|
||||||
alpha2[0], alpha2[1]);
|
alpha2[0], alpha2[1]);
|
||||||
else
|
else
|
||||||
pr_info("Calling CRDA to update world regulatory domain\n");
|
pr_info("Calling CRDA to update world regulatory domain\n");
|
||||||
|
|
||||||
/* query internal regulatory database (if it exists) */
|
|
||||||
reg_regdb_query(alpha2);
|
|
||||||
|
|
||||||
return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env);
|
return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2293,6 +2303,9 @@ int regulatory_hint_user(const char *alpha2,
|
||||||
request->initiator = NL80211_REGDOM_SET_BY_USER;
|
request->initiator = NL80211_REGDOM_SET_BY_USER;
|
||||||
request->user_reg_hint_type = user_reg_hint_type;
|
request->user_reg_hint_type = user_reg_hint_type;
|
||||||
|
|
||||||
|
/* Allow calling CRDA again */
|
||||||
|
reg_crda_timeouts = 0;
|
||||||
|
|
||||||
queue_regulatory_request(request);
|
queue_regulatory_request(request);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2362,6 +2375,9 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
|
||||||
request->alpha2[1] = alpha2[1];
|
request->alpha2[1] = alpha2[1];
|
||||||
request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
|
request->initiator = NL80211_REGDOM_SET_BY_DRIVER;
|
||||||
|
|
||||||
|
/* Allow calling CRDA again */
|
||||||
|
reg_crda_timeouts = 0;
|
||||||
|
|
||||||
queue_regulatory_request(request);
|
queue_regulatory_request(request);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2415,6 +2431,9 @@ void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band,
|
||||||
request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
|
request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
|
||||||
request->country_ie_env = env;
|
request->country_ie_env = env;
|
||||||
|
|
||||||
|
/* Allow calling CRDA again */
|
||||||
|
reg_crda_timeouts = 0;
|
||||||
|
|
||||||
queue_regulatory_request(request);
|
queue_regulatory_request(request);
|
||||||
request = NULL;
|
request = NULL;
|
||||||
out:
|
out:
|
||||||
|
@ -2893,7 +2912,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
|
||||||
* multiple drivers can be ironed out later. Caller must've already
|
* multiple drivers can be ironed out later. Caller must've already
|
||||||
* kmalloc'd the rd structure.
|
* kmalloc'd the rd structure.
|
||||||
*/
|
*/
|
||||||
int set_regdom(const struct ieee80211_regdomain *rd)
|
int set_regdom(const struct ieee80211_regdomain *rd,
|
||||||
|
enum ieee80211_regd_source regd_src)
|
||||||
{
|
{
|
||||||
struct regulatory_request *lr;
|
struct regulatory_request *lr;
|
||||||
bool user_reset = false;
|
bool user_reset = false;
|
||||||
|
@ -2904,6 +2924,9 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (regd_src == REGD_SOURCE_CRDA)
|
||||||
|
reg_crda_timeouts = 0;
|
||||||
|
|
||||||
lr = get_last_request();
|
lr = get_last_request();
|
||||||
|
|
||||||
/* Note that this doesn't update the wiphys, this is done below */
|
/* 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)
|
||||||
{
|
{
|
||||||
REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
|
REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
reg_crda_timeouts++;
|
||||||
restore_regulatory_settings(true);
|
restore_regulatory_settings(true);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum ieee80211_regd_source {
|
||||||
|
REGD_SOURCE_INTERNAL_DB,
|
||||||
|
REGD_SOURCE_CRDA,
|
||||||
|
};
|
||||||
|
|
||||||
extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
|
extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
|
||||||
|
|
||||||
bool reg_is_valid_request(const char *alpha2);
|
bool reg_is_valid_request(const char *alpha2);
|
||||||
|
@ -46,7 +51,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy);
|
||||||
int __init regulatory_init(void);
|
int __init regulatory_init(void);
|
||||||
void regulatory_exit(void);
|
void regulatory_exit(void);
|
||||||
|
|
||||||
int set_regdom(const struct ieee80211_regdomain *rd);
|
int set_regdom(const struct ieee80211_regdomain *rd,
|
||||||
|
enum ieee80211_regd_source regd_src);
|
||||||
|
|
||||||
unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
||||||
const struct ieee80211_reg_rule *rule);
|
const struct ieee80211_reg_rule *rule);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue