Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 089027e5 authored by Janusz Dziedzic's avatar Janusz Dziedzic Committed by Johannes Berg
Browse files

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: default avatarJanusz Dziedzic <janusz.dziedzic@tieto.com>
[rewrap commit log]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent fb5c9636
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -151,6 +151,7 @@ enum ieee80211_channel_flags {
 * @dfs_state: current state of this channel. Only relevant if radar is required
 * @dfs_state: current state of this channel. Only relevant if radar is required
 *	on this channel.
 *	on this channel.
 * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
 * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
 * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
 */
 */
struct ieee80211_channel {
struct ieee80211_channel {
	enum ieee80211_band band;
	enum ieee80211_band band;
@@ -165,6 +166,7 @@ struct ieee80211_channel {
	int orig_mag, orig_mpwr;
	int orig_mag, orig_mpwr;
	enum nl80211_dfs_state dfs_state;
	enum nl80211_dfs_state dfs_state;
	unsigned long dfs_state_entered;
	unsigned long dfs_state_entered;
	unsigned int dfs_cac_ms;
};
};


/**
/**
+13 −8
Original line number Original line Diff line number Diff line
@@ -155,6 +155,7 @@ struct ieee80211_reg_rule {
	struct ieee80211_freq_range freq_range;
	struct ieee80211_freq_range freq_range;
	struct ieee80211_power_rule power_rule;
	struct ieee80211_power_rule power_rule;
	u32 flags;
	u32 flags;
	u32 dfs_cac_ms;
};
};


struct ieee80211_regdomain {
struct ieee80211_regdomain {
@@ -172,7 +173,7 @@ struct ieee80211_regdomain {
#define DBM_TO_MBM(gain) ((gain) * 100)
#define DBM_TO_MBM(gain) ((gain) * 100)
#define MBM_TO_DBM(gain) ((gain) / 100)
#define MBM_TO_DBM(gain) ((gain) / 100)


#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
#define REG_RULE_EXT(start, end, bw, gain, eirp, dfs_cac, reg_flags)	\
{									\
{									\
	.freq_range.start_freq_khz = MHZ_TO_KHZ(start),			\
	.freq_range.start_freq_khz = MHZ_TO_KHZ(start),			\
	.freq_range.end_freq_khz = MHZ_TO_KHZ(end),			\
	.freq_range.end_freq_khz = MHZ_TO_KHZ(end),			\
@@ -180,6 +181,10 @@ struct ieee80211_regdomain {
	.power_rule.max_antenna_gain = DBI_TO_MBI(gain),		\
	.power_rule.max_antenna_gain = DBI_TO_MBI(gain),		\
	.power_rule.max_eirp = DBM_TO_MBM(eirp),			\
	.power_rule.max_eirp = DBM_TO_MBM(eirp),			\
	.flags = reg_flags,						\
	.flags = reg_flags,						\
	.dfs_cac_ms = dfs_cac,						\
}
}


#define REG_RULE(start, end, bw, gain, eirp, reg_flags) \
	REG_RULE_EXT(start, end, bw, gain, eirp, 0, reg_flags)

#endif
#endif
+6 −0
Original line number Original line Diff line number Diff line
@@ -2335,6 +2335,7 @@ enum nl80211_band_attr {
 * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel
 * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel
 *	using this channel as the primary or any of the secondary channels
 *	using this channel as the primary or any of the secondary channels
 *	isn't possible
 *	isn't possible
 * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
 * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
 * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
 *	currently defined
 *	currently defined
 * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
 * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -2353,6 +2354,7 @@ enum nl80211_frequency_attr {
	NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
	NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
	NL80211_FREQUENCY_ATTR_NO_80MHZ,
	NL80211_FREQUENCY_ATTR_NO_80MHZ,
	NL80211_FREQUENCY_ATTR_NO_160MHZ,
	NL80211_FREQUENCY_ATTR_NO_160MHZ,
	NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,


	/* keep last */
	/* keep last */
	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -2449,6 +2451,8 @@ enum nl80211_reg_type {
 * 	If you don't have one then don't send this.
 * 	If you don't have one then don't send this.
 * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
 * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
 * 	a given frequency range. The value is in mBm (100 * dBm).
 * 	a given frequency range. The value is in mBm (100 * dBm).
 * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
 *	If not present or 0 default CAC time will be used.
 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
 * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
 *	currently defined
 *	currently defined
 * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
 * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
@@ -2464,6 +2468,8 @@ enum nl80211_reg_rule_attr {
	NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
	NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
	NL80211_ATTR_POWER_RULE_MAX_EIRP,
	NL80211_ATTR_POWER_RULE_MAX_EIRP,


	NL80211_ATTR_DFS_CAC_TIME,

	/* keep last */
	/* keep last */
	__NL80211_REG_RULE_ATTR_AFTER_LAST,
	__NL80211_REG_RULE_ATTR_AFTER_LAST,
	NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
	NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
+7 −1
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ function parse_reg_rule()
	units = $8
	units = $8
	sub(/\)/, "", units)
	sub(/\)/, "", units)
	sub(/,/, "", units)
	sub(/,/, "", units)
	dfs_cac = $9
	if (units == "mW") {
	if (units == "mW") {
		if (power == 100) {
		if (power == 100) {
			power = 20
			power = 20
@@ -78,7 +79,12 @@ function parse_reg_rule()
		} else {
		} else {
			print "Unknown power value in database!"
			print "Unknown power value in database!"
		}
		}
	} else {
		dfs_cac = $8
	}
	}
	sub(/,/, "", dfs_cac)
	sub(/\(/, "", dfs_cac)
	sub(/\)/, "", dfs_cac)
	flagstr = ""
	flagstr = ""
	for (i=8; i<=NF; i++)
	for (i=8; i<=NF; i++)
		flagstr = flagstr $i
		flagstr = flagstr $i
@@ -111,7 +117,7 @@ function parse_reg_rule()


	}
	}
	flags = flags "0"
	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++
	rules++
}
}


+12 −1
Original line number Original line Diff line number Diff line
@@ -593,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
			if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
			if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME,
					time))
					time))
				goto nla_put_failure;
				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_FREQ_RANGE_MAX_BW]	= { .type = NLA_U32 },
	[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]	= { .type = NLA_U32 },
	[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]	= { .type = NLA_U32 },
	[NL80211_ATTR_POWER_RULE_MAX_EIRP]	= { .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[],
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 =
		power_rule->max_antenna_gain =
			nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_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;
	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,
		    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
				power_rule->max_antenna_gain) ||
				power_rule->max_antenna_gain) ||
		    nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
		    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;
			goto nla_put_failure_rcu;


		nla_nest_end(msg, nl_reg_rule);
		nla_nest_end(msg, nl_reg_rule);
Loading