mt76: fix double DMA unmap of the first buffer on 7615/7915
authorFelix Fietkau <nbd@nbd.name>
Sat, 25 Jul 2020 12:44:07 +0000 (14:44 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 24 Sep 2020 16:10:13 +0000 (18:10 +0200)
A small part of the first skb buffer is passed to the firmware for parsing
via DMA, while the full buffer is passed as part of the TXP.

Avoid calling DMA unmap on the first part (with a different length than map)

Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/dma.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c

index 6c25859dd386eda7c591972c4d8d6f31b1eb98d4..ade2d58b8da9818ef93ce1009447f8408c17700c 100644 (file)
@@ -61,10 +61,16 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
        for (i = 0; i < nbufs; i += 2, buf += 2) {
                u32 buf0 = buf[0].addr, buf1 = 0;
 
+               if (buf[0].skip_unmap)
+                       q->entry[q->head].skip_buf0 = true;
+               q->entry[q->head].skip_buf1 = i == nbufs - 1;
+
                ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
                if (i < nbufs - 1) {
                        buf1 = buf[1].addr;
                        ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
+                       if (buf[1].skip_unmap)
+                               q->entry[q->head].skip_buf1 = true;
                }
 
                if (i == nbufs - 1)
@@ -107,7 +113,7 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
                                 DMA_TO_DEVICE);
        }
 
-       if (!(ctrl & MT_DMA_CTL_LAST_SEC0)) {
+       if (!e->skip_buf1) {
                __le32 addr = READ_ONCE(q->desc[idx].buf1);
                u32 len = FIELD_GET(MT_DMA_CTL_SD_LEN1, ctrl);
 
index 3dbb5d5382874db0decc431aae887ef51ddc4204..455ecdda995eb2f582dc10181bf0791545718407 100644 (file)
@@ -79,7 +79,8 @@ enum mt76_rxq_id {
 
 struct mt76_queue_buf {
        dma_addr_t addr;
-       int len;
+       u16 len;
+       bool skip_unmap;
 };
 
 struct mt76_tx_info {
@@ -101,6 +102,7 @@ struct mt76_queue_entry {
        };
        enum mt76_txq_id qid;
        bool skip_buf0:1;
+       bool skip_buf1:1;
        bool schedule:1;
        bool done:1;
 };
index 2d67f9a148cdd8a27ba9904178c7a22799c18831..51b2e04675928f74fd539e881d1b4a57cba1dfb6 100644 (file)
@@ -107,6 +107,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
        /* pass partial skb header to fw */
        tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
        tx_info->buf[1].len = MT_CT_PARSE_LEN;
+       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);
index 6825afca1efb04144c37c89cbd421cd777bec298..99ab5fca0f6df1fb87c66d4e1b62f0728578f369 100644 (file)
@@ -715,6 +715,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 
        /* pass partial skb header to fw */
        tx_info->buf[1].len = MT_CT_PARSE_LEN;
+       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);