summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/cam_periph.c43
-rw-r--r--sys/cam/cam_periph.h1
2 files changed, 31 insertions, 13 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 091b96f..942a6c3 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -975,16 +975,6 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
PRELE(curproc);
}
-void
-cam_periph_ccbwait(union ccb *ccb)
-{
-
- if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
- || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
- xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp, PRIBIO,
- "cbwait", 0);
-}
-
int
cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr,
int (*error_routine)(union ccb *ccb,
@@ -1048,13 +1038,38 @@ cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr,
}
static void
+cam_periph_done_panic(struct cam_periph *periph, union ccb *done_ccb)
+{
+
+ panic("%s: already done with ccb %p", __func__, done_ccb);
+}
+
+static void
cam_periph_done(struct cam_periph *periph, union ccb *done_ccb)
{
/* Caller will release the CCB */
+ xpt_path_assert(done_ccb->ccb_h.path, MA_OWNED);
+ done_ccb->ccb_h.cbfcnp = cam_periph_done_panic;
wakeup(&done_ccb->ccb_h.cbfcnp);
}
+static void
+cam_periph_ccbwait(union ccb *ccb)
+{
+
+ if ((ccb->ccb_h.func_code & XPT_FC_QUEUED) != 0) {
+ while (ccb->ccb_h.cbfcnp != cam_periph_done_panic)
+ xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp,
+ PRIBIO, "cbwait", 0);
+ }
+ KASSERT(ccb->ccb_h.pinfo.index == CAM_UNQUEUED_INDEX &&
+ (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG,
+ ("%s: proceeding with incomplete ccb: ccb=%p, func_code=%#x, "
+ "status=%#x, index=%d", __func__, ccb, ccb->ccb_h.func_code,
+ ccb->ccb_h.status, ccb->ccb_h.pinfo.index));
+}
+
int
cam_periph_runccb(union ccb *ccb,
int (*error_routine)(union ccb *ccb,
@@ -1069,6 +1084,9 @@ cam_periph_runccb(union ccb *ccb,
starttime = NULL;
xpt_path_assert(ccb->ccb_h.path, MA_OWNED);
+ KASSERT((ccb->ccb_h.flags & CAM_UNLOCKED) == 0,
+ ("%s: ccb=%p, func_code=%#x, flags=%#x", __func__, ccb,
+ ccb->ccb_h.func_code, ccb->ccb_h.flags));
/*
* If the user has supplied a stats structure, and if we understand
@@ -1088,9 +1106,10 @@ cam_periph_runccb(union ccb *ccb,
cam_periph_ccbwait(ccb);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
error = 0;
- else if (error_routine != NULL)
+ else if (error_routine != NULL) {
+ ccb->ccb_h.cbfcnp = cam_periph_done;
error = (*error_routine)(ccb, camflags, sense_flags);
- else
+ } else
error = 0;
} while (error == ERESTART);
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
index e28d5b1..d5a74a5 100644
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -166,7 +166,6 @@ void cam_periph_unmapmem(union ccb *ccb,
struct cam_periph_map_info *mapinfo);
union ccb *cam_periph_getccb(struct cam_periph *periph,
u_int32_t priority);
-void cam_periph_ccbwait(union ccb *ccb);
int cam_periph_runccb(union ccb *ccb,
int (*error_routine)(union ccb *ccb,
cam_flags camflags,
OpenPOWER on IntegriCloud