/**
  * cfg80211_rx_spurious_frame - inform userspace about a spurious frame
  * @dev: The device the frame matched to
+ * @link_id: the link the frame was received on, -1 if not applicable or unknown
  * @addr: the transmitter address
  * @gfp: context flags
  *
  * Return: %true if the frame was passed to userspace (or this failed
  * for a reason other than not having a subscription.)
  */
-bool cfg80211_rx_spurious_frame(struct net_device *dev,
-                               const u8 *addr, gfp_t gfp);
+bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr,
+                               int link_id, gfp_t gfp);
 
 /**
  * cfg80211_rx_unexpected_4addr_frame - inform about unexpected WDS frame
  * @dev: The device the frame matched to
  * @addr: the transmitter address
+ * @link_id: the link the frame was received on, -1 if not applicable or unknown
  * @gfp: context flags
  *
  * This function is used in AP mode (only!) to inform userspace that
  * Return: %true if the frame was passed to userspace (or this failed
  * for a reason other than not having a subscription.)
  */
-bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
-                                       const u8 *addr, gfp_t gfp);
+bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, const u8 *addr,
+                                       int link_id, gfp_t gfp);
 
 /**
  * cfg80211_probe_status - notify userspace about probe status
 
                }
 
                if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
-                   cfg80211_rx_spurious_frame(rx->sdata->dev,
-                                              hdr->addr2,
-                                              GFP_ATOMIC))
+                   cfg80211_rx_spurious_frame(rx->sdata->dev, hdr->addr2,
+                                              rx->link_id, GFP_ATOMIC))
                        return RX_DROP_U_SPURIOUS;
 
                return RX_DROP;
                        if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT))
                                cfg80211_rx_unexpected_4addr_frame(
                                        rx->sdata->dev, sta->sta.addr,
-                                       GFP_ATOMIC);
+                                       rx->link_id, GFP_ATOMIC);
                        return RX_DROP_U_UNEXPECTED_4ADDR_FRAME;
                }
                /*
                if (rx->sta &&
                    !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT))
                        cfg80211_rx_unexpected_4addr_frame(
-                               rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC);
+                               rx->sdata->dev, rx->sta->sta.addr, rx->link_id,
+                               GFP_ATOMIC);
                return RX_DROP;
        }
 
 
 EXPORT_SYMBOL(cfg80211_conn_failed);
 
 static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd,
-                                      const u8 *addr, gfp_t gfp)
+                                      const u8 *addr, int link_id, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
-           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
+           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
+           (link_id >= 0 &&
+            nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
        return true;
 }
 
-bool cfg80211_rx_spurious_frame(struct net_device *dev,
-                               const u8 *addr, gfp_t gfp)
+bool cfg80211_rx_spurious_frame(struct net_device *dev, const u8 *addr,
+                               int link_id, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        bool ret;
 
-       trace_cfg80211_rx_spurious_frame(dev, addr);
+       trace_cfg80211_rx_spurious_frame(dev, addr, link_id);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO)) {
                return false;
        }
        ret = __nl80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME,
-                                        addr, gfp);
+                                        addr, link_id, gfp);
        trace_cfg80211_return_bool(ret);
        return ret;
 }
 EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
 
-bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
-                                       const u8 *addr, gfp_t gfp)
+bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, const u8 *addr,
+                                       int link_id, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        bool ret;
 
-       trace_cfg80211_rx_unexpected_4addr_frame(dev, addr);
+       trace_cfg80211_rx_unexpected_4addr_frame(dev, addr, link_id);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
        }
        ret = __nl80211_unexpected_frame(dev,
                                         NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
-                                        addr, gfp);
+                                        addr, link_id, gfp);
        trace_cfg80211_return_bool(ret);
        return ret;
 }
 
 );
 
 DECLARE_EVENT_CLASS(cfg80211_rx_evt,
-       TP_PROTO(struct net_device *netdev, const u8 *addr),
-       TP_ARGS(netdev, addr),
+       TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id),
+       TP_ARGS(netdev, addr, link_id),
        TP_STRUCT__entry(
                NETDEV_ENTRY
                MAC_ENTRY(addr)
+               __field(int, link_id)
        ),
        TP_fast_assign(
                NETDEV_ASSIGN;
                MAC_ASSIGN(addr, addr);
+               __entry->link_id = link_id;
        ),
-       TP_printk(NETDEV_PR_FMT ", %pM", NETDEV_PR_ARG, __entry->addr)
+       TP_printk(NETDEV_PR_FMT ", %pM, link_id:%d", NETDEV_PR_ARG,
+                 __entry->addr, __entry->link_id)
 );
 
 DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
-       TP_PROTO(struct net_device *netdev, const u8 *addr),
-       TP_ARGS(netdev, addr)
+       TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id),
+       TP_ARGS(netdev, addr, link_id)
 );
 
 DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
-       TP_PROTO(struct net_device *netdev, const u8 *addr),
-       TP_ARGS(netdev, addr)
+       TP_PROTO(struct net_device *netdev, const u8 *addr, int link_id),
+       TP_ARGS(netdev, addr, link_id)
 );
 
 TRACE_EVENT(cfg80211_ibss_joined,