lockdep_assert_wiphy(local->hw.wiphy);
 
        list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
-               unsigned long last_active = ieee80211_sta_last_active(sta);
+               unsigned long last_active = ieee80211_sta_last_active(sta, -1);
 
                if (sdata != sta->sdata)
                        continue;
 }
 
 static struct ieee80211_sta_rx_stats *
-sta_get_last_rx_stats(struct sta_info *sta)
+sta_get_last_rx_stats(struct sta_info *sta, int link_id)
 {
-       struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats;
+       struct ieee80211_sta_rx_stats *stats;
+       struct link_sta_info *link_sta_info;
        int cpu;
 
-       if (!sta->deflink.pcpu_rx_stats)
+       if (link_id < 0)
+               link_sta_info = &sta->deflink;
+       else
+               link_sta_info = wiphy_dereference(sta->local->hw.wiphy,
+                                                 sta->link[link_id]);
+
+       stats = &link_sta_info->rx_stats;
+
+       if (!link_sta_info->pcpu_rx_stats)
                return stats;
 
        for_each_possible_cpu(cpu) {
                struct ieee80211_sta_rx_stats *cpustats;
 
-               cpustats = per_cpu_ptr(sta->deflink.pcpu_rx_stats, cpu);
+               cpustats = per_cpu_ptr(link_sta_info->pcpu_rx_stats, cpu);
 
                if (time_after(cpustats->last_rx, stats->last_rx))
                        stats = cpustats;
        }
 }
 
-static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
+static int sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo,
+                               int link_id)
 {
-       u32 rate = READ_ONCE(sta_get_last_rx_stats(sta)->last_rate);
+       u32 rate = READ_ONCE(sta_get_last_rx_stats(sta, link_id)->last_rate);
 
        if (rate == STA_STATS_RATE_INVALID)
                return -EINVAL;
 
 static void sta_set_tidstats(struct sta_info *sta,
                             struct cfg80211_tid_stats *tidstats,
-                            int tid)
+                            int tid, int link_id)
 {
        struct ieee80211_local *local = sta->local;
+       struct link_sta_info *link_sta_info;
        int cpu;
 
+       if (link_id < 0)
+               link_sta_info = &sta->deflink;
+       else
+               link_sta_info = wiphy_dereference(sta->local->hw.wiphy,
+                                                 sta->link[link_id]);
+
        if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
-               tidstats->rx_msdu += sta_get_tidstats_msdu(&sta->deflink.rx_stats,
-                                                          tid);
+               tidstats->rx_msdu +=
+                       sta_get_tidstats_msdu(&link_sta_info->rx_stats,
+                                             tid);
 
-               if (sta->deflink.pcpu_rx_stats) {
+               if (link_sta_info->pcpu_rx_stats) {
                        for_each_possible_cpu(cpu) {
                                struct ieee80211_sta_rx_stats *cpurxs;
 
-                               cpurxs = per_cpu_ptr(sta->deflink.pcpu_rx_stats,
+                               cpurxs = per_cpu_ptr(link_sta_info->pcpu_rx_stats,
                                                     cpu);
                                tidstats->rx_msdu +=
                                        sta_get_tidstats_msdu(cpurxs, tid);
 
        if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
                tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
-               tidstats->tx_msdu = sta->deflink.tx_stats.msdu[tid];
+               tidstats->tx_msdu = link_sta_info->tx_stats.msdu[tid];
        }
 
        if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
            ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
                tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
-               tidstats->tx_msdu_retries = sta->deflink.status_stats.msdu_retries[tid];
+               tidstats->tx_msdu_retries =
+                       link_sta_info->status_stats.msdu_retries[tid];
        }
 
        if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
            ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
                tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
-               tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
+               tidstats->tx_msdu_failed =
+                       link_sta_info->status_stats.msdu_failed[tid];
        }
 
        if (tid < IEEE80211_NUM_TIDS) {
        int i, ac, cpu;
        struct ieee80211_sta_rx_stats *last_rxstats;
 
-       last_rxstats = sta_get_last_rx_stats(sta);
+       last_rxstats = sta_get_last_rx_stats(sta, -1);
 
        sinfo->generation = sdata->local->sta_generation;
 
        sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
        sinfo->assoc_at = sta->assoc_at;
        sinfo->inactive_time =
-               jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta));
+               jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, -1));
 
        if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
                               BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
            !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) {
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BEACON_RX) |
                                 BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG);
-               sinfo->rx_beacon_signal_avg = ieee80211_ave_rssi(&sdata->vif);
+               sinfo->rx_beacon_signal_avg =
+                       ieee80211_ave_rssi(&sdata->vif, -1);
        }
 
        if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
 
        if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) &&
            !sta->sta.valid_links) {
-               if (sta_set_rate_info_rx(sta, &sinfo->rxrate) == 0)
+               if (sta_set_rate_info_rx(sta, &sinfo->rxrate, -1) == 0)
                        sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
        }
 
        if (tidstats && !cfg80211_sinfo_alloc_tid_stats(sinfo, GFP_KERNEL)) {
                for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
-                       sta_set_tidstats(sta, &sinfo->pertid[i], i);
+                       sta_set_tidstats(sta, &sinfo->pertid[i], i, -1);
        }
 
 #ifdef CONFIG_MAC80211_MESH
        return thr;
 }
 
-unsigned long ieee80211_sta_last_active(struct sta_info *sta)
+unsigned long ieee80211_sta_last_active(struct sta_info *sta, int link_id)
 {
-       struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
+       struct ieee80211_sta_rx_stats *stats;
+       struct link_sta_info *link_sta_info;
+
+       stats = sta_get_last_rx_stats(sta, link_id);
 
-       if (!sta->deflink.status_stats.last_ack ||
-           time_after(stats->last_rx, sta->deflink.status_stats.last_ack))
+       if (link_id < 0)
+               link_sta_info = &sta->deflink;
+       else
+               link_sta_info = wiphy_dereference(sta->local->hw.wiphy,
+                                                 sta->link[link_id]);
+
+       if (!link_sta_info->status_stats.last_ack ||
+           time_after(stats->last_rx, link_sta_info->status_stats.last_ack))
                return stats->last_rx;
-       return sta->deflink.status_stats.last_ack;
+
+       return link_sta_info->status_stats.last_ack;
 }
 
 int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id)