aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-10-15 03:03:05 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-10-15 10:17:09 -0400
commitc7d319e542a3126bca029745735cdef5a5ca55c2 (patch)
tree5e8fc98483271df35fb413988c22398aa2124a78
parentcecbb069cce37dac754380d36c31e286a276e4c3 (diff)
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: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/wireless/reg.c102
1 files changed, 58 insertions, 44 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index ed3330579dc0..bc29c9a754a5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -453,65 +453,70 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd)
453} 453}
454 454
455#ifdef CONFIG_CFG80211_INTERNAL_REGDB 455#ifdef CONFIG_CFG80211_INTERNAL_REGDB
456struct reg_regdb_search_request { 456struct reg_regdb_apply_request {
457 char alpha2[2];
458 struct list_head list; 457 struct list_head list;
458 const struct ieee80211_regdomain *regdom;
459}; 459};
460 460
461static LIST_HEAD(reg_regdb_search_list); 461static LIST_HEAD(reg_regdb_apply_list);
462static DEFINE_MUTEX(reg_regdb_search_mutex); 462static DEFINE_MUTEX(reg_regdb_apply_mutex);
463 463
464static void reg_regdb_search(struct work_struct *work) 464static void reg_regdb_apply(struct work_struct *work)
465{ 465{
466 struct reg_regdb_search_request *request; 466 struct reg_regdb_apply_request *request;
467 const struct ieee80211_regdomain *curdom, *regdom = NULL;
468 int i;
469 467
470 rtnl_lock(); 468 rtnl_lock();
471 469
472 mutex_lock(&reg_regdb_search_mutex); 470 mutex_lock(&reg_regdb_apply_mutex);
473 while (!list_empty(&reg_regdb_search_list)) { 471 while (!list_empty(&reg_regdb_apply_list)) {
474 request = list_first_entry(&reg_regdb_search_list, 472 request = list_first_entry(&reg_regdb_apply_list,
475 struct reg_regdb_search_request, 473 struct reg_regdb_apply_request,
476 list); 474 list);
477 list_del(&request->list); 475 list_del(&request->list);
478 476
479 for (i = 0; i < reg_regdb_size; i++) { 477 set_regdom(request->regdom, REGD_SOURCE_INTERNAL_DB);
480 curdom = reg_regdb[i];
481
482 if (alpha2_equal(request->alpha2, curdom->alpha2)) {
483 regdom = reg_copy_regd(curdom);
484 break;
485 }
486 }
487
488 kfree(request); 478 kfree(request);
489 } 479 }
490 mutex_unlock(&reg_regdb_search_mutex); 480 mutex_unlock(&reg_regdb_apply_mutex);
491
492 if (!IS_ERR_OR_NULL(regdom))
493 set_regdom(regdom, REGD_SOURCE_INTERNAL_DB);
494 481
495 rtnl_unlock(); 482 rtnl_unlock();
496} 483}
497 484
498static DECLARE_WORK(reg_regdb_work, reg_regdb_search); 485static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);
499 486
500static void reg_regdb_query(const char *alpha2) 487static int reg_regdb_query(const char *alpha2)
501{ 488{
502 struct reg_regdb_search_request *request; 489 const struct ieee80211_regdomain *regdom = NULL;
490 struct reg_regdb_apply_request *request;
491 unsigned int i;
492
493 for (i = 0; i < reg_regdb_size; i++) {
494 if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
495 regdom = reg_regdb[i];
496 break;
497 }
498 }
499
500 if (!regdom)
501 return -ENODATA;
503 502
504 request = kzalloc(sizeof(struct reg_regdb_search_request), GFP_KERNEL); 503 request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL);
505 if (!request) 504 if (!request)
506 return; 505 return -ENOMEM;
507 506
508 memcpy(request->alpha2, alpha2, 2); 507 request->regdom = reg_copy_regd(regdom);
508 if (IS_ERR_OR_NULL(request->regdom)) {
509 kfree(request);
510 return -ENOMEM;
511 }
509 512
510 mutex_lock(&reg_regdb_search_mutex); 513 mutex_lock(&reg_regdb_apply_mutex);
511 list_add_tail(&request->list, &reg_regdb_search_list); 514 list_add_tail(&request->list, &reg_regdb_apply_list);
512 mutex_unlock(&reg_regdb_search_mutex); 515 mutex_unlock(&reg_regdb_apply_mutex);
513 516
514 schedule_work(&reg_regdb_work); 517 schedule_work(&reg_regdb_work);
518
519 return 0;
515} 520}
516 521
517/* Feel free to add any other sanity checks here */ 522/* Feel free to add any other sanity checks here */
@@ -522,7 +527,10 @@ static void reg_regdb_size_check(void)
522} 527}
523#else 528#else
524static inline void reg_regdb_size_check(void) {} 529static inline void reg_regdb_size_check(void) {}
525static inline void reg_regdb_query(const char *alpha2) {} 530static inline int reg_regdb_query(const char *alpha2)
531{
532 return -ENODATA;
533}
526#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ 534#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
527 535
528/* 536/*
@@ -533,13 +541,11 @@ static int call_crda(const char *alpha2)
533{ 541{
534 char country[12]; 542 char country[12];
535 char *env[] = { country, NULL }; 543 char *env[] = { country, NULL };
544 int ret;
536 545
537 snprintf(country, sizeof(country), "COUNTRY=%c%c", 546 snprintf(country, sizeof(country), "COUNTRY=%c%c",
538 alpha2[0], alpha2[1]); 547 alpha2[0], alpha2[1]);
539 548
540 /* query internal regulatory database (if it exists) */
541 reg_regdb_query(alpha2);
542
543 if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) { 549 if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
544 pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n"); 550 pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n");
545 return -EINVAL; 551 return -EINVAL;
@@ -551,17 +557,25 @@ static int call_crda(const char *alpha2)
551 else 557 else
552 pr_debug("Calling CRDA to update world regulatory domain\n"); 558 pr_debug("Calling CRDA to update world regulatory domain\n");
553 559
554 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env); 560 ret = kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, env);
561 if (ret)
562 return ret;
563
564 queue_delayed_work(system_power_efficient_wq,
565 &reg_timeout, msecs_to_jiffies(3142));
566 return 0;
555} 567}
556 568
557static bool reg_query_database(struct regulatory_request *request) 569static bool reg_query_database(struct regulatory_request *request)
558{ 570{
559 if (call_crda(request->alpha2)) 571 /* query internal regulatory database (if it exists) */
560 return false; 572 if (reg_regdb_query(request->alpha2) == 0)
573 return true;
561 574
562 queue_delayed_work(system_power_efficient_wq, 575 if (call_crda(request->alpha2) == 0)
563 &reg_timeout, msecs_to_jiffies(3142)); 576 return true;
564 return true; 577
578 return false;
565} 579}
566 580
567bool reg_is_valid_request(const char *alpha2) 581bool reg_is_valid_request(const char *alpha2)