FIELD_PREP(MT_TXD5_PID, pid));
 }
 
-void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
-                          struct sk_buff *skb, struct mt76_wcid *wcid,
-                          struct ieee80211_key_conf *key, bool beacon)
+static void
+mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
+                     struct sk_buff *skb, struct mt76_wcid *wcid,
+                     struct ieee80211_key_conf *key, int pid,
+                     bool beacon)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_vif *vif = info->control.vif;
 
        txwi[3] = cpu_to_le32(val);
        txwi[4] = 0;
-       txwi[5] = 0;
+
+       val = FIELD_PREP(MT_TXD5_PID, pid);
+       if (pid >= MT_PACKET_ID_FIRST)
+               val |= MT_TXD5_TX_STATUS_HOST;
+       txwi[5] = cpu_to_le32(val);
+
        txwi[6] = 0;
        txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
 
                return id;
 
        mt7921_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
-                             false);
+                             MT_PACKET_ID_NO_SKB, false);
 
        txp = (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE);
        memset(txp, 0, sizeof(struct mt7921_txp_common));
        mt76_worker_schedule(&dev->mt76.tx_worker);
 }
 
+static bool
+mt7921_mac_add_txs_skb(struct mt7921_dev *dev, struct mt76_wcid *wcid, int pid,
+                      __le32 *txs_data)
+{
+       struct mt76_dev *mdev = &dev->mt76;
+       struct ieee80211_tx_info *info;
+       struct sk_buff_head list;
+       struct sk_buff *skb;
+
+       mt76_tx_status_lock(mdev, &list);
+       skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
+       if (!skb)
+               goto out;
+
+       info = IEEE80211_SKB_CB(skb);
+       if (!(txs_data[0] & le32_to_cpu(MT_TXS0_ACK_ERROR_MASK)))
+               info->flags |= IEEE80211_TX_STAT_ACK;
+
+       info->status.ampdu_len = 1;
+       info->status.ampdu_ack_len = !!(info->flags &
+                                       IEEE80211_TX_STAT_ACK);
+
+       info->status.rates[0].idx = -1;
+       mt76_tx_status_skb_done(mdev, skb, &list);
+
+out:
+       mt76_tx_status_unlock(mdev, &list);
+
+       return !!skb;
+}
+
+static void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
+{
+       struct mt7921_sta *msta = NULL;
+       struct mt76_wcid *wcid;
+       __le32 *txs_data = data;
+       u16 wcidx;
+       u32 txs;
+       u8 pid;
+
+       txs = le32_to_cpu(txs_data[0]);
+       if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
+               return;
+
+       txs = le32_to_cpu(txs_data[2]);
+       wcidx = FIELD_GET(MT_TXS2_WCID, txs);
+
+       txs = le32_to_cpu(txs_data[3]);
+       pid = FIELD_GET(MT_TXS3_PID, txs);
+
+       if (pid < MT_PACKET_ID_FIRST)
+               return;
+
+       if (wcidx >= MT7921_WTBL_SIZE)
+               return;
+
+       rcu_read_lock();
+
+       wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
+       if (!wcid)
+               goto out;
+
+       mt7921_mac_add_txs_skb(dev, wcid, pid, txs_data);
+
+       if (!wcid->sta)
+               goto out;
+
+       msta = container_of(wcid, struct mt7921_sta, wcid);
+       spin_lock_bh(&dev->sta_poll_lock);
+       if (list_empty(&msta->poll_list))
+               list_add_tail(&msta->poll_list, &dev->sta_poll_list);
+       spin_unlock_bh(&dev->sta_poll_lock);
+
+out:
+       rcu_read_unlock();
+}
+
 void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
                         struct sk_buff *skb)
 {
        struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
        __le32 *rxd = (__le32 *)skb->data;
+       __le32 *end = (__le32 *)&skb->data[skb->len];
        enum rx_pkt_type type;
        u16 flag;
 
        case PKT_TYPE_RX_EVENT:
                mt7921_mcu_rx_event(dev, skb);
                break;
+       case PKT_TYPE_TXS:
+               for (rxd += 2; rxd + 8 <= end; rxd += 8)
+                       mt7921_mac_add_txs(dev, rxd);
+               dev_kfree_skb(skb);
+               break;
        case PKT_TYPE_NORMAL_MCU:
        case PKT_TYPE_NORMAL:
                if (!mt7921_mac_fill_rx(dev, skb)) {
        }
 
        mt7921_mutex_release(phy->dev);
+
+       mt76_tx_status_check(mphy->dev, NULL, false);
        ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
                                     MT7921_WATCHDOG_TIME);
 }