static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev,
                                   struct rtw89_core_tx_request *tx_req)
 {
+       struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
        struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link;
        struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link;
 
+       if (desc_info->mlo && !desc_info->sw_mld) {
+               if (rtwsta_link)
+                       return rtw89_sta_get_main_macid(rtwsta_link->rtwsta);
+               else
+                       return rtw89_vif_get_main_macid(rtwvif_link->rtwvif);
+       }
+
        if (!rtwsta_link)
                return rtwvif_link->mac_id;
 
 static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev,
                                    struct rtw89_vif_link *rtwvif_link,
                                    struct rtw89_sta_link *rtwsta_link,
-                                   struct sk_buff *skb, int *qsel)
+                                   struct sk_buff *skb, int *qsel, bool sw_mld)
 {
        struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link);
        struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
        tx_req.sta = sta;
        tx_req.rtwvif_link = rtwvif_link;
        tx_req.rtwsta_link = rtwsta_link;
+       tx_req.desc_info.sw_mld = sw_mld;
 
        rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true);
        rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true);
                }
        }
 
-       return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel);
+       return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel, false);
 }
 
 static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info)
 
 static __le32 rtw89_build_txwd_body3_v2(struct rtw89_tx_desc_info *desc_info)
 {
-       u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq);
+       u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq) |
+                   FIELD_PREP(BE_TXD_BODY3_MLO_FLAG, desc_info->mlo) |
+                   FIELD_PREP(BE_TXD_BODY3_IS_MLD_SW_EN, desc_info->sw_mld);
 
        return cpu_to_le32(dword);
 }