return true;
 }
 
+static int nl80211_fill_link_station(struct sk_buff *msg,
+                                    struct cfg80211_registered_device *rdev,
+                                    struct link_station_info *link_sinfo)
+{
+       struct nlattr *bss_param, *link_sinfoattr;
+
+#define PUT_LINK_SINFO(attr, memb, type) do {                          \
+       BUILD_BUG_ON(sizeof(type) == sizeof(u64));                      \
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) &&  \
+           nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr,            \
+                            link_sinfo->memb))                         \
+               goto nla_put_failure;                                   \
+       } while (0)
+#define PUT_LINK_SINFO_U64(attr, memb) do {                            \
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_ ## attr) &&  \
+           nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr,           \
+                             link_sinfo->memb, NL80211_STA_INFO_PAD))  \
+               goto nla_put_failure;                                   \
+       } while (0)
+
+       link_sinfoattr = nla_nest_start_noflag(msg, NL80211_ATTR_STA_INFO);
+       if (!link_sinfoattr)
+               goto nla_put_failure;
+
+       PUT_LINK_SINFO(INACTIVE_TIME, inactive_time, u32);
+
+       if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES) |
+                            BIT_ULL(NL80211_STA_INFO_RX_BYTES64)) &&
+           nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
+                       (u32)link_sinfo->rx_bytes))
+               goto nla_put_failure;
+
+       if (link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES) |
+                            BIT_ULL(NL80211_STA_INFO_TX_BYTES64)) &&
+           nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
+                       (u32)link_sinfo->tx_bytes))
+               goto nla_put_failure;
+
+       PUT_LINK_SINFO_U64(RX_BYTES64, rx_bytes);
+       PUT_LINK_SINFO_U64(TX_BYTES64, tx_bytes);
+       PUT_LINK_SINFO_U64(RX_DURATION, rx_duration);
+       PUT_LINK_SINFO_U64(TX_DURATION, tx_duration);
+
+       if (wiphy_ext_feature_isset(&rdev->wiphy,
+                                   NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
+               PUT_LINK_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);
+
+       switch (rdev->wiphy.signal_type) {
+       case CFG80211_SIGNAL_TYPE_MBM:
+               PUT_LINK_SINFO(SIGNAL, signal, u8);
+               PUT_LINK_SINFO(SIGNAL_AVG, signal_avg, u8);
+               break;
+       default:
+               break;
+       }
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
+               if (!nl80211_put_signal(msg, link_sinfo->chains,
+                                       link_sinfo->chain_signal,
+                                       NL80211_STA_INFO_CHAIN_SIGNAL))
+                       goto nla_put_failure;
+       }
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
+               if (!nl80211_put_signal(msg, link_sinfo->chains,
+                                       link_sinfo->chain_signal_avg,
+                                       NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
+                       goto nla_put_failure;
+       }
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) {
+               if (!nl80211_put_sta_rate(msg, &link_sinfo->txrate,
+                                         NL80211_STA_INFO_TX_BITRATE))
+                       goto nla_put_failure;
+       }
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) {
+               if (!nl80211_put_sta_rate(msg, &link_sinfo->rxrate,
+                                         NL80211_STA_INFO_RX_BITRATE))
+                       goto nla_put_failure;
+       }
+
+       PUT_LINK_SINFO(RX_PACKETS, rx_packets, u32);
+       PUT_LINK_SINFO(TX_PACKETS, tx_packets, u32);
+       PUT_LINK_SINFO(TX_RETRIES, tx_retries, u32);
+       PUT_LINK_SINFO(TX_FAILED, tx_failed, u32);
+       PUT_LINK_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
+       PUT_LINK_SINFO(BEACON_LOSS, beacon_loss_count, u32);
+
+       if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) {
+               bss_param = nla_nest_start_noflag(msg,
+                                                 NL80211_STA_INFO_BSS_PARAM);
+               if (!bss_param)
+                       goto nla_put_failure;
+
+               if (((link_sinfo->bss_param.flags &
+                     BSS_PARAM_FLAGS_CTS_PROT) &&
+                    nla_put_flag(msg, NL80211_STA_BSS_PARAM_CTS_PROT)) ||
+                   ((link_sinfo->bss_param.flags &
+                     BSS_PARAM_FLAGS_SHORT_PREAMBLE) &&
+                    nla_put_flag(msg,
+                                 NL80211_STA_BSS_PARAM_SHORT_PREAMBLE)) ||
+                   ((link_sinfo->bss_param.flags &
+                     BSS_PARAM_FLAGS_SHORT_SLOT_TIME) &&
+                    nla_put_flag(msg,
+                                 NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME)) ||
+                   nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD,
+                              link_sinfo->bss_param.dtim_period) ||
+                   nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
+                               link_sinfo->bss_param.beacon_interval))
+                       goto nla_put_failure;
+
+               nla_nest_end(msg, bss_param);
+       }
+
+       PUT_LINK_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
+       PUT_LINK_SINFO_U64(BEACON_RX, rx_beacon);
+       PUT_LINK_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
+       PUT_LINK_SINFO(RX_MPDUS, rx_mpdu_count, u32);
+       PUT_LINK_SINFO(FCS_ERROR_COUNT, fcs_err_count, u32);
+       if (wiphy_ext_feature_isset(&rdev->wiphy,
+                                   NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT)) {
+               PUT_LINK_SINFO(ACK_SIGNAL, ack_signal, u8);
+               PUT_LINK_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
+       }
+
+#undef PUT_LINK_SINFO
+#undef PUT_LINK_SINFO_U64
+
+       if (link_sinfo->pertid) {
+               struct nlattr *tidsattr;
+               int tid;
+
+               tidsattr = nla_nest_start_noflag(msg,
+                                                NL80211_STA_INFO_TID_STATS);
+               if (!tidsattr)
+                       goto nla_put_failure;
+
+               for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
+                       struct cfg80211_tid_stats *tidstats;
+                       struct nlattr *tidattr;
+
+                       tidstats = &link_sinfo->pertid[tid];
+
+                       if (!tidstats->filled)
+                               continue;
+
+                       tidattr = nla_nest_start_noflag(msg, tid + 1);
+                       if (!tidattr)
+                               goto nla_put_failure;
+
+#define PUT_TIDVAL_U64(attr, memb) do {                                        \
+       if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) &&       \
+           nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr,          \
+                             tidstats->memb, NL80211_TID_STATS_PAD))   \
+               goto nla_put_failure;                                   \
+       } while (0)
+
+                       PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
+                       PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
+                       PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
+                       PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
+
+#undef PUT_TIDVAL_U64
+                       if ((tidstats->filled &
+                            BIT(NL80211_TID_STATS_TXQ_STATS)) &&
+                           !nl80211_put_txq_stats(msg, &tidstats->txq_stats,
+                                                  NL80211_TID_STATS_TXQ_STATS))
+                               goto nla_put_failure;
+
+                       nla_nest_end(msg, tidattr);
+               }
+
+               nla_nest_end(msg, tidsattr);
+       }
+
+       nla_nest_end(msg, link_sinfoattr);
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
                                u32 seq, int flags,
                                struct cfg80211_registered_device *rdev,
 {
        void *hdr;
        struct nlattr *sinfoattr, *bss_param;
+       struct link_station_info *link_sinfo;
+       struct nlattr *links, *link;
+       int link_id;
 
        hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
        if (!hdr) {
                        goto nla_put_failure;
        }
 
+       if (sinfo->valid_links) {
+               links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
+               if (!links)
+                       goto nla_put_failure;
+
+               for_each_valid_link(sinfo, link_id) {
+                       link_sinfo = sinfo->links[link_id];
+
+                       if (WARN_ON_ONCE(!link_sinfo))
+                               continue;
+
+                       if (!is_valid_ether_addr(link_sinfo->addr))
+                               continue;
+
+                       link = nla_nest_start(msg, link_id + 1);
+                       if (!link)
+                               goto nla_put_failure;
+
+                       if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID,
+                                      link_id))
+                               goto nla_put_failure;
+
+                       if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
+                                   link_sinfo->addr))
+                               goto nla_put_failure;
+
+                       if (nl80211_fill_link_station(msg, rdev, link_sinfo))
+                               goto nla_put_failure;
+
+                       nla_nest_end(msg, link);
+               }
+               nla_nest_end(msg, links);
+       }
+
        cfg80211_sinfo_release_content(sinfo);
        genlmsg_end(msg, hdr);
        return 0;