*
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
        u8 reserved[4 - (NUM_MAC_INDEX % 4)];
 } __packed; /* STATISTICS_GENERAL_API_S_VER_8 */
 
+/**
+ * struct mvm_statistics_load - RX statistics for multi-queue devices
+ * @air_time: accumulated air time, per mac
+ * @byte_count: accumulated byte count, per mac
+ * @pkt_count: accumulated packet count, per mac
+ * @avg_energy: average RSSI, per station
+ */
+struct mvm_statistics_load {
+       __le32 air_time[NUM_MAC_INDEX];
+       __le32 byte_count[NUM_MAC_INDEX];
+       __le32 pkt_count[NUM_MAC_INDEX];
+       u8 avg_energy[IWL_MVM_STATION_COUNT];
+} __packed; /* STATISTICS_RX_MAC_STATION_S_VER_1 */
+
 struct mvm_statistics_rx {
        struct mvm_statistics_rx_phy ofdm;
        struct mvm_statistics_rx_phy cck;
  * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the
  * STATISTICS_CMD (0x9c), below.
  */
-
 struct iwl_notif_statistics_v10 {
        __le32 flag;
        struct mvm_statistics_rx rx;
        struct mvm_statistics_general_v8 general;
 } __packed; /* STATISTICS_NTFY_API_S_VER_10 */
 
+struct iwl_notif_statistics_v11 {
+       __le32 flag;
+       struct mvm_statistics_rx rx;
+       struct mvm_statistics_tx tx;
+       struct mvm_statistics_general_v8 general;
+       struct mvm_statistics_load load_stats;
+} __packed; /* STATISTICS_NTFY_API_S_VER_11 */
+
 #define IWL_STATISTICS_FLG_CLEAR               0x1
 #define IWL_STATISTICS_FLG_DISABLE_NOTIF       0x2
 
 
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
+       if (mvmsta->avg_energy) {
+               sinfo->signal_avg = mvmsta->avg_energy;
+               sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG);
+       }
+
        if (fw_has_capa(&mvm->fw->ucode_capa,
                        IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
                return;
 
        __le32 mac_id;
        u8 beacon_filter_average_energy;
        struct mvm_statistics_general_v8 *general;
+       struct mvm_statistics_load *load;
 };
 
 static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
 void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
                                  struct iwl_rx_packet *pkt)
 {
-       struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data;
+       struct iwl_notif_statistics_v11 *stats = (void *)&pkt->data;
        struct iwl_mvm_stat_data data = {
                .mvm = mvm,
        };
+       int expected_size = iwl_mvm_has_new_rx_api(mvm) ? sizeof(*stats) :
+                           sizeof(struct iwl_notif_statistics_v10);
        u32 temperature;
 
-       if (iwl_rx_packet_payload_len(pkt) != sizeof(*stats))
+       if (iwl_rx_packet_payload_len(pkt) != expected_size)
                goto invalid;
 
        temperature = le32_to_cpu(stats->general.radio_temperature);
                le64_to_cpu(stats->general.on_time_scan);
 
        data.general = &stats->general;
+       if (iwl_mvm_has_new_rx_api(mvm)) {
+               int i;
+
+               data.load = &stats->load_stats;
+
+               rcu_read_lock();
+               for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+                       struct iwl_mvm_sta *sta;
+
+                       if (!data.load->avg_energy[i])
+                               continue;
+
+                       sta = iwl_mvm_sta_from_staid_rcu(mvm, i);
+                       if (!sta)
+                               continue;
+                       sta->avg_energy = data.load->avg_energy[i];
+               }
+               rcu_read_unlock();
+       }
 
        iwl_mvm_rx_stats_check_trigger(mvm, pkt);