enum mt76_wcid_flags {
        MT_WCID_FLAG_CHECK_PS,
        MT_WCID_FLAG_PS,
+       MT_WCID_FLAG_4ADDR,
 };
 
 #define MT76_N_WCIDS 288
 
        tx_info->buf[1].skip_unmap = true;
        tx_info->nbuf = MT_CT_DMA_BUF_NUM;
 
-       txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD);
+       txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD | MT_CT_INFO_FROM_HOST);
 
        if (!key)
                txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
                return id;
 
        txp->token = cpu_to_le16(id);
-       txp->rept_wds_wcid = 0xff;
+       if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
+               txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
+       else
+               txp->rept_wds_wcid = cpu_to_le16(0x3ff);
        tx_info->skb = DMA_DUMMY_DATA;
 
        return 0;
 
 #define MT_CT_INFO_MGMT_FRAME          BIT(2)
 #define MT_CT_INFO_NONE_CIPHER_FRAME   BIT(3)
 #define MT_CT_INFO_HSR2_TX             BIT(4)
+#define MT_CT_INFO_FROM_HOST           BIT(7)
 
 #define MT_TXD_SIZE                    (8 * 4)
 
        __le16 flags;
        __le16 token;
        u8 bss_idx;
-       u8 rept_wds_wcid;
-       u8 rsv;
+       __le16 rept_wds_wcid;
        u8 nbuf;
        __le32 buf[MT_TXP_MAX_BUF_NUM];
        __le16 len[MT_TXP_MAX_BUF_NUM];
 
                mtxq->wcid = &mvif->sta.wcid;
        }
 
+       vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR;
+
 out:
        mutex_unlock(&dev->mt76.mutex);
 
        ieee80211_queue_work(hw, &dev->rc_work);
 }
 
+static void mt7915_sta_set_4addr(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_sta *sta,
+                                bool enabled)
+{
+       struct mt7915_dev *dev = mt7915_hw_dev(hw);
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+
+       if (enabled)
+               set_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
+       else
+               clear_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags);
+
+       mt7915_mcu_sta_update_hdr_trans(dev, vif, sta);
+}
+
 const struct ieee80211_ops mt7915_ops = {
        .tx = mt7915_tx,
        .start = mt7915_start,
        .set_antenna = mt7915_set_antenna,
        .set_coverage_class = mt7915_set_coverage_class,
        .sta_statistics = mt7915_sta_statistics,
+       .sta_set_4addr = mt7915_sta_set_4addr,
 #ifdef CONFIG_MAC80211_DEBUGFS
        .sta_add_debugfs = mt7915_sta_add_debugfs,
 #endif
 
                        mcu_txd->set_query = MCU_Q_SET;
        }
 
-       mcu_txd->s2d_index = MCU_S2D_H2N;
+       if (cmd == MCU_EXT_CMD_MWDS_SUPPORT)
+               mcu_txd->s2d_index = MCU_S2D_H2C;
+       else
+               mcu_txd->s2d_index = MCU_S2D_H2N;
        WARN_ON(cmd == MCU_EXT_CMD_EFUSE_ACCESS &&
                mcu_txd->set_query != MCU_Q_QUERY);
 
                              struct ieee80211_sta *sta,
                              void *sta_wtbl, void *wtbl_tlv)
 {
+       struct mt7915_sta *msta;
        struct wtbl_hdr_trans *htr = NULL;
        struct tlv *tlv;
 
                htr->to_ds = true;
        else
                htr->from_ds = true;
+
+       if (!sta)
+               return;
+
+       msta = (struct mt7915_sta *)sta->drv_priv;
+       if (test_bit(MT_WCID_FLAG_4ADDR, &msta->wcid.flags)) {
+               htr->to_ds = true;
+               htr->from_ds = true;
+       }
+}
+
+int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_sta *sta)
+{
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct wtbl_req_hdr *wtbl_hdr;
+       struct sk_buff *skb;
+
+       skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, MT7915_WTBL_UPDATE_MAX_SIZE);
+       if (!skb)
+               return -ENOMEM;
+
+       wtbl_hdr = mt7915_mcu_alloc_wtbl_req(dev, msta, WTBL_SET, NULL, &skb);
+       mt7915_mcu_wtbl_hdr_trans_tlv(skb, vif, sta, NULL, wtbl_hdr);
+
+       return __mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, true);
 }
 
 int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                                   &data, sizeof(data), false);
 }
 
+static int mt7915_mcu_set_mwds(struct mt7915_dev *dev, bool enabled)
+{
+       struct {
+               u8 enable;
+               u8 _rsv[3];
+       } __packed req = {
+               .enable = enabled
+       };
+
+       return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MWDS_SUPPORT,
+                                  &req, sizeof(req), false);
+}
+
 int mt7915_mcu_init(struct mt7915_dev *dev)
 {
        static const struct mt76_mcu_ops mt7915_mcu_ops = {
 
        set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
        mt7915_mcu_fw_log_2_host(dev, 0);
+       mt7915_mcu_set_mwds(dev, 1);
 
        return 0;
 }
 
        MCU_EXT_CMD_EDCA_UPDATE = 0x27,
        MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
        MCU_EXT_CMD_THERMAL_CTRL = 0x2c,
+       MCU_EXT_CMD_WTBL_UPDATE = 0x32,
        MCU_EXT_CMD_SET_DRR_CTRL = 0x36,
        MCU_EXT_CMD_SET_RDD_CTRL = 0x3a,
        MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
        MCU_EXT_CMD_RX_HDR_TRANS = 0x47,
        MCU_EXT_CMD_SET_RX_PATH = 0x4e,
        MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
+       MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
        MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,
        MCU_EXT_CMD_SCS_CTRL = 0x82,
        MCU_EXT_CMD_RATE_CTRL = 0x87,
 
                       struct ieee80211_sta *sta, bool enable);
 int mt7915_mcu_add_sta_adv(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta, bool enable);
+int mt7915_mcu_sta_update_hdr_trans(struct mt7915_dev *dev,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_sta *sta);
 int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev,
                         struct ieee80211_ampdu_params *params,
                         bool add);