Propagate CAM_DIS_DISCONNECT on through:

1. If we get frozen, unfreeze for disable disconnects.
2. Put CAM_DIS_DISCONNECT commands at the head of the work queue
(we have a target still connected and we can't run anything else
until this command completes).

If we had an error sending the last CTIO, unfreeze the queue anyway.
This commit is contained in:
Matt Jacob 2001-07-30 00:19:50 +00:00
parent 4c7bc18993
commit c2accd3411
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=80573

View File

@ -487,7 +487,8 @@ targbhstart(struct cam_periph *periph, union ccb *start_ccb)
desc = (struct targbh_cmd_desc *)atio->ccb_h.ccb_descr;
/* Is this a tagged request? */
flags = atio->ccb_h.flags & (CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
flags = atio->ccb_h.flags &
(CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
csio = &start_ccb->csio;
/*
@ -529,6 +530,19 @@ targbhstart(struct cam_periph *periph, union ccb *start_ccb)
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("Sending a CTIO\n"));
xpt_action(start_ccb);
/*
* If the queue was frozen waiting for the response
* to this ATIO (for instance disconnection was disallowed),
* then release it now that our response has been queued.
*/
if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) {
cam_release_devq(periph->path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
atio->ccb_h.status &= ~CAM_DEV_QFRZN;
}
s = splbio();
ccbh = TAILQ_FIRST(&softc->work_queue);
splx(s);
@ -556,6 +570,7 @@ targbhdone(struct cam_periph *periph, union ccb *done_ccb)
struct ccb_accept_tio *atio;
struct targbh_cmd_desc *descr;
u_int8_t *cdb;
int priority;
atio = &done_ccb->atio;
descr = (struct targbh_cmd_desc*)atio->ccb_h.ccb_descr;
@ -645,9 +660,16 @@ targbhdone(struct cam_periph *periph, union ccb *done_ccb)
}
/* Queue us up to receive a Continue Target I/O ccb. */
TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h,
periph_links.tqe);
xpt_schedule(periph, /*priority*/1);
if ((atio->ccb_h.flags & CAM_DIS_DISCONNECT) != 0) {
TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h,
periph_links.tqe);
priority = 0;
} else {
TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h,
periph_links.tqe);
priority = 1;
}
xpt_schedule(periph, priority);
break;
}
case XPT_CONT_TARGET_IO:
@ -672,7 +694,22 @@ targbhdone(struct cam_periph *periph, union ccb *done_ccb)
done_ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
done_ccb->ccb_h.status &= ~CAM_SENT_SENSE;
/* XXX Check for errors */
/*
* Any errors will not change the data we return,
* so make sure the queue is not left frozen.
* XXX - At some point there may be errors that
* leave us in a connected state with the
* initiator...
*/
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
printf("Releasing Queue\n");
cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
}
desc->data_resid -= desc->data_increment;
xpt_release_ccb(done_ccb);
if (softc->state != TARGBH_STATE_TEARDOWN) {
@ -696,11 +733,23 @@ targbhdone(struct cam_periph *periph, union ccb *done_ccb)
}
case XPT_IMMED_NOTIFY:
{
int frozen;
frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0;
if (softc->state == TARGBH_STATE_TEARDOWN
|| done_ccb->ccb_h.status == CAM_REQ_ABORTED) {
printf("Freed an immediate notify\n");
free(done_ccb, M_DEVBUF);
} else {
/* Requeue for another immediate event */
xpt_action(done_ccb);
}
if (frozen != 0)
cam_release_devq(periph->path,
/*relsim_flags*/0,
/*opening reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
break;
}
default: