summaryrefslogtreecommitdiff
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2023-02-26 13:28:13 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2023-02-26 13:28:13 +0000
commit74e05c09bf0e669a1b3c0a7ccdd38b53e0374bfe (patch)
tree615ff02f930718690a879db4fb6f40c06abc32f1 /sys/dev/fdt
parent7b8bfaa26930bb7f2556d9c346084b077280857d (diff)
Defragment mbufs in the tx path to work around a (not fully understood)
issue on the StarFive JH7100 SoC where packets spanning multiple mbufs are corrupted. Makes ethernet work reliably on the StarFive VisionFive 1 board. ok patrick@
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/if_dwge.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/sys/dev/fdt/if_dwge.c b/sys/dev/fdt/if_dwge.c
index eed03e3fa37..c5c42ecf6c4 100644
--- a/sys/dev/fdt/if_dwge.c
+++ b/sys/dev/fdt/if_dwge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_dwge.c,v 1.14 2023/01/14 17:02:57 kettenis Exp $ */
+/* $OpenBSD: if_dwge.c,v 1.15 2023/02/26 13:28:12 kettenis Exp $ */
/*
* Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
* Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -253,6 +253,7 @@ struct dwge_softc {
int sc_phyloc;
int sc_force_thresh_dma_mode;
int sc_enh_desc;
+ int sc_defrag;
struct dwge_dmamem *sc_txring;
struct dwge_buf *sc_txbuf;
@@ -406,6 +407,16 @@ dwge_attach(struct device *parent, struct device *self, void *aux)
sc->sc_enh_desc = 1;
}
+ /*
+ * The GMAC on the StarFive JH7100 (core version 3.70)
+ * sometimes transmits corrupted packets. The exact
+ * conditions under which this happens are unclear, but
+ * defragmenting mbufs before transmitting them fixes the
+ * issue.
+ */
+ if (OF_is_compatible(faa->fa_node, "starfive,jh7100-gmac"))
+ sc->sc_defrag = 1;
+
/* Power up PHY. */
phy_supply = OF_getpropint(faa->fa_node, "phy-supply", 0);
if (phy_supply)
@@ -1252,6 +1263,11 @@ dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx, int *used)
cur = frag = *idx;
map = sc->sc_txbuf[cur].tb_map;
+ if (sc->sc_defrag) {
+ if (m_defrag(m, M_DONTWAIT))
+ return (ENOBUFS);
+ }
+
if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT)) {
if (m_defrag(m, M_DONTWAIT))
return (EFBIG);