Index: head/sys/dev/neta/if_mvneta.c =================================================================== --- head/sys/dev/neta/if_mvneta.c +++ head/sys/dev/neta/if_mvneta.c @@ -483,9 +483,9 @@ 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 @@ 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 @@ 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 @@ /* 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_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_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 @@ } 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 @@ } 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 @@ /* 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 @@ 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 @@ 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; Index: head/sys/dev/neta/if_mvneta_fdt.c =================================================================== --- head/sys/dev/neta/if_mvneta_fdt.c +++ head/sys/dev/neta/if_mvneta_fdt.c @@ -106,12 +106,33 @@ 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)); } Index: head/sys/dev/neta/if_mvnetavar.h =================================================================== --- head/sys/dev/neta/if_mvnetavar.h +++ head/sys/dev/neta/if_mvnetavar.h @@ -32,15 +32,12 @@ #define _IF_MVNETAVAR_H_ #include -#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 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;