WIPHY_VENDOR_CMD_NEED_RUNNING = BIT(2),
 };
 
+/**
+ * enum wiphy_opmode_flag - Station's ht/vht operation mode information flags
+ *
+ * @STA_OPMODE_MAX_BW_CHANGED: Max Bandwidth changed
+ * @STA_OPMODE_SMPS_MODE_CHANGED: SMPS mode changed
+ * @STA_OPMODE_N_SS_CHANGED: max N_SS (number of spatial streams) changed
+ *
+ */
+enum wiphy_opmode_flag {
+       STA_OPMODE_MAX_BW_CHANGED       = BIT(0),
+       STA_OPMODE_SMPS_MODE_CHANGED    = BIT(1),
+       STA_OPMODE_N_SS_CHANGED         = BIT(2),
+};
+
+/**
+ * struct sta_opmode_info - Station's ht/vht operation mode information
+ * @changed: contains value from &enum wiphy_opmode_flag
+ * @smps_mode: New SMPS mode of a station
+ * @bw: new max bandwidth value of a station
+ * @rx_nss: new rx_nss value of a station
+ */
+
+struct sta_opmode_info {
+       u32 changed;
+       u8 smps_mode;
+       u8 bw;
+       u8 rx_nss;
+};
+
 /**
  * struct wiphy_vendor_command - vendor command definition
  * @info: vendor command identifying information, as used in nl80211
 void cfg80211_radar_event(struct wiphy *wiphy,
                          struct cfg80211_chan_def *chandef, gfp_t gfp);
 
+/**
+ * cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event
+ * @dev: network device
+ * @mac: MAC address of a station which opmode got modified
+ * @sta_opmode: station's current opmode value
+ * @gfp: context flags
+ *
+ * Driver should call this function when station's opmode modified via action
+ * frame.
+ */
+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+                                      struct sta_opmode_info *sta_opmode,
+                                      gfp_t gfp);
+
 /**
  * cfg80211_cac_event - Channel availability check (CAC) event
  * @netdev: network device
 
  *     user space through the connect result as the user space would have
  *     initiated the connection through the connect request.
  *
+ * @NL80211_CMD_STA_OPMODE_CHANGED: An event that notify station's
+ *     ht opmode or vht opmode changes using any of &NL80211_ATTR_SMPS_MODE,
+ *     &NL80211_ATTR_CHANNEL_WIDTH,&NL80211_ATTR_NSS attributes with its
+ *     address(specified in &NL80211_ATTR_MAC).
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
 
        NL80211_CMD_EXTERNAL_AUTH,
 
+       NL80211_CMD_STA_OPMODE_CHANGED,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
  *     authentication processing to user space if this capability is indicated
  *     in NL80211_CMD_CONNECT requests from the user space.
  *
+ * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
+ *     u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
+ *
  * @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_EXTERNAL_AUTH_ACTION,
        NL80211_ATTR_EXTERNAL_AUTH_SUPPORT,
 
+       NL80211_ATTR_NSS,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
 
        nlmsg_free(msg);
 }
 
+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+                                      struct sta_opmode_info *sta_opmode,
+                                      gfp_t gfp)
+{
+       struct sk_buff *msg;
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+       void *hdr;
+
+       if (WARN_ON(!mac))
+               return;
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STA_OPMODE_CHANGED);
+       if (!hdr) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
+               goto nla_put_failure;
+
+       if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
+               goto nla_put_failure;
+
+       if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
+               goto nla_put_failure;
+
+       if ((sta_opmode->changed & STA_OPMODE_SMPS_MODE_CHANGED) &&
+           nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, sta_opmode->smps_mode))
+               goto nla_put_failure;
+
+       if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) &&
+           nla_put_u8(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw))
+               goto nla_put_failure;
+
+       if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) &&
+           nla_put_u8(msg, NL80211_ATTR_NSS, sta_opmode->rx_nss))
+               goto nla_put_failure;
+
+       genlmsg_end(msg, hdr);
+
+       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+                               NL80211_MCGRP_MLME, gfp);
+
+       return;
+
+nla_put_failure:
+       nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_sta_opmode_change_notify);
+
 void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
                           u64 cookie, bool acked, gfp_t gfp)
 {