diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2015-11-20 03:35:24 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2015-11-20 03:35:24 +0000 |
commit | 93d7f55b038092ded0514b3f745fd014c1845492 (patch) | |
tree | da8fbd80cf246b5a4ebcdf952d9bb7b92cbe5e19 /sys | |
parent | d3a33e8102f3bbde40bab36e7fc5067836baf064 (diff) |
shuffle struct ifqueue so in flight mbufs are protected by a mutex.
the code is refactored so the IFQ macros call newly implemented ifq
functions. the ifq code is split so each discipline (priq and hfsc
in our case) is an opaque set of operations that the common ifq
code can call. the common code does the locking, accounting (ifq_len
manipulation), and freeing of the mbuf if the disciplines enqueue
function rejects it. theyre kind of like bufqs in the block layer
with their fifo and nscan disciplines.
the new api also supports atomic switching of disciplines at runtime.
the hfsc setup in pf_ioctl.c has been tweaked to build a complete
hfsc_if structure which it attaches to the send queue in a single
operation, rather than attaching to the interface up front and
building up a list of queues.
the send queue is now mutexed, which raises the expectation that
packets can be enqueued or purged on one cpu while another cpu is
dequeueing them in a driver for transmission. a lot of drivers use
IFQ_POLL to peek at an mbuf and attempt to fit it on the ring before
committing to it with a later IFQ_DEQUEUE operation. if the mbuf
gets freed in between the POLL and DEQUEUE operations, fireworks
will ensue.
to avoid this, the ifq api introduces ifq_deq_begin, ifq_deq_rollback,
and ifq_deq_commit. ifq_deq_begin allows a driver to take the ifq
mutex and get a reference to the mbuf they wish to try and tx. if
there's space, they can ifq_deq_commit it to remove the mbuf and
release the mutex. if there's no space, ifq_deq_rollback simply
releases the mutex. this api was developed to make updating the
drivers using IFQ_POLL easy, instead of having to do significant
semantic changes to avoid POLL that we cannot test on all the
hardware.
the common code has been tested pretty hard, and all the driver
modifications are straightforward except for de(4). if that breaks
it can be dealt with later.
ok mpi@ jmatthew@
Diffstat (limited to 'sys')
77 files changed, 1079 insertions, 687 deletions
diff --git a/sys/arch/armv7/imx/imxenet.c b/sys/arch/armv7/imx/imxenet.c index eb6a39ec6ba..e6067b5d03c 100644 --- a/sys/arch/armv7/imx/imxenet.c +++ b/sys/arch/armv7/imx/imxenet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imxenet.c,v 1.17 2015/10/27 15:07:56 mpi Exp $ */ +/* $OpenBSD: imxenet.c,v 1.18 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> * @@ -816,16 +816,17 @@ imxenet_start(struct ifnet *ifp) return; for (;;) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (imxenet_encap(sc, m_head)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); ifp->if_opackets++; diff --git a/sys/arch/armv7/sunxi/sxie.c b/sys/arch/armv7/sunxi/sxie.c index 3a7f2fb8031..15c2eaa8548 100644 --- a/sys/arch/armv7/sunxi/sxie.c +++ b/sys/arch/armv7/sunxi/sxie.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sxie.c,v 1.10 2015/10/27 15:07:56 mpi Exp $ */ +/* $OpenBSD: sxie.c,v 1.11 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> * Copyright (c) 2013 Artturi Alm @@ -471,17 +471,19 @@ sxie_start(struct ifnet *ifp) m = NULL; head = NULL; trynext: - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) return; if (m->m_pkthdr.len > SXIE_MAX_PKT_SIZE) { + ifq_deq_commit(&ifp->if_snd, m); printf("sxie_start: packet too big\n"); m_freem(m); return; } if (sc->txf_inuse > 1) { + ifq_deq_rollback(&ifp->if_snd, m); printf("sxie_start: tx fifos in use.\n"); ifp->if_flags |= IFF_OACTIVE; return; @@ -505,7 +507,7 @@ trynext: /* transmit to PHY from fifo */ SXISET4(sc, SXIE_TXCR0 + (fifo * 4), 1); ifp->if_timer = 5; - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/arch/sgi/dev/if_iec.c b/sys/arch/sgi/dev/if_iec.c index 90629b2400b..39d5a61a4d2 100644 --- a/sys/arch/sgi/dev/if_iec.c +++ b/sys/arch/sgi/dev/if_iec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iec.c,v 1.16 2015/10/25 13:22:09 mpi Exp $ */ +/* $OpenBSD: if_iec.c,v 1.17 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 2009 Miodrag Vallat. @@ -760,12 +760,14 @@ iec_start(struct ifnet *ifp) for (;;) { /* Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; - if (sc->sc_txpending == IEC_NTXDESC) + if (sc->sc_txpending == IEC_NTXDESC) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } /* * Get the next available transmit descriptor. @@ -779,7 +781,7 @@ iec_start(struct ifnet *ifp) DPRINTF(IEC_DEBUG_START, ("iec_start: len = %d, nexttx = %d\n", len, nexttx)); - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (len <= IEC_TXD_BUFSIZE) { /* * If the packet is small enough, diff --git a/sys/arch/sgi/dev/if_mec.c b/sys/arch/sgi/dev/if_mec.c index 97e64c1afa0..25d83dd797a 100644 --- a/sys/arch/sgi/dev/if_mec.c +++ b/sys/arch/sgi/dev/if_mec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mec.c,v 1.31 2015/10/25 13:22:09 mpi Exp $ */ +/* $OpenBSD: if_mec.c,v 1.32 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: if_mec_mace.c,v 1.5 2004/08/01 06:36:36 tsutsui Exp $ */ /* @@ -738,11 +738,12 @@ mec_start(struct ifnet *ifp) for (;;) { /* Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; if (sc->sc_txpending == MEC_NTXDESC) { + ifq_deq_rollback(&ifp->if_snd, m0); break; } @@ -763,7 +764,7 @@ mec_start(struct ifnet *ifp) DPRINTF(MEC_DEBUG_START, ("mec_start: len = %d, nexttx = %d\n", len, nexttx)); - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (len < ETHER_PAD_LEN) { /* * I don't know if MEC chip does auto padding, diff --git a/sys/arch/sgi/hpc/if_sq.c b/sys/arch/sgi/hpc/if_sq.c index 620f52af5b3..c79b06b2871 100644 --- a/sys/arch/sgi/hpc/if_sq.c +++ b/sys/arch/sgi/hpc/if_sq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sq.c,v 1.18 2015/10/25 13:22:09 mpi Exp $ */ +/* $OpenBSD: if_sq.c,v 1.19 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: if_sq.c,v 1.42 2011/07/01 18:53:47 dyoung Exp $ */ /* @@ -671,7 +671,7 @@ sq_start(struct ifnet *ifp) /* * Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd, m0); if (m0 == NULL) break; m = NULL; @@ -696,6 +696,7 @@ sq_start(struct ifnet *ifp) BUS_DMA_NOWAIT) != 0) { MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { + ifq_deq_rollback(&ifp->if_snd, m0); printf("%s: unable to allocate Tx mbuf\n", sc->sc_dev.dv_xname); break; @@ -703,6 +704,7 @@ sq_start(struct ifnet *ifp) if (len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { + ifq_deq_rollback(&ifp->if_snd, m0); printf("%s: unable to allocate Tx " "cluster\n", sc->sc_dev.dv_xname); @@ -722,6 +724,7 @@ sq_start(struct ifnet *ifp) if ((err = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m, BUS_DMA_NOWAIT)) != 0) { + ifq_deq_rollback(&ifp->if_snd, m0); printf("%s: unable to load Tx buffer, " "error = %d\n", sc->sc_dev.dv_xname, err); @@ -734,6 +737,7 @@ sq_start(struct ifnet *ifp) * the packet. */ if (dmamap->dm_nsegs > sc->sc_nfreetx) { + ifq_deq_rollback(&ifp->if_snd, m0); /* * Not enough free descriptors to transmit this * packet. We haven't committed to anything yet, @@ -751,7 +755,7 @@ sq_start(struct ifnet *ifp) break; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); #if NBPFILTER > 0 /* * Pass the packet to any BPF listeners. diff --git a/sys/arch/socppc/dev/if_tsec.c b/sys/arch/socppc/dev/if_tsec.c index 667ce15da69..2fb835c3cb7 100644 --- a/sys/arch/socppc/dev/if_tsec.c +++ b/sys/arch/socppc/dev/if_tsec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tsec.c,v 1.39 2015/11/06 11:35:48 mpi Exp $ */ +/* $OpenBSD: if_tsec.c,v 1.40 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 2008 Mark Kettenis @@ -527,24 +527,25 @@ tsec_start(struct ifnet *ifp) idx = sc->sc_tx_prod; while ((sc->sc_txdesc[idx].td_status & TSEC_TX_TO1) == 0) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; error = tsec_encap(sc, m, &idx); if (error == ENOBUFS) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } if (error == EFBIG) { - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); /* give up: drop it */ ifp->if_oerrors++; continue; } /* Now we are committed to transmit the packet. */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/arch/sparc64/dev/vnet.c b/sys/arch/sparc64/dev/vnet.c index ec19e013526..21943833f67 100644 --- a/sys/arch/sparc64/dev/vnet.c +++ b/sys/arch/sparc64/dev/vnet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vnet.c,v 1.47 2015/10/25 13:22:09 mpi Exp $ */ +/* $OpenBSD: vnet.c,v 1.48 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 2009, 2015 Mark Kettenis * @@ -1101,24 +1101,26 @@ vnet_start(struct ifnet *ifp) start = prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1); while (sc->sc_vd->vd_desc[prod].hdr.dstate == VIO_DESC_FREE) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; count = sc->sc_tx_prod - sc->sc_tx_cons; if (count >= (sc->sc_vd->vd_nentries - 1) || map->lm_count >= map->lm_nentries) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO); if (buf == NULL) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } m_copydata(m, 0, m->m_pkthdr.len, buf + VNET_ETHER_ALIGN); - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 /* @@ -1176,24 +1178,26 @@ vnet_start_desc(struct ifnet *ifp) u_int prod, count; for (;;) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; count = sc->sc_tx_prod - sc->sc_tx_cons; if (count >= (sc->sc_vd->vd_nentries - 1) || map->lm_count >= map->lm_nentries) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; return; } buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO); if (buf == NULL) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; return; } m_copydata(m, 0, m->m_pkthdr.len, buf); - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 /* diff --git a/sys/arch/vax/if/if_qe.c b/sys/arch/vax/if/if_qe.c index 137fd914a4c..065dfae355a 100644 --- a/sys/arch/vax/if/if_qe.c +++ b/sys/arch/vax/if/if_qe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_qe.c,v 1.37 2015/11/14 17:26:40 mpi Exp $ */ +/* $OpenBSD: if_qe.c,v 1.38 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: if_qe.c,v 1.51 2002/06/08 12:28:37 ragge Exp $ */ /* * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved. @@ -442,7 +442,7 @@ qestart(struct ifnet *ifp) continue; } idx = sc->sc_nexttx; - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd, m); if (m == NULL) goto out; /* @@ -457,11 +457,12 @@ qestart(struct ifnet *ifp) panic("qestart"); if ((i + sc->sc_inq) >= (TXDESCS - 1)) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; goto out; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/ic/aic6915.c b/sys/dev/ic/aic6915.c index fd90f712c38..13150cb0e93 100644 --- a/sys/dev/ic/aic6915.c +++ b/sys/dev/ic/aic6915.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aic6915.c,v 1.18 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: aic6915.c,v 1.19 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: aic6915.c,v 1.15 2005/12/24 20:27:29 perry Exp $ */ /*- @@ -363,7 +363,7 @@ sf_start(struct ifnet *ifp) /* * Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; m = NULL; @@ -385,6 +385,7 @@ sf_start(struct ifnet *ifp) BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) { MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { + ifq_deq_rollback(&ifp->if_snd, m0); printf("%s: unable to allocate Tx mbuf\n", sc->sc_dev.dv_xname); break; @@ -392,6 +393,7 @@ sf_start(struct ifnet *ifp) if (m0->m_pkthdr.len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { + ifq_deq_rollback(&ifp->if_snd, m0); printf("%s: unable to allocate Tx " "cluster\n", sc->sc_dev.dv_xname); m_freem(m); @@ -403,6 +405,7 @@ sf_start(struct ifnet *ifp) error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); if (error) { + ifq_deq_rollback(&ifp->if_snd, m0); printf("%s: unable to load Tx buffer, " "error = %d\n", sc->sc_dev.dv_xname, error); m_freem(m); @@ -413,7 +416,7 @@ sf_start(struct ifnet *ifp) /* * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */ - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m != NULL) { m_freem(m0); m0 = m; diff --git a/sys/dev/ic/an.c b/sys/dev/ic/an.c index 1d29bfed8db..abb6bac0ac2 100644 --- a/sys/dev/ic/an.c +++ b/sys/dev/ic/an.c @@ -1,4 +1,4 @@ -/* $OpenBSD: an.c,v 1.66 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: an.c,v 1.67 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: an.c,v 1.34 2005/06/20 02:49:18 atatat Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -1097,18 +1097,19 @@ an_start(struct ifnet *ifp) DPRINTF(("an_start: not running %d\n", ic->ic_state)); break; } - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) { DPRINTF2(("an_start: no pending mbuf\n")); break; } if (sc->sc_txd[cur].d_inuse) { + ifq_deq_rollback(&ifp->if_snd, m); DPRINTF2(("an_start: %x/%d busy\n", sc->sc_txd[cur].d_fid, cur)); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); ifp->if_opackets++; #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/ic/dc.c b/sys/dev/ic/dc.c index 6a4a903cfe5..e45edf8f7d9 100644 --- a/sys/dev/ic/dc.c +++ b/sys/dev/ic/dc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dc.c,v 1.145 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: dc.c,v 1.146 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -2618,7 +2618,7 @@ dc_start(struct ifnet *ifp) idx = sc->dc_cdata.dc_tx_prod; while(sc->dc_cdata.dc_tx_chain[idx].sd_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; @@ -2628,7 +2628,7 @@ dc_start(struct ifnet *ifp) /* note: dc_coal breaks the poll-and-dequeue rule. * if dc_coal fails, we lose the packet. */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); if (dc_coal(sc, &m_head)) { ifp->if_flags |= IFF_OACTIVE; break; @@ -2636,6 +2636,9 @@ dc_start(struct ifnet *ifp) } if (dc_encap(sc, m_head, &idx)) { + if ((sc->dc_flags & DC_TX_COALESCE) == 0) + ifq_deq_rollback(&ifp->if_snd, m_head); + ifp->if_flags |= IFF_OACTIVE; break; } @@ -2644,7 +2647,7 @@ dc_start(struct ifnet *ifp) if (sc->dc_flags & DC_TX_COALESCE) { /* if mbuf is coalesced, it is already dequeued */ } else - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); /* * If there's a BPF listener, bounce a copy of this frame diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c index 328a60e8495..726adc476bd 100644 --- a/sys/dev/ic/elink3.c +++ b/sys/dev/ic/elink3.c @@ -1,4 +1,4 @@ -/* $OpenBSD: elink3.c,v 1.88 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: elink3.c,v 1.89 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: elink3.c,v 1.32 1997/05/14 00:22:00 thorpej Exp $ */ /* @@ -954,7 +954,7 @@ epstart(struct ifnet *ifp) startagain: /* Sneak a peek at the next packet */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) return; @@ -973,7 +973,7 @@ startagain: if (len + pad > ETHER_MAX_LEN) { /* packet is obviously too large: toss it */ ++ifp->if_oerrors; - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); m_freem(m0); goto readcheck; } @@ -983,6 +983,7 @@ startagain: bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad + 4) >> sc->txashift)); /* not enough room in FIFO */ + ifq_deq_rollback(&ifp->if_snd, m0); ifp->if_flags |= IFF_OACTIVE; return; } else { @@ -990,7 +991,7 @@ startagain: SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE); } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m0 == NULL) return; diff --git a/sys/dev/ic/fxp.c b/sys/dev/ic/fxp.c index 78388fc26d7..e31e1863368 100644 --- a/sys/dev/ic/fxp.c +++ b/sys/dev/ic/fxp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fxp.c,v 1.123 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: fxp.c,v 1.124 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: if_fxp.c,v 1.2 1997/06/05 02:01:55 thorpej Exp $ */ /* @@ -689,19 +689,22 @@ fxp_start(struct ifnet *ifp) txs = txs->tx_next; - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; if (bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map, m0, BUS_DMA_NOWAIT) != 0) { MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) + if (m == NULL) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } if (m0->m_pkthdr.len > MHLEN) { MCLGET(m, M_DONTWAIT); if (!(m->m_flags & M_EXT)) { m_freem(m); + ifq_deq_rollback(&ifp->if_snd, m0); break; } } @@ -710,11 +713,12 @@ fxp_start(struct ifnet *ifp) if (bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map, m, BUS_DMA_NOWAIT) != 0) { m_freem(m); + ifq_deq_rollback(&ifp->if_snd, m0); break; } } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m != NULL) { m_freem(m0); m0 = m; diff --git a/sys/dev/ic/gem.c b/sys/dev/ic/gem.c index 62cc2070bce..f00ada669fe 100644 --- a/sys/dev/ic/gem.c +++ b/sys/dev/ic/gem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gem.c,v 1.114 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: gem.c,v 1.115 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: gem.c,v 1.1 2001/09/16 00:11:43 eeh Exp $ */ /* @@ -1657,7 +1657,7 @@ gem_start(struct ifnet *ifp) return; while (sc->sc_txd[sc->sc_tx_prod].sd_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; @@ -1685,12 +1685,13 @@ gem_start(struct ifnet *ifp) if ((sc->sc_tx_cnt + map->dm_nsegs) > (GEM_NTXDESC - 2)) { bus_dmamap_unload(sc->sc_dmatag, map); + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } /* We are now committed to transmitting the packet. */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 /* @@ -1736,7 +1737,7 @@ gem_start(struct ifnet *ifp) return; drop: - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); ifp->if_oerrors++; } diff --git a/sys/dev/ic/hme.c b/sys/dev/ic/hme.c index 41da924046a..b946c441dfb 100644 --- a/sys/dev/ic/hme.c +++ b/sys/dev/ic/hme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hme.c,v 1.75 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: hme.c,v 1.76 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: hme.c,v 1.21 2001/07/07 15:59:37 thorpej Exp $ */ /*- @@ -644,7 +644,7 @@ hme_start(struct ifnet *ifp) return; while (sc->sc_txd[sc->sc_tx_prod].sd_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; @@ -672,12 +672,13 @@ hme_start(struct ifnet *ifp) if ((HME_TX_RING_SIZE - (sc->sc_tx_cnt + map->dm_nsegs)) < 5) { bus_dmamap_unload(sc->sc_dmatag, map); + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } /* We are now committed to transmitting the packet. */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); #if NBPFILTER > 0 /* @@ -732,7 +733,7 @@ hme_start(struct ifnet *ifp) return; drop: - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); ifp->if_oerrors++; } diff --git a/sys/dev/ic/lemac.c b/sys/dev/ic/lemac.c index 9b9a8bdcd18..c9c1078f1ed 100644 --- a/sys/dev/ic/lemac.c +++ b/sys/dev/ic/lemac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lemac.c,v 1.22 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: lemac.c,v 1.23 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: lemac.c,v 1.20 2001/06/13 10:46:02 wiz Exp $ */ /*- @@ -641,13 +641,14 @@ lemac_ifstart(struct ifnet *ifp) struct mbuf *m0; int tx_pg; - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC)) >= lemac_txmax) { sc->sc_cntrs.cntr_txfull++; + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } @@ -662,11 +663,12 @@ lemac_ifstart(struct ifnet *ifp) */ if (tx_pg == 0 || tx_pg > sc->sc_lastpage) { sc->sc_cntrs.cntr_txnospc++; + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); /* * The first four bytes of each transmit buffer are for diff --git a/sys/dev/ic/pgt.c b/sys/dev/ic/pgt.c index ef6c8174a31..aa35c109a6b 100644 --- a/sys/dev/ic/pgt.c +++ b/sys/dev/ic/pgt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pgt.c,v 1.79 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: pgt.c,v 1.80 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> @@ -2120,15 +2120,17 @@ pgt_start(struct ifnet *ifp) for (; sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_TX] < PGT_QUEUE_FULL_THRESHOLD && !IFQ_IS_EMPTY(&ifp->if_snd);) { pd = TAILQ_FIRST(&sc->sc_freeq[PGT_QUEUE_DATA_LOW_TX]); - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; if (m->m_pkthdr.len <= PGT_FRAG_SIZE) { error = pgt_load_tx_desc_frag(sc, PGT_QUEUE_DATA_LOW_TX, pd); - if (error) + if (error) { + ifq_deq_rollback(&ifp->if_snd, m); break; - IFQ_DEQUEUE(&ifp->if_snd, m); + } + ifq_deq_commit(&ifp->if_snd, m); m_copydata(m, 0, m->m_pkthdr.len, pd->pd_mem); pgt_desc_transmit(sc, PGT_QUEUE_DATA_LOW_TX, pd, m->m_pkthdr.len, 0); @@ -2142,8 +2144,10 @@ pgt_start(struct ifnet *ifp) * even support a full two.) */ if (sc->sc_dirtyq_count[PGT_QUEUE_DATA_LOW_TX] + 2 > - PGT_QUEUE_FULL_THRESHOLD) + PGT_QUEUE_FULL_THRESHOLD) { + ifq_deq_rollback(&ifp->if_snd, m); break; + } pd2 = TAILQ_NEXT(pd, pd_link); error = pgt_load_tx_desc_frag(sc, PGT_QUEUE_DATA_LOW_TX, pd); @@ -2157,9 +2161,11 @@ pgt_start(struct ifnet *ifp) pd_link); } } - if (error) + if (error) { + ifq_deq_rollback(&ifp->if_snd, m); break; - IFQ_DEQUEUE(&ifp->if_snd, m); + } + ifq_deq_commit(&ifp->if_snd, m); m_copydata(m, 0, PGT_FRAG_SIZE, pd->pd_mem); pgt_desc_transmit(sc, PGT_QUEUE_DATA_LOW_TX, pd, PGT_FRAG_SIZE, 1); @@ -2168,7 +2174,7 @@ pgt_start(struct ifnet *ifp) pgt_desc_transmit(sc, PGT_QUEUE_DATA_LOW_TX, pd2, m->m_pkthdr.len - PGT_FRAG_SIZE, 0); } else { - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); ifp->if_oerrors++; m_freem(m); m = NULL; diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index 7161304df00..2f0c2ca5c98 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.183 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: re.c,v 1.184 2015/11/20 03:35:22 dlg Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -1848,29 +1848,31 @@ re_start(struct ifnet *ifp) idx = sc->rl_ldata.rl_txq_prodidx; for (;;) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; if (sc->rl_ldata.rl_txq[idx].txq_mbuf != NULL) { KASSERT(idx == sc->rl_ldata.rl_txq_considx); + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } error = re_encap(sc, m, &idx); if (error != 0 && error != ENOBUFS) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } else if (error != 0) { - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); ifp->if_oerrors++; continue; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); queued++; #if NBPFILTER > 0 diff --git a/sys/dev/ic/rt2560.c b/sys/dev/ic/rt2560.c index e766fe3cb0a..75b69c79cb2 100644 --- a/sys/dev/ic/rt2560.c +++ b/sys/dev/ic/rt2560.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2560.c,v 1.74 2015/11/04 12:11:59 dlg Exp $ */ +/* $OpenBSD: rt2560.c,v 1.75 2015/11/20 03:35:22 dlg Exp $ */ /*- * Copyright (c) 2005, 2006 @@ -1948,15 +1948,16 @@ rt2560_start(struct ifnet *ifp) } else { if (ic->ic_state != IEEE80211_S_RUN) break; - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) { + ifq_deq_rollback(&ifp->if_snd, m0); ifp->if_flags |= IFF_OACTIVE; sc->sc_flags |= RT2560_DATA_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); #if NBPFILTER > 0 if (ifp->if_bpf != NULL) bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c index 55fed910a64..1fefe88c366 100644 --- a/sys/dev/ic/rt2661.c +++ b/sys/dev/ic/rt2661.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661.c,v 1.84 2015/11/04 12:11:59 dlg Exp $ */ +/* $OpenBSD: rt2661.c,v 1.85 2015/11/20 03:35:22 dlg Exp $ */ /*- * Copyright (c) 2006 @@ -1952,15 +1952,16 @@ rt2661_start(struct ifnet *ifp) } else { if (ic->ic_state != IEEE80211_S_RUN) break; - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; if (sc->txq[0].queued >= RT2661_TX_RING_COUNT - 1) { + ifq_deq_rollback(&ifp->if_snd, m0); /* there is no place left in this ring */ ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); #if NBPFILTER > 0 if (ifp->if_bpf != NULL) bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); diff --git a/sys/dev/ic/rtw.c b/sys/dev/ic/rtw.c index 07c66cb5dfb..ebf94678520 100644 --- a/sys/dev/ic/rtw.c +++ b/sys/dev/ic/rtw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtw.c,v 1.92 2015/11/04 12:11:59 dlg Exp $ */ +/* $OpenBSD: rtw.c,v 1.93 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: rtw.c,v 1.29 2004/12/27 19:49:16 dyoung Exp $ */ /*- @@ -2755,7 +2755,7 @@ rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp, *mp = NULL; - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) { DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame ready\n", __func__)); @@ -2764,12 +2764,13 @@ rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp, if (rtw_txring_choose(sc, tsbp, tdbp, RTW_TXPRIMD) == -1) { DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no descriptor\n", __func__)); + ifq_deq_rollback(&ifp->if_snd, m0); *if_flagsp |= IFF_OACTIVE; sc->sc_if.if_timer = 1; return 0; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m0 == NULL) { DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame/ring ready\n", __func__)); diff --git a/sys/dev/ic/smc83c170.c b/sys/dev/ic/smc83c170.c index c5cf4458a3d..8940373ec28 100644 --- a/sys/dev/ic/smc83c170.c +++ b/sys/dev/ic/smc83c170.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smc83c170.c,v 1.23 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: smc83c170.c,v 1.24 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: smc83c170.c,v 1.59 2005/02/27 00:27:02 perry Exp $ */ /*- @@ -352,7 +352,7 @@ epic_start(struct ifnet *ifp) /* * Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; m = NULL; @@ -380,12 +380,15 @@ epic_start(struct ifnet *ifp) bus_dmamap_unload(sc->sc_dmat, dmamap); MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) + if (m == NULL) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } if (m0->m_pkthdr.len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); + ifq_deq_rollback(&ifp->if_snd, m0); break; } } @@ -393,10 +396,12 @@ epic_start(struct ifnet *ifp) m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); - if (error) + if (error) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m != NULL) { m_freem(m0); m0 = m; diff --git a/sys/dev/ic/smc91cxx.c b/sys/dev/ic/smc91cxx.c index 22f13c0b086..6d36e9a75f0 100644 --- a/sys/dev/ic/smc91cxx.c +++ b/sys/dev/ic/smc91cxx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smc91cxx.c,v 1.42 2015/10/25 12:48:46 mpi Exp $ */ +/* $OpenBSD: smc91cxx.c,v 1.43 2015/11/20 03:35:22 dlg Exp $ */ /* $NetBSD: smc91cxx.c,v 1.11 1998/08/08 23:51:41 mycroft Exp $ */ /*- @@ -548,7 +548,7 @@ smc91cxx_start(ifp) /* * Peek at the next packet. */ - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) return; @@ -568,7 +568,7 @@ smc91cxx_start(ifp) if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) { printf("%s: large packet discarded\n", sc->sc_dev.dv_xname); ifp->if_oerrors++; - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); goto readcheck; } @@ -620,6 +620,7 @@ smc91cxx_start(ifp) ifp->if_timer = 5; ifp->if_flags |= IFF_OACTIVE; + ifq_deq_rollback(&ifp->if_snd, m); return; } @@ -645,7 +646,7 @@ smc91cxx_start(ifp) * Get the packet from the kernel. This will include the Ethernet * frame header, MAC address, etc. */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); /* * Push the packet out to the card. diff --git a/sys/dev/ic/ti.c b/sys/dev/ic/ti.c index e40dd748c25..fb49a965d6c 100644 --- a/sys/dev/ic/ti.c +++ b/sys/dev/ic/ti.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ti.c,v 1.19 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: ti.c,v 1.20 2015/11/20 03:35:22 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -1961,7 +1961,7 @@ ti_start(struct ifnet *ifp) prodidx = sc->ti_tx_saved_prodidx; while(sc->ti_cdata.ti_tx_chain[prodidx] == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; @@ -1976,12 +1976,13 @@ ti_start(struct ifnet *ifp) error = ti_encap_tigon2(sc, m_head, &prodidx); if (error) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); pkts++; /* diff --git a/sys/dev/isa/if_ef_isapnp.c b/sys/dev/isa/if_ef_isapnp.c index 62caa7f6d3d..cb004cea46e 100644 --- a/sys/dev/isa/if_ef_isapnp.c +++ b/sys/dev/isa/if_ef_isapnp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ef_isapnp.c,v 1.31 2015/10/25 13:13:06 mpi Exp $ */ +/* $OpenBSD: if_ef_isapnp.c,v 1.32 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1999 Jason L. Wright (jason@thought.net) @@ -243,7 +243,7 @@ efstart(ifp) return; startagain: - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) return; @@ -254,7 +254,7 @@ startagain: if (len + pad > ETHER_MAX_LEN) { ifp->if_oerrors++; - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); m_freem(m0); goto startagain; } @@ -262,6 +262,7 @@ startagain: if (bus_space_read_2(iot, ioh, EF_W1_FREE_TX) < len + pad + 4) { bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad) >> 2)); + ifq_deq_rollback(&ifp->if_snd, m0); ifp->if_flags |= IFF_OACTIVE; return; } else { @@ -277,7 +278,7 @@ startagain: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); #endif - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m0 == NULL) /* XXX not needed */ return; diff --git a/sys/dev/isa/if_ex.c b/sys/dev/isa/if_ex.c index 7c2d29a43f2..147dbcf27a8 100644 --- a/sys/dev/isa/if_ex.c +++ b/sys/dev/isa/if_ex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ex.c,v 1.41 2015/10/25 13:13:06 mpi Exp $ */ +/* $OpenBSD: if_ex.c,v 1.42 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1997, Donald A. Schmidt * Copyright (c) 1996, Javier Martín Rueda (jmrueda@diatel.upm.es) @@ -389,7 +389,7 @@ ex_start(struct ifnet *ifp) * more packets left, or the card cannot accept any more yet. */ while (!(ifp->if_flags & IFF_OACTIVE)) { - IFQ_POLL(&ifp->if_snd, opkt); + opkt = ifq_deq_begin(&ifp->if_snd); if (opkt == NULL) break; @@ -414,7 +414,7 @@ ex_start(struct ifnet *ifp) avail = -i; DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail);); if (avail >= len + XMT_HEADER_LEN) { - IFQ_DEQUEUE(&ifp->if_snd, opkt); + ifq_deq_commit(&ifp->if_snd, opkt); #ifdef EX_PSA_INTR /* @@ -519,6 +519,7 @@ ex_start(struct ifnet *ifp) ifp->if_opackets++; m_freem(opkt); } else { + ifq_deq_rollback(&ifp->if_snd, opkt); ifp->if_flags |= IFF_OACTIVE; DODEBUG(Status, printf("OACTIVE start\n");); } diff --git a/sys/dev/pci/if_bce.c b/sys/dev/pci/if_bce.c index 7c51e70c10e..1c5a5208753 100644 --- a/sys/dev/pci/if_bce.c +++ b/sys/dev/pci/if_bce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bce.c,v 1.47 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_bce.c,v 1.48 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_bce.c,v 1.3 2003/09/29 01:53:02 mrg Exp $ */ /* @@ -535,7 +535,7 @@ bce_start(struct ifnet *ifp) while (txsfree > 0) { /* Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + IFQ_DEQUEUE(&ifp->if_snd, m0); if (m0 == NULL) break; @@ -547,9 +547,6 @@ bce_start(struct ifnet *ifp) ctrl = m0->m_pkthdr.len & CTRL_BC_MASK; ctrl |= CTRL_SOF | CTRL_EOF | CTRL_IOC; - /* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */ - IFQ_DEQUEUE(&ifp->if_snd, m0); - #if NBPFILTER > 0 /* Pass the packet to any BPF listeners. */ if (ifp->if_bpf) diff --git a/sys/dev/pci/if_bnx.c b/sys/dev/pci/if_bnx.c index 051a3c592ae..e839c226a8b 100644 --- a/sys/dev/pci/if_bnx.c +++ b/sys/dev/pci/if_bnx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bnx.c,v 1.115 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_bnx.c,v 1.116 2015/11/20 03:35:23 dlg Exp $ */ /*- * Copyright (c) 2006 Broadcom Corporation @@ -5006,7 +5006,7 @@ bnx_start(struct ifnet *ifp) */ while (sc->used_tx_bd < sc->max_tx_bd) { /* Check for any frames to send. */ - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; @@ -5016,6 +5016,7 @@ bnx_start(struct ifnet *ifp) * for the NIC to drain the chain. */ if (bnx_tx_encap(sc, m_head)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; DBPRINT(sc, BNX_INFO_SEND, "TX chain is closed for " "business! Total tx_bd used = %d\n", @@ -5023,7 +5024,7 @@ bnx_start(struct ifnet *ifp) break; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); count++; #if NBPFILTER > 0 diff --git a/sys/dev/pci/if_cas.c b/sys/dev/pci/if_cas.c index 7334b390c3e..7035cae3964 100644 --- a/sys/dev/pci/if_cas.c +++ b/sys/dev/pci/if_cas.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cas.c,v 1.43 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_cas.c,v 1.44 2015/11/20 03:35:23 dlg Exp $ */ /* * @@ -1863,7 +1863,7 @@ cas_start(struct ifnet *ifp) bix = sc->sc_tx_prod; while (sc->sc_txd[bix].sd_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; @@ -1881,11 +1881,12 @@ cas_start(struct ifnet *ifp) * or fail... */ if (cas_encap(sc, m, &bix)) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); ifp->if_timer = 5; } diff --git a/sys/dev/pci/if_de.c b/sys/dev/pci/if_de.c index 7c5c31299de..16cef9fb3b1 100644 --- a/sys/dev/pci/if_de.c +++ b/sys/dev/pci/if_de.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_de.c,v 1.126 2015/11/04 00:10:50 dlg Exp $ */ +/* $OpenBSD: if_de.c,v 1.127 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_de.c,v 1.58 1998/01/12 09:39:58 thorpej Exp $ */ /*- @@ -3800,12 +3800,7 @@ tulip_txput(tulip_softc_t * const sc, struct mbuf *m, int notonqueue) int segcnt, freedescs; u_int32_t d_status; bus_dmamap_t map; - int error; struct ifnet *ifp = &sc->tulip_if; -#ifdef DIAGNOSTIC - struct mbuf *ombuf = m; -#endif - int compressed = 0; #if defined(TULIP_DEBUG) if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) { @@ -3858,47 +3853,24 @@ tulip_txput(tulip_softc_t * const sc, struct mbuf *m, int notonqueue) #endif goto finish; } - error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT); - if (error != 0) { - if (error == EFBIG) { - /* - * The packet exceeds the number of transmit buffer - * entries that we can use for one packet, so we have - * to recopy it into one mbuf and then try again. - */ - struct mbuf *tmp; - if (!notonqueue) { -#ifdef DIAGNOSTIC - if (IFQ_IS_EMPTY(&ifp->if_snd)) - panic("%s: if_snd queue empty", ifp->if_xname); -#endif - IFQ_DEQUEUE(&ifp->if_snd, tmp); -#ifdef DIAGNOSTIC - if (tmp != ombuf) - panic("tulip_txput: different mbuf dequeued!"); -#endif - } - compressed = 1; - m = tulip_mbuf_compress(m); - if (m == NULL) { -#if defined(TULIP_DEBUG) - sc->tulip_dbg.dbg_txput_finishes[2]++; -#endif - tulip_free_txmap(sc, map); - goto finish; - } - error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT); - } - if (error != 0) { - printf(TULIP_PRINTF_FMT ": unable to load tx map, " - "error = %d\n", TULIP_PRINTF_ARGS, error); -#if defined(TULIP_DEBUG) - sc->tulip_dbg.dbg_txput_finishes[3]++; -#endif - tulip_free_txmap(sc, map); - goto finish; - } + switch (bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT)) { + case 0: + break; + case EFBIG: + /* + * The packet exceeds the number of transmit buffer + * entries that we can use for one packet, so we have + * to recopy it into one mbuf and then try again. + */ + if (m_defrag(m, M_DONTWAIT) == 0 && + bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT) == 0) + break; + /* FALLTHROUGH */ + default: + tulip_free_txmap(sc, map); + goto finish; } + if ((freedescs -= (map->dm_nsegs + 1) / 2) <= 0 /* * See if there's any unclaimed space in the transmit ring. @@ -3949,19 +3921,8 @@ tulip_txput(tulip_softc_t * const sc, struct mbuf *m, int notonqueue) * The descriptors have been filled in. Now get ready * to transmit. */ - if (!compressed && !notonqueue) { - /* remove the mbuf from the queue */ - struct mbuf *tmp; -#ifdef DIAGNOSTIC - if (IFQ_IS_EMPTY(&ifp->if_snd)) - panic("%s: if_snd queue empty", ifp->if_xname); -#endif - IFQ_DEQUEUE(&ifp->if_snd, tmp); -#ifdef DIAGNOSTIC - if (tmp != ombuf) - panic("tulip_txput: different mbuf dequeued!"); -#endif - } + if (!notonqueue) + ifq_deq_commit(&ifp->if_snd, m); ml_enqueue(&sc->tulip_txq, m); m = NULL; @@ -4198,21 +4159,21 @@ tulip_ifstart(struct ifnet * const ifp) { TULIP_PERFSTART(ifstart) tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp); + struct mbuf *m, *m0; if (sc->tulip_if.if_flags & IFF_RUNNING) { if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) tulip_txput_setup(sc); - while (!IFQ_IS_EMPTY(&sc->tulip_if.if_snd)) { - struct mbuf *m, *m0; - IFQ_POLL(&sc->tulip_if.if_snd, m); + for (;;) { + m = ifq_deq_begin(&sc->tulip_if.if_snd); if (m == NULL) break; - if ((m0 = tulip_txput(sc, m, 0)) != NULL) { - if (m0 != m) - /* should not happen */ - printf("tulip_if_start: txput failed!\n"); + m0 = tulip_txput(sc, m, 0); + if (m0 != NULL) { + KASSERT(m == m0); + ifq_deq_rollback(&sc->tulip_if.if_snd, m); break; } } diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index f8d4b7d064e..31d7d2336d4 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em.c,v 1.310 2015/10/29 03:19:42 jsg Exp $ */ +/* $OpenBSD: if_em.c,v 1.311 2015/11/20 03:35:23 dlg Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -605,16 +605,17 @@ em_start(struct ifnet *ifp) } for (;;) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (em_encap(sc, m_head)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* Send a copy of the frame to the BPF listener */ diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c index 4c8a496c8b9..05480c89b76 100644 --- a/sys/dev/pci/if_ipw.c +++ b/sys/dev/pci/if_ipw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ipw.c,v 1.110 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_ipw.c,v 1.111 2015/11/20 03:35:23 dlg Exp $ */ /*- * Copyright (c) 2004-2008 @@ -1299,19 +1299,20 @@ ipw_start(struct ifnet *ifp) return; for (;;) { - IFQ_POLL(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->txfree < 1 + IPW_MAX_NSEG) { ifp->if_flags |= IFF_OACTIVE; break; } + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) + break; + #if NBPFILTER > 0 if (ifp->if_bpf != NULL) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif + m = ieee80211_encap(ifp, m, &ni); if (m == NULL) continue; diff --git a/sys/dev/pci/if_iwi.c b/sys/dev/pci/if_iwi.c index 3d93c2bca65..e24246400f0 100644 --- a/sys/dev/pci/if_iwi.c +++ b/sys/dev/pci/if_iwi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwi.c,v 1.127 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_iwi.c,v 1.128 2015/11/20 03:35:23 dlg Exp $ */ /*- * Copyright (c) 2004-2008 @@ -1389,15 +1389,15 @@ iwi_start(struct ifnet *ifp) return; for (;;) { - IFQ_POLL(&ifp->if_snd, m0); - if (m0 == NULL) - break; - - if (sc->txq[0].queued >= IWI_TX_RING_COUNT - 8) { + if (sc->txq[0].queued + IWI_MAX_NSEG + 2 >= IWI_TX_RING_COUNT) { ifp->if_flags |= IFF_OACTIVE; break; } + IFQ_DEQUEUE(&ifp->if_snd, m0); + if (m0 == NULL) + break; + #if NBPFILTER > 0 if (ifp->if_bpf != NULL) bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT); diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index 6d1c0fe1062..8f12f70bcf1 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ix.c,v 1.127 2015/11/04 00:20:35 dlg Exp $ */ +/* $OpenBSD: if_ix.c,v 1.128 2015/11/20 03:35:23 dlg Exp $ */ /****************************************************************************** @@ -378,16 +378,17 @@ ixgbe_start(struct ifnet * ifp) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); for (;;) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (ixgbe_encap(txr, m_head)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/pci/if_ixgb.c b/sys/dev/pci/if_ixgb.c index c9c524a2850..1f5282ab273 100644 --- a/sys/dev/pci/if_ixgb.c +++ b/sys/dev/pci/if_ixgb.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_ixgb.c,v 1.66 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_ixgb.c,v 1.67 2015/11/20 03:35:23 dlg Exp $ */ #include <dev/pci/if_ixgb.h> @@ -283,16 +283,17 @@ ixgb_start(struct ifnet *ifp) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); for (;;) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (ixgb_encap(sc, m_head)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* Send a copy of the frame to the BPF listener */ diff --git a/sys/dev/pci/if_lge.c b/sys/dev/pci/if_lge.c index 7e5a7138069..31fbe7b35c1 100644 --- a/sys/dev/pci/if_lge.c +++ b/sys/dev/pci/if_lge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lge.c,v 1.68 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_lge.c,v 1.69 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2000, 2001 @@ -956,17 +956,18 @@ lge_start(struct ifnet *ifp) if (CSR_READ_1(sc, LGE_TXCMDFREE_8BIT) == 0) break; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (lge_encap(sc, m_head, &idx)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); pkts++; #if NBPFILTER > 0 diff --git a/sys/dev/pci/if_lii.c b/sys/dev/pci/if_lii.c index 159b11912e5..ab8f9b97317 100644 --- a/sys/dev/pci/if_lii.c +++ b/sys/dev/pci/if_lii.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lii.c,v 1.38 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_lii.c,v 1.39 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2007 The NetBSD Foundation. @@ -798,12 +798,13 @@ lii_start(struct ifnet *ifp) return; for (;;) { - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; if (!sc->sc_free_tx_slots || lii_free_tx_space(sc) < m0->m_pkthdr.len) { + ifq_deq_rollback(&ifp->if_snd, m0); ifp->if_flags |= IFF_OACTIVE; break; } @@ -819,7 +820,7 @@ lii_start(struct ifnet *ifp) LII_WRITE_2(sc, LII_MB_TXD_WR_IDX, sc->sc_txd_cur/4); - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); #if NBPFILTER > 0 if (ifp->if_bpf != NULL) diff --git a/sys/dev/pci/if_msk.c b/sys/dev/pci/if_msk.c index 948c23ad786..d1d9339797b 100644 --- a/sys/dev/pci/if_msk.c +++ b/sys/dev/pci/if_msk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_msk.c,v 1.118 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_msk.c,v 1.119 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -1544,7 +1544,7 @@ msk_start(struct ifnet *ifp) DPRINTFN(2, ("msk_start\n")); while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; @@ -1554,12 +1554,13 @@ msk_start(struct ifnet *ifp) * for the NIC to drain the ring. */ if (msk_encap(sc_if, m_head, &idx)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); pkts++; /* diff --git a/sys/dev/pci/if_nep.c b/sys/dev/pci/if_nep.c index 84de99ea56b..0af16e780bf 100644 --- a/sys/dev/pci/if_nep.c +++ b/sys/dev/pci/if_nep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nep.c,v 1.20 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_nep.c,v 1.21 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2014, 2015 Mark Kettenis * @@ -1877,17 +1877,18 @@ nep_start(struct ifnet *ifp) idx = sc->sc_tx_prod; for (;;) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; if (sc->sc_tx_cnt >= (NEP_NTXDESC - NEP_NTXSEGS)) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } /* Now we are committed to transmit the packet. */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); if (nep_encap(sc, &m, &idx)) break; diff --git a/sys/dev/pci/if_nfe.c b/sys/dev/pci/if_nfe.c index b33bfc9a321..a59393dfc81 100644 --- a/sys/dev/pci/if_nfe.c +++ b/sys/dev/pci/if_nfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nfe.c,v 1.113 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_nfe.c,v 1.114 2015/11/20 03:35:23 dlg Exp $ */ /*- * Copyright (c) 2006, 2007 Damien Bergamini <damien.bergamini@free.fr> @@ -974,17 +974,18 @@ nfe_start(struct ifnet *ifp) return; for (;;) { - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; if (nfe_encap(sc, m0) != 0) { + ifq_deq_rollback(&ifp->if_snd, m0); ifp->if_flags |= IFF_OACTIVE; break; } /* packet put in h/w queue, remove from s/w queue */ - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); #if NBPFILTER > 0 if (ifp->if_bpf != NULL) diff --git a/sys/dev/pci/if_nge.c b/sys/dev/pci/if_nge.c index d573d5955df..f1c89ec918e 100644 --- a/sys/dev/pci/if_nge.c +++ b/sys/dev/pci/if_nge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nge.c,v 1.87 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_nge.c,v 1.88 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2000, 2001 @@ -1408,17 +1408,18 @@ nge_start(struct ifnet *ifp) return; while(sc->nge_ldata->nge_tx_list[idx].nge_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (nge_encap(sc, m_head, &idx)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); pkts++; #if NBPFILTER > 0 diff --git a/sys/dev/pci/if_nxe.c b/sys/dev/pci/if_nxe.c index ca16738ac2f..d75f414c01d 100644 --- a/sys/dev/pci/if_nxe.c +++ b/sys/dev/pci/if_nxe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_nxe.c,v 1.68 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_nxe.c,v 1.69 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -1322,17 +1322,18 @@ nxe_start(struct ifnet *ifp) bzero(txd, sizeof(struct nxe_tx_desc)); do { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; pkt = nxe_pkt_get(sc->sc_tx_pkts); if (pkt == NULL) { + ifq_deq_rollback(&ifp->if_snd, m); SET(ifp->if_flags, IFF_OACTIVE); break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); dmap = pkt->pkt_dmap; m = nxe_load_pkt(sc, dmap, m); diff --git a/sys/dev/pci/if_pcn.c b/sys/dev/pci/if_pcn.c index 9e8467253a2..2f970cce7eb 100644 --- a/sys/dev/pci/if_pcn.c +++ b/sys/dev/pci/if_pcn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pcn.c,v 1.38 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_pcn.c,v 1.39 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_pcn.c,v 1.26 2005/05/07 09:15:44 is Exp $ */ /* @@ -833,14 +833,16 @@ pcn_start(struct ifnet *ifp) */ for (;;) { /* Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; m = NULL; /* Get a work queue entry. */ - if (sc->sc_txsfree == 0) + if (sc->sc_txsfree == 0) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } txs = &sc->sc_txsoft[sc->sc_txsnext]; dmamap = txs->txs_dmamap; @@ -854,11 +856,14 @@ pcn_start(struct ifnet *ifp) if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) { MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) + if (m == NULL) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } if (m0->m_pkthdr.len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { + ifq_deq_rollback(&ifp->if_snd, m0); m_freem(m); break; } @@ -867,8 +872,10 @@ pcn_start(struct ifnet *ifp) m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); - if (error) + if (error) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } } /* @@ -892,10 +899,11 @@ pcn_start(struct ifnet *ifp) bus_dmamap_unload(sc->sc_dmat, dmamap); if (m != NULL) m_freem(m); + ifq_deq_rollback(&ifp->if_snd, m0); break; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); if (m != NULL) { m_freem(m0); m0 = m; diff --git a/sys/dev/pci/if_se.c b/sys/dev/pci/if_se.c index f1ebdc9ed3e..645b642ba1b 100644 --- a/sys/dev/pci/if_se.c +++ b/sys/dev/pci/if_se.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_se.c,v 1.14 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_se.c,v 1.15 2015/11/20 03:35:23 dlg Exp $ */ /*- * Copyright (c) 2009, 2010 Christopher Zimmermann <madroach@zakweb.de> @@ -1217,17 +1217,18 @@ se_start(struct ifnet *ifp) i = cd->se_tx_prod; while (cd->se_tx_mbuf[i] == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (se_encap(sc, m_head, &i) != 0) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); queued++; /* diff --git a/sys/dev/pci/if_sis.c b/sys/dev/pci/if_sis.c index 0127affd8ce..2538701bf71 100644 --- a/sys/dev/pci/if_sis.c +++ b/sys/dev/pci/if_sis.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sis.c,v 1.128 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_sis.c,v 1.129 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. @@ -1677,17 +1677,18 @@ sis_start(struct ifnet *ifp) return; while(sc->sis_ldata->sis_tx_list[idx].sis_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; if (sis_encap(sc, m_head, &idx)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); queued++; diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c index 1dba8e67a28..5abc88c1244 100644 --- a/sys/dev/pci/if_sk.c +++ b/sys/dev/pci/if_sk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sk.c,v 1.179 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_sk.c,v 1.180 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -1498,7 +1498,7 @@ sk_start(struct ifnet *ifp) DPRINTFN(2, ("sk_start\n")); while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) { - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) break; @@ -1508,12 +1508,13 @@ sk_start(struct ifnet *ifp) * for the NIC to drain the ring. */ if (sk_encap(sc_if, m_head, &idx)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; break; } /* now we are committed to transmit the packet */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); pkts++; /* diff --git a/sys/dev/pci/if_stge.c b/sys/dev/pci/if_stge.c index 5c6db61ba53..4deaa8598c6 100644 --- a/sys/dev/pci/if_stge.c +++ b/sys/dev/pci/if_stge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_stge.c,v 1.63 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_stge.c,v 1.64 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_stge.c,v 1.27 2005/05/16 21:35:32 bouyer Exp $ */ /*- @@ -482,7 +482,7 @@ stge_start(struct ifnet *ifp) /* * Grab a packet off the queue. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) break; @@ -490,8 +490,10 @@ stge_start(struct ifnet *ifp) * Leave one unused descriptor at the end of the * list to prevent wrapping completely around. */ - if (sc->sc_txpending == (STGE_NTXDESC - 1)) + if (sc->sc_txpending == (STGE_NTXDESC - 1)) { + ifq_deq_rollback(&ifp->if_snd, m0); break; + } /* * Get the last and next available transmit descriptor. @@ -517,17 +519,18 @@ stge_start(struct ifnet *ifp) printf("%s: Tx packet consumes too many " "DMA segments (%u), dropping...\n", sc->sc_dev.dv_xname, dmamap->dm_nsegs); - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); m_freem(m0); continue; } /* * Short on resources, just stop for now. */ + ifq_deq_rollback(&ifp->if_snd, m0); break; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); /* * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. diff --git a/sys/dev/pci/if_tht.c b/sys/dev/pci/if_tht.c index 4b4bf59af4e..d53d367a94c 100644 --- a/sys/dev/pci/if_tht.c +++ b/sys/dev/pci/if_tht.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tht.c,v 1.134 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_tht.c,v 1.135 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -1111,17 +1111,18 @@ tht_start(struct ifnet *ifp) tht_fifo_pre(sc, &sc->sc_txt); do { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; pkt = tht_pkt_get(&sc->sc_tx_list); if (pkt == NULL) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); if (tht_load_pkt(sc, pkt, m) != 0) { m_freem(m); tht_pkt_put(&sc->sc_tx_list, pkt); diff --git a/sys/dev/pci/if_txp.c b/sys/dev/pci/if_txp.c index 03724f54fe0..aeb5e940dd0 100644 --- a/sys/dev/pci/if_txp.c +++ b/sys/dev/pci/if_txp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_txp.c,v 1.118 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_txp.c,v 1.119 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2001 @@ -1282,7 +1282,7 @@ txp_start(struct ifnet *ifp) cnt = r->r_cnt; while (1) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; mnew = NULL; @@ -1307,7 +1307,7 @@ txp_start(struct ifnet *ifp) } m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, caddr_t)); mnew->m_pkthdr.len = mnew->m_len = m->m_pkthdr.len; - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); m = mnew; if (bus_dmamap_load_mbuf(sc->sc_dmat, sd->sd_map, m, @@ -1394,7 +1394,7 @@ txp_start(struct ifnet *ifp) * the packet. */ if (mnew == NULL) - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); ifp->if_timer = 5; @@ -1436,6 +1436,7 @@ txp_start(struct ifnet *ifp) oactive: bus_dmamap_unload(sc->sc_dmat, sd->sd_map); oactive1: + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; r->r_prod = firstprod; r->r_cnt = firstcnt; diff --git a/sys/dev/pci/if_vic.c b/sys/dev/pci/if_vic.c index 2a94fb30106..ad7bcefedbc 100644 --- a/sys/dev/pci/if_vic.c +++ b/sys/dev/pci/if_vic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vic.c,v 1.92 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_vic.c,v 1.93 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> @@ -1053,12 +1053,13 @@ vic_start(struct ifnet *ifp) break; } - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; idx = sc->sc_data->vd_tx_nextidx; if (idx >= sc->sc_data->vd_tx_length) { + ifq_deq_rollback(&ifp->if_snd, m); printf("%s: tx idx is corrupt\n", DEVNAME(sc)); ifp->if_oerrors++; break; @@ -1068,6 +1069,7 @@ vic_start(struct ifnet *ifp) txb = &sc->sc_txbuf[idx]; if (txb->txb_m != NULL) { + ifq_deq_rollback(&ifp->if_snd, m); printf("%s: tx ring is corrupt\n", DEVNAME(sc)); sc->sc_data->vd_tx_stopped = 1; ifp->if_oerrors++; @@ -1078,7 +1080,7 @@ vic_start(struct ifnet *ifp) * we're committed to sending it now. if we cant map it into * dma memory then we drop it. */ - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); if (vic_load_txb(sc, txb, m) != 0) { m_freem(m); ifp->if_oerrors++; diff --git a/sys/dev/pci/if_vio.c b/sys/dev/pci/if_vio.c index a844301d6ea..fa15a882002 100644 --- a/sys/dev/pci/if_vio.c +++ b/sys/dev/pci/if_vio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vio.c,v 1.34 2015/10/25 13:04:28 mpi Exp $ */ +/* $OpenBSD: if_vio.c,v 1.35 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. @@ -738,12 +738,13 @@ again: int slot, r; struct virtio_net_hdr *hdr; - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; r = virtio_enqueue_prep(vq, &slot); if (r == EAGAIN) { + ifq_deq_rollback(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } @@ -780,7 +781,7 @@ again: r = vio_encap(sc, slot, m); if (r != 0) { virtio_enqueue_abort(vq, slot); - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); m_freem(m); ifp->if_oerrors++; continue; @@ -790,11 +791,12 @@ again: if (r != 0) { bus_dmamap_unload(vsc->sc_dmat, sc->sc_tx_dmamaps[slot]); + ifq_deq_rollback(&ifp->if_snd, m); sc->sc_tx_mbufs[slot] = NULL; ifp->if_flags |= IFF_OACTIVE; break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); bus_dmamap_sync(vsc->sc_dmat, sc->sc_tx_dmamaps[slot], 0, sc->sc_tx_dmamaps[slot]->dm_mapsize, BUS_DMASYNC_PREWRITE); diff --git a/sys/dev/pci/if_xge.c b/sys/dev/pci/if_xge.c index d5e9963ce67..0d277c9af4d 100644 --- a/sys/dev/pci/if_xge.c +++ b/sys/dev/pci/if_xge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_xge.c,v 1.64 2015/11/14 17:54:57 mpi Exp $ */ +/* $OpenBSD: if_xge.c,v 1.65 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_xge.c,v 1.1 2005/09/09 10:30:27 ragge Exp $ */ /* @@ -1068,23 +1068,26 @@ xge_start(struct ifnet *ifp) par = lcr = 0; for (;;) { - IFQ_POLL(&ifp->if_snd, m); + m = ifq_deq_begin(&ifp->if_snd); if (m == NULL) break; /* out of packets */ - if (sc->sc_nexttx == sc->sc_lasttx) + if (sc->sc_nexttx == sc->sc_lasttx) { + ifq_deq_rollback(&ifp->if_snd, m); break; /* No more space */ + } nexttx = sc->sc_nexttx; dmp = sc->sc_txm[nexttx]; if ((error = bus_dmamap_load_mbuf(sc->sc_dmat, dmp, m, BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0) { + ifq_deq_rollback(&ifp->if_snd, m); printf("%s: bus_dmamap_load_mbuf error %d\n", XNAME, error); break; } - IFQ_DEQUEUE(&ifp->if_snd, m); + ifq_deq_commit(&ifp->if_snd, m); bus_dmamap_sync(sc->sc_dmat, dmp, 0, dmp->dm_mapsize, BUS_DMASYNC_PREWRITE); diff --git a/sys/dev/pcmcia/if_malo.c b/sys/dev/pcmcia/if_malo.c index 75f6e8c27c7..5a98cb117b2 100644 --- a/sys/dev/pcmcia/if_malo.c +++ b/sys/dev/pcmcia/if_malo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_malo.c,v 1.87 2015/11/11 10:07:25 mpi Exp $ */ +/* $OpenBSD: if_malo.c,v 1.88 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> @@ -996,7 +996,6 @@ cmalo_start(struct ifnet *ifp) if (m == NULL) return; - #if NBPFILTER > 0 if (ifp->if_bpf) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); diff --git a/sys/dev/pcmcia/if_xe.c b/sys/dev/pcmcia/if_xe.c index 96962d764c3..da87735a16c 100644 --- a/sys/dev/pcmcia/if_xe.c +++ b/sys/dev/pcmcia/if_xe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_xe.c,v 1.53 2015/10/25 13:13:06 mpi Exp $ */ +/* $OpenBSD: if_xe.c,v 1.54 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist, Brandon Creighton, Job de Haas @@ -1090,7 +1090,7 @@ xe_start(ifp) return; /* Peek at the next packet. */ - IFQ_POLL(&ifp->if_snd, m0); + m0 = ifq_deq_begin(&ifp->if_snd); if (m0 == NULL) return; @@ -1107,13 +1107,14 @@ xe_start(ifp) PAGE(sc, 0); space = bus_space_read_2(bst, bsh, offset + TSO0) & 0x7fff; if (len + pad + 2 > space) { + ifq_deq_rollback(&ifp->if_snd, m0); DPRINTF(XED_FIFO, ("%s: not enough space in output FIFO (%d > %d)\n", sc->sc_dev.dv_xname, len + pad + 2, space)); return; } - IFQ_DEQUEUE(&ifp->if_snd, m0); + ifq_deq_commit(&ifp->if_snd, m0); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c index f65900d2c73..78b906dd237 100644 --- a/sys/dev/usb/if_aue.c +++ b/sys/dev/usb/if_aue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_aue.c,v 1.101 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_aue.c,v 1.102 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_aue.c,v 1.82 2003/03/05 17:37:36 shiba Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -1244,16 +1244,17 @@ aue_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (aue_send(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* diff --git a/sys/dev/usb/if_axe.c b/sys/dev/usb/if_axe.c index 0f39523f49d..1912c057923 100644 --- a/sys/dev/usb/if_axe.c +++ b/sys/dev/usb/if_axe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_axe.c,v 1.133 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_axe.c,v 1.134 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org> @@ -1253,15 +1253,16 @@ axe_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (axe_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); /* * If there's a BPF listener, bounce a copy of this frame diff --git a/sys/dev/usb/if_axen.c b/sys/dev/usb/if_axen.c index 2e84cbe50b5..e02c06bf6fa 100644 --- a/sys/dev/usb/if_axen.c +++ b/sys/dev/usb/if_axen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_axen.c,v 1.17 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_axen.c,v 1.18 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2013 Yojiro UO <yuo@openbsd.org> @@ -1273,15 +1273,16 @@ axen_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (axen_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); /* * If there's a BPF listener, bounce a copy of this frame diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c index 596371f65ca..d8435a28d67 100644 --- a/sys/dev/usb/if_cdce.c +++ b/sys/dev/usb/if_cdce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cdce.c,v 1.66 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_cdce.c,v 1.67 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> @@ -389,16 +389,17 @@ cdce_start(struct ifnet *ifp) if (usbd_is_dying(sc->cdce_udev) || (ifp->if_flags & IFF_OACTIVE)) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (cdce_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/usb/if_cdcef.c b/sys/dev/usb/if_cdcef.c index 8b32dfec7fe..4f3c0a9e9d1 100644 --- a/sys/dev/usb/if_cdcef.c +++ b/sys/dev/usb/if_cdcef.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cdcef.c,v 1.38 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_cdcef.c,v 1.39 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org> @@ -277,7 +277,7 @@ cdcef_start(struct ifnet *ifp) if(ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd, m_head); if (m_head == NULL) { return; } @@ -287,17 +287,18 @@ cdcef_start(struct ifnet *ifp) * drop packet because receiver is not listening, * or if packet is larger than xmit buffer */ - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); m_freem(m_head); return; } if (cdcef_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c index e4c17ddb7c9..eb85e2bb574 100644 --- a/sys/dev/usb/if_cue.c +++ b/sys/dev/usb/if_cue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_cue.c,v 1.72 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_cue.c,v 1.73 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_cue.c,v 1.40 2002/07/11 21:14:26 augustss Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -887,16 +887,17 @@ cue_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (cue_send(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c index 5abe5cf9729..d8497babd1a 100644 --- a/sys/dev/usb/if_kue.c +++ b/sys/dev/usb/if_kue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_kue.c,v 1.81 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_kue.c,v 1.82 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_kue.c,v 1.50 2002/07/16 22:00:31 augustss Exp $ */ /* * Copyright (c) 1997, 1998, 1999, 2000 @@ -858,16 +858,17 @@ kue_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (kue_send(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* diff --git a/sys/dev/usb/if_mos.c b/sys/dev/usb/if_mos.c index 3d41c10a20e..beebf669e71 100644 --- a/sys/dev/usb/if_mos.c +++ b/sys/dev/usb/if_mos.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mos.c,v 1.32 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_mos.c,v 1.33 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net> @@ -1138,15 +1138,16 @@ mos_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (mos_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); /* * If there's a BPF listener, bounce a copy of this frame diff --git a/sys/dev/usb/if_smsc.c b/sys/dev/usb/if_smsc.c index aff4fd8732f..2c812bd70ea 100644 --- a/sys/dev/usb/if_smsc.c +++ b/sys/dev/usb/if_smsc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_smsc.c,v 1.21 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_smsc.c,v 1.22 2015/11/20 03:35:23 dlg Exp $ */ /* $FreeBSD: src/sys/dev/usb/net/if_smsc.c,v 1.1 2012/08/15 04:03:55 gonzo Exp $ */ /*- * Copyright (c) 2012 @@ -610,15 +610,16 @@ smsc_start(struct ifnet *ifp) return; } - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (smsc_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c index e4ddd0ad63d..ec0531eba92 100644 --- a/sys/dev/usb/if_udav.c +++ b/sys/dev/usb/if_udav.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_udav.c,v 1.73 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_udav.c,v 1.74 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_udav.c,v 1.3 2004/04/23 17:25:25 itojun Exp $ */ /* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */ /* @@ -918,16 +918,17 @@ udav_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (udav_send(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/usb/if_ugl.c b/sys/dev/usb/if_ugl.c index e7595880f4b..599c8dec796 100644 --- a/sys/dev/usb/if_ugl.c +++ b/sys/dev/usb/if_ugl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ugl.c,v 1.14 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_ugl.c,v 1.15 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_upl.c,v 1.19 2002/07/11 21:14:26 augustss Exp $ */ /* * Copyright (c) 2013 SASANO Takayoshi <uaa@uaa.org.uk> @@ -604,16 +604,17 @@ ugl_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (ugl_send(sc, m_head, 0)) { + ifq_deq_commit(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* diff --git a/sys/dev/usb/if_upl.c b/sys/dev/usb/if_upl.c index 87b37296e9c..2c58fa65fd8 100644 --- a/sys/dev/usb/if_upl.c +++ b/sys/dev/usb/if_upl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_upl.c,v 1.67 2015/06/30 13:54:42 mpi Exp $ */ +/* $OpenBSD: if_upl.c,v 1.68 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_upl.c,v 1.19 2002/07/11 21:14:26 augustss Exp $ */ /* * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -580,16 +580,17 @@ upl_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (upl_send(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 /* diff --git a/sys/dev/usb/if_url.c b/sys/dev/usb/if_url.c index a9a4cbe113c..a60397df06b 100644 --- a/sys/dev/usb/if_url.c +++ b/sys/dev/usb/if_url.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_url.c,v 1.76 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_url.c,v 1.77 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_url.c,v 1.6 2002/09/29 10:19:21 martin Exp $ */ /* * Copyright (c) 2001, 2002 @@ -791,16 +791,17 @@ url_start(struct ifnet *ifp) if (ifp->if_flags & IFF_OACTIVE) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (url_send(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 if (ifp->if_bpf) diff --git a/sys/dev/usb/if_urndis.c b/sys/dev/usb/if_urndis.c index 73036bc8ff5..3e6fa3634b8 100644 --- a/sys/dev/usb/if_urndis.c +++ b/sys/dev/usb/if_urndis.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_urndis.c,v 1.56 2015/10/25 12:11:56 mpi Exp $ */ +/* $OpenBSD: if_urndis.c,v 1.57 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org> @@ -1148,15 +1148,16 @@ urndis_start(struct ifnet *ifp) if (usbd_is_dying(sc->sc_udev) || (ifp->if_flags & IFF_OACTIVE)) return; - IFQ_POLL(&ifp->if_snd, m_head); + m_head = ifq_deq_begin(&ifp->if_snd); if (m_head == NULL) return; if (urndis_encap(sc, m_head, 0)) { + ifq_deq_rollback(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; return; } - IFQ_DEQUEUE(&ifp->if_snd, m_head); + ifq_deq_commit(&ifp->if_snd, m_head); /* * If there's a BPF listener, bounce a copy of this frame diff --git a/sys/net/hfsc.c b/sys/net/hfsc.c index 1b0f3752c94..05cd4f9e978 100644 --- a/sys/net/hfsc.c +++ b/sys/net/hfsc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hfsc.c,v 1.30 2015/11/09 01:06:31 dlg Exp $ */ +/* $OpenBSD: hfsc.c,v 1.31 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2012-2013 Henning Brauer <henning@openbsd.org> @@ -181,11 +181,11 @@ struct hfsc_class { */ struct hfsc_if { struct hfsc_if *hif_next; /* interface state list */ - struct ifqueue *hif_ifq; /* backpointer to ifq */ struct hfsc_class *hif_rootclass; /* root class */ struct hfsc_class *hif_defaultclass; /* default class */ struct hfsc_class **hif_class_tbl; - struct hfsc_class *hif_pollcache; /* cache for poll operation */ + + u_int64_t hif_microtime; /* time at deq_begin */ u_int hif_allocated; /* # of slots in hif_class_tbl */ u_int hif_classes; /* # of classes in the tree */ @@ -206,9 +206,8 @@ int hfsc_class_destroy(struct hfsc_if *, struct hfsc_class *); struct hfsc_class *hfsc_nextclass(struct hfsc_class *); -struct mbuf *hfsc_cl_dequeue(struct hfsc_class *); -struct mbuf *hfsc_cl_poll(struct hfsc_class *); -void hfsc_cl_purge(struct hfsc_if *, struct hfsc_class *); +void hfsc_cl_purge(struct hfsc_if *, struct hfsc_class *, + struct mbuf_list *); void hfsc_deferred(void *); void hfsc_update_cfmin(struct hfsc_class *); @@ -256,6 +255,30 @@ struct hfsc_class *hfsc_clh2cph(struct hfsc_if *, u_int32_t); struct pool hfsc_class_pl, hfsc_internal_sc_pl; +/* + * ifqueue glue. + */ + +void *hfsc_alloc(void *); +void hfsc_free(void *); +int hfsc_enq(struct ifqueue *, struct mbuf *); +struct mbuf *hfsc_deq_begin(struct ifqueue *, void **); +void hfsc_deq_commit(struct ifqueue *, struct mbuf *, void *); +void hfsc_deq_rollback(struct ifqueue *, struct mbuf *, void *); +void hfsc_purge(struct ifqueue *, struct mbuf_list *); + +const struct ifq_ops hfsc_ops = { + hfsc_alloc, + hfsc_free, + hfsc_enq, + hfsc_deq_begin, + hfsc_deq_commit, + hfsc_deq_rollback, + hfsc_purge, +}; + +const struct ifq_ops * const ifq_hfsc_ops = &hfsc_ops; + u_int64_t hfsc_microuptime(void) { @@ -296,64 +319,37 @@ hfsc_initialize(void) { pool_init(&hfsc_class_pl, sizeof(struct hfsc_class), 0, 0, PR_WAITOK, "hfscclass", NULL); + pool_setipl(&hfsc_class_pl, IPL_NONE); pool_init(&hfsc_internal_sc_pl, sizeof(struct hfsc_internal_sc), 0, 0, PR_WAITOK, "hfscintsc", NULL); + pool_setipl(&hfsc_internal_sc_pl, IPL_NONE); } -int -hfsc_attach(struct ifnet *ifp) +struct hfsc_if * +hfsc_pf_alloc(struct ifnet *ifp) { struct hfsc_if *hif; - if (ifp == NULL || ifp->if_snd.ifq_hfsc != NULL) - return (0); + KASSERT(ifp != NULL); - hif = malloc(sizeof(struct hfsc_if), M_DEVBUF, M_WAITOK | M_ZERO); + hif = malloc(sizeof(*hif), M_DEVBUF, M_WAITOK | M_ZERO); TAILQ_INIT(&hif->hif_eligible); hif->hif_class_tbl = mallocarray(HFSC_DEFAULT_CLASSES, sizeof(void *), M_DEVBUF, M_WAITOK | M_ZERO); hif->hif_allocated = HFSC_DEFAULT_CLASSES; - hif->hif_ifq = &ifp->if_snd; - ifp->if_snd.ifq_hfsc = hif; - timeout_set(&hif->hif_defer, hfsc_deferred, ifp); - /* XXX HRTIMER don't schedule it yet, only when some packets wait. */ - timeout_add(&hif->hif_defer, 1); - return (0); + return (hif); } int -hfsc_detach(struct ifnet *ifp) +hfsc_pf_addqueue(struct hfsc_if *hif, struct pf_queuespec *q) { - struct hfsc_if *hif; - - if (ifp == NULL) - return (0); - - hif = ifp->if_snd.ifq_hfsc; - timeout_del(&hif->hif_defer); - ifp->if_snd.ifq_hfsc = NULL; - - free(hif->hif_class_tbl, M_DEVBUF, hif->hif_allocated * sizeof(void *)); - free(hif, M_DEVBUF, sizeof(struct hfsc_if)); - - return (0); -} - -int -hfsc_addqueue(struct pf_queuespec *q) -{ - struct hfsc_if *hif; struct hfsc_class *cl, *parent; struct hfsc_sc rtsc, lssc, ulsc; - if (q->kif->pfik_ifp == NULL) - return (0); - - if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL) - return (EINVAL); + KASSERT(hif != NULL); if (q->parent_qid == HFSC_NULLCLASS_HANDLE && hif->hif_rootclass == NULL) @@ -386,61 +382,82 @@ hfsc_addqueue(struct pf_queuespec *q) } int -hfsc_delqueue(struct pf_queuespec *q) -{ - struct hfsc_if *hif; - struct hfsc_class *cl; - - if (q->kif->pfik_ifp == NULL) - return (0); - - if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL) - return (EINVAL); - - if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL) - return (EINVAL); - - return (hfsc_class_destroy(hif, cl)); -} - -int -hfsc_qstats(struct pf_queuespec *q, void *ubuf, int *nbytes) +hfsc_pf_qstats(struct pf_queuespec *q, void *ubuf, int *nbytes) { + struct ifnet *ifp = q->kif->pfik_ifp; struct hfsc_if *hif; struct hfsc_class *cl; struct hfsc_class_stats stats; int error = 0; - if (q->kif->pfik_ifp == NULL) - return (EBADF); - - if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL) + if (ifp == NULL) return (EBADF); - if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL) + if (*nbytes < sizeof(stats)) return (EINVAL); - if (*nbytes < sizeof(stats)) + hif = ifq_q_enter(&ifp->if_snd, ifq_hfsc_ops); + if (hif == NULL) + return (EBADF); + + if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL) { + ifq_q_leave(&ifp->if_snd, hif); return (EINVAL); + } hfsc_getclstats(&stats, cl); + ifq_q_leave(&ifp->if_snd, hif); if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0) return (error); + *nbytes = sizeof(stats); return (0); } void -hfsc_purge(struct ifqueue *ifq) +hfsc_pf_free(struct hfsc_if *hif) +{ + hfsc_free(hif); +} + +void * +hfsc_alloc(void *q) +{ + struct hfsc_if *hif = q; + KASSERT(hif != NULL); + + timeout_add(&hif->hif_defer, 1); + return (hif); +} + +void +hfsc_free(void *q) { - struct hfsc_if *hif = ifq->ifq_hfsc; + struct hfsc_if *hif = q; + int i; + + KERNEL_ASSERT_LOCKED(); + + timeout_del(&hif->hif_defer); + + i = hif->hif_allocated; + do + hfsc_class_destroy(hif, hif->hif_class_tbl[--i]); + while (i > 0); + + free(hif->hif_class_tbl, M_DEVBUF, hif->hif_allocated * sizeof(void *)); + free(hif, M_DEVBUF, sizeof(*hif)); +} + +void +hfsc_purge(struct ifqueue *ifq, struct mbuf_list *ml) +{ + struct hfsc_if *hif = ifq->ifq_q; struct hfsc_class *cl; for (cl = hif->hif_rootclass; cl != NULL; cl = hfsc_nextclass(cl)) - if (ml_len(&cl->cl_q.q) > 0) - hfsc_cl_purge(hif, cl); - hif->hif_ifq->ifq_len = 0; + hfsc_cl_purge(hif, cl, ml); } struct hfsc_class * @@ -555,9 +572,7 @@ hfsc_class_destroy(struct hfsc_if *hif, struct hfsc_class *cl) return (EBUSY); s = splnet(); - - if (ml_len(&cl->cl_q.q) > 0) - hfsc_cl_purge(hif, cl); + KASSERT(ml_empty(&cl->cl_q.q)); if (cl->cl_parent != NULL) { struct hfsc_class *p = cl->cl_parent->cl_children; @@ -624,9 +639,9 @@ hfsc_nextclass(struct hfsc_class *cl) } int -hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m) +hfsc_enq(struct ifqueue *ifq, struct mbuf *m) { - struct hfsc_if *hif = ifq->ifq_hfsc; + struct hfsc_if *hif = ifq->ifq_q; struct hfsc_class *cl; if ((cl = hfsc_clh2cph(hif, m->m_pkthdr.pf.qid)) == NULL || @@ -638,12 +653,12 @@ hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m) } if (ml_len(&cl->cl_q.q) >= cl->cl_q.qlimit) { - /* drop. mbuf needs to be freed */ + /* drop occurred. mbuf needs to be freed */ PKTCNTR_INC(&cl->cl_stats.drop_cnt, m->m_pkthdr.len); return (ENOBUFS); } + ml_enqueue(&cl->cl_q.q, m); - ifq->ifq_len++; m->m_pkthdr.pf.prio = IFQ_MAXPRIO; /* successfully queued. */ @@ -654,71 +669,68 @@ hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m) } struct mbuf * -hfsc_dequeue(struct ifqueue *ifq, int remove) +hfsc_deq_begin(struct ifqueue *ifq, void **cookiep) { - struct hfsc_if *hif = ifq->ifq_hfsc; + struct hfsc_if *hif = ifq->ifq_q; struct hfsc_class *cl, *tcl; struct mbuf *m; - int next_len, realtime = 0; u_int64_t cur_time; - if (IFQ_LEN(ifq) == 0) - return (NULL); - cur_time = hfsc_microuptime(); - if (remove && hif->hif_pollcache != NULL) { - cl = hif->hif_pollcache; - hif->hif_pollcache = NULL; - /* check if the class was scheduled by real-time criteria */ - if (cl->cl_rsc != NULL) - realtime = (cl->cl_e <= cur_time); - } else { + /* + * if there are eligible classes, use real-time criteria. + * find the class with the minimum deadline among + * the eligible classes. + */ + cl = hfsc_ellist_get_mindl(hif, cur_time); + if (cl == NULL) { /* - * if there are eligible classes, use real-time criteria. - * find the class with the minimum deadline among - * the eligible classes. + * use link-sharing criteria + * get the class with the minimum vt in the hierarchy */ - if ((cl = hfsc_ellist_get_mindl(hif, cur_time)) != NULL) { - realtime = 1; - } else { + cl = NULL; + tcl = hif->hif_rootclass; + + while (tcl != NULL && tcl->cl_children != NULL) { + tcl = hfsc_actlist_firstfit(tcl, cur_time); + if (tcl == NULL) + continue; + /* - * use link-sharing criteria - * get the class with the minimum vt in the hierarchy + * update parent's cl_cvtmin. + * don't update if the new vt is smaller. */ - cl = NULL; - tcl = hif->hif_rootclass; + if (tcl->cl_parent->cl_cvtmin < tcl->cl_vt) + tcl->cl_parent->cl_cvtmin = tcl->cl_vt; - while (tcl != NULL && tcl->cl_children != NULL) { - tcl = hfsc_actlist_firstfit(tcl, cur_time); - if (tcl == NULL) - continue; + cl = tcl; + } + /* XXX HRTIMER plan hfsc_deferred precisely here. */ + if (cl == NULL) + return (NULL); + } - /* - * update parent's cl_cvtmin. - * don't update if the new vt is smaller. - */ - if (tcl->cl_parent->cl_cvtmin < tcl->cl_vt) - tcl->cl_parent->cl_cvtmin = tcl->cl_vt; + m = ml_dequeue(&cl->cl_q.q); + KASSERT(m != NULL); - cl = tcl; - } - /* XXX HRTIMER plan hfsc_deferred precisely here. */ - if (cl == NULL) - return (NULL); - } + hif->hif_microtime = cur_time; + *cookiep = cl; + return (m); +} - if (!remove) { - hif->hif_pollcache = cl; - m = hfsc_cl_poll(cl); - return (m); - } - } +void +hfsc_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie) +{ + struct hfsc_if *hif = ifq->ifq_q; + struct hfsc_class *cl = cookie; + int next_len, realtime = 0; + u_int64_t cur_time = hif->hif_microtime; - if ((m = hfsc_cl_dequeue(cl)) == NULL) - panic("hfsc_dequeue"); + /* check if the class was scheduled by real-time criteria */ + if (cl->cl_rsc != NULL) + realtime = (cl->cl_e <= cur_time); - ifq->ifq_len--; PKTCNTR_INC(&cl->cl_stats.xmit_cnt, m->m_pkthdr.len); hfsc_update_vf(cl, m->m_pkthdr.len, cur_time); @@ -739,51 +751,49 @@ hfsc_dequeue(struct ifqueue *ifq, int remove) /* the class becomes passive */ hfsc_set_passive(hif, cl); } +} - return (m); +void +hfsc_deq_rollback(struct ifqueue *ifq, struct mbuf *m, void *cookie) +{ + struct hfsc_class *cl = cookie; + + ml_requeue(&cl->cl_q.q, m); } void hfsc_deferred(void *arg) { struct ifnet *ifp = arg; + struct hfsc_if *hif; int s; + KERNEL_ASSERT_LOCKED(); + KASSERT(HFSC_ENABLED(&ifp->if_snd)); + s = splnet(); - if (HFSC_ENABLED(&ifp->if_snd) && !IFQ_IS_EMPTY(&ifp->if_snd)) + if (!IFQ_IS_EMPTY(&ifp->if_snd)) if_start(ifp); splx(s); - /* XXX HRTIMER nearest virtual/fit time is likely less than 1/HZ. */ - timeout_add(&ifp->if_snd.ifq_hfsc->hif_defer, 1); -} - -struct mbuf * -hfsc_cl_dequeue(struct hfsc_class *cl) -{ - return (ml_dequeue(&cl->cl_q.q)); -} + hif = ifp->if_snd.ifq_q; -struct mbuf * -hfsc_cl_poll(struct hfsc_class *cl) -{ - /* XXX */ - return (cl->cl_q.q.ml_head); + /* XXX HRTIMER nearest virtual/fit time is likely less than 1/HZ. */ + timeout_add(&hif->hif_defer, 1); } void -hfsc_cl_purge(struct hfsc_if *hif, struct hfsc_class *cl) +hfsc_cl_purge(struct hfsc_if *hif, struct hfsc_class *cl, struct mbuf_list *ml) { struct mbuf *m; if (ml_empty(&cl->cl_q.q)) return; - while ((m = hfsc_cl_dequeue(cl)) != NULL) { + MBUF_LIST_FOREACH(&cl->cl_q.q, m) PKTCNTR_INC(&cl->cl_stats.drop_cnt, m->m_pkthdr.len); - m_freem(m); - hif->hif_ifq->ifq_len--; - } + + ml_enlist(ml, &cl->cl_q.q); hfsc_update_vf(cl, 0, 0); /* remove cl from the actlist */ hfsc_set_passive(hif, cl); @@ -1544,25 +1554,4 @@ hfsc_clh2cph(struct hfsc_if *hif, u_int32_t chandle) return (cl); return (NULL); } - -#else /* NPF > 0 */ - -void -hfsc_purge(struct ifqueue *q) -{ - panic("hfsc_purge called on hfsc-less kernel"); -} - -int -hfsc_enqueue(struct ifqueue *q, struct mbuf *m) -{ - panic("hfsc_enqueue called on hfsc-less kernel"); -} - -struct mbuf * -hfsc_dequeue(struct ifqueue *q, int i) -{ - panic("hfsc_enqueue called on hfsc-less kernel"); -} - #endif diff --git a/sys/net/hfsc.h b/sys/net/hfsc.h index ae746e50ad0..544d9df6259 100644 --- a/sys/net/hfsc.h +++ b/sys/net/hfsc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hfsc.h,v 1.10 2015/11/09 01:06:31 dlg Exp $ */ +/* $OpenBSD: hfsc.h,v 1.11 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2012-2013 Henning Brauer <henning@openbsd.org> @@ -112,19 +112,18 @@ struct ifqueue; struct pf_queuespec; struct hfsc_if; -#define HFSC_ENABLED(ifq) ((ifq)->ifq_hfsc != NULL) +extern const struct ifq_ops * const ifq_hfsc_ops; + +#define HFSC_ENABLED(ifq) ((ifq)->ifq_ops == ifq_hfsc_ops) #define HFSC_DEFAULT_QLIMIT 50 +struct hfsc_if *hfsc_pf_alloc(struct ifnet *); +int hfsc_pf_addqueue(struct hfsc_if *, struct pf_queuespec *); +void hfsc_pf_free(struct hfsc_if *); +int hfsc_pf_qstats(struct pf_queuespec *, void *, int *); + void hfsc_initialize(void); -int hfsc_attach(struct ifnet *); -int hfsc_detach(struct ifnet *); -void hfsc_purge(struct ifqueue *); -int hfsc_enqueue(struct ifqueue *, struct mbuf *); -struct mbuf *hfsc_dequeue(struct ifqueue *, int); u_int64_t hfsc_microuptime(void); -int hfsc_addqueue(struct pf_queuespec *); -int hfsc_delqueue(struct pf_queuespec *); -int hfsc_qstats(struct pf_queuespec *, void *, int *); #endif /* _KERNEL */ #endif /* _HFSC_H_ */ diff --git a/sys/net/if.c b/sys/net/if.c index 2f4d0399f6f..75b3e96b7f8 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.407 2015/11/18 13:58:02 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.408 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -397,9 +397,6 @@ if_attachsetup(struct ifnet *ifp) if_addgroup(ifp, IFG_ALL); - if (ifp->if_snd.ifq_maxlen == 0) - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - if_attachdomain(ifp); #if NPF > 0 pfi_attach_ifnet(ifp); @@ -510,6 +507,8 @@ if_attach_common(struct ifnet *ifp) TAILQ_INIT(&ifp->if_addrlist); TAILQ_INIT(&ifp->if_maddrlist); + ifq_init(&ifp->if_snd); + ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks), M_TEMP, M_WAITOK); TAILQ_INIT(ifp->if_addrhooks); @@ -538,7 +537,7 @@ if_start(struct ifnet *ifp) splassert(IPL_NET); - if (ifp->if_snd.ifq_len >= min(8, ifp->if_snd.ifq_maxlen) && + if (ifq_len(&ifp->if_snd) >= min(8, ifp->if_snd.ifq_maxlen) && !ISSET(ifp->if_flags, IFF_OACTIVE)) { if (ISSET(ifp->if_xflags, IFXF_TXREADY)) { TAILQ_REMOVE(&iftxlist, ifp, if_txlist); @@ -783,8 +782,6 @@ if_input_process(void *xmq) s = splnet(); while ((m = ml_dequeue(&ml)) != NULL) { - sched_pause(); - ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freem(m); @@ -942,6 +939,8 @@ if_detach(struct ifnet *ifp) if_idxmap_remove(ifp); splx(s); + + ifq_destroy(&ifp->if_snd); } /* @@ -2725,6 +2724,327 @@ niq_enlist(struct niqueue *niq, struct mbuf_list *ml) return (rv); } +/* + * send queues. + */ + +void *priq_alloc(void *); +void priq_free(void *); +int priq_enq(struct ifqueue *, struct mbuf *); +struct mbuf *priq_deq_begin(struct ifqueue *, void **); +void priq_deq_commit(struct ifqueue *, struct mbuf *, void *); +void priq_deq_rollback(struct ifqueue *, struct mbuf *, void *); +void priq_purge(struct ifqueue *, struct mbuf_list *); + +const struct ifq_ops priq_ops = { + priq_alloc, + priq_free, + priq_enq, + priq_deq_begin, + priq_deq_commit, + priq_deq_rollback, + priq_purge, +}; + +const struct ifq_ops * const ifq_priq_ops = &priq_ops; + +struct priq_list { + struct mbuf *head; + struct mbuf *tail; +}; + +struct priq { + struct priq_list pq_lists[IFQ_NQUEUES]; +}; + +void * +priq_alloc(void *null) +{ + return (malloc(sizeof(struct priq), M_DEVBUF, M_WAITOK | M_ZERO)); +} + +void +priq_free(void *pq) +{ + free(pq, M_DEVBUF, sizeof(struct priq)); +} + +int +priq_enq(struct ifqueue *ifq, struct mbuf *m) +{ + struct priq *pq; + struct priq_list *pl; + + if (ifq_len(ifq) >= ifq->ifq_maxlen) + return (ENOBUFS); + + pq = ifq->ifq_q; + KASSERT(m->m_pkthdr.pf.prio < IFQ_MAXPRIO); + pl = &pq->pq_lists[m->m_pkthdr.pf.prio]; + + m->m_nextpkt = NULL; + if (pl->tail == NULL) + pl->head = m; + else + pl->tail->m_nextpkt = m; + pl->tail = m; + + return (0); +} + +struct mbuf * +priq_deq_begin(struct ifqueue *ifq, void **cookiep) +{ + struct priq *pq = ifq->ifq_q; + struct priq_list *pl; + unsigned int prio = nitems(pq->pq_lists); + struct mbuf *m; + + do { + pl = &pq->pq_lists[--prio]; + m = pl->head; + if (m != NULL) { + *cookiep = pl; + return (m); + } + } while (prio > 0); + + return (NULL); +} + +void +priq_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie) +{ + struct priq_list *pl = cookie; + + KASSERT(pl->head == m); + + pl->head = m->m_nextpkt; + m->m_nextpkt = NULL; + + if (pl->head == NULL) + pl->tail = NULL; +} + +void +priq_deq_rollback(struct ifqueue *ifq, struct mbuf *m, void *cookie) +{ +#ifdef DIAGNOSTIC + struct priq_list *pl = cookie; + + KASSERT(pl->head == m); +#endif +} + +void +priq_purge(struct ifqueue *ifq, struct mbuf_list *ml) +{ + struct priq *pq = ifq->ifq_q; + struct priq_list *pl; + unsigned int prio = nitems(pq->pq_lists); + struct mbuf *m, *n; + + do { + pl = &pq->pq_lists[--prio]; + + for (m = pl->head; m != NULL; m = n) { + n = m->m_nextpkt; + ml_enqueue(ml, m); + } + + pl->head = pl->tail = NULL; + } while (prio > 0); +} + +int +ifq_enqueue_try(struct ifqueue *ifq, struct mbuf *m) +{ + int rv; + + mtx_enter(&ifq->ifq_mtx); + rv = ifq->ifq_ops->ifqop_enq(ifq, m); + if (rv == 0) + ifq->ifq_len++; + else + ifq->ifq_drops++; + mtx_leave(&ifq->ifq_mtx); + + return (rv); +} + +int +ifq_enq(struct ifqueue *ifq, struct mbuf *m) +{ + int err; + + err = ifq_enqueue_try(ifq, m); + if (err != 0) + m_freem(m); + + return (err); +} + +struct mbuf * +ifq_deq_begin(struct ifqueue *ifq) +{ + struct mbuf *m = NULL; + void *cookie; + + mtx_enter(&ifq->ifq_mtx); + if (ifq->ifq_len == 0 || + (m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie)) == NULL) { + mtx_leave(&ifq->ifq_mtx); + return (NULL); + } + + m->m_pkthdr.ph_cookie = cookie; + + return (m); +} + +void +ifq_deq_commit(struct ifqueue *ifq, struct mbuf *m) +{ + void *cookie; + + KASSERT(m != NULL); + cookie = m->m_pkthdr.ph_cookie; + + ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie); + ifq->ifq_len--; + mtx_leave(&ifq->ifq_mtx); +} + +void +ifq_deq_rollback(struct ifqueue *ifq, struct mbuf *m) +{ + void *cookie; + + KASSERT(m != NULL); + cookie = m->m_pkthdr.ph_cookie; + + ifq->ifq_ops->ifqop_deq_rollback(ifq, m, cookie); + mtx_leave(&ifq->ifq_mtx); +} + +struct mbuf * +ifq_deq(struct ifqueue *ifq) +{ + struct mbuf *m; + + m = ifq_deq_begin(ifq); + if (m == NULL) + return (NULL); + + ifq_deq_commit(ifq, m); + + return (m); +} + +unsigned int +ifq_purge(struct ifqueue *ifq) +{ + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + unsigned int rv; + + mtx_enter(&ifq->ifq_mtx); + ifq->ifq_ops->ifqop_purge(ifq, &ml); + rv = ifq->ifq_len; + ifq->ifq_len = 0; + ifq->ifq_drops += rv; + mtx_leave(&ifq->ifq_mtx); + + KASSERT(rv == ml_len(&ml)); + + ml_purge(&ml); + + return (rv); +} + +void +ifq_init(struct ifqueue *ifq) +{ + mtx_init(&ifq->ifq_mtx, IPL_NET); + ifq->ifq_drops = 0; + + /* default to priq */ + ifq->ifq_ops = &priq_ops; + ifq->ifq_q = priq_ops.ifqop_alloc(NULL); + + ifq->ifq_serializer = 0; + ifq->ifq_len = 0; + + if (ifq->ifq_maxlen == 0) + ifq_set_maxlen(ifq, IFQ_MAXLEN); +} + +void +ifq_attach(struct ifqueue *ifq, const struct ifq_ops *newops, void *opsarg) +{ + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + struct mbuf_list free_ml = MBUF_LIST_INITIALIZER(); + struct mbuf *m; + const struct ifq_ops *oldops; + void *newq, *oldq; + + newq = newops->ifqop_alloc(opsarg); + + mtx_enter(&ifq->ifq_mtx); + ifq->ifq_ops->ifqop_purge(ifq, &ml); + ifq->ifq_len = 0; + + oldops = ifq->ifq_ops; + oldq = ifq->ifq_q; + + ifq->ifq_ops = newops; + ifq->ifq_q = newq; + + while ((m = ml_dequeue(&ml)) != NULL) { + if (ifq->ifq_ops->ifqop_enq(ifq, m) != 0) { + ifq->ifq_drops++; + ml_enqueue(&free_ml, m); + } else + ifq->ifq_len++; + } + mtx_leave(&ifq->ifq_mtx); + + oldops->ifqop_free(oldq); + + ml_purge(&free_ml); +} + +void * +ifq_q_enter(struct ifqueue *ifq, const struct ifq_ops *ops) +{ + mtx_enter(&ifq->ifq_mtx); + if (ifq->ifq_ops == ops) + return (ifq->ifq_q); + + mtx_leave(&ifq->ifq_mtx); + + return (NULL); +} + +void +ifq_q_leave(struct ifqueue *ifq, void *q) +{ + KASSERT(q == ifq->ifq_q); + mtx_leave(&ifq->ifq_mtx); +} + +void +ifq_destroy(struct ifqueue *ifq) +{ + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + + /* don't need to lock because this is the last use of the ifq */ + + ifq->ifq_ops->ifqop_purge(ifq, &ml); + ifq->ifq_ops->ifqop_free(ifq->ifq_q); + + ml_purge(&ml); +} + __dead void unhandled_af(int af) { diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 6f0dff68a9d..948a0f0f296 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tun.c,v 1.159 2015/10/25 12:05:40 mpi Exp $ */ +/* $OpenBSD: if_tun.c,v 1.160 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */ /* @@ -685,10 +685,11 @@ tun_dev_ioctl(struct tun_softc *tp, u_long cmd, caddr_t data, int flag, tp->tun_flags &= ~TUN_ASYNC; break; case FIONREAD: - IFQ_POLL(&tp->tun_if.if_snd, m); - if (m != NULL) + m = ifq_deq_begin(&tp->tun_if.if_snd); + if (m != NULL) { *(int *)data = m->m_pkthdr.len; - else + ifq_deq_rollback(&tp->tun_if.if_snd, m); + } else *(int *)data = 0; break; case TIOCSPGRP: @@ -810,6 +811,14 @@ tun_dev_read(struct tun_softc *tp, struct uio *uio, int ioflag) } while (m0 == NULL); splx(s); + if (tp->tun_flags & TUN_LAYER2) { +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); +#endif + ifp->if_opackets++; + } + while (m0 != NULL && uio->uio_resid > 0 && error == 0) { len = min(uio->uio_resid, m0->m_len); if (len != 0) @@ -1007,7 +1016,7 @@ tun_dev_poll(struct tun_softc *tp, int events, struct proc *p) { int revents, s; struct ifnet *ifp; - struct mbuf *m; + unsigned int len; ifp = &tp->tun_if; revents = 0; @@ -1015,10 +1024,9 @@ tun_dev_poll(struct tun_softc *tp, int events, struct proc *p) TUNDEBUG(("%s: tunpoll\n", ifp->if_xname)); if (events & (POLLIN | POLLRDNORM)) { - IFQ_POLL(&ifp->if_snd, m); - if (m != NULL) { - TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname, - IFQ_LEN(ifp->if_snd))); + len = IFQ_LEN(&ifp->if_snd); + if (len > 0) { + TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname, len)); revents |= events & (POLLIN | POLLRDNORM); } else { TUNDEBUG(("%s: tunpoll waiting\n", ifp->if_xname)); @@ -1114,7 +1122,7 @@ filt_tunread(struct knote *kn, long hint) int s; struct tun_softc *tp; struct ifnet *ifp; - struct mbuf *m; + unsigned int len; if (kn->kn_status & KN_DETACHED) { kn->kn_data = 0; @@ -1125,10 +1133,10 @@ filt_tunread(struct knote *kn, long hint) ifp = &tp->tun_if; s = splnet(); - IFQ_POLL(&ifp->if_snd, m); - if (m != NULL) { + len = IFQ_LEN(&ifp->if_snd); + if (len > 0) { splx(s); - kn->kn_data = IFQ_LEN(&ifp->if_snd); + kn->kn_data = len; TUNDEBUG(("%s: tunkqread q=%d\n", ifp->if_xname, IFQ_LEN(&ifp->if_snd))); @@ -1175,21 +1183,11 @@ void tun_start(struct ifnet *ifp) { struct tun_softc *tp = ifp->if_softc; - struct mbuf *m; splassert(IPL_NET); - IFQ_POLL(&ifp->if_snd, m); - if (m != NULL) { - if (tp->tun_flags & TUN_LAYER2) { -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); -#endif - ifp->if_opackets++; - } + if (IFQ_LEN(&ifp->if_snd)) tun_wakeup(tp); - } } void diff --git a/sys/net/if_var.h b/sys/net/if_var.h index abc6af69dbc..470e5543f99 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_var.h,v 1.53 2015/11/18 13:58:02 mpi Exp $ */ +/* $OpenBSD: if_var.h,v 1.54 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -98,17 +98,33 @@ struct if_clone { { { 0 }, name, sizeof(name) - 1, create, destroy } /* - * Structure defining a queue for a network interface. + * Structure defining the send queue for a network interface. */ -struct ifqueue { - struct { - struct mbuf *head; - struct mbuf *tail; - } ifq_q[IFQ_NQUEUES]; - int ifq_len; - int ifq_maxlen; - int ifq_drops; - struct hfsc_if *ifq_hfsc; + +struct ifqueue; + +struct ifq_ops { + void *(*ifqop_alloc)(void *); + void (*ifqop_free)(void *); + int (*ifqop_enq)(struct ifqueue *, struct mbuf *); + struct mbuf *(*ifqop_deq_begin)(struct ifqueue *, void **); + void (*ifqop_deq_commit)(struct ifqueue *, + struct mbuf *, void *); + void (*ifqop_deq_rollback)(struct ifqueue *, + struct mbuf *, void *); + void (*ifqop_purge)(struct ifqueue *, + struct mbuf_list *); +}; + +struct ifqueue { + struct mutex ifq_mtx; + uint64_t ifq_drops; + const struct ifq_ops *ifq_ops; + void *ifq_q; + unsigned int ifq_len; + unsigned int ifq_serializer; + + unsigned int ifq_maxlen; }; /* @@ -256,121 +272,55 @@ struct ifg_list { }; #ifdef _KERNEL -#define IFQ_MAXLEN 256 -#define IFNET_SLOWHZ 1 /* granularity is 1 second */ - /* - * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1) - * input routines have queues of messages stored on ifqueue structures - * (defined above). Entries are added to and deleted from these structures - * by these macros, which should be called with ipl raised to splnet(). + * Interface send queues. */ -#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) -#define IF_DROP(ifq) ((ifq)->ifq_drops++) -#define IF_ENQUEUE(ifq, m) \ -do { \ - (m)->m_nextpkt = NULL; \ - if ((ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail == NULL) \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].head = m; \ - else \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail->m_nextpkt = m; \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail = m; \ - (ifq)->ifq_len++; \ -} while (/* CONSTCOND */0) -#define IF_PREPEND(ifq, m) \ -do { \ - (m)->m_nextpkt = (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].head; \ - if ((ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail == NULL) \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail = (m); \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].head = (m); \ - (ifq)->ifq_len++; \ -} while (/* CONSTCOND */0) -#define IF_POLL(ifq, m) \ -do { \ - int if_dequeue_prio = IFQ_MAXPRIO; \ - do { \ - (m) = (ifq)->ifq_q[if_dequeue_prio].head; \ - } while (!(m) && --if_dequeue_prio >= 0); \ -} while (/* CONSTCOND */0) +void ifq_init(struct ifqueue *); +void ifq_attach(struct ifqueue *, const struct ifq_ops *, void *); +void ifq_destroy(struct ifqueue *); +int ifq_enq_try(struct ifqueue *, struct mbuf *); +int ifq_enq(struct ifqueue *, struct mbuf *); +struct mbuf *ifq_deq_begin(struct ifqueue *); +void ifq_deq_commit(struct ifqueue *, struct mbuf *); +void ifq_deq_rollback(struct ifqueue *, struct mbuf *); +struct mbuf *ifq_deq(struct ifqueue *); +unsigned int ifq_purge(struct ifqueue *); +void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *); +void ifq_q_leave(struct ifqueue *, void *); + +#define ifq_len(_ifq) ((_ifq)->ifq_len) +#define ifq_empty(_ifq) (ifq_len(_ifq) == 0) +#define ifq_set_maxlen(_ifq, _l) ((_ifq)->ifq_maxlen = (_l)) + +extern const struct ifq_ops * const ifq_priq_ops; -#define IF_DEQUEUE(ifq, m) \ -do { \ - int if_dequeue_prio = IFQ_MAXPRIO; \ - do { \ - (m) = (ifq)->ifq_q[if_dequeue_prio].head; \ - if (m) { \ - if (((ifq)->ifq_q[if_dequeue_prio].head = \ - (m)->m_nextpkt) == NULL) \ - (ifq)->ifq_q[if_dequeue_prio].tail = NULL; \ - (m)->m_nextpkt = NULL; \ - (ifq)->ifq_len--; \ - } \ - } while (!(m) && --if_dequeue_prio >= 0); \ -} while (/* CONSTCOND */0) +#define IFQ_MAXLEN 256 +#define IFNET_SLOWHZ 1 /* granularity is 1 second */ -#define IF_PURGE(ifq) \ -do { \ - struct mbuf *__m0; \ - \ - for (;;) { \ - IF_DEQUEUE((ifq), __m0); \ - if (__m0 == NULL) \ - break; \ - else \ - m_freem(__m0); \ - } \ -} while (/* CONSTCOND */0) -#define IF_LEN(ifq) ((ifq)->ifq_len) -#define IF_IS_EMPTY(ifq) ((ifq)->ifq_len == 0) +/* + * IFQ compat on ifq API + */ #define IFQ_ENQUEUE(ifq, m, err) \ do { \ - if (HFSC_ENABLED(ifq)) \ - (err) = hfsc_enqueue(((struct ifqueue *)(ifq)), m); \ - else { \ - if (IF_QFULL((ifq))) { \ - (err) = ENOBUFS; \ - } else { \ - IF_ENQUEUE((ifq), (m)); \ - (err) = 0; \ - } \ - } \ - if ((err)) { \ - m_freem((m)); \ - (ifq)->ifq_drops++; \ - } \ + (err) = ifq_enq((ifq), (m)); \ } while (/* CONSTCOND */0) #define IFQ_DEQUEUE(ifq, m) \ do { \ - if (HFSC_ENABLED((ifq))) \ - (m) = hfsc_dequeue(((struct ifqueue *)(ifq)), 1); \ - else \ - IF_DEQUEUE((ifq), (m)); \ -} while (/* CONSTCOND */0) - -#define IFQ_POLL(ifq, m) \ -do { \ - if (HFSC_ENABLED((ifq))) \ - (m) = hfsc_dequeue(((struct ifqueue *)(ifq)), 0); \ - else \ - IF_POLL((ifq), (m)); \ + (m) = ifq_deq(ifq); \ } while (/* CONSTCOND */0) #define IFQ_PURGE(ifq) \ do { \ - if (HFSC_ENABLED((ifq))) \ - hfsc_purge(((struct ifqueue *)(ifq))); \ - else \ - IF_PURGE((ifq)); \ + (void)ifq_purge(ifq); \ } while (/* CONSTCOND */0) -#define IFQ_SET_READY(ifq) /* nothing */ - -#define IFQ_LEN(ifq) IF_LEN(ifq) -#define IFQ_IS_EMPTY(ifq) ((ifq)->ifq_len == 0) -#define IFQ_SET_MAXLEN(ifq, len) ((ifq)->ifq_maxlen = (len)) +#define IFQ_LEN(ifq) ifq_len(ifq) +#define IFQ_IS_EMPTY(ifq) ifq_empty(ifq) +#define IFQ_SET_MAXLEN(ifq, len) ifq_set_maxlen(ifq, len) +#define IFQ_SET_READY(ifq) do { } while (0) /* default interface priorities */ #define IF_WIRED_DEFAULT_PRIORITY 0 @@ -405,6 +355,7 @@ extern struct ifnet_head ifnet; extern unsigned int lo0ifidx; void if_start(struct ifnet *); +int if_enqueue_try(struct ifnet *, struct mbuf *); int if_enqueue(struct ifnet *, struct mbuf *); void if_input(struct ifnet *, struct mbuf_list *); int if_input_local(struct ifnet *, struct mbuf *, sa_family_t); diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c index 25bf59347d6..fdef0783f43 100644 --- a/sys/net/pf_if.c +++ b/sys/net/pf_if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_if.c,v 1.81 2015/10/30 11:33:55 mikeb Exp $ */ +/* $OpenBSD: pf_if.c,v 1.82 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright 2005 Henning Brauer <henning@openbsd.org> @@ -258,11 +258,6 @@ pfi_detach_ifnet(struct ifnet *ifp) hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie); pfi_kif_update(kif); - if (HFSC_ENABLED(&ifp->if_snd)) { - pf_remove_queues(ifp); - pf_free_queues(pf_queues_active, ifp); - } - kif->pfik_ifp = NULL; ifp->if_pf_kif = NULL; pfi_kif_unref(kif, PFI_KIF_REF_NONE); diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index 0709b8fb9ed..7d8d74f2435 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.291 2015/10/13 19:32:31 sashan Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.292 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -85,8 +85,10 @@ int pfclose(dev_t, int, int, struct proc *); int pfioctl(dev_t, u_long, caddr_t, int, struct proc *); int pf_begin_rules(u_int32_t *, const char *); int pf_rollback_rules(u_int32_t, char *); -int pf_create_queues(void); +int pf_enable_queues(void); +void pf_remove_queues(void); int pf_commit_queues(void); +void pf_free_queues(struct pf_queuehead *); int pf_setup_pfsync_matching(struct pf_ruleset *); void pf_hash_rule(MD5_CTX *, struct pf_rule *); void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *); @@ -517,68 +519,144 @@ pf_rollback_rules(u_int32_t ticket, char *anchor) /* queue defs only in the main ruleset */ if (anchor[0]) return (0); - return (pf_free_queues(pf_queues_inactive, NULL)); + + pf_free_queues(pf_queues_inactive); + + return (0); } -int -pf_free_queues(struct pf_queuehead *where, struct ifnet *ifp) +void +pf_free_queues(struct pf_queuehead *where) { struct pf_queuespec *q, *qtmp; TAILQ_FOREACH_SAFE(q, where, entries, qtmp) { - if (ifp && q->kif->pfik_ifp != ifp) - continue; TAILQ_REMOVE(where, q, entries); pfi_kif_unref(q->kif, PFI_KIF_REF_RULE); pool_put(&pf_queue_pl, q); } - return (0); } -int -pf_remove_queues(struct ifnet *ifp) +void +pf_remove_queues(void) { struct pf_queuespec *q; - int error = 0; - - /* remove queues */ - TAILQ_FOREACH_REVERSE(q, pf_queues_active, pf_queuehead, entries) { - if (ifp && q->kif->pfik_ifp != ifp) - continue; - if ((error = hfsc_delqueue(q)) != 0) - return (error); - } + struct ifnet *ifp; /* put back interfaces in normal queueing mode */ TAILQ_FOREACH(q, pf_queues_active, entries) { - if (ifp && q->kif->pfik_ifp != ifp) + if (q->parent_qid != 0) + continue; + + ifp = q->kif->pfik_ifp; + if (ifp == NULL) continue; - if (q->parent_qid == 0) - if ((error = hfsc_detach(q->kif->pfik_ifp)) != 0) - return (error); + + KASSERT(HFSC_ENABLED(&ifp->if_snd)); + + ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL); } +} - return (0); +struct pf_hfsc_queue { + struct ifnet *ifp; + struct hfsc_if *hif; + struct pf_hfsc_queue *next; +}; + +static inline struct pf_hfsc_queue * +pf_hfsc_ifp2q(struct pf_hfsc_queue *list, struct ifnet *ifp) +{ + struct pf_hfsc_queue *phq = list; + + while (phq != NULL) { + if (phq->ifp == ifp) + return (phq); + + phq = phq->next; + } + + return (phq); } int pf_create_queues(void) { struct pf_queuespec *q; - int error = 0; + struct ifnet *ifp; + struct pf_hfsc_queue *list = NULL, *phq; + int error; + + /* find root queues and alloc hfsc for these interfaces */ + TAILQ_FOREACH(q, pf_queues_active, entries) { + if (q->parent_qid != 0) + continue; + + ifp = q->kif->pfik_ifp; + if (ifp == NULL) + continue; + + phq = malloc(sizeof(*phq), M_TEMP, M_WAITOK); + phq->ifp = ifp; + phq->hif = hfsc_pf_alloc(ifp); - /* find root queues and attach hfsc to these interfaces */ - TAILQ_FOREACH(q, pf_queues_active, entries) - if (q->parent_qid == 0) - if ((error = hfsc_attach(q->kif->pfik_ifp)) != 0) - return (error); + phq->next = list; + list = phq; + } /* and now everything */ - TAILQ_FOREACH(q, pf_queues_active, entries) - if ((error = hfsc_addqueue(q)) != 0) - return (error); + TAILQ_FOREACH(q, pf_queues_active, entries) { + ifp = q->kif->pfik_ifp; + if (ifp == NULL) + continue; + + phq = pf_hfsc_ifp2q(list, ifp); + KASSERT(phq != NULL); + + error = hfsc_pf_addqueue(phq->hif, q); + if (error != 0) + goto error; + } + + /* find root queues in old list to disable them if necessary */ + TAILQ_FOREACH(q, pf_queues_inactive, entries) { + if (q->parent_qid != 0) + continue; + + ifp = q->kif->pfik_ifp; + if (ifp == NULL) + continue; + + phq = pf_hfsc_ifp2q(list, ifp); + if (phq != NULL) + continue; + + ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL); + } + + /* commit the new queues */ + while (list != NULL) { + phq = list; + list = phq->next; + + ifp = phq->ifp; + + ifq_attach(&ifp->if_snd, ifq_hfsc_ops, phq->hif); + free(phq, M_TEMP, sizeof(*phq)); + } return (0); + +error: + while (list != NULL) { + phq = list; + list = phq->next; + + hfsc_pf_free(phq->hif); + free(phq, M_TEMP, sizeof(*phq)); + } + + return (error); } int @@ -587,16 +665,21 @@ pf_commit_queues(void) struct pf_queuehead *qswap; int error; - if ((error = pf_remove_queues(NULL)) != 0) + /* swap */ + qswap = pf_queues_active; + pf_queues_active = pf_queues_inactive; + pf_queues_inactive = qswap; + + error = pf_create_queues(); + if (error != 0) { + pf_queues_inactive = pf_queues_active; + pf_queues_active = qswap; return (error); + } - /* swap */ - qswap = pf_queues_active; - pf_queues_active = pf_queues_inactive; - pf_queues_inactive = qswap; - pf_free_queues(pf_queues_inactive, NULL); + pf_free_queues(pf_queues_inactive); - return (pf_create_queues()); + return (0); } #define PF_MD5_UPD(st, elm) \ @@ -935,7 +1018,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) else { pf_status.running = 0; pf_status.since = time_second; - pf_remove_queues(NULL); + pf_remove_queues(); DPFPRINTF(LOG_NOTICE, "pf: stopped"); } break; @@ -1001,7 +1084,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } bcopy(qs, &pq->queue, sizeof(pq->queue)); - error = hfsc_qstats(qs, pq->buf, &nbytes); + error = hfsc_pf_qstats(qs, pq->buf, &nbytes); if (error == 0) pq->nbytes = nbytes; break; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index aad10865ed3..5c5a30e3879 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.422 2015/10/30 11:33:55 mikeb Exp $ */ +/* $OpenBSD: pfvar.h,v 1.423 2015/11/20 03:35:23 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1657,9 +1657,6 @@ extern struct pf_queuehead pf_queues[2]; extern struct pf_queuehead *pf_queues_active, *pf_queues_inactive; extern u_int32_t ticket_pabuf; -extern int pf_free_queues(struct pf_queuehead *, - struct ifnet *); -extern int pf_remove_queues(struct ifnet *); extern int pf_tbladdr_setup(struct pf_ruleset *, struct pf_addr_wrap *); extern void pf_tbladdr_remove(struct pf_addr_wrap *); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index f1f43ff8003..81bcdddacc5 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mbuf.h,v 1.202 2015/11/13 10:12:39 mpi Exp $ */ +/* $OpenBSD: mbuf.h,v 1.203 2015/11/20 03:35:23 dlg Exp $ */ /* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ /* @@ -392,6 +392,21 @@ struct mbstat { u_short m_mtypes[256]; /* type specific mbuf allocations */ }; +#include <sys/mutex.h> + +struct mbuf_list { + struct mbuf *ml_head; + struct mbuf *ml_tail; + u_int ml_len; +}; + +struct mbuf_queue { + struct mutex mq_mtx; + struct mbuf_list mq_list; + u_int mq_maxlen; + u_int mq_drops; +}; + #ifdef _KERNEL extern struct mbstat mbstat; @@ -474,14 +489,6 @@ struct m_tag *m_tag_next(struct mbuf *, struct m_tag *); * mbuf lists */ -#include <sys/mutex.h> - -struct mbuf_list { - struct mbuf *ml_head; - struct mbuf *ml_tail; - u_int ml_len; -}; - #define MBUF_LIST_INITIALIZER() { NULL, NULL, 0 } void ml_init(struct mbuf_list *); @@ -504,13 +511,6 @@ unsigned int ml_purge(struct mbuf_list *); * mbuf queues */ -struct mbuf_queue { - struct mutex mq_mtx; - struct mbuf_list mq_list; - u_int mq_maxlen; - u_int mq_drops; -}; - #define MBUF_QUEUE_INITIALIZER(_maxlen, _ipl) \ { MUTEX_INITIALIZER(_ipl), MBUF_LIST_INITIALIZER(), (_maxlen), 0 } |