cfg80211: regulatory: allow getting DFS CAC time from userspace
Introduce DFS CAC time as a regd param, configured per REG_RULE and set per channel in cfg80211. DFS CAC time is close connected with regulatory database configuration. Instead of using hardcoded values, get DFS CAC time form regulatory database. Pass DFS CAC time to user mode (mainly for iw reg get, iw list, iw info). Allow setting DFS CAC time via CRDA. Add support for internal regulatory database. Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> [rewrap commit log] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:

committed by
Johannes Berg

parent
fb5c96368f
commit
089027e57c
@@ -66,6 +66,7 @@ function parse_reg_rule()
|
||||
units = $8
|
||||
sub(/\)/, "", units)
|
||||
sub(/,/, "", units)
|
||||
dfs_cac = $9
|
||||
if (units == "mW") {
|
||||
if (power == 100) {
|
||||
power = 20
|
||||
@@ -78,7 +79,12 @@ function parse_reg_rule()
|
||||
} else {
|
||||
print "Unknown power value in database!"
|
||||
}
|
||||
} else {
|
||||
dfs_cac = $8
|
||||
}
|
||||
sub(/,/, "", dfs_cac)
|
||||
sub(/\(/, "", dfs_cac)
|
||||
sub(/\)/, "", dfs_cac)
|
||||
flagstr = ""
|
||||
for (i=8; i<=NF; i++)
|
||||
flagstr = flagstr $i
|
||||
@@ -111,7 +117,7 @@ function parse_reg_rule()
|
||||
|
||||
}
|
||||
flags = flags "0"
|
||||
printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
|
||||
printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
|
||||
rules++
|
||||
}
|
||||
|
||||
|
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
|
||||
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
|
||||
time))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_u32(msg,
|
||||
NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
|
||||
chan->dfs_cac_ms))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4614,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] =
|
||||
[NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int parse_reg_rule(struct nlattr *tb[],
|
||||
@@ -4649,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[],
|
||||
power_rule->max_antenna_gain =
|
||||
nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]);
|
||||
|
||||
if (tb[NL80211_ATTR_DFS_CAC_TIME])
|
||||
reg_rule->dfs_cac_ms =
|
||||
nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5136,7 +5145,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
|
||||
power_rule->max_antenna_gain) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
|
||||
power_rule->max_eirp))
|
||||
power_rule->max_eirp) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
|
||||
reg_rule->dfs_cac_ms))
|
||||
goto nla_put_failure_rcu;
|
||||
|
||||
nla_nest_end(msg, nl_reg_rule);
|
||||
|
@@ -756,6 +756,9 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
|
||||
power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
|
||||
power_rule2->max_antenna_gain);
|
||||
|
||||
intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
|
||||
rule2->dfs_cac_ms);
|
||||
|
||||
if (!is_valid_reg_rule(intersected_rule))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1078,6 +1081,14 @@ static void handle_channel(struct wiphy *wiphy,
|
||||
min_t(int, chan->orig_mag,
|
||||
MBI_TO_DBI(power_rule->max_antenna_gain));
|
||||
chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
|
||||
|
||||
if (chan->flags & IEEE80211_CHAN_RADAR) {
|
||||
if (reg_rule->dfs_cac_ms)
|
||||
chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
|
||||
else
|
||||
chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
|
||||
}
|
||||
|
||||
if (chan->orig_mpwr) {
|
||||
/*
|
||||
* Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
|
||||
@@ -2256,9 +2267,9 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
||||
const struct ieee80211_reg_rule *reg_rule = NULL;
|
||||
const struct ieee80211_freq_range *freq_range = NULL;
|
||||
const struct ieee80211_power_rule *power_rule = NULL;
|
||||
char bw[32];
|
||||
char bw[32], cac_time[32];
|
||||
|
||||
pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
|
||||
pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n");
|
||||
|
||||
for (i = 0; i < rd->n_reg_rules; i++) {
|
||||
reg_rule = &rd->reg_rules[i];
|
||||
@@ -2273,23 +2284,32 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
|
||||
snprintf(bw, sizeof(bw), "%d KHz",
|
||||
freq_range->max_bandwidth_khz);
|
||||
|
||||
if (reg_rule->flags & NL80211_RRF_DFS)
|
||||
scnprintf(cac_time, sizeof(cac_time), "%u s",
|
||||
reg_rule->dfs_cac_ms/1000);
|
||||
else
|
||||
scnprintf(cac_time, sizeof(cac_time), "N/A");
|
||||
|
||||
|
||||
/*
|
||||
* There may not be documentation for max antenna gain
|
||||
* in certain regions
|
||||
*/
|
||||
if (power_rule->max_antenna_gain)
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm)\n",
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n",
|
||||
freq_range->start_freq_khz,
|
||||
freq_range->end_freq_khz,
|
||||
bw,
|
||||
power_rule->max_antenna_gain,
|
||||
power_rule->max_eirp);
|
||||
power_rule->max_eirp,
|
||||
cac_time);
|
||||
else
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm)\n",
|
||||
pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n",
|
||||
freq_range->start_freq_khz,
|
||||
freq_range->end_freq_khz,
|
||||
bw,
|
||||
power_rule->max_eirp);
|
||||
power_rule->max_eirp,
|
||||
cac_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user