summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_bge.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2014-07-03 13:26:06 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2014-07-03 13:26:06 +0000
commit586d750798150b1bd0db0465ddefe1305923ea91 (patch)
tree0a8d308e28077d7deb9521ef5fd072fb76262372 /sys/dev/pci/if_bge.c
parent5b60228aa8af4c04eb19307df7f3da685445cfac (diff)
sending a heavily fragmented packet will cause the bus_dmamap_load
in bge_encap to fail because the dmamap lacks space, not necessarily because the ring is full. however, bge_encap failure sets the OACTIVE flag on the interface and keeps the packet at the start of the send queue. the next time we try to fill the tx ring we'll try to load the same packet and fail. an empty tx ring means bge_txeof hasnt got anything which is where the OACTIVE condition is cleared. this diff adds handling of fragmented packets via m_defrag. this might fix the issues landry@ has been complaining about on his bulk build machines. i can reproduce the above problem in contrived circumstances here and this diff fixes it, so its going in so landry@ is forced to test it.
Diffstat (limited to 'sys/dev/pci/if_bge.c')
-rw-r--r--sys/dev/pci/if_bge.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c
index e31ae3ee060..3666964ab8b 100644
--- a/sys/dev/pci/if_bge.c
+++ b/sys/dev/pci/if_bge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bge.c,v 1.354 2014/04/22 11:54:46 naddy Exp $ */
+/* $OpenBSD: if_bge.c,v 1.355 2014/07/03 13:26:05 dlg Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
@@ -4022,9 +4022,20 @@ doit:
* the fragment pointers. Stop when we run out
* of fragments or hit the end of the mbuf chain.
*/
- if (bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m_head,
- BUS_DMA_NOWAIT))
+ switch (bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m_head,
+ BUS_DMA_NOWAIT)) {
+ case 0:
+ break;
+ case EFBIG:
+ if (m_defrag(m_head, M_DONTWAIT) == 0 &&
+ bus_dmamap_load_mbuf(sc->bge_dmatag, dmamap, m_head,
+ BUS_DMA_NOWAIT) == 0)
+ break;
+
+ /* FALLTHROUGH */
+ default:
return (ENOBUFS);
+ }
/* Check if we have enough free send BDs. */
if (sc->bge_txcnt + dmamap->dm_nsegs >= BGE_TX_RING_CNT)