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:
parent
4c7bc18993
commit
c2accd3411
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user