you cant test a variable and then sleep on it without blocking
interrupts, cos a completion could change the variables state between
those two actions.
could anyone test setting a hotspare on ami(4) while doing io?
dlg
Index: ami.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/ami.c,v
retrieving revision 1.204
diff -u -p ami.c
--- ami.c 20 May 2010 00:55:17 -0000 1.204
+++ ami.c 31 May 2010 12:42:47 -0000
@@ -186,11 +186,8 @@ ami_remove_runq(struct ami_ccb *ccb)
splassert(IPL_BIO);
TAILQ_REMOVE(&ccb->ccb_sc->sc_ccb_runq, ccb, ccb_link);
- if (TAILQ_EMPTY(&ccb->ccb_sc->sc_ccb_runq)) {
- ccb->ccb_sc->sc_drained = 1;
- if (ccb->ccb_sc->sc_drainio)
- wakeup(ccb->ccb_sc);
- }
+ if (ccb->ccb_sc->sc_drainio && TAILQ_EMPTY(&ccb->ccb_sc->sc_ccb_runq))
+ wakeup(ccb->ccb_sc);
}
void
@@ -198,7 +195,6 @@ ami_insert_runq(struct ami_ccb *ccb)
{
splassert(IPL_BIO);
- ccb->ccb_sc->sc_drained = 0;
TAILQ_INSERT_TAIL(&ccb->ccb_sc->sc_ccb_runq, ccb, ccb_link);
}
@@ -539,7 +535,6 @@ ami_attach(struct ami_softc *sc)
/* error already printed */
goto free_mbox;
}
- sc->sc_drained = 1;
/* hack for hp netraid version encoding */
if ('A' <= sc->sc_fwver[2] && sc->sc_fwver[2] <= 'Z' &&
@@ -1016,7 +1011,6 @@ ami_runqueue(struct ami_softc *sc)
while ((ccb = TAILQ_FIRST(&sc->sc_ccb_preq)) != NULL) {
if (sc->sc_exec(sc, &ccb->ccb_cmd) != 0) {
- /* this is now raceable too with other incoming io */
timeout_add(&sc->sc_run_tmo, 1);
break;
}
@@ -1895,10 +1889,8 @@ ami_mgmt(struct ami_softc *sc, u_int8_t opcode, u_int8
goto err;
}
ccb->ccb_done = ami_done_ioctl;
- } else {
+ } else
ccb = sc->sc_mgmtccb;
- ccb->ccb_done = ami_done_dummy;
- }
if (size) {
if ((am = ami_allocmem(sc, size)) == NULL) {
@@ -1930,22 +1922,29 @@ ami_mgmt(struct ami_softc *sc, u_int8_t opcode, u_int8
if (opcode != AMI_CHSTATE) {
ami_start(sc, ccb);
+ s = splbio();
while (ccb->ccb_state != AMI_CCB_READY)
tsleep(ccb, PRIBIO,"ami_mgmt", 0);
+ splx(s);
} else {
/* change state must be run with id 0xfe and MUST be polled */
+ s = splbio();
sc->sc_drainio = 1;
- while (sc->sc_drained != 1)
+ while (!TAILQ_EMPTY(&sc->sc_ccb_runq)) {
if (tsleep(sc, PRIBIO, "ami_mgmt_drain", hz * 60) ==
EWOULDBLOCK) {
printf("%s: drain io timeout\n", DEVNAME(sc));
ccb->ccb_flags |= AMI_CCB_F_ERR;
goto restartio;
}
- ami_poll(sc, ccb);
+ }
+
+ error = sc->sc_poll(sc, &ccb->ccb_cmd);
+ if (error == -1)
+ ccb->ccb_flags |= AMI_CCB_F_ERR;
+
restartio:
/* restart io */
- s = splbio();
sc->sc_drainio = 0;
ami_runqueue(sc);
splx(s);
@@ -1966,7 +1965,6 @@ memerr:
} else {
ccb->ccb_flags = 0;
ccb->ccb_state = AMI_CCB_FREE;
- ccb->ccb_done = NULL;
}
err:
Index: amivar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/amivar.h,v
retrieving revision 1.54
diff -u -p amivar.h
--- amivar.h 28 Oct 2008 11:43:10 -0000 1.54
+++ amivar.h 31 May 2010 12:42:47 -0000
@@ -149,7 +149,6 @@ struct ami_softc {
char sc_plist[AMI_BIG_MAX_PDRIVES];
struct ami_ccb *sc_mgmtccb;
- int sc_drained;
int sc_drainio;
u_int8_t sc_drvinscnt;
};