diff options
author | Can Erkin Acar <canacar@cvs.openbsd.org> | 2016-01-07 04:41:18 +0000 |
---|---|---|
committer | Can Erkin Acar <canacar@cvs.openbsd.org> | 2016-01-07 04:41:18 +0000 |
commit | b3d7fe65f90c08b02498624ed6f60596abb575b6 (patch) | |
tree | b3c0c3d83ee85338ffbd45a4bd9758d9ee946b97 /sys/arch/armv7 | |
parent | 12a1b9dfd6754705dacb1152d73ce4c7b705a462 (diff) |
Handle receive queue full condition instead of hanging.This can be
triggered by flodding the interface. Also drop received packets
that span multiple buffers (which should not happen).
Tested on Beagle Bone Black by jsg@
ok bmercer@, djm@, jsg@
Diffstat (limited to 'sys/arch/armv7')
-rw-r--r-- | sys/arch/armv7/omap/if_cpsw.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/sys/arch/armv7/omap/if_cpsw.c b/sys/arch/armv7/omap/if_cpsw.c index ad70fba0eb3..d508ff04247 100644 --- a/sys/arch/armv7/omap/if_cpsw.c +++ b/sys/arch/armv7/omap/if_cpsw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cpsw.c,v 1.31 2015/11/25 11:12:53 mpi Exp $ */ +/* $OpenBSD: if_cpsw.c,v 1.32 2016/01/07 04:41:17 canacar Exp $ */ /* $NetBSD: if_cpsw.c,v 1.3 2013/04/17 14:36:34 bouyer Exp $ */ /* @@ -978,6 +978,8 @@ cpsw_rxintr(void *arg) u_int i; u_int len, off; + sc->sc_rxeoq = false; + for (;;) { KASSERT(sc->sc_rxhead < CPSW_NRXDESCS); @@ -998,14 +1000,8 @@ cpsw_rxintr(void *arg) goto done; } - if ((bd.flags & (CPDMA_BD_SOP|CPDMA_BD_EOP)) != - (CPDMA_BD_SOP|CPDMA_BD_EOP)) { - /* Debugger(); */ - } - bus_dmamap_sync(sc->sc_bdt, dm, 0, dm->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_bdt, dm); if (cpsw_new_rxbuf(sc, i) != 0) { /* drop current packet, reuse buffer for new */ @@ -1013,6 +1009,16 @@ cpsw_rxintr(void *arg) goto next; } + if ((bd.flags & (CPDMA_BD_SOP|CPDMA_BD_EOP)) != + (CPDMA_BD_SOP|CPDMA_BD_EOP)) { + if (bd.flags & CPDMA_BD_SOP) { + printf("cpsw: rx packet too large\n"); + ifp->if_ierrors++; + } + m_freem(m); + goto next; + } + off = bd.bufoff; len = bd.pktlen; @@ -1028,17 +1034,17 @@ next: sc->sc_rxhead = RXDESC_NEXT(sc->sc_rxhead); if (bd.flags & CPDMA_BD_EOQ) { sc->sc_rxeoq = true; - break; - } else { - sc->sc_rxeoq = false; + sc->sc_rxrun = false; } bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_CP(0), cpsw_rxdesc_paddr(sc, i)); } if (sc->sc_rxeoq) { - printf("rxeoq\n"); - /* Debugger(); */ + bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_RX_HDP(0), + cpsw_rxdesc_paddr(sc, sc->sc_rxhead)); + sc->sc_rxrun = true; + sc->sc_rxeoq = false; } bus_space_write_4(sc->sc_bst, sc->sc_bsh, CPSW_CPDMA_CPDMA_EOI_VECTOR, |