History

cfg80211: regulatory: introduce NL80211_RRF_AUTO_BW rule flag

Introduce NL80211_RRF_AUTO_BW rule flag. If this flag set maximum available bandwidth should be calculated base on contiguous rules and wider channels will be allowed to cross multiple contiguous/overlapping frequency ranges. In case of old kernels maximum bandwidth from regulatory rule will be used, while there is no NL80211_RRF_AUTO_BW flag. This fixes the previous commit 9752482083066af7ac18a5ca376f ("cfg80211: regulatory introduce maximum bandwidth calculation") which was found to be a problem for userspace API compatibility. Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> [edit commit log, use sizeof()] Signed-off-by: Johannes Berg <johannes.berg@intel.com>

Janusz Dziedzic committed 12 years ago

Commit b0dfd2e1 parent 37e33084 files · +58 −43Browse files

Unified · Split

4 files
  1. include/uapi/linux/nl80211.h +5 −4
  2. net/wireless/genregdb.awk +2 −0
  3. net/wireless/nl80211.c +4 −3
  4. net/wireless/reg.c +47 −36
include/uapi/linux/nl80211.h+5−4
@@ -2443,10 +2443,7 @@ enum nl80211_reg_type { · 2442 unmodified lines
24432443 * in KHz. This is not a center a frequency but an actual regulatory
24442444 * band edge.
24452445 * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
2446− * frequency range, in KHz. If not present or 0, maximum available
2447− * bandwidth should be calculated base on contiguous rules and wider
2448− * channels will be allowed to cross multiple contiguous/overlapping
2449− * frequency ranges.
2446+ * frequency range, in KHz.
24502447 * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
24512448 * for a given frequency range. The value is in mBi (100 * dBi).
24522449 * If you don't have one then don't send this.
@@ -2517,6 +2514,9 @@ enum nl80211_sched_scan_match_attr { · 64 unmodified lines
25172514 * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
25182515 * this includes probe requests or modes of operation that require
25192516 * beaconing.
2517+ * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
2518+ * base on contiguous rules and wider channels will be allowed to cross
2519+ * multiple contiguous/overlapping frequency ranges.
25202520 */
25212521 enum nl80211_reg_rule_flags {
25222522 NL80211_RRF_NO_OFDM = 1<<0,
@@ -2528,6 +2528,7 @@ enum nl80211_reg_rule_flags { · 5 unmodified lines
25282528 NL80211_RRF_PTMP_ONLY = 1<<6,
25292529 NL80211_RRF_NO_IR = 1<<7,
25302530 __NL80211_RRF_NO_IBSS = 1<<8,
2531+ NL80211_RRF_AUTO_BW = 1<<11,
25312532 };
25322533
25332534 #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
net/wireless/genregdb.awk+2−0
@@ -105,6 +105,8 @@ function parse_reg_rule() · 104 unmodified lines
105105 flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
106106 } else if (flagarray[arg] == "NO-IR") {
107107 flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
108+ } else if (flagarray[arg] == "AUTO-BW") {
109+ flags = flags "\n\t\t\tNL80211_RRF_AUTO_BW | "
108110 }
109111
110112 }
net/wireless/nl80211.c+4−3
@@ -4628,6 +4628,8 @@ static int parse_reg_rule(struct nlattr *tb[], · 4627 unmodified lines
46284628 return -EINVAL;
46294629 if (!tb[NL80211_ATTR_FREQ_RANGE_END])
46304630 return -EINVAL;
4631+ if (!tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
4632+ return -EINVAL;
46314633 if (!tb[NL80211_ATTR_POWER_RULE_MAX_EIRP])
46324634 return -EINVAL;
46334635
@@ -4637,9 +4639,8 @@ static int parse_reg_rule(struct nlattr *tb[], · 3 unmodified lines
46374639 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]);
46384640 freq_range->end_freq_khz =
46394641 nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]);
4640− if (tb[NL80211_ATTR_FREQ_RANGE_MAX_BW])
4641− freq_range->max_bandwidth_khz =
4642− nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
4642+ freq_range->max_bandwidth_khz =
4643+ nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]);
46434644
46444645 power_rule->max_eirp =
46454646 nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]);
net/wireless/reg.c+47−36
@@ -563,9 +563,6 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, · 562 unmodified lines
563563 if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
564564 break;
565565
566− if (freq_range_tmp->max_bandwidth_khz)
567− break;
568−
569566 freq_range = freq_range_tmp;
570567 }
571568
@@ -582,9 +579,6 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, · 10 unmodified lines
582579 if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
583580 break;
584581
585− if (freq_range_tmp->max_bandwidth_khz)
586− break;
587−
588582 freq_range = freq_range_tmp;
589583 }
590584
@@ -729,21 +723,29 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, · 138 unmodified lines
729723 max_bandwidth1 = freq_range1->max_bandwidth_khz;
730724 max_bandwidth2 = freq_range2->max_bandwidth_khz;
731725
732− /*
733− * In case max_bandwidth1 == 0 and max_bandwith2 == 0 set
734− * output bandwidth as 0 (auto calculation). Next we will
735− * calculate this correctly in handle_channel function.
736− * In other case calculate output bandwidth here.
737− */
738− if (max_bandwidth1 || max_bandwidth2) {
739− if (!max_bandwidth1)
740− max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1);
741− if (!max_bandwidth2)
742− max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2);
743− }
726+ if (rule1->flags & NL80211_RRF_AUTO_BW)
727+ max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1);
728+ if (rule2->flags & NL80211_RRF_AUTO_BW)
729+ max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2);
744730
745731 freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2);
746732
733+ intersected_rule->flags = rule1->flags | rule2->flags;
734+
735+ /*
736+ * In case NL80211_RRF_AUTO_BW requested for both rules
737+ * set AUTO_BW in intersected rule also. Next we will
738+ * calculate BW correctly in handle_channel function.
739+ * In other case remove AUTO_BW flag while we calculate
740+ * maximum bandwidth correctly and auto calculation is
741+ * not required.
742+ */
743+ if ((rule1->flags & NL80211_RRF_AUTO_BW) &&
744+ (rule2->flags & NL80211_RRF_AUTO_BW))
745+ intersected_rule->flags |= NL80211_RRF_AUTO_BW;
746+ else
747+ intersected_rule->flags &= ~NL80211_RRF_AUTO_BW;
748+
747749 freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
748750 if (freq_range->max_bandwidth_khz > freq_diff)
749751 freq_range->max_bandwidth_khz = freq_diff;
@@ -753,8 +755,6 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, · 3 unmodified lines
753755 power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
754756 power_rule2->max_antenna_gain);
755757
756− intersected_rule->flags = rule1->flags | rule2->flags;
757−
758758 if (!is_valid_reg_rule(intersected_rule))
759759 return -EINVAL;
760760
@@ -938,31 +938,42 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator) · 177 unmodified lines
938938 EXPORT_SYMBOL(reg_initiator_name);
939939
940940 #ifdef CONFIG_CFG80211_REG_DEBUG
941−static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan,
941+static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd,
942+ struct ieee80211_channel *chan,
942943 const struct ieee80211_reg_rule *reg_rule)
943944 {
944945 const struct ieee80211_power_rule *power_rule;
945946 const struct ieee80211_freq_range *freq_range;
946− char max_antenna_gain[32];
947+ char max_antenna_gain[32], bw[32];
947948
948949 power_rule = &reg_rule->power_rule;
949950 freq_range = &reg_rule->freq_range;
950951
951952 if (!power_rule->max_antenna_gain)
952− snprintf(max_antenna_gain, 32, "N/A");
953+ snprintf(max_antenna_gain, sizeof(max_antenna_gain), "N/A");
953954 else
954− snprintf(max_antenna_gain, 32, "%d", power_rule->max_antenna_gain);
955+ snprintf(max_antenna_gain, sizeof(max_antenna_gain), "%d",
956+ power_rule->max_antenna_gain);
957+
958+ if (reg_rule->flags & NL80211_RRF_AUTO_BW)
959+ snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO",
960+ freq_range->max_bandwidth_khz,
961+ reg_get_max_bandwidth(regd, reg_rule));
962+ else
963+ snprintf(bw, sizeof(bw), "%d KHz",
964+ freq_range->max_bandwidth_khz);
955965
956966 REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n",
957967 chan->center_freq);
958968
959− REG_DBG_PRINT("%d KHz - %d KHz @ %d KHz), (%s mBi, %d mBm)\n",
969+ REG_DBG_PRINT("%d KHz - %d KHz @ %s), (%s mBi, %d mBm)\n",
960970 freq_range->start_freq_khz, freq_range->end_freq_khz,
961− freq_range->max_bandwidth_khz, max_antenna_gain,
971+ bw, max_antenna_gain,
962972 power_rule->max_eirp);
963973 }
964974 #else
965−static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan,
975+static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd,
976+ struct ieee80211_channel *chan,
966977 const struct ieee80211_reg_rule *reg_rule)
967978 {
968979 return;
@@ -1022,17 +1033,16 @@ static void handle_channel(struct wiphy *wiphy, · 53 unmodified lines
10221033 return;
10231034 }
10241035
1025− chan_reg_rule_print_dbg(chan, reg_rule);
1036+ regd = reg_get_regdomain(wiphy);
1037+ chan_reg_rule_print_dbg(regd, chan, reg_rule);
10261038
10271039 power_rule = &reg_rule->power_rule;
10281040 freq_range = &reg_rule->freq_range;
10291041
10301042 max_bandwidth_khz = freq_range->max_bandwidth_khz;
10311043 /* Check if auto calculation requested */
1032− if (!max_bandwidth_khz) {
1033− regd = reg_get_regdomain(wiphy);
1044+ if (reg_rule->flags & NL80211_RRF_AUTO_BW)
10341045 max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
1035− }
10361046
10371047 if (max_bandwidth_khz < MHZ_TO_KHZ(40))
10381048 bw_flags = IEEE80211_CHAN_NO_HT40;
@@ -1437,14 +1447,14 @@ static void handle_channel_custom(struct wiphy *wiphy, · 398 unmodified lines
14371447 return;
14381448 }
14391449
1440− chan_reg_rule_print_dbg(chan, reg_rule);
1450+ chan_reg_rule_print_dbg(regd, chan, reg_rule);
14411451
14421452 power_rule = &reg_rule->power_rule;
14431453 freq_range = &reg_rule->freq_range;
14441454
14451455 max_bandwidth_khz = freq_range->max_bandwidth_khz;
14461456 /* Check if auto calculation requested */
1447− if (!max_bandwidth_khz)
1457+ if (reg_rule->flags & NL80211_RRF_AUTO_BW)
14481458 max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
14491459
14501460 if (max_bandwidth_khz < MHZ_TO_KHZ(40))
@@ -2254,11 +2264,12 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) · 803 unmodified lines
22542264 freq_range = &reg_rule->freq_range;
22552265 power_rule = &reg_rule->power_rule;
22562266
2257− if (!freq_range->max_bandwidth_khz)
2258− snprintf(bw, 32, "%d KHz, AUTO",
2267+ if (reg_rule->flags & NL80211_RRF_AUTO_BW)
2268+ snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO",
2269+ freq_range->max_bandwidth_khz,
22592270 reg_get_max_bandwidth(rd, reg_rule));
22602271 else
2261− snprintf(bw, 32, "%d KHz",
2272+ snprintf(bw, sizeof(bw), "%d KHz",
22622273 freq_range->max_bandwidth_khz);
22632274
22642275 /*