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

Commit d3e84ab8 authored by Peng Xu's avatar Peng Xu
Browse files

nl80211: Support ACS offload feature flag and attribute



Added support for offloading ACS functionality to host driver.
A new feature flag NL80211_FEATURE_AP_ACS_OFFLOAD and a new attribute
NL80211_ATTR_ACS_OFFLOAD are added to support ACS (Automatic Channel
Selection) offload to driver. This allows driver to advertise its ACS
capability.
When hostapd starts, if channel is set to 0 hostapd will check if driver
has the capability of doing ACS. If driver has such capability
then hostapd set the attribut NL80211_ATTR_ACS_OFFLOAD to indicate to
kernel that channel selection is done in driver. Meanwhile kernel skips
validation of channel information since it is null when initially passed
by hostapd.
After channel is selected by driver, a channel change event is sent from
driver to kernel. Kernel updates channel information it maintains using
the new channel.

CRs-fixed: 714883
Change-Id: I195b0978031d7fad4f93688a0f919fd9a4d54193
Signed-off-by: default avatarPeng Xu <pxu@codeaurora.org>
parent d122742c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -1572,6 +1572,16 @@ enum nl80211_commands {
 *	connection.
 * @NL80211_ATTR_PMK_LEN: The length of the PMK.
 *
 * @NL80211_ATTR_IFACE_SOCKET_OWNER: flag attribute, if set during interface
 *	creation then the new interface will be owned by the netlink socket
 *	that created it and will be destroyed when the socket is closed
 *
 * @NL80211_ATTR_ACS_OFFLOAD: A flag indicating that driver will perform
 *	automatic channel selection when an AP is started. If the flag is set,
 *      kernel skips channel validation at AP starting time, after driver
 *	selects a channel, a channel change event is sent to kernel and
 *	hostapd so that they could update the channel information.
 *
 * @NL80211_ATTR_MAX: highest attribute number currently defined
 * @__NL80211_ATTR_AFTER_LAST: internal use
 */
@@ -1917,6 +1927,10 @@ enum nl80211_attrs {
	NL80211_ATTR_PMK,
	NL80211_ATTR_PMK_LEN,

	NL80211_ATTR_IFACE_SOCKET_OWNER,

	NL80211_ATTR_ACS_OFFLOAD,

	/* add attributes here, update the policy in nl80211.c */

	__NL80211_ATTR_AFTER_LAST,
@@ -3783,6 +3797,8 @@ enum nl80211_ap_sme_features {
 * @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic
 *	channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the
 *	lifetime of a BSS.
 * @NL80211_FEATURE_AP_ACS_OFFLOAD: This driver supports ACS (Automatic Channel
 *	Selection) during AP starting time.
 */
enum nl80211_feature_flags {
	NL80211_FEATURE_SK_TX_STATUS			= 1 << 0,
@@ -3803,6 +3819,7 @@ enum nl80211_feature_flags {
	NL80211_FEATURE_FULL_AP_CLIENT_STATE		= 1 << 15,
	NL80211_FEATURE_USERSPACE_MPM			= 1 << 16,
	NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE	= 1 << 18,
	NL80211_FEATURE_AP_ACS_OFFLOAD			= 1 << 19,
};

/**
+33 −26
Original line number Diff line number Diff line
@@ -400,6 +400,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
	[NL80211_ATTR_PMK] = { .type = NLA_BINARY,
				   .len = NL80211_KEY_LEN_PMK },
	[NL80211_ATTR_PMK_LEN] = { .type = NLA_U32 },
	[NL80211_ATTR_ACS_OFFLOAD] = { .type = NLA_U8 },
};

/* policy for the key attributes */
@@ -1887,7 +1888,8 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
			}

			/* Only allow dynamic channel width changes */
			if (chandef.chan != wdev->preset_chandef.chan) {
			if ((wdev->preset_chandef.chan != NULL) &&
				(chandef.chan != wdev->preset_chandef.chan)) {
				result = -EBUSY;
				break;
			}
@@ -3242,8 +3244,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
			return -EINVAL;
	}

	if (!info->attrs[NL80211_ATTR_ACS_OFFLOAD]) {
		if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
		err = nl80211_parse_chandef(rdev, info, &params.chandef);
			err = nl80211_parse_chandef(rdev,
						info, &params.chandef);
			if (err)
				return err;
		} else if (wdev->preset_chandef.chan) {
@@ -3254,7 +3258,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
		if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
			return -EINVAL;

	err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef);
		err = cfg80211_chandef_dfs_required(wdev->wiphy,
						&params.chandef);
		if (err < 0)
			return err;
		if (err) {
@@ -3271,6 +3276,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)

		if (err)
			return err;
	}

	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
		params.acl = parse_acl_data(&rdev->wiphy, info);
@@ -10710,6 +10716,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
		goto out;

	wdev->channel = chandef->chan;
	wdev->preset_chandef.chan = chandef->chan;
	nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
out:
	wdev_unlock(wdev);