summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2013-09-12 01:44:14 +0000
committerdlg <dlg@openbsd.org>2013-09-12 01:44:14 +0000
commitd7fae90b92a8e5cc93f30395ce10c1a890acc033 (patch)
treed808670d7f1e3df6257b16840e8f35e61506e22c
parentfix connection crash when sending break (~B) on ControlPersist'd session; (diff)
downloadwireguard-openbsd-d7fae90b92a8e5cc93f30395ce10c1a890acc033.tar.xz
wireguard-openbsd-d7fae90b92a8e5cc93f30395ce10c1a890acc033.zip
rearrange cpsw_start() a bit.
- cope with errors more consistently, which will avoid us leaking mbufs in failure paths. - use m_defrag when we get EFBIG back from bus_dmamap_load_mbuf rather than printf and lose. - shuffle some ops to be more like other drivers we have.
-rw-r--r--sys/arch/armv7/omap/if_cpsw.c52
1 files changed, 29 insertions, 23 deletions
diff --git a/sys/arch/armv7/omap/if_cpsw.c b/sys/arch/armv7/omap/if_cpsw.c
index 0c933db4723..99c4e3dac75 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.11 2013/09/12 01:13:10 dlg Exp $ */
+/* $OpenBSD: if_cpsw.c,v 1.12 2013/09/12 01:44:14 dlg Exp $ */
/* $NetBSD: if_cpsw.c,v 1.3 2013/04/17 14:36:34 bouyer Exp $ */
/*
@@ -509,39 +509,45 @@ cpsw_start(struct ifnet *ifp)
bool pad;
u_int mlen;
- if (__predict_false((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) !=
- IFF_RUNNING)) {
+ if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
+ ISSET(ifp->if_flags, IFF_OACTIVE) ||
+ IFQ_IS_EMPTY(&ifp->if_snd))
return;
- }
if (sc->sc_txnext >= sc->sc_txhead)
txfree = CPSW_NTXDESCS - 1 + sc->sc_txhead - sc->sc_txnext;
else
txfree = sc->sc_txhead - sc->sc_txnext - 1;
- while (txfree > 0) {
+ for (;;) {
+ if (txfree <= CPSW_TXFRAGS) {
+ SET(ifp->if_flags, IFF_OACTIVE);
+ break;
+ }
+
IFQ_POLL(&ifp->if_snd, m);
if (m == NULL)
break;
- dm = rdp->tx_dm[sc->sc_txnext];
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ dm = rdp->tx_dm[sc->sc_txnext];
error = bus_dmamap_load_mbuf(sc->sc_bdt, dm, m, BUS_DMA_NOWAIT);
- if (error == EFBIG) {
- printf("won't fit\n");
- IFQ_DEQUEUE(&ifp->if_snd, m);
+ switch (error) {
+ case 0:
+ break;
+
+ case EFBIG: /* mbuf chain is too fragmented */
+ if (m_defrag(m, M_DONTWAIT) == 0 &&
+ bus_dmamap_load_mbuf(sc->sc_bdt, dm, m,
+ BUS_DMA_NOWAIT) == 0)
+ break;
+
+ /* FALLTHROUGH */
+ default:
m_freem(m);
ifp->if_oerrors++;
continue;
- } else if (error != 0) {
- printf("error\n");
- break;
- }
-
- if (dm->dm_nsegs + 1 >= txfree) {
- ifp->if_flags |= IFF_OACTIVE;
- bus_dmamap_unload(sc->sc_bdt, dm);
- break;
}
mlen = m_length(m);
@@ -549,7 +555,11 @@ cpsw_start(struct ifnet *ifp)
KASSERT(rdp->tx_mb[sc->sc_txnext] == NULL);
rdp->tx_mb[sc->sc_txnext] = m;
- IFQ_DEQUEUE(&ifp->if_snd, m);
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
bus_dmamap_sync(sc->sc_bdt, dm, 0, dm->dm_mapsize,
BUS_DMASYNC_PREWRITE);
@@ -588,10 +598,6 @@ cpsw_start(struct ifnet *ifp)
eopi = sc->sc_txnext;
sc->sc_txnext = TXDESC_NEXT(sc->sc_txnext);
}
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
-#endif
}
if (txstart >= 0) {