summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorCan Erkin Acar <canacar@cvs.openbsd.org>2016-01-07 04:41:18 +0000
committerCan Erkin Acar <canacar@cvs.openbsd.org>2016-01-07 04:41:18 +0000
commitb3d7fe65f90c08b02498624ed6f60596abb575b6 (patch)
treeb3c0c3d83ee85338ffbd45a4bd9758d9ee946b97 /sys
parent12a1b9dfd6754705dacb1152d73ce4c7b705a462 (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')
-rw-r--r--sys/arch/armv7/omap/if_cpsw.c30
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,