@@ -697,6 +697,18 @@ struct cfg80211_bitrate_mask {
} control[NUM_NL80211_BANDS];
};
+/*
+ * cfg80211_ul_bitrate_mask - masks for MU uplink bitrate control
+ */
+struct cfg80211_ul_bitrate_mask {
+ struct {
+ u16 he_ul_mcs[NL80211_HE_NSS_MAX];
+ enum nl80211_he_gi he_ul_gi;
+ enum nl80211_he_ltf he_ul_ltf;
+ bool he_ul_ldpc;
+ bool he_ul_stbc;
+ } control[NUM_NL80211_BANDS];
+};
/**
* struct cfg80211_tid_cfg - TID specific configuration
@@ -4233,6 +4245,11 @@ struct cfg80211_ops {
const u8 *peer,
const struct cfg80211_bitrate_mask *mask);
+ int (*set_ul_bitrate_mask)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_ul_bitrate_mask *mask);
+
int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
int idx, struct survey_info *info);
@@ -1232,6 +1232,10 @@
* &NL80211_ATTR_FILS_NONCES - for FILS Nonces
* (STA Nonce 16 bytes followed by AP Nonce 16 bytes)
*
+ * @NL80211_CMD_SET_UL_BITRATE_MASK: Set the mask of rates to be used in MU
+ * uplink rate selection. %NL80211_ATTR_IFINDEX is used to specify the
+ * interface and @NL80211_ATTR_UL_RATES the set of allowed rates.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1474,6 +1478,7 @@ enum nl80211_commands {
NL80211_CMD_SET_FILS_AAD,
+ NL80211_CMD_SET_UL_BITRATE_MASK,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -2646,6 +2651,13 @@ enum nl80211_commands {
* switching on a different channel during CAC detection on the selected
* radar channel.
*
+ * @NL80211_ATTR_UL_RATES: Nested set of attributes
+ * (enum nl80211_ul_rate_attributes) describing MU uplink rates per
+ * specified band. The enum nl80211_band value is used as the index
+ * nla_type() of the nested data. This attribute is used with
+ * %NL80211_CMD_SET_UL_BITRATE_MASK and it must specify just a single
+ * bitrate, which is to be used for MU uplink transmission.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3154,6 +3166,7 @@ enum nl80211_attrs {
NL80211_ATTR_RADAR_OFFCHAN,
+ NL80211_ATTR_UL_RATES,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -4981,6 +4994,38 @@ enum nl80211_txrate_gi {
};
/**
+ * enum nl80211_ul_rate_attributes - MU uplink rate set attributes
+ * @NL80211_UL_RATE_HE: HE MU UL MCS rates for MU uplink traffic,
+ * see &struct nl80211_ul_rate_he
+ * @NL80211_UL_RATE_HE_GI: configure HE UL GI, 0.8us, 1.6us and 3.2us.
+ * @NL80211_UL_RATE_HE_LTF: configure HE UL LTF, 1XLTF, 2XLTF and 4XLTF.
+ * @NL80211_UL_RATE_HE_LDPC: configure HE UL LDPC, enable and disable.
+ * @NL80211_UL_RATE_HE_STBC: configure HE UL STBC, enable and disable.
+ * @__NL80211_TXRATE_AFTER_LAST: internal
+ * @NL80211_TXRATE_MAX: highest TX rate attribute
+ */
+enum nl80211_ul_rate_attributes {
+ NL80211_UL_RATE_HE,
+ NL80211_UL_RATE_HE_GI,
+ NL80211_UL_RATE_HE_LTF,
+ NL80211_UL_RATE_HE_LDPC,
+ NL80211_UL_RATE_HE_STBC,
+
+ /* keep last */
+ __NL80211_UL_RATE_AFTER_LAST,
+ NL80211_UL_RATE_MAX = __NL80211_UL_RATE_AFTER_LAST - 1
+};
+
+/**
+ * struct nl80211_ul_rate_he - Uplink HE MCS/NSS rate bitmap for MU
+ * transmission.
+ * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
+ */
+struct nl80211_ul_rate_he {
+ __u16 mcs[NL80211_HE_NSS_MAX];
+};
+
+/**
* enum nl80211_band - Frequency band
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
* @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
@@ -386,6 +386,18 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = {
NL80211_RATE_INFO_HE_4XLTF),
};
+static const struct nla_policy nl80211_ul_rate_attr_policy[NL80211_UL_RATE_MAX + 1] = {
+ [NL80211_UL_RATE_HE] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_ul_rate_he)),
+ [NL80211_UL_RATE_HE_GI] = NLA_POLICY_RANGE(NLA_U8,
+ NL80211_RATE_INFO_HE_GI_0_8,
+ NL80211_RATE_INFO_HE_GI_3_2),
+ [NL80211_UL_RATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8,
+ NL80211_RATE_INFO_HE_1XLTF,
+ NL80211_RATE_INFO_HE_4XLTF),
+ [NL80211_UL_RATE_HE_LDPC] = { .type = NLA_FLAG },
+ [NL80211_UL_RATE_HE_STBC] = { .type = NLA_FLAG },
+};
+
static const struct nla_policy
nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
[NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
@@ -4954,6 +4966,63 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info,
return 0;
}
+static int nl80211_parse_ul_bitrate_mask(struct genl_info *info,
+ struct nlattr *attrs[],
+ enum nl80211_attrs attr,
+ struct cfg80211_ul_bitrate_mask *mask,
+ struct net_device *dev,
+ bool default_all_enabled)
+{
+ struct nlattr *tb[NL80211_TXRATE_MAX + 1];
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int rem;
+ struct nlattr *tx_rates;
+ struct ieee80211_supported_band *sband;
+
+ memset(mask, 0, sizeof(*mask));
+
+ /* The nested attribute uses enum nl80211_band as the index. This maps
+ * directly to the enum nl80211_band values used in cfg80211.
+ */
+ nla_for_each_nested(tx_rates, attrs[attr], rem) {
+ enum nl80211_band band = nla_type(tx_rates);
+ int err;
+
+ if (band < 0 || band >= NUM_NL80211_BANDS)
+ return -EINVAL;
+ sband = rdev->wiphy.bands[band];
+ if (!sband)
+ return -EINVAL;
+ err = nla_parse_nested_deprecated(tb, NL80211_UL_RATE_MAX,
+ tx_rates,
+ nl80211_ul_rate_attr_policy,
+ info->extack);
+ if (err)
+ return err;
+ if (tb[NL80211_UL_RATE_HE] &&
+ !he_set_mcs_mask(info, wdev, sband,
+ nla_data(tb[NL80211_UL_RATE_HE]),
+ mask->control[band].he_ul_mcs))
+ return -EINVAL;
+
+ if (tb[NL80211_UL_RATE_HE_GI])
+ mask->control[band].he_ul_gi =
+ nla_get_u8(tb[NL80211_UL_RATE_HE_GI]);
+ if (tb[NL80211_UL_RATE_HE_LTF])
+ mask->control[band].he_ul_ltf =
+ nla_get_u8(tb[NL80211_UL_RATE_HE_LTF]);
+ if (tb[NL80211_UL_RATE_HE_LDPC])
+ mask->control[band].he_ul_ldpc =
+ !nla_get_flag(tb[NL80211_UL_RATE_HE_LDPC]);
+ if (tb[NL80211_UL_RATE_HE_STBC])
+ mask->control[band].he_ul_stbc =
+ !nla_get_flag(tb[NL80211_UL_RATE_HE_STBC]);
+ }
+
+ return 0;
+}
+
static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
enum nl80211_band band,
struct cfg80211_bitrate_mask *beacon_rate)
@@ -11546,6 +11615,26 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
}
+static int nl80211_set_ul_bitrate_mask(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_ul_bitrate_mask mask;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ int err;
+
+ if (!rdev->ops->set_bitrate_mask)
+ return -EOPNOTSUPP;
+
+ err = nl80211_parse_ul_bitrate_mask(info, info->attrs,
+ NL80211_ATTR_UL_RATES, &mask,
+ dev, true);
+ if (err)
+ return err;
+
+ return rdev_set_ul_bitrate_mask(rdev, dev, NULL, &mask);
+}
+
static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -15740,6 +15829,13 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV,
},
{
+ .cmd = NL80211_CMD_SET_UL_BITRATE_MASK,
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+ .doit = nl80211_set_ul_bitrate_mask,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV,
+ },
+ {
.cmd = NL80211_CMD_REGISTER_FRAME,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_register_mgmt,
@@ -661,6 +661,18 @@ rdev_set_bitrate_mask(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int
+rdev_set_ul_bitrate_mask(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *peer,
+ const struct cfg80211_ul_bitrate_mask *mask)
+{
+ int ret;
+ trace_rdev_set_ul_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+ ret = rdev->ops->set_ul_bitrate_mask(&rdev->wiphy, dev, peer, mask);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
static inline int rdev_dump_survey(struct cfg80211_registered_device *rdev,
struct net_device *netdev, int idx,
struct survey_info *info)
@@ -1635,6 +1635,24 @@ TRACE_EVENT(rdev_set_bitrate_mask,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
);
+TRACE_EVENT(rdev_set_ul_bitrate_mask,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ const u8 *peer, const struct cfg80211_ul_bitrate_mask *mask),
+ TP_ARGS(wiphy, netdev, peer, mask),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(peer)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(peer, peer);
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
+
TRACE_EVENT(rdev_update_mgmt_frame_registrations,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
struct mgmt_frame_regs *upd),
This patch adds nl80211 definitions, policies and parsing code required to pass HE uplink MU fixed rate settings utiliized in UL trigger. Signed-off-by: Muna Sinada <msinada@codeaurora.org> --- v3: - restructured flow of passing uplink MU transmission settings. No longer utilizing existing bitrate structures and attributes, new ones are created for uplink MU transmission. - added HE LTF/GI/LDPC/STBC along with HE fixed rate setting for uplink MU transmissions, which are part of the UL Trigger. - modified commit message from "nl80211: Add HE UL MU fixed rate setting" in order to include all the rate settings related to UL Trigger. --- include/net/cfg80211.h | 17 ++++++++ include/uapi/linux/nl80211.h | 45 +++++++++++++++++++++ net/wireless/nl80211.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ net/wireless/rdev-ops.h | 12 ++++++ net/wireless/trace.h | 18 +++++++++ 5 files changed, 188 insertions(+)