Commit c7d319e5 authored by Johannes Berg's avatar Johannes Berg

cfg80211: reg: search built-in database directly

Instead of searching the built-in database only in the worker,
search it directly and return an error if the entry cannot be
found (or memory cannot be allocated.) This means that builtin
database queries no longer rely on the timeout.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent cecbb069
......@@ -453,65 +453,70 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd)
}
#ifdef CONFIG_CFG80211_INTERNAL_REGDB
struct reg_regdb_search_request {
char alpha2[2];
struct reg_regdb_apply_request {
struct list_head list;
const struct ieee80211_regdomain *regdom;
};
static LIST_HEAD(reg_regdb_search_list);
static DEFINE_MUTEX(reg_regdb_search_mutex);
static LIST_HEAD(reg_regdb_apply_list);
static DEFINE_MUTEX(reg_regdb_apply_mutex);
static void reg_regdb_search(struct work_struct *work)
static void reg_regdb_apply(struct work_struct *work)
{
struct reg_regdb_search_request *request;
const struct ieee80211_regdomain *curdom, *regdom = NULL;
int i;
struct reg_regdb_apply_request *request;
rtnl_lock();
mutex_lock(&reg_regdb_search_mutex);
while (!list_empty(&reg_regdb_search_list)) {
request = list_first_entry(&reg_regdb_search_list,
struct reg_regdb_search_request,
mutex_lock(&reg_regdb_apply_mutex);
while (!list_empty(&reg_regdb_apply_list)) {
request = list_first_entry(&reg_regdb_apply_list,
struct reg_regdb_apply_request,
list);
list_del(&request->list);
for (i = 0; i < reg_regdb_size; i++) {
curdom = reg_regdb[i];
if (alpha2_equal(request->alpha2, curdom->alpha2)) {
regdom = reg_copy_regd(curdom);
break;
}
}
set_regdom(request->regdom, REGD_SOURCE_INTERNAL_DB);
kfree(request);
}
mutex_unlock(&reg_regdb_search_mutex);
if (!IS_ERR_OR_NULL(regdom))
set_regdom(regdom, REGD_SOURCE_INTERNAL_DB);
mutex_unlock(&reg_regdb_apply_mutex);
rtnl_unlock();
}
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);
static void reg_regdb_query(const char *alpha2)
static int reg_regdb_query(const char *alpha2)
{
struct reg_regdb_search_request *request;
const struct ieee80211_regdomain *regdom = NULL;
struct reg_regdb_apply_request *request;
unsigned int i;
for (i = 0; i < reg_regdb_size; i++) {
if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
regdom = reg_regdb[i];
break;
}
}
if (!regdom)
return -ENODATA;
request = kzalloc(sizeof(struct reg_regdb_search_request), GFP_KERNEL);
request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL);
if (!request)
return;
return -ENOMEM;
memcpy(request->alpha2, alpha2, 2);
request->regdom = reg_copy_regd(regdom);
if (IS_ERR_OR_NULL(request->regdom)) {
kfree(request);
return -ENOMEM;
}
mutex_lock(&reg_regdb_search_mutex);
list_add_tail(&request->list, &reg_regdb_search_list);
mutex_unlock(&reg_regdb_search_mutex);
mutex_lock(&reg_regdb_apply_mutex);
list_add_tail(&request->list, &reg_regdb_apply_list);
mutex_unlock(&reg_regdb_apply_mutex);
schedule_work(&reg_regdb_work);
return 0;
}
/* Feel free to add any other sanity checks here */
......@@ -522,7 +527,10 @@ static void reg_regdb_size_check(void)
}
#else
static inline void reg_regdb_size_check(void) {}
static inline void reg_regdb_query(const char *alpha2) {}
static inline int reg_regdb_query(const char *alpha2)
{
return -ENODATA;
}
#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
/*
......@@ -533,13 +541,11 @@ static int call_crda(const char *alpha2)
{
char country[12];
char *env[] = { country, NULL };
int ret;
snprintf(country, sizeof(country), "COUNTRY=%c%c",
alpha2[0], alpha2[1]);
/* query internal regulatory database (if it exists) */
reg_regdb_query(alpha2);
if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n");
return -EINVAL;
......@@ -551,17 +557,25 @@ static int call_crda(const char *alpha2)
else
pr_debug("Calling CRDA to update world regulatory domain\n");
return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
ret = kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
if (ret)
return ret;
queue_delayed_work(system_power_efficient_wq,
&reg_timeout, msecs_to_jiffies(3142));
return 0;
}
static bool reg_query_database(struct regulatory_request *request)
{
if (call_crda(request->alpha2))
return false;
/* query internal regulatory database (if it exists) */
if (reg_regdb_query(request->alpha2) == 0)
return true;
queue_delayed_work(system_power_efficient_wq,
&reg_timeout, msecs_to_jiffies(3142));
return true;
if (call_crda(request->alpha2) == 0)
return true;
return false;
}
bool reg_is_valid_request(const char *alpha2)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment