From 56fd04f19a61078618898230093b9b2dfacff435 Mon Sep 17 00:00:00 2001 From: dlg Date: Sun, 5 Jun 2022 02:54:18 +0000 Subject: [PATCH] enable interrupt coalescing. mvneta only supports coalescing tx completions by count, so this uses the txmit value or half the ring as the threshold, whichever is lower. rx coalescing has a threshold on the number of packets, and a max time it will wait before interrupting. however, it also has a threshold for how many spare/empty descriptors there are on the ring too. we use this latter threshold to have the chip interrupt as soon as it uses the allocation that the rx ring moderation has granted, and then first two to otherwise rate limit rx to about 4k interrupts per second. ok patrick@ --- sys/dev/fdt/if_mvneta.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/sys/dev/fdt/if_mvneta.c b/sys/dev/fdt/if_mvneta.c index a61e6855187..2339ca82186 100644 --- a/sys/dev/fdt/if_mvneta.c +++ b/sys/dev/fdt/if_mvneta.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mvneta.c,v 1.25 2022/06/01 08:19:15 dlg Exp $ */ +/* $OpenBSD: if_mvneta.c,v 1.26 2022/06/05 02:54:18 dlg Exp $ */ /* $NetBSD: if_mvneta.c,v 1.41 2015/04/15 10:15:40 hsuenaga Exp $ */ /* * Copyright (c) 2007, 2008, 2013 KIYOHARA Takashi @@ -137,6 +137,8 @@ struct mvneta_softc { bus_dma_tag_t sc_dmat; void *sc_ih; + uint64_t sc_clk_freq; + struct arpcom sc_ac; #define sc_enaddr sc_ac.ac_enaddr struct mii_data sc_mii; @@ -453,6 +455,7 @@ mvneta_attach(struct device *parent, struct device *self, void *aux) sc->sc_node = faa->fa_node; clock_enable(faa->fa_node, NULL); + sc->sc_clk_freq = clock_get_frequency_idx(faa->fa_node, 0); pinctrl_byname(faa->fa_node, "default"); @@ -837,7 +840,7 @@ mvneta_intr(void *arg) if (ic & MVNETA_PRXTXTI_TBTCQ(0)) mvneta_tx_proc(sc); - if (ic & MVNETA_PRXTXTI_RBICTAPQ(0)) + if (ISSET(ic, MVNETA_PRXTXTI_RBICTAPQ(0) | MVNETA_PRXTXTI_RDTAQ(0))) mvneta_rx_proc(sc); return 1; @@ -1134,7 +1137,24 @@ mvneta_up(struct mvneta_softc *sc) MVNETA_WRITE(sc, MVNETA_PRXDQA(0), MVNETA_DMA_DVA(sc->sc_rxring)); MVNETA_WRITE(sc, MVNETA_PRXDQS(0), MVNETA_RX_RING_CNT | ((MCLBYTES >> 3) << 19)); - MVNETA_WRITE(sc, MVNETA_PRXDQTH(0), 0); + + if (sc->sc_clk_freq != 0) { + /* + * Use the Non Occupied Descriptors Threshold to + * interrupt when the descriptors granted by rxr are + * used up, otherwise wait until the RX Interrupt + * Time Threshold is reached. + */ + MVNETA_WRITE(sc, MVNETA_PRXDQTH(0), + MVNETA_PRXDQTH_ODT(MVNETA_RX_RING_CNT) | + MVNETA_PRXDQTH_NODT(2)); + MVNETA_WRITE(sc, MVNETA_PRXITTH(0), sc->sc_clk_freq / 4000); + } else { + /* Time based moderation is hard without a clock */ + MVNETA_WRITE(sc, MVNETA_PRXDQTH(0), 0); + MVNETA_WRITE(sc, MVNETA_PRXITTH(0), 0); + } + MVNETA_WRITE(sc, MVNETA_PRXC(0), 0); /* Set Tx queue bandwidth. */ @@ -1144,7 +1164,8 @@ mvneta_up(struct mvneta_softc *sc) /* Set Tx descriptor ring data. */ MVNETA_WRITE(sc, MVNETA_PTXDQA(0), MVNETA_DMA_DVA(sc->sc_txring)); MVNETA_WRITE(sc, MVNETA_PTXDQS(0), - MVNETA_PTXDQS_DQS(MVNETA_TX_RING_CNT)); + MVNETA_PTXDQS_DQS(MVNETA_TX_RING_CNT) | + MVNETA_PTXDQS_TBT(MIN(MVNETA_TX_RING_CNT / 2, ifp->if_txmit))); sc->sc_rx_prod = sc->sc_rx_cons = 0; @@ -1178,7 +1199,8 @@ mvneta_up(struct mvneta_softc *sc) /* Enable interrupt masks */ MVNETA_WRITE(sc, MVNETA_PRXTXTIM, MVNETA_PRXTXTI_RBICTAPQ(0) | - MVNETA_PRXTXTI_TBTCQ(0) | MVNETA_PRXTXTI_PMISCICSUMMARY); + MVNETA_PRXTXTI_TBTCQ(0) | MVNETA_PRXTXTI_RDTAQ(0) | + MVNETA_PRXTXTI_PMISCICSUMMARY); MVNETA_WRITE(sc, MVNETA_PMIM, MVNETA_PMI_PHYSTATUSCHNG | MVNETA_PMI_LINKCHANGE | MVNETA_PMI_PSCSYNCCHNG); -- 2.20.1