diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2007-04-20 13:59:35 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2007-04-20 13:59:35 +0000 |
commit | 2930a1ebd7be5bf6d335a99b8883e5425b0e9443 (patch) | |
tree | c4dbcf48973e66de7230384fb28553b5c1991cc5 /sys/dev | |
parent | 5f54c56c238f7174ef82a202058cb52745d73b07 (diff) |
add a lock around ioctl handling to prevent the posssibility that someone
will try to bring the interface up in the middle of it being brought down.
im sleeping in tht_down while waiting for the tx fifos to drain, so its
possible something else can enter the ioctl handler while that's happening.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_tht.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/dev/pci/if_tht.c b/sys/dev/pci/if_tht.c index 286424ea608..e3e73ef7573 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.34 2007/04/20 13:46:40 dlg Exp $ */ +/* $OpenBSD: if_tht.c,v 1.35 2007/04/20 13:59:34 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -34,6 +34,7 @@ #include <sys/device.h> #include <sys/proc.h> #include <sys/queue.h> +#include <sys/rwlock.h> #include <machine/bus.h> @@ -326,6 +327,8 @@ struct tht_softc { struct tht_fifo sc_rxf; struct tht_fifo sc_rxd; struct tht_fifo sc_txf; + + struct rwlock sc_lock; }; int tht_match(struct device *, void *, void *); @@ -549,6 +552,7 @@ tht_attach(struct device *parent, struct device *self, void *aux) struct ifnet *ifp; sc->sc_thtc = csc; + rw_init(&sc->sc_lock, "thtioc"); if (bus_space_subregion(csc->sc_memt, csc->sc_memh, THT_PORT_REGION(taa->taa_port), THT_PORT_SIZE, @@ -629,13 +633,12 @@ tht_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) int error; int s; + rw_enter_write(&sc->sc_lock); s = splnet(); error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr); - if (error > 0) { - splx(s); - return (error); - } + if (error > 0) + goto err; switch (cmd) { case SIOCSIFADDR: @@ -669,7 +672,9 @@ tht_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) break; } +err: splx(s); + rw_exit_write(&sc->sc_lock); return (error); } |