Module Name:    src
Committed By:   christos
Date:           Thu Mar 12 18:53:22 UTC 2015

Modified Files:
        src/sys/dev/ic: ciss.c

Log Message:
Untangle the poll/wait/timeout code in ciss_cmd() Tested on a DL-360.


To generate a diff of this commit:
cvs rdiff -u -r1.33 -r1.34 src/sys/dev/ic/ciss.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/ciss.c
diff -u src/sys/dev/ic/ciss.c:1.33 src/sys/dev/ic/ciss.c:1.34
--- src/sys/dev/ic/ciss.c:1.33	Thu Mar 12 11:33:10 2015
+++ src/sys/dev/ic/ciss.c	Thu Mar 12 14:53:22 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ciss.c,v 1.33 2015/03/12 15:33:10 christos Exp $	*/
+/*	$NetBSD: ciss.c,v 1.34 2015/03/12 18:53:22 christos Exp $	*/
 /*	$OpenBSD: ciss.c,v 1.68 2013/05/30 16:15:02 deraadt Exp $	*/
 
 /*
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.33 2015/03/12 15:33:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.34 2015/03/12 18:53:22 christos Exp $");
 
 #include "bio.h"
 
@@ -437,6 +437,97 @@ cissminphys(struct buf *bp)
 	minphys(bp);
 }
 
+static struct ciss_ccb *
+ciss_poll1(struct ciss_softc *sc)
+{
+	struct ciss_ccb *ccb;
+	uint32_t id;
+
+	if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem)) {
+		CISS_DPRINTF(CISS_D_CMD, ("N"));
+		return NULL;
+	}
+
+	if (sc->cfg.methods & CISS_METH_FIFO64) {
+		if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_HI) ==
+		    0xffffffff) {
+			CISS_DPRINTF(CISS_D_CMD, ("Q"));
+			return NULL;
+		}
+		id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_LO);
+	} else if (sc->cfg.methods & CISS_METH_FIFO64_RRO) {
+		id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_LO);
+		if (id == 0xffffffff) {
+			CISS_DPRINTF(CISS_D_CMD, ("Q"));
+			return NULL;
+		}
+		(void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ64_HI);
+	} else {
+		id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ);
+		if (id == 0xffffffff) {
+			CISS_DPRINTF(CISS_D_CMD, ("Q"));
+			return NULL;
+		}
+	}
+
+	CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
+	ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen);
+	ccb->ccb_cmd.id = htole32(id);
+	ccb->ccb_cmd.id_hi = htole32(0);
+	return ccb;
+}
+
+static int
+ciss_poll(struct ciss_softc *sc, struct ciss_ccb *ccb, int ms)
+{
+	struct ciss_ccb *ccb1;
+
+	ms /= 10;
+
+	while (ms-- > 0) {
+		DELAY(10);
+		ccb1 = ciss_poll1(sc);
+		if (ccb1 == NULL)
+			continue;
+		ciss_done(ccb1);
+		if (ccb1 == ccb)
+			return 0;
+	}
+
+	return ETIMEDOUT;
+}
+
+static int
+ciss_wait(struct ciss_softc *sc, struct ciss_ccb *ccb, int ms)
+{
+	int tohz, etick;
+
+	tohz = mstohz(ms);
+	if (tohz == 0)
+		tohz = 1;
+	etick = tick + tohz;
+
+	for (;;) {
+		ccb->ccb_state = CISS_CCB_POLL;
+		CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz));
+		mutex_enter(&sc->sc_mutex);
+		if (cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, tohz)
+		    == EWOULDBLOCK) {
+			mutex_exit(&sc->sc_mutex);
+			return EWOULDBLOCK;
+		}
+		mutex_exit(&sc->sc_mutex);
+		if (ccb->ccb_state == CISS_CCB_ONQ) {
+			ciss_done(ccb);
+			return 0;
+		}
+		tohz = etick - tick;
+		if (tohz <= 0)
+			return EWOULDBLOCK;
+		CISS_DPRINTF(CISS_D_CMD, ("T"));
+	}
+}
+
 /*
  * submit a command and optionally wait for completition.
  * wait arg abuses XS_CTL_POLL|XS_CTL_NOSLEEP flags to request
@@ -448,11 +539,9 @@ ciss_cmd(struct ciss_ccb *ccb, int flags
 {
 	struct ciss_softc *sc = ccb->ccb_sc;
 	struct ciss_cmd *cmd = &ccb->ccb_cmd;
-	struct ciss_ccb *ccb1;
 	bus_dmamap_t dmap = ccb->ccb_dmamap;
-	u_int32_t id;
 	u_int64_t addr;
-	int i, tohz, error = 0;
+	int i, error = 0;
 
 	if (ccb->ccb_state != CISS_CCB_READY) {
 		printf("%s: ccb %d not ready state=0x%x\n", device_xname(sc->sc_dev),
@@ -527,83 +616,18 @@ ciss_cmd(struct ciss_ccb *ccb, int flags
 		    ccb->ccb_cmdpa);
 
 	if (wait & XS_CTL_POLL) {
-		int etick;
+		int ms;
 		CISS_DPRINTF(CISS_D_CMD, ("waiting "));
 
-		i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000;
-		tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000);
-		if (tohz == 0)
-			tohz = 1;
-		for (i *= 100, etick = tick + tohz; i--; ) {
-			if (!(wait & XS_CTL_NOSLEEP)) {
-				ccb->ccb_state = CISS_CCB_POLL;
-				CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz));
-				mutex_enter(&sc->sc_mutex);
-				if (cv_timedwait(&sc->sc_condvar,
-				    &sc->sc_mutex, tohz) == EWOULDBLOCK) {
-					mutex_exit(&sc->sc_mutex);
-					break;
-				}
-				mutex_exit(&sc->sc_mutex);
-				if (ccb->ccb_state != CISS_CCB_ONQ) {
-					tohz = etick - tick;
-					if (tohz <= 0)
-						break;
-					CISS_DPRINTF(CISS_D_CMD, ("T"));
-					continue;
-				}
-				ccb1 = ccb;
-			} else {
-				DELAY(10);
-
-				if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
-				    CISS_ISR) & sc->iem)) {
-					CISS_DPRINTF(CISS_D_CMD, ("N"));
-					continue;
-				}
-
-				if (sc->cfg.methods & CISS_METH_FIFO64) {
-					if (bus_space_read_4(sc->sc_iot,
-					    sc->sc_ioh,
-					    CISS_OUTQ64_HI) == 0xffffffff) {
-						CISS_DPRINTF(CISS_D_CMD, ("Q"));
-						continue;
-					}
-					id = bus_space_read_4(sc->sc_iot,
-					    sc->sc_ioh, CISS_OUTQ64_LO);
-				} else if (sc->cfg.methods &
-				    CISS_METH_FIFO64_RRO) {
-					id = bus_space_read_4(sc->sc_iot,
-					    sc->sc_ioh, CISS_OUTQ64_LO);
-					if (id == 0xffffffff) {
-						CISS_DPRINTF(CISS_D_CMD, ("Q"));
-						continue;
-					}
-					(void)bus_space_read_4(sc->sc_iot,
-					    sc->sc_ioh, CISS_OUTQ64_HI);
-				} else {
-					id = bus_space_read_4(sc->sc_iot,
-					    sc->sc_ioh, CISS_OUTQ);
-					if (id == 0xffffffff) {
-						CISS_DPRINTF(CISS_D_CMD, ("Q"));
-						continue;
-					}
-				}
-
-				CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
-				ccb1 = (struct ciss_ccb *)
-					((char *)sc->ccbs + (id >> 2) * sc->ccblen);
-				ccb1->ccb_cmd.id = htole32(id);
-				ccb1->ccb_cmd.id_hi = htole32(0);
-			}
-
-			error = ciss_done(ccb1);
-			if (ccb1 == ccb)
-				break;
-		}
+		ms = ccb->ccb_xs ? ccb->ccb_xs->timeout : 60000;
+		if (wait & XS_CTL_NOSLEEP)
+			error = ciss_poll(sc, ccb, ms);
+		else
+			error = ciss_wait(sc, ccb, ms);
 
 		/* if never got a chance to be done above... */
 		if (ccb->ccb_state != CISS_CCB_FREE) {
+			KASSERT(error);
 			ccb->ccb_err.cmd_stat = CISS_ERR_TMO;
 			error = ciss_done(ccb);
 		}

Reply via email to