From e8d26067d0142d9d16b066c2dfb8b54a3e5f7725 Mon Sep 17 00:00:00 2001 From: gibbs Date: Mon, 16 Aug 1999 22:22:41 +0000 Subject: Implement the guts of the XPT_ABORT function code. Clear residuals for XPT_TARGET_IO/XPT_CONT_TARGET_IO calls just as we do for XPT_SCSI_IO calls. Make xpt_release_devq a proper reciprocal of xpt_freeze_devq by allowing the caller to decrement the count more than once per call. Change the semantics of xpt_path_cmp to return 1 for a match with a wildcard from path1 and 2 for a match with wildcards from path2. This change doesn't affect most callers as they only check for >=0 (exact match or one containing a wildcard). When cleaning up a device node, ensure that there are no timeouts outstanding that reference it. --- sys/cam/cam_xpt.c | 142 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 111 insertions(+), 31 deletions(-) (limited to 'sys/cam/cam_xpt.c') diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index b56c50f..d5dfa30 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cam_xpt.c,v 1.65 1999/07/11 06:10:47 jmg Exp $ + * $Id: cam_xpt.c,v 1.66 1999/08/16 17:47:39 mjacob Exp $ */ #include #include @@ -592,6 +592,7 @@ static u_int bus_generation; #ifdef CAMDEBUG struct cam_path *cam_dpath; u_int32_t cam_dflags; +u_int32_t cam_debug_delay; #endif #if defined(CAM_DEBUG_FLAGS) && !defined(CAMDEBUG) @@ -643,6 +644,8 @@ static void xpt_run_dev_sendq(struct cam_eb *bus); static timeout_t xpt_release_devq_timeout; static timeout_t xpt_release_simq_timeout; static void xpt_release_bus(struct cam_eb *bus); +static void xpt_release_devq_device(struct cam_ed *dev, u_int count, + int run_queue); static struct cam_et* xpt_alloc_target(struct cam_eb *bus, target_id_t target_id); static void xpt_release_target(struct cam_eb *bus, struct cam_et *target); @@ -948,9 +951,6 @@ xptioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) } /* FALLTHROUGH */ case XPT_SCAN_LUN: - case XPT_RESET_DEV: - case XPT_ENG_INQ: /* XXX not implemented yet */ - case XPT_ENG_EXEC: ccb = xpt_alloc_ccb(); @@ -2762,17 +2762,18 @@ xpt_action(union ccb *start_ccb) start_ccb->ccb_h.target_lun << 5; } start_ccb->csio.scsi_status = SCSI_STATUS_OK; - start_ccb->csio.sense_resid = 0; - start_ccb->csio.resid = 0; CAM_DEBUG(path, CAM_DEBUG_CDB,("%s. CDB: %s\n", scsi_op_desc(start_ccb->csio.cdb_io.cdb_bytes[0], &path->device->inq_data), scsi_cdb_string(start_ccb->csio.cdb_io.cdb_bytes, cdb_str, sizeof(cdb_str)))); - /* FALLTRHOUGH */ + /* FALLTHROUGH */ } case XPT_TARGET_IO: case XPT_CONT_TARGET_IO: + start_ccb->csio.sense_resid = 0; + start_ccb->csio.resid = 0; + /* FALLTHROUGH */ case XPT_ENG_EXEC: { struct cam_path *path; @@ -2800,6 +2801,9 @@ xpt_action(union ccb *start_ccb) break; } case XPT_CALC_GEOMETRY: + { + struct cam_sim *sim; + /* Filter out garbage */ if (start_ccb->ccg.block_size == 0 || start_ccb->ccg.volume_size == 0) { @@ -2823,9 +2827,63 @@ xpt_action(union ccb *start_ccb) start_ccb->ccb_h.status = CAM_REQ_CMP; break; } - /* FALLTHROUGH */ #endif + sim = start_ccb->ccb_h.path->bus->sim; + (*(sim->sim_action))(sim, start_ccb); + break; + } case XPT_ABORT: + { + union ccb* abort_ccb; + int s; + + abort_ccb = start_ccb->cab.abort_ccb; + if (XPT_FC_IS_DEV_QUEUED(abort_ccb)) { + + if (abort_ccb->ccb_h.pinfo.index >= 0) { + struct cam_ccbq *ccbq; + + ccbq = &abort_ccb->ccb_h.path->device->ccbq; + cam_ccbq_remove_ccb(ccbq, abort_ccb); + abort_ccb->ccb_h.status = + CAM_REQ_ABORTED|CAM_DEV_QFRZN; + xpt_freeze_devq(abort_ccb->ccb_h.path, 1); + s = splcam(); + xpt_done(abort_ccb); + splx(s); + start_ccb->ccb_h.status = CAM_REQ_CMP; + break; + } + if (abort_ccb->ccb_h.pinfo.index == CAM_UNQUEUED_INDEX + && (abort_ccb->ccb_h.status & CAM_SIM_QUEUED) == 0) { + /* + * We've caught this ccb en route to + * the SIM. Flag it for abort and the + * SIM will do so just before starting + * real work on the CCB. + */ + abort_ccb->ccb_h.status = + CAM_REQ_ABORTED|CAM_DEV_QFRZN; + xpt_freeze_devq(abort_ccb->ccb_h.path, 1); + start_ccb->ccb_h.status = CAM_REQ_CMP; + break; + } + } + if (XPT_FC_IS_QUEUED(abort_ccb) + && (abort_ccb->ccb_h.pinfo.index == CAM_DONEQ_INDEX)) { + /* + * It's already completed but waiting + * for our SWI to get to it. + */ + start_ccb->ccb_h.status = CAM_UA_ABORT; + break; + } + /* + * If we weren't able to take care of the abort request + * in the XPT, pass the request down to the SIM for processing. + */ + /* FALLTHROUGH */ + } case XPT_RESET_DEV: case XPT_ACCEPT_TARGET_IO: case XPT_EN_LUN: @@ -3224,7 +3282,7 @@ xpt_action(union ccb *start_ccb) if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) { - xpt_release_devq(crs->ccb_h.path->device, + xpt_release_devq(crs->ccb_h.path, /*count*/1, /*run_queue*/TRUE); } start_ccb->crs.qfrozen_cnt = dev->qfrozen_cnt; @@ -3244,6 +3302,9 @@ xpt_action(union ccb *start_ccb) int s; s = splcam(); +#ifdef CAM_DEBUG_DELAY + cam_debug_delay = CAM_DEBUG_DELAY; +#endif cam_dflags = start_ccb->cdbg.flags; if (cam_dpath != NULL) { xpt_free_path(cam_dpath); @@ -3810,7 +3871,8 @@ xpt_free_path(struct cam_path *path) /* - * Return -1 for failure, 0 for exact match, 1 for match with wildcards. + * Return -1 for failure, 0 for exact match, 1 for match with wildcards + * in path1, 2 for match with wildcards in path2. */ int xpt_path_comp(struct cam_path *path1, struct cam_path *path2) @@ -3818,23 +3880,28 @@ xpt_path_comp(struct cam_path *path1, struct cam_path *path2) int retval = 0; if (path1->bus != path2->bus) { - if (path1->bus->path_id == CAM_BUS_WILDCARD - || path2->bus->path_id == CAM_BUS_WILDCARD) + if (path1->bus->path_id == CAM_BUS_WILDCARD) retval = 1; + else if (path2->bus->path_id == CAM_BUS_WILDCARD) + retval = 2; else return (-1); } if (path1->target != path2->target) { - if (path1->target->target_id == CAM_TARGET_WILDCARD - || path2->target->target_id == CAM_TARGET_WILDCARD) - retval = 1; + if (path1->target->target_id == CAM_TARGET_WILDCARD) { + if (retval == 0) + retval = 1; + } else if (path2->target->target_id == CAM_TARGET_WILDCARD) + retval = 2; else return (-1); } if (path1->device != path2->device) { - if (path1->device->lun_id == CAM_LUN_WILDCARD - || path2->device->lun_id == CAM_LUN_WILDCARD) - retval = 1; + if (path1->device->lun_id == CAM_LUN_WILDCARD) { + if (retval == 0) + retval = 1; + } else if (path2->device->lun_id == CAM_LUN_WILDCARD) + retval = 2; else return (-1); } @@ -4280,11 +4347,17 @@ xpt_release_devq_timeout(void *arg) device = (struct cam_ed *)arg; - xpt_release_devq(device, /*run_queue*/TRUE); + xpt_release_devq_device(device, /*count*/1, /*run_queue*/TRUE); } void -xpt_release_devq(struct cam_ed *dev, int run_queue) +xpt_release_devq(struct cam_path *path, u_int count, int run_queue) +{ + xpt_release_devq_device(path->device, count, run_queue); +} + +static void +xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue) { int rundevq; int s; @@ -4293,7 +4366,8 @@ xpt_release_devq(struct cam_ed *dev, int run_queue) s = splcam(); if (dev->qfrozen_cnt > 0) { - dev->qfrozen_cnt--; + count = (count > dev->qfrozen_cnt) ? dev->qfrozen_cnt : count; + dev->qfrozen_cnt -= count; if (dev->qfrozen_cnt == 0) { /* @@ -4620,6 +4694,11 @@ xpt_release_device(struct cam_eb *bus, struct cam_et *target, if (device->alloc_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX || device->send_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX) panic("Removing device while still queued for ccbs"); + + if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) + untimeout(xpt_release_devq_timeout, device, + device->c_handle); + TAILQ_REMOVE(&target->ed_entries, device,links); target->generation++; xpt_max_ccbs -= device->ccbq.devq_openings; @@ -5308,7 +5387,8 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) return; else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path->device, + xpt_release_devq(done_ccb->ccb_h.path, + /*count*/1, /*run_queue*/TRUE); } softc->action = PROBE_INQUIRY; @@ -5360,7 +5440,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) return; } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path->device, + xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, /*run_queue*/TRUE); } /* @@ -5401,8 +5481,8 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) return; } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path->device, - /*run_queue*/TRUE); + xpt_release_devq(done_ccb->ccb_h.path, + /*count*/1, /*run_queue*/TRUE); } xpt_release_ccb(done_ccb); free(mode_hdr, M_TEMP); @@ -5458,7 +5538,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) return; } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path->device, + xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, /*run_queue*/TRUE); } @@ -5522,7 +5602,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) case PROBE_TUR_FOR_NEGOTIATION: if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { /* Don't wedge the queue */ - xpt_release_devq(done_ccb->ccb_h.path->device, + xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, /*run_queue*/TRUE); } @@ -6095,8 +6175,8 @@ camisr(cam_isrq_t *queue) STAILQ_REMOVE_HEAD(hphead, xpt_links.stqe); - xpt_release_devq(send_ccb->ccb_h.path->device, - TRUE); + xpt_release_devq(send_ccb->ccb_h.path, + /*count*/1, /*runqueue*/TRUE); } } if ((ccb_h->func_code & XPT_FC_USER_CCB) == 0) { @@ -6115,7 +6195,7 @@ camisr(cam_isrq_t *queue) || ((dev->flags & CAM_DEV_REL_ON_QUEUE_EMPTY) != 0 && (dev->ccbq.dev_active == 0))) { - xpt_release_devq(ccb_h->path->device, + xpt_release_devq(ccb_h->path, /*count*/1, /*run_queue*/TRUE); } @@ -6136,7 +6216,7 @@ camisr(cam_isrq_t *queue) /*run_queue*/TRUE); } else if ((ccb_h->flags & CAM_DEV_QFRZDIS) && (ccb_h->status & CAM_DEV_QFRZN)) { - xpt_release_devq(ccb_h->path->device, + xpt_release_devq(ccb_h->path, /*count*/1, /*run_queue*/TRUE); ccb_h->status &= ~CAM_DEV_QFRZN; } else if (runq) { -- cgit v1.1