Skip to content

Commit

Permalink
cfg80211: reg: search built-in database directly
Browse files Browse the repository at this point in the history
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: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Oct 15, 2015
1 parent cecbb06 commit c7d319e
Showing 1 changed file with 58 additions and 44 deletions.
102 changes: 58 additions & 44 deletions net/wireless/reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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 */

/*
Expand All @@ -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;
Expand All @@ -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)
Expand Down

0 comments on commit c7d319e

Please sign in to comment.