aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Wojtas <mw@FreeBSD.org>2020-02-08 13:33:47 +0000
committerMarcin Wojtas <mw@FreeBSD.org>2020-02-08 13:33:47 +0000
commit73f20bb3a9a1f6b6c3bd156d3cecd9f0ff4a17cd (patch)
treef8d311f9d7362a6bf8f96684f5d98f4f3b5c38c8
parent3599e81c97cae796bc8abc359ab2cfe8f597c2b8 (diff)
Notes
-rw-r--r--sys/dev/neta/if_mvneta.c50
-rw-r--r--sys/dev/neta/if_mvneta_fdt.c21
-rw-r--r--sys/dev/neta/if_mvnetavar.h16
3 files changed, 68 insertions, 19 deletions
diff --git a/sys/dev/neta/if_mvneta.c b/sys/dev/neta/if_mvneta.c
index 2c444abc6c51..88926331f143 100644
--- a/sys/dev/neta/if_mvneta.c
+++ b/sys/dev/neta/if_mvneta.c
@@ -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 data)
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 data)
} 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 data)
}
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;
diff --git a/sys/dev/neta/if_mvneta_fdt.c b/sys/dev/neta/if_mvneta_fdt.c
index 6b773e379e88..df7840845fcd 100644
--- a/sys/dev/neta/if_mvneta_fdt.c
+++ b/sys/dev/neta/if_mvneta_fdt.c
@@ -106,13 +106,34 @@ 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));
}
diff --git a/sys/dev/neta/if_mvnetavar.h b/sys/dev/neta/if_mvnetavar.h
index 8ac37fb65bfd..e78a9ca0f3ee 100644
--- a/sys/dev/neta/if_mvnetavar.h
+++ b/sys/dev/neta/if_mvnetavar.h
@@ -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;