diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2009-03-29 01:02:36 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2009-03-29 01:02:36 +0000 |
commit | 39de1898b28cee31d6f85151bef7c97ed717c251 (patch) | |
tree | 8ed98d83694bebfb0168f325c95b4971f8bd4992 /sys | |
parent | d850dd2bb32de14e6aafe432fdc04f9468fb454c (diff) |
fix a small race in mfi_mgmt between the checking of a ccbs completion and
the sleep waiting for the completion. it is possible to get the interrupt
completing the command just before the tsleep, which will never get a
wakeup because the interrupt with the wakeup has already happened.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/mfi.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c index 6afdd503868..43e75445df2 100644 --- a/sys/dev/ic/mfi.c +++ b/sys/dev/ic/mfi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mfi.c,v 1.89 2009/02/16 21:19:06 miod Exp $ */ +/* $OpenBSD: mfi.c,v 1.90 2009/03/29 01:02:35 dlg Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * @@ -1163,6 +1163,7 @@ mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len, struct mfi_ccb *ccb; struct mfi_dcmd_frame *dcmd; int rv = 1; + int s; DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt %#x\n", DEVNAME(sc), opc); @@ -1199,11 +1200,13 @@ mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len, if (mfi_poll(ccb)) goto done; } else { + s = splbio(); mfi_post(sc, ccb); DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt sleeping\n", DEVNAME(sc)); while (ccb->ccb_state != MFI_CCB_DONE) tsleep(ccb, PRIBIO, "mfi_mgmt", 0); + splx(s); if (ccb->ccb_flags & MFI_CCB_F_ERR) goto done; |