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

Commit ee4bc9e7 authored by Simon Wunderlich's avatar Simon Wunderlich Committed by Johannes Berg
Browse files

nl80211: enable IBSS support for channel switch announcements

parent 9449410f
Loading
Loading
Loading
Loading
+34 −15
Original line number Original line Diff line number Diff line
@@ -5634,15 +5634,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
	static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
	static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
	u8 radar_detect_width = 0;
	u8 radar_detect_width = 0;
	int err;
	int err;
	bool need_new_beacon = false;


	if (!rdev->ops->channel_switch ||
	if (!rdev->ops->channel_switch ||
	    !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
	    !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;


	/* may add IBSS support later */
	switch (dev->ieee80211_ptr->iftype) {
	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
	case NL80211_IFTYPE_AP:
	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
	case NL80211_IFTYPE_P2P_GO:
		need_new_beacon = true;

		/* useless if AP is not running */
		if (!wdev->beacon_interval)
			return -EINVAL;
		break;
	case NL80211_IFTYPE_ADHOC:
		break;
	default:
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}


	memset(&params, 0, sizeof(params));
	memset(&params, 0, sizeof(params));


@@ -5651,15 +5662,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
		return -EINVAL;
		return -EINVAL;


	/* only important for AP, IBSS and mesh create IEs internally */
	/* only important for AP, IBSS and mesh create IEs internally */
	if (!info->attrs[NL80211_ATTR_CSA_IES])
	if (need_new_beacon &&
		return -EINVAL;
	    (!info->attrs[NL80211_ATTR_CSA_IES] ||

	     !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON]))
	/* useless if AP is not running */
	if (!wdev->beacon_interval)
		return -EINVAL;
		return -EINVAL;


	params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
	params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);


	if (!need_new_beacon)
		goto skip_beacons;

	err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
	err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
	if (err)
	if (err)
		return err;
		return err;
@@ -5699,6 +5711,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
			return -EINVAL;
			return -EINVAL;
	}
	}


skip_beacons:
	err = nl80211_parse_chandef(rdev, info, &params.chandef);
	err = nl80211_parse_chandef(rdev, info, &params.chandef);
	if (err)
	if (err)
		return err;
		return err;
@@ -5706,13 +5719,18 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
	if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
		return -EINVAL;
		return -EINVAL;


	err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef);
	/* DFS channels are only supported for AP/P2P GO ... for now. */
	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
	    dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
		err = cfg80211_chandef_dfs_required(wdev->wiphy,
						    &params.chandef);
		if (err < 0) {
		if (err < 0) {
			return err;
			return err;
		} else if (err) {
		} else if (err) {
			radar_detect_width = BIT(params.chandef.width);
			radar_detect_width = BIT(params.chandef.width);
			params.radar_required = true;
			params.radar_required = true;
		}
		}
	}


	err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
	err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
					   params.chandef.chan,
					   params.chandef.chan,
@@ -10740,7 +10758,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
	wdev_lock(wdev);
	wdev_lock(wdev);


	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
		    wdev->iftype != NL80211_IFTYPE_P2P_GO))
		    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
		    wdev->iftype != NL80211_IFTYPE_ADHOC))
		goto out;
		goto out;


	wdev->channel = chandef->chan;
	wdev->channel = chandef->chan;