diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2015-12-09 03:22:40 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2015-12-09 03:22:40 +0000 |
commit | 73edb8b2dbafe9653dcd8663aadb5b7afc1e13d2 (patch) | |
tree | 39101baaff466e2820fe429f168ca685c4adc35c /sys/dev/pci/if_myx.c | |
parent | 9be3316e1891b75e30eb2a619ce99010f78f04f6 (diff) |
rework the if_start mpsafe serialisation so it can serialise arbitrary work
work is represented by struct task.
the start routine is now wrapped by a task which is serialised by the
infrastructure. if_start_barrier has been renamed to ifq_barrier and
is now implemented as a task that gets serialised with the start
routine.
this also adds an ifq_restart() function. it serialises a call to
ifq_clr_oactive and calls the start routine again. it exists to
avoid a race that kettenis@ identified in between when a start
routine discovers theres no space left on a ring, and when it calls
ifq_set_oactive. if the txeof side of the driver empties the ring
and calls ifq_clr_oactive in between the above calls in start, the
queue will be marked oactive and the stack will never call the start
routine again.
by serialising the ifq_set_oactive call in the start routine and
ifq_clr_oactive calls we avoid that race.
tested on various nics
ok mpi@
Diffstat (limited to 'sys/dev/pci/if_myx.c')
-rw-r--r-- | sys/dev/pci/if_myx.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/sys/dev/pci/if_myx.c b/sys/dev/pci/if_myx.c index f1c98245fbb..56239c5c30f 100644 --- a/sys/dev/pci/if_myx.c +++ b/sys/dev/pci/if_myx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_myx.c,v 1.90 2015/12/03 12:45:56 dlg Exp $ */ +/* $OpenBSD: if_myx.c,v 1.91 2015/12/09 03:22:39 dlg Exp $ */ /* * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> @@ -1208,7 +1208,7 @@ myx_up(struct myx_softc *sc) ifq_clr_oactive(&ifp->if_snd); SET(ifp->if_flags, IFF_RUNNING); myx_iff(sc); - myx_start(ifp); + if_start(ifp); return; @@ -1330,6 +1330,8 @@ myx_down(struct myx_softc *sc) int s; int ring; + CLR(ifp->if_flags, IFF_RUNNING); + bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); sc->sc_linkdown = sts->ms_linkdown; @@ -1362,8 +1364,7 @@ myx_down(struct myx_softc *sc) } ifq_clr_oactive(&ifp->if_snd); - CLR(ifp->if_flags, IFF_RUNNING); - if_start_barrier(ifp); + ifq_barrier(&ifp->if_snd); for (ring = 0; ring < 2; ring++) { struct myx_rx_ring *mrr = &sc->sc_rx_ring[ring]; @@ -1702,9 +1703,8 @@ myx_txeof(struct myx_softc *sc, u_int32_t done_count) sc->sc_tx_ring_cons = idx; sc->sc_tx_cons = cons; - ifq_clr_oactive(&ifp->if_snd); - if (!ifq_empty(&ifp->if_snd)) - if_start(ifp); + if (ifq_is_oactive(&ifp->if_snd)) + ifq_restart(&ifp->if_snd); } void |