Date: Sat, 8 Feb 2020 13:33:47 +0000 (UTC) From: Marcin Wojtas <mw@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357676 - head/sys/dev/neta Message-ID: <202002081333.018DXmVK072180@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202002081333.018DXmVK072180>