]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: rtw89: pci: define TX/RX buffer descriptor pool
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 26 Aug 2025 08:52:58 +0000 (16:52 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 1 Sep 2025 02:53:30 +0000 (10:53 +0800)
Buffer descriptor (BD) is a helper of DMA for each ring. The new hardware
design expects a continual memory across all rings, so allocate a pool
and assign to each ring rather than allocate a buffer for a ring
individually.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250826085258.28308-1-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/pci.c
drivers/net/wireless/realtek/rtw89/pci.h

index d4677df35861ca2456de4aeda3a6a7652cf9b98f..d4f78396dfdef9faf9f07d61b81d779debd7601e 100644 (file)
@@ -3249,15 +3249,6 @@ static void rtw89_pci_free_tx_ring(struct rtw89_dev *rtwdev,
                                   struct pci_dev *pdev,
                                   struct rtw89_pci_tx_ring *tx_ring)
 {
-       int ring_sz;
-       u8 *head;
-       dma_addr_t dma;
-
-       head = tx_ring->bd_ring.head;
-       dma = tx_ring->bd_ring.dma;
-       ring_sz = tx_ring->bd_ring.desc_size * tx_ring->bd_ring.len;
-       dma_free_coherent(&pdev->dev, ring_sz, head, dma);
-
        tx_ring->bd_ring.head = NULL;
 }
 
@@ -3265,6 +3256,7 @@ static void rtw89_pci_free_tx_rings(struct rtw89_dev *rtwdev,
                                    struct pci_dev *pdev)
 {
        struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+       struct rtw89_pci_dma_pool *bd_pool = &rtwpci->tx.bd_pool;
        const struct rtw89_pci_info *info = rtwdev->pci_info;
        struct rtw89_pci_tx_ring *tx_ring;
        int i;
@@ -3276,6 +3268,8 @@ static void rtw89_pci_free_tx_rings(struct rtw89_dev *rtwdev,
                rtw89_pci_free_tx_wd_ring(rtwdev, pdev, tx_ring);
                rtw89_pci_free_tx_ring(rtwdev, pdev, tx_ring);
        }
+
+       dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma);
 }
 
 static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev,
@@ -3286,8 +3280,6 @@ static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev,
        struct sk_buff *skb;
        dma_addr_t dma;
        u32 buf_sz;
-       u8 *head;
-       int ring_sz = rx_ring->bd_ring.desc_size * rx_ring->bd_ring.len;
        int i;
 
        buf_sz = rx_ring->buf_sz;
@@ -3303,10 +3295,6 @@ static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev,
                rx_ring->buf[i] = NULL;
        }
 
-       head = rx_ring->bd_ring.head;
-       dma = rx_ring->bd_ring.dma;
-       dma_free_coherent(&pdev->dev, ring_sz, head, dma);
-
        rx_ring->bd_ring.head = NULL;
 }
 
@@ -3314,6 +3302,7 @@ static void rtw89_pci_free_rx_rings(struct rtw89_dev *rtwdev,
                                    struct pci_dev *pdev)
 {
        struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+       struct rtw89_pci_dma_pool *bd_pool = &rtwpci->rx.bd_pool;
        struct rtw89_pci_rx_ring *rx_ring;
        int i;
 
@@ -3321,6 +3310,8 @@ static void rtw89_pci_free_rx_rings(struct rtw89_dev *rtwdev,
                rx_ring = &rtwpci->rx.rings[i];
                rtw89_pci_free_rx_ring(rtwdev, pdev, rx_ring);
        }
+
+       dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma);
 }
 
 static void rtw89_pci_free_trx_rings(struct rtw89_dev *rtwdev,
@@ -3412,12 +3403,10 @@ static int rtw89_pci_alloc_tx_ring(struct rtw89_dev *rtwdev,
                                   struct pci_dev *pdev,
                                   struct rtw89_pci_tx_ring *tx_ring,
                                   u32 desc_size, u32 len,
-                                  enum rtw89_tx_channel txch)
+                                  enum rtw89_tx_channel txch,
+                                  void *head, dma_addr_t dma)
 {
        const struct rtw89_pci_ch_dma_addr *txch_addr;
-       int ring_sz = desc_size * len;
-       u8 *head;
-       dma_addr_t dma;
        int ret;
 
        ret = rtw89_pci_alloc_tx_wd_ring(rtwdev, pdev, tx_ring, txch);
@@ -3432,12 +3421,6 @@ static int rtw89_pci_alloc_tx_ring(struct rtw89_dev *rtwdev,
                goto err_free_wd_ring;
        }
 
-       head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL);
-       if (!head) {
-               ret = -ENOMEM;
-               goto err_free_wd_ring;
-       }
-
        INIT_LIST_HEAD(&tx_ring->busy_pages);
        tx_ring->bd_ring.head = head;
        tx_ring->bd_ring.dma = dma;
@@ -3460,25 +3443,48 @@ static int rtw89_pci_alloc_tx_rings(struct rtw89_dev *rtwdev,
                                    struct pci_dev *pdev)
 {
        struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+       struct rtw89_pci_dma_pool *bd_pool = &rtwpci->tx.bd_pool;
        const struct rtw89_pci_info *info = rtwdev->pci_info;
        struct rtw89_pci_tx_ring *tx_ring;
+       u32 i, tx_allocated;
+       dma_addr_t dma;
        u32 desc_size;
+       u32 ring_sz;
+       u32 pool_sz;
+       u32 ch_num;
+       void *head;
        u32 len;
-       u32 i, tx_allocated;
        int ret;
 
+       BUILD_BUG_ON(RTW89_PCI_TXBD_NUM_MAX % 16);
+
+       desc_size = sizeof(struct rtw89_pci_tx_bd_32);
+       len = RTW89_PCI_TXBD_NUM_MAX;
+       ch_num = RTW89_TXCH_NUM - hweight32(info->tx_dma_ch_mask);
+       ring_sz = desc_size * len;
+       pool_sz = ring_sz * ch_num;
+
+       head = dma_alloc_coherent(&pdev->dev, pool_sz, &dma, GFP_KERNEL);
+       if (!head)
+               return -ENOMEM;
+
+       bd_pool->head = head;
+       bd_pool->dma = dma;
+       bd_pool->size = pool_sz;
+
        for (i = 0; i < RTW89_TXCH_NUM; i++) {
                if (info->tx_dma_ch_mask & BIT(i))
                        continue;
                tx_ring = &rtwpci->tx.rings[i];
-               desc_size = sizeof(struct rtw89_pci_tx_bd_32);
-               len = RTW89_PCI_TXBD_NUM_MAX;
                ret = rtw89_pci_alloc_tx_ring(rtwdev, pdev, tx_ring,
-                                             desc_size, len, i);
+                                             desc_size, len, i, head, dma);
                if (ret) {
                        rtw89_err(rtwdev, "failed to alloc tx ring %d\n", i);
                        goto err_free;
                }
+
+               head += ring_sz;
+               dma += ring_sz;
        }
 
        return 0;
@@ -3490,20 +3496,20 @@ err_free:
                rtw89_pci_free_tx_ring(rtwdev, pdev, tx_ring);
        }
 
+       dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma);
+
        return ret;
 }
 
 static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev,
                                   struct pci_dev *pdev,
                                   struct rtw89_pci_rx_ring *rx_ring,
-                                  u32 desc_size, u32 len, u32 rxch)
+                                  u32 desc_size, u32 len, u32 rxch,
+                                  void *head, dma_addr_t dma)
 {
        const struct rtw89_pci_info *info = rtwdev->pci_info;
        const struct rtw89_pci_ch_dma_addr *rxch_addr;
        struct sk_buff *skb;
-       u8 *head;
-       dma_addr_t dma;
-       int ring_sz = desc_size * len;
        int buf_sz = RTW89_PCI_RX_BUF_SIZE;
        int i, allocated;
        int ret;
@@ -3514,12 +3520,6 @@ static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev,
                return ret;
        }
 
-       head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL);
-       if (!head) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
        rx_ring->bd_ring.head = head;
        rx_ring->bd_ring.dma = dma;
        rx_ring->bd_ring.len = len;
@@ -3568,12 +3568,8 @@ err_free:
                rx_ring->buf[i] = NULL;
        }
 
-       head = rx_ring->bd_ring.head;
-       dma = rx_ring->bd_ring.dma;
-       dma_free_coherent(&pdev->dev, ring_sz, head, dma);
-
        rx_ring->bd_ring.head = NULL;
-err:
+
        return ret;
 }
 
@@ -3581,22 +3577,43 @@ static int rtw89_pci_alloc_rx_rings(struct rtw89_dev *rtwdev,
                                    struct pci_dev *pdev)
 {
        struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+       struct rtw89_pci_dma_pool *bd_pool = &rtwpci->rx.bd_pool;
        struct rtw89_pci_rx_ring *rx_ring;
+       int i, rx_allocated;
+       dma_addr_t dma;
        u32 desc_size;
+       u32 ring_sz;
+       u32 pool_sz;
+       void *head;
        u32 len;
-       int i, rx_allocated;
        int ret;
 
+       desc_size = sizeof(struct rtw89_pci_rx_bd_32);
+       len = RTW89_PCI_RXBD_NUM_MAX;
+       ring_sz = desc_size * len;
+       pool_sz = ring_sz * RTW89_RXCH_NUM;
+
+       head = dma_alloc_coherent(&pdev->dev, pool_sz, &dma, GFP_KERNEL);
+       if (!head)
+               return -ENOMEM;
+
+       bd_pool->head = head;
+       bd_pool->dma = dma;
+       bd_pool->size = pool_sz;
+
        for (i = 0; i < RTW89_RXCH_NUM; i++) {
                rx_ring = &rtwpci->rx.rings[i];
-               desc_size = sizeof(struct rtw89_pci_rx_bd_32);
-               len = RTW89_PCI_RXBD_NUM_MAX;
+
                ret = rtw89_pci_alloc_rx_ring(rtwdev, pdev, rx_ring,
-                                             desc_size, len, i);
+                                             desc_size, len, i,
+                                             head, dma);
                if (ret) {
                        rtw89_err(rtwdev, "failed to alloc rx ring %d\n", i);
                        goto err_free;
                }
+
+               head += ring_sz;
+               dma += ring_sz;
        }
 
        return 0;
@@ -3608,6 +3625,8 @@ err_free:
                rtw89_pci_free_rx_ring(rtwdev, pdev, rx_ring);
        }
 
+       dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma);
+
        return ret;
 }
 
index 3156b4f9ebfca23dfee168e60b4f91870700527e..f00d717b668bfaaeb7216a68e1cc03644e8b770a 100644 (file)
@@ -1495,6 +1495,12 @@ struct rtw89_pci_dma_ring {
        u32 rp; /* hw idx */
 };
 
+struct rtw89_pci_dma_pool {
+       void *head;
+       dma_addr_t dma;
+       u32 size;
+};
+
 struct rtw89_pci_tx_wd_ring {
        void *head;
        dma_addr_t dma;
@@ -1526,6 +1532,7 @@ struct rtw89_pci_tx_ring {
 
 struct rtw89_pci_tx_rings {
        struct rtw89_pci_tx_ring rings[RTW89_TXCH_NUM];
+       struct rtw89_pci_dma_pool bd_pool;
 };
 
 struct rtw89_pci_rx_ring {
@@ -1539,6 +1546,7 @@ struct rtw89_pci_rx_ring {
 
 struct rtw89_pci_rx_rings {
        struct rtw89_pci_rx_ring rings[RTW89_RXCH_NUM];
+       struct rtw89_pci_dma_pool bd_pool;
 };
 
 struct rtw89_pci_isrs {