]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
eth: fbnic: Reuse RX mailbox pages
authorMohsin Bashir <mohsin.bashr@gmail.com>
Thu, 15 Jan 2026 00:33:51 +0000 (16:33 -0800)
committerJakub Kicinski <kuba@kernel.org>
Wed, 21 Jan 2026 02:18:41 +0000 (18:18 -0800)
Currently, the RX mailbox frees and reallocates a page for each received
message. Since FW Rx messages are processed synchronously, and nothing
hold these pages (unlike skbs which we hand over to the stack), reuse
the pages and put them back on the Rx ring. Now that we ensure the ring
is always fully populated we don't have to worry about filling it up
after partial population during init, either. Update
fbnic_mbx_process_rx_msgs() to recycle pages after message processing.

Signed-off-by: Mohsin Bashir <mohsin.bashr@gmail.com>
Link: https://patch.msgid.link/20260115003353.4150771-4-mohsin.bashr@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/meta/fbnic/fbnic_fw.c

index 09252b3e03cac2f9a089bdfeb04e54dbe428d512..66c9412f4057a8a8c00ae90f4750a37bff894ffe 100644 (file)
@@ -1592,7 +1592,7 @@ static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
 static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd)
 {
        struct fbnic_fw_mbx *rx_mbx = &fbd->mbx[FBNIC_IPC_MBX_RX_IDX];
-       u8 head = rx_mbx->head;
+       u8 head = rx_mbx->head, tail = rx_mbx->tail;
        u64 desc, length;
 
        while (head != rx_mbx->tail) {
@@ -1603,8 +1603,8 @@ static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd)
                if (!(desc & FBNIC_IPC_MBX_DESC_FW_CMPL))
                        break;
 
-               dma_unmap_single(fbd->dev, rx_mbx->buf_info[head].addr,
-                                PAGE_SIZE, DMA_FROM_DEVICE);
+               dma_sync_single_for_cpu(fbd->dev, rx_mbx->buf_info[head].addr,
+                                       FBNIC_RX_PAGE_SIZE, DMA_FROM_DEVICE);
 
                msg = rx_mbx->buf_info[head].msg;
 
@@ -1637,19 +1637,26 @@ static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd)
 
                dev_dbg(fbd->dev, "Parsed msg type %d\n", msg->hdr.type);
 next_page:
+               fw_wr32(fbd, FBNIC_IPC_MBX(FBNIC_IPC_MBX_RX_IDX, head), 0);
 
-               free_page((unsigned long)rx_mbx->buf_info[head].msg);
+               rx_mbx->buf_info[tail] = rx_mbx->buf_info[head];
                rx_mbx->buf_info[head].msg = NULL;
+               rx_mbx->buf_info[head].addr = 0;
 
-               head++;
-               head %= FBNIC_IPC_MBX_DESC_LEN;
+               __fbnic_mbx_wr_desc(fbd, FBNIC_IPC_MBX_RX_IDX, tail,
+                                   FIELD_PREP(FBNIC_IPC_MBX_DESC_LEN_MASK,
+                                              FBNIC_RX_PAGE_SIZE) |
+                                   (rx_mbx->buf_info[tail].addr &
+                                    FBNIC_IPC_MBX_DESC_ADDR_MASK) |
+                                   FBNIC_IPC_MBX_DESC_HOST_CMPL);
+
+               head = (head + 1) & (FBNIC_IPC_MBX_DESC_LEN - 1);
+               tail = (tail + 1) & (FBNIC_IPC_MBX_DESC_LEN - 1);
        }
 
        /* Record head for next interrupt */
        rx_mbx->head = head;
-
-       /* Make sure we have at least one page for the FW to write to */
-       fbnic_mbx_alloc_rx_msgs(fbd);
+       rx_mbx->tail = tail;
 }
 
 void fbnic_mbx_poll(struct fbnic_dev *fbd)