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

Commit 2beb6dab authored by Luciano Coelho's avatar Luciano Coelho Committed by Johannes Berg
Browse files

cfg80211/mac80211: refactor cfg80211_chandef_dfs_required()



Some interface types don't require DFS (such as STATION, P2P_CLIENT
etc).  In order to centralize these decisions, make
cfg80211_chandef_dfs_required() take the iftype into consideration.

Signed-off-by: default avatarLuciano Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent cb2d956d
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -446,10 +446,13 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
 * cfg80211_chandef_dfs_required - checks if radar detection is required
 * @wiphy: the wiphy to validate against
 * @chandef: the channel definition to check
 * Return: 1 if radar detection is required, 0 if it is not, < 0 on error
 * @iftype: the interface type as specified in &enum nl80211_iftype
 * Returns:
 *	1 if radar detection is required, 0 if it is not, < 0 on error
 */
int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
				  const struct cfg80211_chan_def *chandef);
				  const struct cfg80211_chan_def *chandef,
				  enum nl80211_iftype);

/**
 * ieee80211_chandef_rate_flags - returns rate flags for a channel
+16 −16
Original line number Diff line number Diff line
@@ -228,7 +228,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
	struct beacon_data *presp;
	enum nl80211_bss_scan_width scan_width;
	bool have_higher_than_11mbit;
	bool radar_required = false;
	bool radar_required;
	int err;

	sdata_assert_lock(sdata);
@@ -284,20 +284,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
	}

	err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
					    &chandef);
					    &chandef, NL80211_IFTYPE_ADHOC);
	if (err < 0) {
		sdata_info(sdata,
			   "Failed to join IBSS, invalid chandef\n");
		return;
	}
	if (err > 0) {
		if (!ifibss->userspace_handles_dfs) {
	if (err > 0 && !ifibss->userspace_handles_dfs) {
		sdata_info(sdata,
			   "Failed to join IBSS, DFS channel without control program\n");
		return;
	}
		radar_required = true;
	}

	radar_required = err;

	mutex_lock(&local->mtx);
	if (ieee80211_vif_use_channel(sdata, &chandef,
@@ -777,7 +776,8 @@ static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
	 * unavailable.
	 */
	err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
					    &ifibss->chandef);
					    &ifibss->chandef,
					    NL80211_IFTYPE_ADHOC);
	if (err > 0)
		cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef,
				     GFP_ATOMIC);
@@ -876,17 +876,17 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
	}

	err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
					    &params.chandef);
					    &params.chandef,
					    NL80211_IFTYPE_ADHOC);
	if (err < 0)
		goto disconnect;
	if (err) {
	if (err > 0 && !ifibss->userspace_handles_dfs) {
		/* IBSS-DFS only allowed with a control program */
		if (!ifibss->userspace_handles_dfs)
		goto disconnect;

		params.radar_required = true;
	}

	params.radar_required = err;

	if (cfg80211_chandef_identical(&params.chandef,
				       &sdata->vif.bss_conf.chandef)) {
		ibss_dbg(sdata,
+5 −4
Original line number Diff line number Diff line
@@ -903,14 +903,15 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
	}

	err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
					    &params.chandef);
					    &params.chandef,
					    NL80211_IFTYPE_MESH_POINT);
	if (err < 0)
		return false;
	if (err) {
		params.radar_required = true;
	if (err > 0)
		/* TODO: DFS not (yet) supported */
		return false;
	}

	params.radar_required = err;

	if (cfg80211_chandef_identical(&params.chandef,
				       &sdata->vif.bss_conf.chandef)) {
+56 −18
Original line number Diff line number Diff line
@@ -326,28 +326,57 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,


int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
				  const struct cfg80211_chan_def *chandef)
				  const struct cfg80211_chan_def *chandef,
				  enum nl80211_iftype iftype)
{
	int width;
	int r;
	int ret;

	if (WARN_ON(!cfg80211_chandef_valid(chandef)))
		return -EINVAL;

	switch (iftype) {
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
	case NL80211_IFTYPE_MESH_POINT:
		width = cfg80211_chandef_get_width(chandef);
		if (width < 0)
			return -EINVAL;

	r = cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq1,
		ret = cfg80211_get_chans_dfs_required(wiphy,
						      chandef->center_freq1,
						      width);
	if (r)
		return r;
		if (ret < 0)
			return ret;
		else if (ret > 0)
			return BIT(chandef->width);

		if (!chandef->center_freq2)
			return 0;

	return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
		ret = cfg80211_get_chans_dfs_required(wiphy,
						      chandef->center_freq2,
						      width);
		if (ret < 0)
			return ret;
		else if (ret > 0)
			return BIT(chandef->width);

		break;
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_MONITOR:
	case NL80211_IFTYPE_AP_VLAN:
	case NL80211_IFTYPE_WDS:
	case NL80211_IFTYPE_P2P_DEVICE:
	case NL80211_IFTYPE_UNSPECIFIED:
		break;
	case NUM_NL80211_IFTYPES:
		WARN_ON(1);
	}

	return 0;
}
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);

@@ -749,7 +778,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
	    !cfg80211_go_permissive_chan(rdev, chandef->chan))
		prohibited_flags |= IEEE80211_CHAN_NO_IR;

	if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
	if (cfg80211_chandef_dfs_required(wiphy, chandef,
					  NL80211_IFTYPE_UNSPECIFIED) > 0 &&
	    cfg80211_chandef_dfs_available(wiphy, chandef)) {
		/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
		prohibited_flags = IEEE80211_CHAN_DISABLED;
@@ -779,6 +809,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
		        enum cfg80211_chan_mode *chanmode,
		        u8 *radar_detect)
{
	int ret;

	*chan = NULL;
	*chanmode = CHAN_MODE_UNDEFINED;

@@ -821,8 +853,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
			*chan = wdev->chandef.chan;
			*chanmode = CHAN_MODE_SHARED;

			if (cfg80211_chandef_dfs_required(wdev->wiphy,
							  &wdev->chandef))
			ret = cfg80211_chandef_dfs_required(wdev->wiphy,
							    &wdev->chandef,
							    wdev->iftype);
			WARN_ON(ret < 0);
			if (ret > 0)
				*radar_detect |= BIT(wdev->chandef.width);
		}
		return;
@@ -831,8 +866,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
			*chan = wdev->chandef.chan;
			*chanmode = CHAN_MODE_SHARED;

			if (cfg80211_chandef_dfs_required(wdev->wiphy,
							  &wdev->chandef))
			ret = cfg80211_chandef_dfs_required(wdev->wiphy,
							    &wdev->chandef,
							    wdev->iftype);
			WARN_ON(ret < 0);
			if (ret > 0)
				*radar_detect |= BIT(wdev->chandef.width);
		}
		return;
+5 −2
Original line number Diff line number Diff line
@@ -179,10 +179,13 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
				     NL80211_IFTYPE_MESH_POINT))
		return -EINVAL;

	err = cfg80211_chandef_dfs_required(wdev->wiphy, &setup->chandef);
	err = cfg80211_chandef_dfs_required(wdev->wiphy,
					    &setup->chandef,
					    NL80211_IFTYPE_MESH_POINT);
	if (err < 0)
		return err;
	if (err)

	if (err > 0)
		radar_detect_width = BIT(setup->chandef.width);

	err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
Loading