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

Commit 923b352f authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Johannes Berg
Browse files

cfg80211: use RTNL locked reg_can_beacon for IR-relaxation



The RTNL is required to check for IR-relaxation conditions that allow
more channels to beacon. Export an RTNL locked version of reg_can_beacon
and use it where possible in AP/STA interface type flows, where
IR-relaxation may be applicable.

Fixes: 06f207fc ("cfg80211: change GO_CONCURRENT to IR_CONCURRENT for STA")
Signed-off-by: default avatarArik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b3e7de87
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -4868,6 +4868,23 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
			     struct cfg80211_chan_def *chandef,
			     enum nl80211_iftype iftype);

/**
 * cfg80211_reg_can_beacon_relax - check if beaconing is allowed with relaxation
 * @wiphy: the wiphy
 * @chandef: the channel definition
 * @iftype: interface type
 *
 * Return: %true if there is no secondary channel or the secondary channel(s)
 * can be used for beaconing (i.e. is not a radar channel etc.). This version
 * also checks if IR-relaxation conditions apply, to allow beaconing under
 * more permissive conditions.
 *
 * Requires the RTNL to be held.
 */
bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
				   struct cfg80211_chan_def *chandef,
				   enum nl80211_iftype iftype);

/*
 * cfg80211_ch_switch_notify - update wdev channel and notify userspace
 * @dev: the device which switched channels
+3 −3
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
	struct ieee80211_channel *ch;
	struct cfg80211_chan_def chandef;
	int i, subband_start;
	struct wiphy *wiphy = sdata->local->hw.wiphy;

	for (i = start; i <= end; i += spacing) {
		if (!ch_cnt)
@@ -70,8 +71,7 @@ ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
			/* we will be active on the channel */
			cfg80211_chandef_create(&chandef, ch,
						NL80211_CHAN_NO_HT);
			if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy,
						    &chandef,
			if (cfg80211_reg_can_beacon_relax(wiphy, &chandef,
							  sdata->wdev.iftype)) {
				ch_cnt++;
				/*
+34 −11
Original line number Diff line number Diff line
@@ -797,23 +797,18 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
	return false;
}

bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
				     struct cfg80211_chan_def *chandef,
			     enum nl80211_iftype iftype)
				     enum nl80211_iftype iftype,
				     bool check_no_ir)
{
	bool res;
	u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
			       IEEE80211_CHAN_RADAR;

	trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype);
	trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);

	/*
	 * Under certain conditions suggested by some regulatory bodies a
	 * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
	 * only if such relaxations are not enabled and the conditions are not
	 * met.
	 */
	if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan))
	if (check_no_ir)
		prohibited_flags |= IEEE80211_CHAN_NO_IR;

	if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
@@ -827,8 +822,36 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
	trace_cfg80211_return_bool(res);
	return res;
}

bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
			     struct cfg80211_chan_def *chandef,
			     enum nl80211_iftype iftype)
{
	return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true);
}
EXPORT_SYMBOL(cfg80211_reg_can_beacon);

bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
				   struct cfg80211_chan_def *chandef,
				   enum nl80211_iftype iftype)
{
	bool check_no_ir;

	ASSERT_RTNL();

	/*
	 * Under certain conditions suggested by some regulatory bodies a
	 * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
	 * only if such relaxations are not enabled and the conditions are not
	 * met.
	 */
	check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype,
						   chandef->chan);

	return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
}
EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax);

int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
				 struct cfg80211_chan_def *chandef)
{
+8 −6
Original line number Diff line number Diff line
@@ -2003,7 +2003,8 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
	switch (iftype) {
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
		if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) {
		if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
						   iftype)) {
			result = -EINVAL;
			break;
		}
@@ -3403,7 +3404,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
	} else if (!nl80211_get_ap_channel(rdev, &params))
		return -EINVAL;

	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef,
	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
					   wdev->iftype))
		return -EINVAL;

@@ -6492,7 +6493,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
	if (err)
		return err;

	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef,
	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
					   wdev->iftype))
		return -EINVAL;

@@ -10170,7 +10171,8 @@ static int nl80211_tdls_channel_switch(struct sk_buff *skb,
		return -EINVAL;

	/* we will be active on the TDLS link */
	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype))
	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
					   wdev->iftype))
		return -EINVAL;

	/* don't allow switching to DFS channels */
+1 −1
Original line number Diff line number Diff line
@@ -1589,7 +1589,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
	case NL80211_IFTYPE_ADHOC:
		return cfg80211_reg_can_beacon(wiphy, &chandef, iftype);
		return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
		return cfg80211_chandef_usable(wiphy, &chandef,
Loading