diff --git a/mt7996/mac.c b/mt7996/mac.c index 9f03f988..3ff9f3cd 100644 --- a/mt7996/mac.c +++ b/mt7996/mac.c @@ -1244,6 +1244,35 @@ mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta, clear_bit(tid, &wcid->ampdu_state); } +/* mt7996/mt7992 provide a HW MAC-TXP for AddBA req frames (MT_TXD7_MAC_TXD), + * but are otherwise FW-TXP devices. mt76_connac_txp_skb_unmap() would decode + * the MAC-TXP as a fw-txp and read nbuf as 0, leaving the skb mapping in + * buf[1] leaked. Unmap it from the MAC-TXP layout instead. + */ +static void +mt7996_txp_skb_unmap(struct mt76_dev *mdev, struct mt76_txwi_cache *t) +{ + u8 *txwi_ptr = mt76_get_txwi_ptr(mdev, t); + __le32 *txwi = (__le32 *)txwi_ptr; + __le32 *txp; + dma_addr_t addr; + u32 val; + + if (!(le32_to_cpu(txwi[7]) & MT_TXD7_MAC_TXD)) { + mt76_connac_txp_skb_unmap(mdev, t); + return; + } + + txp = (__le32 *)(txwi_ptr + MT_TXD_SIZE); + val = le32_to_cpu(txp[3]); + addr = le32_to_cpu(txp[2]); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + addr |= (dma_addr_t)FIELD_GET(MT_TXP3_DMA_ADDR_H, val) << 32; +#endif + dma_unmap_single(mdev->dma_dev, addr, FIELD_GET(MT_TXP_BUF_LEN, val), + DMA_TO_DEVICE); +} + static void mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, struct ieee80211_link_sta *link_sta, @@ -1253,7 +1282,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t, __le32 *txwi; u16 wcid_idx; - mt76_connac_txp_skb_unmap(mdev, t); + mt7996_txp_skb_unmap(mdev, t); if (!t->skb) goto out;