summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h2
-rw-r--r--include/uapi/linux/nl80211.h33
-rw-r--r--net/wireless/nl80211.c24
3 files changed, 59 insertions, 0 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2ed1f80f7eb6..a2ddcf2398fd 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -664,6 +664,7 @@ struct cfg80211_acl_data {
* @crypto: crypto settings
* @privacy: the BSS uses privacy
* @auth_type: Authentication type (algorithm)
+ * @smps_mode: SMPS mode
* @inactivity_timeout: time in seconds to determine station's inactivity.
* @p2p_ctwindow: P2P CT Window
* @p2p_opp_ps: P2P opportunistic PS
@@ -682,6 +683,7 @@ struct cfg80211_ap_settings {
struct cfg80211_crypto_settings crypto;
bool privacy;
enum nl80211_auth_type auth_type;
+ enum nl80211_smps_mode smps_mode;
int inactivity_timeout;
u8 p2p_ctwindow;
bool p2p_opp_ps;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index e5b8caf5e466..4b28dc07bcb1 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1635,6 +1635,9 @@ enum nl80211_commands {
* @NL80211_ATTR_ADMITTED_TIME: admitted time in units of 32 microseconds
* (per second) (u16 attribute)
*
+ * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see
+ * &enum nl80211_smps_mode.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1985,6 +1988,8 @@ enum nl80211_attrs {
NL80211_ATTR_USER_PRIO,
NL80211_ATTR_ADMITTED_TIME,
+ NL80211_ATTR_SMPS_MODE,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -4030,6 +4035,13 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_ACKTO_ESTIMATION: This driver supports dynamic ACK timeout
* estimation (dynack). %NL80211_ATTR_WIPHY_DYN_ACK flag attribute is used
* to enable dynack.
+ * @NL80211_FEATURE_STATIC_SMPS: Device supports static spatial
+ * multiplexing powersave, ie. can turn off all but one chain
+ * even on HT connections that should be using more chains.
+ * @NL80211_FEATURE_DYNAMIC_SMPS: Device supports dynamic spatial
+ * multiplexing powersave, ie. can turn off all but one chain
+ * and then wake the rest up as required after, for example,
+ * rts/cts handshake.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -4056,6 +4068,8 @@ enum nl80211_feature_flags {
NL80211_FEATURE_QUIET = 1 << 21,
NL80211_FEATURE_TX_POWER_INSERTION = 1 << 22,
NL80211_FEATURE_ACKTO_ESTIMATION = 1 << 23,
+ NL80211_FEATURE_STATIC_SMPS = 1 << 24,
+ NL80211_FEATURE_DYNAMIC_SMPS = 1 << 25,
};
/**
@@ -4130,6 +4144,25 @@ enum nl80211_acl_policy {
};
/**
+ * enum nl80211_smps_mode - SMPS mode
+ *
+ * Requested SMPS mode (for AP mode)
+ *
+ * @NL80211_SMPS_OFF: SMPS off (use all antennas).
+ * @NL80211_SMPS_STATIC: static SMPS (use a single antenna)
+ * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and
+ * turn on other antennas after CTS/RTS).
+ */
+enum nl80211_smps_mode {
+ NL80211_SMPS_OFF,
+ NL80211_SMPS_STATIC,
+ NL80211_SMPS_DYNAMIC,
+
+ __NL80211_SMPS_AFTER_LAST,
+ NL80211_SMPS_MAX = __NL80211_SMPS_AFTER_LAST - 1
+};
+
+/**
* enum nl80211_radar_event - type of radar event for DFS operation
*
* Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e8114c7a37e3..4cce3e17964d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -394,6 +394,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_TSID] = { .type = NLA_U8 },
[NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
+ [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
};
/* policy for the key attributes */
@@ -3345,6 +3346,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
return PTR_ERR(params.acl);
}
+ if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
+ params.smps_mode =
+ nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
+ switch (params.smps_mode) {
+ case NL80211_SMPS_OFF:
+ break;
+ case NL80211_SMPS_STATIC:
+ if (!(rdev->wiphy.features &
+ NL80211_FEATURE_STATIC_SMPS))
+ return -EINVAL;
+ break;
+ case NL80211_SMPS_DYNAMIC:
+ if (!(rdev->wiphy.features &
+ NL80211_FEATURE_DYNAMIC_SMPS))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ params.smps_mode = NL80211_SMPS_OFF;
+ }
+
wdev_lock(wdev);
err = rdev_start_ap(rdev, dev, &params);
if (!err) {