* @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
  *     frame should be transmitted on the specific link. This really is
  *     only relevant for frames that do not have data present, and is
- *     also not used for 802.3 format frames.
+ *     also not used for 802.3 format frames. Note that even if the frame
+ *     is on a specific link, address translation might still apply if
+ *     it's intended for an MLD.
  *
  * These flags are used in tx_info->control.flags.
  */
 
        mgmt->u.action.u.addba_req.start_seq_num =
                                        cpu_to_le16(start_seq_num << 4);
 
-       ieee80211_tx_skb_tid(sdata, skb, tid);
+       ieee80211_tx_skb_tid(sdata, skb, tid, -1);
 }
 
 void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
 
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
                                        IEEE80211_TX_CTL_REQ_TX_STATUS;
-       ieee80211_tx_skb_tid(sdata, skb, tid);
+       ieee80211_tx_skb_tid(sdata, skb, tid, -1);
 }
 EXPORT_SYMBOL(ieee80211_send_bar);
 
 
                    struct sta_info *sta, struct sk_buff *skb);
 
 void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
-                                struct sk_buff *skb, int tid,
+                                struct sk_buff *skb, int tid, int link_id,
                                 enum nl80211_band band);
 
 /* sta_out needs to be checked for ERR_PTR() before using */
                          enum nl80211_band band)
 {
        rcu_read_lock();
-       __ieee80211_tx_skb_tid_band(sdata, skb, tid, band);
+       __ieee80211_tx_skb_tid_band(sdata, skb, tid, -1, band);
        rcu_read_unlock();
 }
 
 void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
-                         struct sk_buff *skb, int tid);
+                         struct sk_buff *skb, int tid, int link_id);
 
 static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
                                    struct sk_buff *skb)
 {
        /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
-       ieee80211_tx_skb_tid(sdata, skb, 7);
+       ieee80211_tx_skb_tid(sdata, skb, 7, -1);
 }
 
 /**
 
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
-       struct sta_info *sta;
+       struct sta_info *sta = NULL;
        const struct ieee80211_mgmt *mgmt = (void *)params->buf;
        bool need_offchan = false;
+       bool mlo_sta = false;
+       int link_id = -1;
        u32 flags;
        int ret;
        u8 *data;
                    !ieee80211_vif_is_mesh(&sdata->vif) &&
                    !sdata->bss->active)
                        need_offchan = true;
+
+               rcu_read_lock();
+               sta = sta_info_get_bss(sdata, mgmt->da);
+               mlo_sta = sta && sta->sta.mlo;
+
                if (!ieee80211_is_action(mgmt->frame_control) ||
                    mgmt->u.action.category == WLAN_CATEGORY_PUBLIC ||
                    mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED ||
-                   mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT)
+                   mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
+                       rcu_read_unlock();
                        break;
-               rcu_read_lock();
-               sta = sta_info_get_bss(sdata, mgmt->da);
-               rcu_read_unlock();
-               if (!sta)
+               }
+
+               if (!sta) {
+                       rcu_read_unlock();
                        return -ENOLINK;
+               }
+               if (params->link_id >= 0 &&
+                   !(sta->sta.valid_links & BIT(params->link_id))) {
+                       rcu_read_unlock();
+                       return -ENOLINK;
+               }
+               link_id = params->link_id;
+               rcu_read_unlock();
                break;
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_P2P_CLIENT:
                if (!sdata->u.mgd.associated ||
                    (params->offchan && params->wait &&
                     local->ops->remain_on_channel &&
-                    memcmp(sdata->deflink.u.mgd.bssid,
-                           mgmt->bssid, ETH_ALEN)))
+                    memcmp(sdata->vif.cfg.ap_addr, mgmt->bssid, ETH_ALEN)))
                        need_offchan = true;
                sdata_unlock(sdata);
                break;
        mutex_lock(&local->mtx);
 
        /* Check if the operating channel is the requested channel */
-       if (!need_offchan) {
+       if (!params->chan && mlo_sta) {
+               need_offchan = false;
+       } else if (!need_offchan) {
                struct ieee80211_chanctx_conf *chanctx_conf = NULL;
                int i;
 
                        if (!chanctx_conf)
                                continue;
 
+                       if (mlo_sta && params->chan == chanctx_conf->def.chan &&
+                           ether_addr_equal(sdata->vif.addr, mgmt->sa)) {
+                               link_id = i;
+                               break;
+                       }
+
                        if (ether_addr_equal(conf->addr, mgmt->sa))
                                break;
 
                        need_offchan = params->chan &&
                                       (params->chan !=
                                        chanctx_conf->def.chan);
-               } else if (!params->chan) {
-                       ret = -EINVAL;
-                       rcu_read_unlock();
-                       goto out_unlock;
                } else {
                        need_offchan = true;
                }
        }
 
        if (!need_offchan) {
-               ieee80211_tx_skb(sdata, skb);
+               ieee80211_tx_skb_tid(sdata, skb, 7, link_id);
                ret = 0;
                goto out_unlock;
        }
 
                                        local->hw.offchannel_tx_hw_queue;
                }
 
-               __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
+               __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, -1,
                                            status->band);
        }
        dev_kfree_skb(rx->skb);
 
 EXPORT_SYMBOL(ieee80211_unreserve_tid);
 
 void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
-                                struct sk_buff *skb, int tid,
+                                struct sk_buff *skb, int tid, int link_id,
                                 enum nl80211_band band)
 {
        const struct ieee80211_hdr *hdr = (void *)skb->data;
 
        if (!sdata->vif.valid_links) {
                link = 0;
+       } else if (link_id >= 0) {
+               link = link_id;
        } else if (memcmp(sdata->vif.addr, hdr->addr2, ETH_ALEN) == 0) {
                /* address from the MLD */
                link = IEEE80211_LINK_UNSPECIFIED;
 }
 
 void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
-                         struct sk_buff *skb, int tid)
+                         struct sk_buff *skb, int tid, int link_id)
 {
        struct ieee80211_chanctx_conf *chanctx_conf;
        enum nl80211_band band;
 
        rcu_read_lock();
        if (!sdata->vif.valid_links) {
+               WARN_ON(link_id >= 0);
                chanctx_conf =
                        rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
                if (WARN_ON(!chanctx_conf)) {
                }
                band = chanctx_conf->def.chan->band;
        } else {
+               WARN_ON(link_id >= 0 &&
+                       !(sdata->vif.valid_links & BIT(link_id)));
                /* MLD transmissions must not rely on the band */
                band = 0;
        }
 
-       __ieee80211_tx_skb_tid_band(sdata, skb, tid, band);
+       __ieee80211_tx_skb_tid_band(sdata, skb, tid, link_id, band);
        rcu_read_unlock();
 }