support building a single packet out of multiple rx descriptors.
authordlg <dlg@openbsd.org>
Wed, 21 Aug 2024 01:12:52 +0000 (01:12 +0000)
committerdlg <dlg@openbsd.org>
Wed, 21 Aug 2024 01:12:52 +0000 (01:12 +0000)
rge is a bit like intel nics where you can put small mbufs on the
rx ring and it will chain them together to make a jumbo packet.
except unlike intel you can use any sized mbufs for the rx descriptors.

this adds the handling of these packets to the rx path. we're still
putting 9k frames on the ring though.

sys/dev/pci/if_rge.c
sys/dev/pci/if_rgereg.h

index 01eae86..44ce8f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_rge.c,v 1.31 2024/08/21 00:56:58 dlg Exp $ */
+/*     $OpenBSD: if_rge.c,v 1.32 2024/08/21 01:12:52 dlg Exp $ */
 
 /*
  * Copyright (c) 2019, 2020, 2023, 2024
@@ -883,6 +883,12 @@ rge_stop(struct ifnet *ifp)
        ifq_barrier(&ifp->if_snd);
        ifq_clr_oactive(&ifp->if_snd);
 
+       if (q->q_rx.rge_head != NULL) {
+               m_freem(q->q_rx.rge_head);
+               q->q_rx.rge_head = NULL;
+               q->q_rx.rge_tail = &q->q_rx.rge_head;
+       }
+
        /* Free the TX list buffers. */
        for (i = 0; i < RGE_TX_LIST_CNT; i++) {
                if (q->q_tx.rge_txq[i].txq_mbuf != NULL) {
@@ -1193,6 +1199,8 @@ rge_rx_list_init(struct rge_queues *q)
        memset(q->q_rx.rge_rx_list, 0, RGE_RX_LIST_SZ);
 
        q->q_rx.rge_rxq_prodidx = q->q_rx.rge_rxq_considx = 0;
+       q->q_rx.rge_head = NULL;
+       q->q_rx.rge_tail = &q->q_rx.rge_head;
 
        if_rxr_init(&q->q_rx.rge_rx_ring, 32, RGE_RX_LIST_CNT - 1);
        rge_fill_rx_ring(q);
@@ -1244,7 +1252,7 @@ rge_rxeof(struct rge_queues *q)
        struct rge_rx_desc *cur_rx;
        struct rge_rxq *rxq;
        uint32_t rxstat, extsts;
-       int i, total_len, rx = 0;
+       int i, mlen, rx = 0;
        int cons;
 
        i = cons = q->q_rx.rge_rxq_considx;
@@ -1274,23 +1282,44 @@ rge_rxeof(struct rge_queues *q)
                if_rxr_put(rxr, 1);
                rx = 1;
 
-               total_len = rxstat & RGE_RDCMDSTS_FRAGLEN;
+               if (ISSET(rxstat, RGE_RDCMDSTS_SOF)) {
+                       if (q->q_rx.rge_head != NULL) {
+                               ifp->if_ierrors++;
+                               m_freem(q->q_rx.rge_head);
+                               q->q_rx.rge_tail = &q->q_rx.rge_head;
+                       }
 
-               /* We only handle a packet per rx descriptor at the moment */
-               if ((rxstat & (RGE_RDCMDSTS_SOF | RGE_RDCMDSTS_EOF)) !=
-                   (RGE_RDCMDSTS_SOF | RGE_RDCMDSTS_EOF)) {
-                       ifp->if_ierrors++;
+                       m->m_pkthdr.len = 0;
+               } else if (q->q_rx.rge_head == NULL) {
                        m_freem(m);
                        continue;
-               }
+               } else
+                       CLR(m->m_flags, M_PKTHDR);
+
+               *q->q_rx.rge_tail = m;
+               q->q_rx.rge_tail = &m->m_next;
+
+               mlen = rxstat & RGE_RDCMDSTS_FRAGLEN;
+               m->m_len = mlen;
+
+               m = q->q_rx.rge_head;
+               m->m_pkthdr.len += mlen;
 
                if (rxstat & RGE_RDCMDSTS_RXERRSUM) {
                        ifp->if_ierrors++;
                        m_freem(m);
+                       q->q_rx.rge_head = NULL;
+                       q->q_rx.rge_tail = &q->q_rx.rge_head;
                        continue;
                }
 
-               m->m_pkthdr.len = m->m_len = (total_len - ETHER_CRC_LEN);
+               if (!ISSET(rxstat, RGE_RDCMDSTS_EOF))
+                       continue;
+
+               q->q_rx.rge_head = NULL;
+               q->q_rx.rge_tail = &q->q_rx.rge_head;
+
+               m_adj(m, -ETHER_CRC_LEN);
 
                extsts = letoh32(cur_rx->hi_qword1.rx_qword4.rge_extsts);
 
index 62b02f8..bee10d6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_rgereg.h,v 1.12 2024/08/20 00:09:12 dlg Exp $      */
+/*     $OpenBSD: if_rgereg.h,v 1.13 2024/08/21 01:12:52 dlg Exp $      */
 
 /*
  * Copyright (c) 2019, 2020 Kevin Lo <kevlo@openbsd.org>
@@ -270,7 +270,7 @@ struct rge_rx_desc {
                        uint32_t        rsvd8;
                } rx_ptp;
        } hi_qword1;
-};
+} __packed __aligned(16);
 
 #define RGE_RDCMDSTS_RXERRSUM  0x00100000
 #define RGE_RDCMDSTS_EOF       0x01000000
@@ -344,7 +344,7 @@ struct rge_rx {
        struct rge_rx_desc      *rge_rx_list;
 
        struct mbuf             *rge_head;
-       struct mbuf             *rge_tail;
+       struct mbuf             **rge_tail;
 };
 
 struct rge_queues {