aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c81
1 files changed, 60 insertions, 21 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8bfc9b172a49..b725a31a4751 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -799,6 +799,57 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
799 return 0; 799 return 0;
800} 800}
801 801
802/* check whether old rule contains new rule */
803static bool rule_contains(struct ieee80211_reg_rule *r1,
804 struct ieee80211_reg_rule *r2)
805{
806 /* for simplicity, currently consider only same flags */
807 if (r1->flags != r2->flags)
808 return false;
809
810 /* verify r1 is more restrictive */
811 if ((r1->power_rule.max_antenna_gain >
812 r2->power_rule.max_antenna_gain) ||
813 r1->power_rule.max_eirp > r2->power_rule.max_eirp)
814 return false;
815
816 /* make sure r2's range is contained within r1 */
817 if (r1->freq_range.start_freq_khz > r2->freq_range.start_freq_khz ||
818 r1->freq_range.end_freq_khz < r2->freq_range.end_freq_khz)
819 return false;
820
821 /* and finally verify that r1.max_bw >= r2.max_bw */
822 if (r1->freq_range.max_bandwidth_khz <
823 r2->freq_range.max_bandwidth_khz)
824 return false;
825
826 return true;
827}
828
829/* add or extend current rules. do nothing if rule is already contained */
830static void add_rule(struct ieee80211_reg_rule *rule,
831 struct ieee80211_reg_rule *reg_rules, u32 *n_rules)
832{
833 struct ieee80211_reg_rule *tmp_rule;
834 int i;
835
836 for (i = 0; i < *n_rules; i++) {
837 tmp_rule = &reg_rules[i];
838 /* rule is already contained - do nothing */
839 if (rule_contains(tmp_rule, rule))
840 return;
841
842 /* extend rule if possible */
843 if (rule_contains(rule, tmp_rule)) {
844 memcpy(tmp_rule, rule, sizeof(*rule));
845 return;
846 }
847 }
848
849 memcpy(&reg_rules[*n_rules], rule, sizeof(*rule));
850 (*n_rules)++;
851}
852
802/** 853/**
803 * regdom_intersect - do the intersection between two regulatory domains 854 * regdom_intersect - do the intersection between two regulatory domains
804 * @rd1: first regulatory domain 855 * @rd1: first regulatory domain
@@ -818,12 +869,10 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
818{ 869{
819 int r, size_of_regd; 870 int r, size_of_regd;
820 unsigned int x, y; 871 unsigned int x, y;
821 unsigned int num_rules = 0, rule_idx = 0; 872 unsigned int num_rules = 0;
822 const struct ieee80211_reg_rule *rule1, *rule2; 873 const struct ieee80211_reg_rule *rule1, *rule2;
823 struct ieee80211_reg_rule *intersected_rule; 874 struct ieee80211_reg_rule intersected_rule;
824 struct ieee80211_regdomain *rd; 875 struct ieee80211_regdomain *rd;
825 /* This is just a dummy holder to help us count */
826 struct ieee80211_reg_rule dummy_rule;
827 876
828 if (!rd1 || !rd2) 877 if (!rd1 || !rd2)
829 return NULL; 878 return NULL;
@@ -841,7 +890,7 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
841 for (y = 0; y < rd2->n_reg_rules; y++) { 890 for (y = 0; y < rd2->n_reg_rules; y++) {
842 rule2 = &rd2->reg_rules[y]; 891 rule2 = &rd2->reg_rules[y];
843 if (!reg_rules_intersect(rd1, rd2, rule1, rule2, 892 if (!reg_rules_intersect(rd1, rd2, rule1, rule2,
844 &dummy_rule)) 893 &intersected_rule))
845 num_rules++; 894 num_rules++;
846 } 895 }
847 } 896 }
@@ -856,34 +905,24 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
856 if (!rd) 905 if (!rd)
857 return NULL; 906 return NULL;
858 907
859 for (x = 0; x < rd1->n_reg_rules && rule_idx < num_rules; x++) { 908 for (x = 0; x < rd1->n_reg_rules; x++) {
860 rule1 = &rd1->reg_rules[x]; 909 rule1 = &rd1->reg_rules[x];
861 for (y = 0; y < rd2->n_reg_rules && rule_idx < num_rules; y++) { 910 for (y = 0; y < rd2->n_reg_rules; y++) {
862 rule2 = &rd2->reg_rules[y]; 911 rule2 = &rd2->reg_rules[y];
863 /*
864 * This time around instead of using the stack lets
865 * write to the target rule directly saving ourselves
866 * a memcpy()
867 */
868 intersected_rule = &rd->reg_rules[rule_idx];
869 r = reg_rules_intersect(rd1, rd2, rule1, rule2, 912 r = reg_rules_intersect(rd1, rd2, rule1, rule2,
870 intersected_rule); 913 &intersected_rule);
871 /* 914 /*
872 * No need to memset here the intersected rule here as 915 * No need to memset here the intersected rule here as
873 * we're not using the stack anymore 916 * we're not using the stack anymore
874 */ 917 */
875 if (r) 918 if (r)
876 continue; 919 continue;
877 rule_idx++;
878 }
879 }
880 920
881 if (rule_idx != num_rules) { 921 add_rule(&intersected_rule, rd->reg_rules,
882 kfree(rd); 922 &rd->n_reg_rules);
883 return NULL; 923 }
884 } 924 }
885 925
886 rd->n_reg_rules = num_rules;
887 rd->alpha2[0] = '9'; 926 rd->alpha2[0] = '9';
888 rd->alpha2[1] = '8'; 927 rd->alpha2[1] = '8';
889 rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region, 928 rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,