summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_myx.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-12-09 03:22:40 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-12-09 03:22:40 +0000
commit73edb8b2dbafe9653dcd8663aadb5b7afc1e13d2 (patch)
tree39101baaff466e2820fe429f168ca685c4adc35c /sys/dev/pci/if_myx.c
parent9be3316e1891b75e30eb2a619ce99010f78f04f6 (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.c14
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