*     if wme is supported.
  * @max_sp: max Service Period. Only valid if wme is supported.
  * @bandwidth: current bandwidth the station can receive with
+ * @rx_nss: in HT/VHT, the maximum number of spatial streams the
+ *     station can receive at the moment, changed by operating mode
+ *     notifications and capabilities. The value is only valid after
+ *     the station moves to associated state.
  */
 struct ieee80211_sta {
        u32 supp_rates[IEEE80211_NUM_BANDS];
        bool wme;
        u8 uapsd_queues;
        u8 max_sp;
+       u8 rx_nss;
        enum ieee80211_sta_rx_bandwidth bandwidth;
 
        /* must be last */
 
                                         struct ieee80211_vht_cap *vht_cap_ie,
                                         struct sta_info *sta);
 enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
+void ieee80211_sta_set_rx_nss(struct sta_info *sta);
 
 /* Spectrum management */
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
 
        sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
        rcu_read_unlock();
 
+       ieee80211_sta_set_rx_nss(sta);
+
        ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
        set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
 }
 
                return IEEE80211_STA_RX_BW_80;
        }
 }
+
+void ieee80211_sta_set_rx_nss(struct sta_info *sta)
+{
+       u8 ht_rx_nss = 0, vht_rx_nss = 0;
+
+       /* if we received a notification already don't overwrite it */
+       if (sta->sta.rx_nss)
+               return;
+
+       if (sta->sta.ht_cap.ht_supported) {
+               if (sta->sta.ht_cap.mcs.rx_mask[0])
+                       ht_rx_nss++;
+               if (sta->sta.ht_cap.mcs.rx_mask[1])
+                       ht_rx_nss++;
+               if (sta->sta.ht_cap.mcs.rx_mask[2])
+                       ht_rx_nss++;
+               if (sta->sta.ht_cap.mcs.rx_mask[3])
+                       ht_rx_nss++;
+               /* FIXME: consider rx_highest? */
+       }
+
+       if (sta->sta.vht_cap.vht_supported) {
+               int i;
+               u16 rx_mcs_map;
+
+               rx_mcs_map = le16_to_cpu(sta->sta.vht_cap.vht_mcs.rx_mcs_map);
+
+               for (i = 7; i >= 0; i--) {
+                       u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
+
+                       if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
+                               vht_rx_nss = i + 1;
+                               break;
+                       }
+               }
+               /* FIXME: consider rx_highest? */
+       }
+
+       ht_rx_nss = max(ht_rx_nss, vht_rx_nss);
+       sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss);
+}