Author: mw
Date: Sat Feb  8 13:33:47 2020
New Revision: 357676
URL: https://svnweb.freebsd.org/changeset/base/357676

Log:
  Implement jumbo frame support in mvneta driver
  
  This patch introduces processing of the frames
  up to 9kB by the mvneta driver. Some versions of
  this NIC limit TX checksum offloading, depending
  on the frame size, so add appropriate handling
  of this feature.
  
  Submitted by: Kornel Duleba
  Obtained from: Semihalf
  Sponsored by: Stormshield
  Differential Revision: https://reviews.freebsd.org/D23225

Modified:
  head/sys/dev/neta/if_mvneta.c
  head/sys/dev/neta/if_mvneta_fdt.c
  head/sys/dev/neta/if_mvnetavar.h

Modified: head/sys/dev/neta/if_mvneta.c
==============================================================================
--- head/sys/dev/neta/if_mvneta.c       Sat Feb  8 13:25:39 2020        
(r357675)
+++ head/sys/dev/neta/if_mvneta.c       Sat Feb  8 13:33:47 2020        
(r357676)
@@ -483,9 +483,9 @@ mvneta_dma_create(struct mvneta_softc *sc)
            BUS_SPACE_MAXADDR_32BIT,            /* lowaddr */
            BUS_SPACE_MAXADDR,                  /* highaddr */
            NULL, NULL,                         /* filtfunc, filtfuncarg */
-           MVNETA_PACKET_SIZE,                 /* maxsize */
+           MVNETA_MAX_FRAME,                   /* maxsize */
            MVNETA_TX_SEGLIMIT,                 /* nsegments */
-           MVNETA_PACKET_SIZE,                 /* maxsegsz */
+           MVNETA_MAX_FRAME,                   /* maxsegsz */
            BUS_DMA_ALLOCNOW,                   /* flags */
            NULL, NULL,                         /* lockfunc, lockfuncarg */
            &sc->txmbuf_dtag);
@@ -533,8 +533,8 @@ mvneta_dma_create(struct mvneta_softc *sc)
            BUS_SPACE_MAXADDR_32BIT,            /* lowaddr */
            BUS_SPACE_MAXADDR,                  /* highaddr */
            NULL, NULL,                         /* filtfunc, filtfuncarg */
-           MVNETA_PACKET_SIZE, 1,              /* maxsize, nsegments */
-           MVNETA_PACKET_SIZE,                 /* maxsegsz */
+           MVNETA_MAX_FRAME, 1,                /* maxsize, nsegments */
+           MVNETA_MAX_FRAME,                   /* maxsegsz */
            0,                                  /* flags */
            NULL, NULL,                         /* lockfunc, lockfuncarg */
            &sc->rxbuf_dtag);                   /* dmat */
@@ -674,6 +674,8 @@ mvneta_attach(device_t self)
 
        ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP;
 
+       sc->rx_frame_size = MCLBYTES; /* ether_ifattach() always sets normal 
mtu */
+
        /*
         * Device DMA Buffer allocation.
         * Handles resource deallocation in case of failure.
@@ -1158,7 +1160,7 @@ mvneta_initreg(struct ifnet *ifp)
        /* Port MAC Control set 0 */
        reg  = MVNETA_PMACC0_MUSTSET;   /* must write 0x1 */
        reg &= ~MVNETA_PMACC0_PORTEN;   /* port is still disabled */
-       reg |= MVNETA_PMACC0_FRAMESIZELIMIT(MVNETA_MAX_FRAME);
+       reg |= MVNETA_PMACC0_FRAMESIZELIMIT(ifp->if_mtu + MVNETA_ETHER_SIZE);
        MVNETA_WRITE(sc, MVNETA_PMACC0, reg);
 
        /* Port MAC Control set 2 */
@@ -1525,7 +1527,7 @@ mvneta_rx_queue_init(struct ifnet *ifp, int q)
        MVNETA_WRITE(sc, MVNETA_PRXDQA(q), rx->desc_pa);
 
        /* Rx buffer size and descriptor ring size */
-       reg  = MVNETA_PRXDQS_BUFFERSIZE(MVNETA_PACKET_SIZE >> 3);
+       reg  = MVNETA_PRXDQS_BUFFERSIZE(sc->rx_frame_size >> 3);
        reg |= MVNETA_PRXDQS_DESCRIPTORSQUEUESIZE(MVNETA_RX_RING_CNT);
        MVNETA_WRITE(sc, MVNETA_PRXDQS(q), reg);
 #ifdef MVNETA_KTR
@@ -2103,7 +2105,7 @@ mvneta_ioctl(struct ifnet *ifp, u_long cmd, caddr_t da
                mvneta_sc_unlock(sc);
                break;
        case SIOCSIFCAP:
-               if (ifp->if_mtu > MVNETA_MAX_CSUM_MTU &&
+               if (ifp->if_mtu > sc->tx_csum_limit &&
                    ifr->ifr_reqcap & IFCAP_TXCSUM)
                        ifr->ifr_reqcap &= ~IFCAP_TXCSUM;
                mask = ifp->if_capenable ^ ifr->ifr_reqcap;
@@ -2157,7 +2159,12 @@ mvneta_ioctl(struct ifnet *ifp, u_long cmd, caddr_t da
                } else {
                        ifp->if_mtu = ifr->ifr_mtu;
                        mvneta_sc_lock(sc);
-                       if (ifp->if_mtu > MVNETA_MAX_CSUM_MTU) {
+                       if (ifp->if_mtu + MVNETA_ETHER_SIZE <= MCLBYTES) {
+                               sc->rx_frame_size = MCLBYTES;
+                       } else {
+                               sc->rx_frame_size = MJUM9BYTES;
+                       }
+                       if (ifp->if_mtu > sc->tx_csum_limit) {
                                ifp->if_capenable &= ~IFCAP_TXCSUM;
                                ifp->if_hwassist = 0;
                        } else {
@@ -2167,8 +2174,25 @@ mvneta_ioctl(struct ifnet *ifp, u_long cmd, caddr_t da
                        }
 
                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-                               /* Trigger reinitialize sequence */
+                               /* Stop hardware */
                                mvneta_stop_locked(sc);
+                               /*
+                                * Reinitialize RX queues.
+                                * We need to update RX descriptor size.
+                                */
+                               for (q = 0; q < MVNETA_RX_QNUM_MAX; q++) {
+                                       mvneta_rx_lockq(sc, q);
+                                       if (mvneta_rx_queue_init(ifp, q) != 0) {
+                                               device_printf(sc->dev,
+                                                   "initialization failed:"
+                                                   " cannot initialize 
queue\n");
+                                               mvneta_rx_unlockq(sc, q);
+                                               error = ENOBUFS;
+                                               break;
+                                       }
+                                       mvneta_rx_unlockq(sc, q);
+                               }
+                               /* Trigger reinitialization */
                                mvneta_init_locked(sc);
                        }
                        mvneta_sc_unlock(sc);
@@ -2214,6 +2238,8 @@ mvneta_init_locked(void *arg)
        /* Enable port */
        reg  = MVNETA_READ(sc, MVNETA_PMACC0);
        reg |= MVNETA_PMACC0_PORTEN;
+       reg &= ~MVNETA_PMACC0_FRAMESIZELIMIT_MASK;
+       reg |= MVNETA_PMACC0_FRAMESIZELIMIT(ifp->if_mtu + MVNETA_ETHER_SIZE);
        MVNETA_WRITE(sc, MVNETA_PMACC0, reg);
 
        /* Allow access to each TXQ/RXQ from both CPU's */
@@ -2801,6 +2827,10 @@ mvneta_tx_set_csumflag(struct ifnet *ifp,
        iphl = ipoff = 0;
        csum_flags = ifp->if_hwassist & m->m_pkthdr.csum_flags;
        eh = mtod(m, struct ether_header *);
+
+       if (csum_flags == 0)
+               return;
+
        switch (ntohs(eh->ether_type)) {
        case ETHERTYPE_IP:
                ipoff = ETHER_HDR_LEN;
@@ -3158,7 +3188,7 @@ mvneta_rx_queue_refill(struct mvneta_softc *sc, int q)
 
        for (npkt = 0; npkt < refill; npkt++) {
                rxbuf = &rx->rxbuf[rx->cpu];
-               m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+               m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, sc->rx_frame_size);
                if (__predict_false(m == NULL)) {
                        error = ENOBUFS;
                        break;

Modified: head/sys/dev/neta/if_mvneta_fdt.c
==============================================================================
--- head/sys/dev/neta/if_mvneta_fdt.c   Sat Feb  8 13:25:39 2020        
(r357675)
+++ head/sys/dev/neta/if_mvneta_fdt.c   Sat Feb  8 13:33:47 2020        
(r357676)
@@ -106,12 +106,33 @@ mvneta_fdt_probe(device_t dev)
 static int
 mvneta_fdt_attach(device_t dev)
 {
+       struct mvneta_softc *sc;
+       uint32_t tx_csum_limit;
        int err;
 
+       sc = device_get_softc(dev);
+
        /* Try to fetch PHY information from FDT */
        err = mvneta_fdt_phy_acquire(dev);
        if (err != 0)
                return (err);
+
+       if (ofw_bus_is_compatible(dev, "marvell,armada-370-neta")) {
+               tx_csum_limit = MVNETA_A370_MAX_CSUM_MTU;
+       } else {
+               tx_csum_limit = MVNETA_A3700_MAX_CSUM_MTU;
+       }
+
+       if (ofw_bus_has_prop(dev, "tx-csum-limit")) {
+               err = OF_getprop(ofw_bus_get_node(dev), "tx-csum-limit",
+                           &tx_csum_limit, sizeof(tx_csum_limit));
+               if (err <= 0) {
+                       device_printf(dev,
+                               "Failed to acquire tx-csum-limit property\n");
+                       return (ENXIO);
+               }
+       }
+       sc->tx_csum_limit = tx_csum_limit;
 
        return (mvneta_attach(dev));
 }

Modified: head/sys/dev/neta/if_mvnetavar.h
==============================================================================
--- head/sys/dev/neta/if_mvnetavar.h    Sat Feb  8 13:25:39 2020        
(r357675)
+++ head/sys/dev/neta/if_mvnetavar.h    Sat Feb  8 13:33:47 2020        
(r357676)
@@ -32,15 +32,12 @@
 #define        _IF_MVNETAVAR_H_
 #include <net/if.h>
 
-#define        MVNETA_HWHEADER_SIZE    2       /* Marvell Header */
-#define        MVNETA_ETHER_SIZE       22      /* Maximum ether size */
-#define        MVNETA_MAX_CSUM_MTU     1600    /* Port1,2 hw limit */
+#define        MVNETA_HWHEADER_SIZE            2       /* Marvell Header */
+#define        MVNETA_ETHER_SIZE               22      /* Maximum ether size */
+#define        MVNETA_A370_MAX_CSUM_MTU        1600    /* Max frame len for TX 
csum */
+#define        MVNETA_A3700_MAX_CSUM_MTU       9600
 
-/*
- * Limit support for frame up to hw csum limit
- * until jumbo frame support is added.
- */
-#define        MVNETA_MAX_FRAME                (MVNETA_MAX_CSUM_MTU + 
MVNETA_ETHER_SIZE)
+#define        MVNETA_MAX_FRAME                (MJUM9BYTES)
 
 /*
  * Default limit of queue length
@@ -54,7 +51,6 @@
 #define        MVNETA_BUFRING_SIZE     1024
 
 #define        MVNETA_PACKET_OFFSET    64
-#define        MVNETA_PACKET_SIZE      MCLBYTES
 
 #define        MVNETA_RXTH_COUNT       128
 #define        MVNETA_RX_REFILL_COUNT  8
@@ -268,6 +264,8 @@ struct mvneta_softc {
        struct ifnet    *ifp;
        uint32_t        mvneta_if_flags;
        uint32_t        mvneta_media;
+       uint32_t        tx_csum_limit;
+       uint32_t        rx_frame_size;
 
        int                     phy_attached;
        enum mvneta_phy_mode    phy_mode;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to