*     with the get_key() callback, must be in little endian,
  *     length given by @seq_len.
  * @seq_len: length of @seq.
+ * @vlan_id: vlan_id for VLAN group key (if nonzero)
  * @mode: key install mode (RX_TX, NO_TX or SET_TX)
  */
 struct key_params {
        const u8 *seq;
        int key_len;
        int seq_len;
+       u16 vlan_id;
        u32 cipher;
        enum nl80211_key_mode mode;
 };
  *     (bitmask of BIT(%NL80211_STA_FLAG_...))
  * @listen_interval: listen interval or -1 for no change
  * @aid: AID or zero for no change
+ * @vlan_id: VLAN ID for station (if nonzero)
  * @peer_aid: mesh peer AID or zero for no change
  * @plink_action: plink action to take
  * @plink_state: set the peer link state for a station
        u32 sta_modify_mask;
        int listen_interval;
        u16 aid;
+       u16 vlan_id;
        u16 peer_aid;
        u8 supported_rates_len;
        u8 plink_action;
 
  * %NL80211_ATTR_SAE_PASSWORD.
  */
 
+/**
+ * DOC: VLAN offload support for setting group keys and binding STAs to VLANs
+ *
+ * By setting @NL80211_EXT_FEATURE_VLAN_OFFLOAD flag drivers can indicate they
+ * support offloading VLAN functionality in a manner where the driver exposes a
+ * single netdev that uses VLAN tagged frames and separate VLAN-specific netdevs
+ * can then be added using RTM_NEWLINK/IFLA_VLAN_ID similarly to the Ethernet
+ * case. Frames received from stations that are not assigned to any VLAN are
+ * delivered on the main netdev and frames to such stations can be sent through
+ * that main netdev.
+ *
+ * %NL80211_CMD_NEW_KEY (for group keys), %NL80211_CMD_NEW_STATION, and
+ * %NL80211_CMD_SET_STATION will optionally specify vlan_id using
+ * %NL80211_ATTR_VLAN_ID.
+ */
+
 /**
  * enum nl80211_commands - supported nl80211 commands
  *
  *     the allowed channel bandwidth configurations. (u8 attribute)
  *     Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13.
  *
+ * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key
+ *     (u16).
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
        NL80211_ATTR_WIPHY_EDMG_CHANNELS,
        NL80211_ATTR_WIPHY_EDMG_BW_CONFIG,
 
+       NL80211_ATTR_VLAN_ID,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
  * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in
  *     station mode (SAE password is passed as part of the connect command).
  *
+ * @NL80211_EXT_FEATURE_VLAN_OFFLOAD: The driver supports a single netdev
+ *     with VLAN tagged frames and separate VLAN-specific netdevs added using
+ *     vconfig similarly to the Ethernet case.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
        NL80211_EXT_FEATURE_EXT_KEY_ID,
        NL80211_EXT_FEATURE_STA_TX_PWR,
        NL80211_EXT_FEATURE_SAE_OFFLOAD,
+       NL80211_EXT_FEATURE_VLAN_OFFLOAD,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
 
                                        .len = SAE_PASSWORD_MAX_LEN },
        [NL80211_ATTR_TWT_RESPONDER] = { .type = NLA_FLAG },
        [NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
+       [NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
 };
 
 /* policy for the key attributes */
            key.type != NL80211_KEYTYPE_GROUP)
                return -EINVAL;
 
+       if (key.type == NL80211_KEYTYPE_GROUP &&
+           info->attrs[NL80211_ATTR_VLAN_ID])
+               key.p.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
+
        if (!rdev->ops->add_key)
                return -EOPNOTSUPP;
 
        if (info->attrs[NL80211_ATTR_STA_AID])
                params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
 
+       if (info->attrs[NL80211_ATTR_VLAN_ID])
+               params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
+
        if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
                params.listen_interval =
                     nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
        params.listen_interval =
                nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
 
+       if (info->attrs[NL80211_ATTR_VLAN_ID])
+               params.vlan_id = nla_get_u16(info->attrs[NL80211_ATTR_VLAN_ID]);
+
        if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
                params.support_p2p_ps =
                        nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);