git: 8f45652b6bcc - main - genet: fix problems with interface down/up
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 14 Apr 2022 19:10:25 UTC
The branch main has been updated by karels: URL: https://cgit.FreeBSD.org/src/commit/?id=8f45652b6bccc258eb58f8721dea10184f1aaa17 commit 8f45652b6bccc258eb58f8721dea10184f1aaa17 Author: Mike Karels <karels@FreeBSD.org> AuthorDate: 2022-04-11 19:44:49 +0000 Commit: Mike Karels <karels@FreeBSD.org> CommitDate: 2022-04-14 19:10:13 +0000 genet: fix problems with interface down/up The genet interface did not resume operation correctly after doing ifconfig down then up. The down/reset procedure did not clear the RUNNING flag, and did not reset enough of the hardware state. This patch is modeled on OpenBSD code, with a call to gen_reset added to reset the controller completely. Regularize the parameter to gen_dma_disable() while here. PR: 263091 Submitted by: jiahali@blackberry.com --- sys/arm64/broadcom/genet/if_genet.c | 86 ++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/sys/arm64/broadcom/genet/if_genet.c b/sys/arm64/broadcom/genet/if_genet.c index 31fab0f9cf09..4532c8d32f90 100644 --- a/sys/arm64/broadcom/genet/if_genet.c +++ b/sys/arm64/broadcom/genet/if_genet.c @@ -216,7 +216,7 @@ static void gen_set_enaddr(struct gen_softc *sc); static void gen_setup_rxfilter(struct gen_softc *sc); static void gen_reset(struct gen_softc *sc); static void gen_enable(struct gen_softc *sc); -static void gen_dma_disable(device_t dev); +static void gen_dma_disable(struct gen_softc *sc); static int gen_bus_dma_init(struct gen_softc *sc); static void gen_bus_dma_teardown(struct gen_softc *sc); static void gen_enable_intr(struct gen_softc *sc); @@ -289,7 +289,7 @@ gen_attach(device_t dev) /* reset core */ gen_reset(sc); - gen_dma_disable(dev); + gen_dma_disable(sc); /* Setup DMA */ error = gen_bus_dma_init(sc); @@ -484,6 +484,12 @@ gen_reset(struct gen_softc *sc) WR4(sc, GENET_UMAC_MIB_CTRL, GENET_UMAC_MIB_RESET_RUNT | GENET_UMAC_MIB_RESET_RX | GENET_UMAC_MIB_RESET_TX); WR4(sc, GENET_UMAC_MIB_CTRL, 0); +} + +static void +gen_enable(struct gen_softc *sc) +{ + u_int val; WR4(sc, GENET_UMAC_MAX_FRAME_LEN, 1536); @@ -492,12 +498,6 @@ gen_reset(struct gen_softc *sc) WR4(sc, GENET_RBUF_CTRL, val); WR4(sc, GENET_RBUF_TBUF_SIZE_CTRL, 1); -} - -static void -gen_enable(struct gen_softc *sc) -{ - u_int val; /* Enable transmitter and receiver */ val = RD4(sc, GENET_UMAC_CMD); @@ -511,6 +511,33 @@ gen_enable(struct gen_softc *sc) GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE); } +static void +gen_disable_intr(struct gen_softc *sc) +{ + /* Disable interrupts */ + WR4(sc, GENET_INTRL2_CPU_SET_MASK, 0xffffffff); + WR4(sc, GENET_INTRL2_CPU_CLEAR_MASK, 0xffffffff); +} + +static void +gen_disable(struct gen_softc *sc) +{ + uint32_t val; + + /* Stop receiver */ + val = RD4(sc, GENET_UMAC_CMD); + val &= ~GENET_UMAC_CMD_RXEN; + WR4(sc, GENET_UMAC_CMD, val); + + /* Stop transmitter */ + val = RD4(sc, GENET_UMAC_CMD); + val &= ~GENET_UMAC_CMD_TXEN; + WR4(sc, GENET_UMAC_CMD, val); + + /* Disable Interrupt */ + gen_disable_intr(sc); +} + static void gen_enable_offload(struct gen_softc *sc) { @@ -538,9 +565,8 @@ gen_enable_offload(struct gen_softc *sc) } static void -gen_dma_disable(device_t dev) +gen_dma_disable(struct gen_softc *sc) { - struct gen_softc *sc = device_get_softc(dev); int val; val = RD4(sc, GENET_TX_DMA_CTRL); @@ -808,6 +834,44 @@ gen_init_rxrings(struct gen_softc *sc) } +static void +gen_stop(struct gen_softc *sc) +{ + int i; + struct gen_ring_ent *ent; + + GEN_ASSERT_LOCKED(sc); + + callout_stop(&sc->stat_ch); + if_setdrvflagbits(sc->ifp, 0, IFF_DRV_RUNNING); + gen_reset(sc); + gen_disable(sc); + gen_dma_disable(sc); + + /* Clear the tx/rx ring buffer */ + for (i = 0; i < TX_DESC_COUNT; i++) { + ent = &sc->tx_ring_ent[i]; + if (ent->mbuf != NULL) { + bus_dmamap_sync(sc->tx_buf_tag, ent->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->tx_buf_tag, ent->map); + m_freem(ent->mbuf); + ent->mbuf = NULL; + } + } + + for (i = 0; i < RX_DESC_COUNT; i++) { + ent = &sc->rx_ring_ent[i]; + if (ent->mbuf != NULL) { + bus_dmamap_sync(sc->rx_buf_tag, ent->map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->rx_buf_tag, ent->map); + m_freem(ent->mbuf); + ent->mbuf = NULL; + } + } +} + static void gen_init_locked(struct gen_softc *sc) { @@ -1498,7 +1562,7 @@ gen_ioctl(if_t ifp, u_long cmd, caddr_t data) gen_init_locked(sc); } else { if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) - gen_reset(sc); + gen_stop(sc); } sc->if_flags = if_getflags(ifp); GEN_UNLOCK(sc);