MFprojects/camlock r248890, r248897, r248898, r248900, r248903, r248905,

r248917, r248918, r248978, r249001, r249014, r249030:

Remove multilevel freezing mechanism, implemented to handle specifics of
the ATA/SATA error recovery, when post-reset recovery commands should be
allocated when queues are already full of payload requests.  Instead of
removing frozen CCBs with specified range of priorities from the queue
to provide free openings, use simple hack, allowing explicit CCBs over-
allocation for requests with priority higher (numerically lower) then
CAM_PRIORITY_OOB threshold.

Simplify CCB allocation logic by removing SIM-level allocation queue.
After that SIM-level queue manages only CCBs execution, while allocation
logic is localized within each single device.

Suggested by:	gibbs
This commit is contained in:
Alexander Motin 2013-04-14 09:28:14 +00:00
parent 74dbdd24b9
commit cccf422080
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249466
15 changed files with 171 additions and 422 deletions

View File

@ -972,8 +972,6 @@ adaasync(void *callback_arg, u_int32_t code,
else else
break; break;
cam_periph_acquire(periph); cam_periph_acquire(periph);
cam_freeze_devq_arg(periph->path,
RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
xpt_schedule(periph, CAM_PRIORITY_DEV); xpt_schedule(periph, CAM_PRIORITY_DEV);
} }
default: default:
@ -1297,15 +1295,11 @@ adaregister(struct cam_periph *periph, void *arg)
cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) { cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) {
softc->state = ADA_STATE_RAHEAD; softc->state = ADA_STATE_RAHEAD;
cam_periph_acquire(periph); cam_periph_acquire(periph);
cam_freeze_devq_arg(periph->path,
RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
xpt_schedule(periph, CAM_PRIORITY_DEV); xpt_schedule(periph, CAM_PRIORITY_DEV);
} else if (ADA_WC >= 0 && } else if (ADA_WC >= 0 &&
cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) { cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) {
softc->state = ADA_STATE_WCACHE; softc->state = ADA_STATE_WCACHE;
cam_periph_acquire(periph); cam_periph_acquire(periph);
cam_freeze_devq_arg(periph->path,
RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
xpt_schedule(periph, CAM_PRIORITY_DEV); xpt_schedule(periph, CAM_PRIORITY_DEV);
} else } else
softc->state = ADA_STATE_NORMAL; softc->state = ADA_STATE_NORMAL;
@ -1587,8 +1581,6 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
if (softc->flags & ADA_FLAG_PACK_INVALID) { if (softc->flags & ADA_FLAG_PACK_INVALID) {
softc->state = ADA_STATE_NORMAL; softc->state = ADA_STATE_NORMAL;
xpt_release_ccb(start_ccb); xpt_release_ccb(start_ccb);
cam_release_devq(periph->path,
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
adaschedule(periph); adaschedule(periph);
cam_periph_release_locked(periph); cam_periph_release_locked(periph);
return; return;
@ -1612,6 +1604,7 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0); ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0);
start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE; start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE;
} }
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
xpt_action(start_ccb); xpt_action(start_ccb);
break; break;
} }
@ -1624,11 +1617,13 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
struct ada_softc *softc; struct ada_softc *softc;
struct ccb_ataio *ataio; struct ccb_ataio *ataio;
struct ccb_getdev *cgd; struct ccb_getdev *cgd;
struct cam_path *path;
softc = (struct ada_softc *)periph->softc; softc = (struct ada_softc *)periph->softc;
ataio = &done_ccb->ataio; ataio = &done_ccb->ataio;
path = done_ccb->ccb_h.path;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adadone\n")); CAM_DEBUG(path, CAM_DEBUG_TRACE, ("adadone\n"));
switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) { switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) {
case ADA_CCB_BUFFER_IO: case ADA_CCB_BUFFER_IO:
@ -1656,8 +1651,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
* XXX See if this is really a media * XXX See if this is really a media
* XXX change first? * XXX change first?
*/ */
xpt_print(periph->path, xpt_print(path, "Invalidating pack\n");
"Invalidating pack\n");
softc->flags |= ADA_FLAG_PACK_INVALID; softc->flags |= ADA_FLAG_PACK_INVALID;
} }
bp->bio_error = error; bp->bio_error = error;
@ -1670,7 +1664,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
bp->bio_flags |= BIO_ERROR; bp->bio_flags |= BIO_ERROR;
} }
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(done_ccb->ccb_h.path, cam_release_devq(path,
/*relsim_flags*/0, /*relsim_flags*/0,
/*reduction*/0, /*reduction*/0,
/*timeout*/0, /*timeout*/0,
@ -1711,9 +1705,12 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
{ {
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (adaerror(done_ccb, 0, 0) == ERESTART) { if (adaerror(done_ccb, 0, 0) == ERESTART) {
out:
/* Drop freeze taken due to CAM_DEV_QFREEZE */
cam_release_devq(path, 0, 0, 0, FALSE);
return; return;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
cam_release_devq(done_ccb->ccb_h.path, cam_release_devq(path,
/*relsim_flags*/0, /*relsim_flags*/0,
/*reduction*/0, /*reduction*/0,
/*timeout*/0, /*timeout*/0,
@ -1730,7 +1727,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
* operation. * operation.
*/ */
cgd = (struct ccb_getdev *)done_ccb; cgd = (struct ccb_getdev *)done_ccb;
xpt_setup_ccb(&cgd->ccb_h, periph->path, CAM_PRIORITY_NORMAL); xpt_setup_ccb(&cgd->ccb_h, path, CAM_PRIORITY_NORMAL);
cgd->ccb_h.func_code = XPT_GDEV_TYPE; cgd->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action((union ccb *)cgd); xpt_action((union ccb *)cgd);
if (ADA_WC >= 0 && if (ADA_WC >= 0 &&
@ -1738,12 +1735,12 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
softc->state = ADA_STATE_WCACHE; softc->state = ADA_STATE_WCACHE;
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, CAM_PRIORITY_DEV); xpt_schedule(periph, CAM_PRIORITY_DEV);
return; goto out;
} }
softc->state = ADA_STATE_NORMAL; softc->state = ADA_STATE_NORMAL;
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
cam_release_devq(periph->path, /* Drop freeze taken due to CAM_DEV_QFREEZE */
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); cam_release_devq(path, 0, 0, 0, FALSE);
adaschedule(periph); adaschedule(periph);
cam_periph_release_locked(periph); cam_periph_release_locked(periph);
return; return;
@ -1752,9 +1749,9 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
{ {
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (adaerror(done_ccb, 0, 0) == ERESTART) { if (adaerror(done_ccb, 0, 0) == ERESTART) {
return; goto out;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
cam_release_devq(done_ccb->ccb_h.path, cam_release_devq(path,
/*relsim_flags*/0, /*relsim_flags*/0,
/*reduction*/0, /*reduction*/0,
/*timeout*/0, /*timeout*/0,
@ -1772,8 +1769,8 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
* operation. * operation.
*/ */
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
cam_release_devq(periph->path, /* Drop freeze taken due to CAM_DEV_QFREEZE */
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE); cam_release_devq(path, 0, 0, 0, FALSE);
adaschedule(periph); adaschedule(periph);
cam_periph_release_locked(periph); cam_periph_release_locked(periph);
return; return;

View File

@ -249,12 +249,6 @@ proberegister(struct cam_periph *periph, void *arg)
return (status); return (status);
} }
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n")); CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n"));
/*
* Ensure nobody slip in until probe finish.
*/
cam_freeze_devq_arg(periph->path,
RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
probeschedule(periph); probeschedule(periph);
return(CAM_REQ_CMP); return(CAM_REQ_CMP);
} }
@ -661,6 +655,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
default: default:
panic("probestart: invalid action state 0x%x\n", softc->action); panic("probestart: invalid action state 0x%x\n", softc->action);
} }
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
xpt_action(start_ccb); xpt_action(start_ccb);
} }
@ -708,12 +703,15 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (cam_periph_error(done_ccb, if (cam_periph_error(done_ccb,
0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0, 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0,
NULL) == ERESTART) NULL) == ERESTART) {
out:
/* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
cam_release_devq(path, 0, 0, 0, FALSE);
return; return;
}
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE);
/*run_queue*/TRUE);
} }
status = done_ccb->ccb_h.status & CAM_STATUS_MASK; status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
if (softc->restart) { if (softc->restart) {
@ -768,7 +766,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE); PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
/* /*
@ -830,7 +828,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
} }
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
case PROBE_IDENTIFY: case PROBE_IDENTIFY:
{ {
@ -864,7 +862,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_SPINUP); PROBE_SET_ACTION(softc, PROBE_SPINUP);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
ident_buf = &path->device->ident_data; ident_buf = &path->device->ident_data;
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) { if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
@ -954,7 +952,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_SETMODE); PROBE_SET_ACTION(softc, PROBE_SETMODE);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
case PROBE_SPINUP: case PROBE_SPINUP:
if (bootverbose) if (bootverbose)
@ -963,7 +961,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_IDENTIFY); PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
case PROBE_SETMODE: case PROBE_SETMODE:
/* Set supported bits. */ /* Set supported bits. */
bzero(&cts, sizeof(cts)); bzero(&cts, sizeof(cts));
@ -1034,7 +1032,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_SETPM); PROBE_SET_ACTION(softc, PROBE_SETPM);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case PROBE_SETPM: case PROBE_SETPM:
@ -1045,7 +1043,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_SETAPST); PROBE_SET_ACTION(softc, PROBE_SETAPST);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case PROBE_SETAPST: case PROBE_SETAPST:
@ -1055,7 +1053,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_SETDMAAA); PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case PROBE_SETDMAAA: case PROBE_SETDMAAA:
@ -1065,7 +1063,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_SETAN); PROBE_SET_ACTION(softc, PROBE_SETAN);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case PROBE_SETAN: case PROBE_SETAN:
@ -1077,15 +1075,14 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
} }
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
case PROBE_SET_MULTI: case PROBE_SET_MULTI:
if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
path->device->flags &= ~CAM_DEV_UNCONFIGURED; path->device->flags &= ~CAM_DEV_UNCONFIGURED;
xpt_acquire_device(path->device); xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb); xpt_action(done_ccb);
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, xpt_async(AC_FOUND_DEVICE, path, done_ccb);
done_ccb);
} }
PROBE_SET_ACTION(softc, PROBE_DONE); PROBE_SET_ACTION(softc, PROBE_DONE);
break; break;
@ -1118,7 +1115,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
ata_device_transport(path); ata_device_transport(path);
@ -1127,7 +1124,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
xpt_acquire_device(path->device); xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb); xpt_action(done_ccb);
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb); xpt_async(AC_FOUND_DEVICE, path, done_ccb);
} }
PROBE_SET_ACTION(softc, PROBE_DONE); PROBE_SET_ACTION(softc, PROBE_DONE);
break; break;
@ -1145,7 +1142,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
PROBE_SET_ACTION(softc, PROBE_PM_PRV); PROBE_SET_ACTION(softc, PROBE_PM_PRV);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
case PROBE_PM_PRV: case PROBE_PM_PRV:
softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) + softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) +
(done_ccb->ataio.res.lba_mid << 16) + (done_ccb->ataio.res.lba_mid << 16) +
@ -1200,12 +1197,11 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
xpt_acquire_device(path->device); xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb); xpt_action(done_ccb);
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, xpt_async(AC_FOUND_DEVICE, path, done_ccb);
done_ccb);
} else { } else {
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb); xpt_action(done_ccb);
xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb); xpt_async(AC_SCSI_AEN, path, done_ccb);
} }
PROBE_SET_ACTION(softc, PROBE_DONE); PROBE_SET_ACTION(softc, PROBE_DONE);
break; break;
@ -1250,8 +1246,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
xpt_acquire_device(path->device); xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb); xpt_action(done_ccb);
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, xpt_async(AC_FOUND_DEVICE, path, done_ccb);
done_ccb);
} }
PROBE_SET_ACTION(softc, PROBE_DONE); PROBE_SET_ACTION(softc, PROBE_DONE);
break; break;
@ -1263,7 +1258,7 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
softc->restart = 0; softc->restart = 0;
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
probeschedule(periph); probeschedule(periph);
return; goto out;
} }
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
@ -1273,9 +1268,9 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR;
xpt_done(done_ccb); xpt_done(done_ccb);
} }
/* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
cam_release_devq(path, 0, 0, 0, FALSE);
cam_periph_invalidate(periph); cam_periph_invalidate(periph);
cam_release_devq(periph->path,
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
cam_periph_release_locked(periph); cam_periph_release_locked(periph);
} }

View File

@ -80,10 +80,9 @@ typedef struct {
#define CAM_PRIORITY_BUS ((CAM_RL_BUS << 8) + 0x80) #define CAM_PRIORITY_BUS ((CAM_RL_BUS << 8) + 0x80)
#define CAM_PRIORITY_XPT ((CAM_RL_XPT << 8) + 0x80) #define CAM_PRIORITY_XPT ((CAM_RL_XPT << 8) + 0x80)
#define CAM_PRIORITY_DEV ((CAM_RL_DEV << 8) + 0x80) #define CAM_PRIORITY_DEV ((CAM_RL_DEV << 8) + 0x80)
#define CAM_PRIORITY_OOB (CAM_RL_DEV << 8)
#define CAM_PRIORITY_NORMAL ((CAM_RL_NORMAL << 8) + 0x80) #define CAM_PRIORITY_NORMAL ((CAM_RL_NORMAL << 8) + 0x80)
#define CAM_PRIORITY_NONE (u_int32_t)-1 #define CAM_PRIORITY_NONE (u_int32_t)-1
#define CAM_PRIORITY_TO_RL(x) ((x) >> 8)
#define CAM_RL_TO_PRIORITY(x) ((x) << 8)
u_int32_t generation; u_int32_t generation;
int index; int index;
#define CAM_UNQUEUED_INDEX -1 #define CAM_UNQUEUED_INDEX -1

View File

@ -145,8 +145,6 @@ typedef enum {
/* Path statistics (error counts, etc.) */ /* Path statistics (error counts, etc.) */
XPT_GDEV_STATS = 0x0c, XPT_GDEV_STATS = 0x0c,
/* Device statistics (error counts, etc.) */ /* Device statistics (error counts, etc.) */
XPT_FREEZE_QUEUE = 0x0d,
/* Freeze device queue */
XPT_DEV_ADVINFO = 0x0e, XPT_DEV_ADVINFO = 0x0e,
/* Get/Set Device advanced information */ /* Get/Set Device advanced information */
/* SCSI Control Functions: 0x10->0x1F */ /* SCSI Control Functions: 0x10->0x1F */
@ -749,7 +747,6 @@ struct ccb_relsim {
#define RELSIM_RELEASE_AFTER_TIMEOUT 0x02 #define RELSIM_RELEASE_AFTER_TIMEOUT 0x02
#define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04 #define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04
#define RELSIM_RELEASE_AFTER_QEMPTY 0x08 #define RELSIM_RELEASE_AFTER_QEMPTY 0x08
#define RELSIM_RELEASE_RUNLEVEL 0x10
u_int32_t openings; u_int32_t openings;
u_int32_t release_timeout; /* Abstract argument. */ u_int32_t release_timeout; /* Abstract argument. */
u_int32_t qfrozen_cnt; u_int32_t qfrozen_cnt;

View File

@ -1117,21 +1117,12 @@ cam_periph_runccb(union ccb *ccb,
void void
cam_freeze_devq(struct cam_path *path) cam_freeze_devq(struct cam_path *path)
{ {
struct ccb_hdr ccb_h;
cam_freeze_devq_arg(path, 0, 0); xpt_setup_ccb(&ccb_h, path, /*priority*/1);
} ccb_h.func_code = XPT_NOOP;
ccb_h.flags = CAM_DEV_QFREEZE;
void xpt_action((union ccb *)&ccb_h);
cam_freeze_devq_arg(struct cam_path *path, uint32_t flags, uint32_t arg)
{
struct ccb_relsim crs;
xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NONE);
crs.ccb_h.func_code = XPT_FREEZE_QUEUE;
crs.release_flags = flags;
crs.openings = arg;
crs.release_timeout = arg;
xpt_action((union ccb *)&crs);
} }
u_int32_t u_int32_t

View File

@ -171,8 +171,6 @@ int cam_periph_ioctl(struct cam_periph *periph, u_long cmd,
cam_flags camflags, cam_flags camflags,
u_int32_t sense_flags)); u_int32_t sense_flags));
void cam_freeze_devq(struct cam_path *path); void cam_freeze_devq(struct cam_path *path);
void cam_freeze_devq_arg(struct cam_path *path, u_int32_t flags,
uint32_t arg);
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
u_int32_t opening_reduction, u_int32_t arg, u_int32_t opening_reduction, u_int32_t arg,
int getcount_only); int getcount_only);

View File

@ -230,15 +230,8 @@ int
cam_devq_init(struct cam_devq *devq, int devices, int openings) cam_devq_init(struct cam_devq *devq, int devices, int openings)
{ {
bzero(devq, sizeof(*devq)); bzero(devq, sizeof(*devq));
if (camq_init(&devq->alloc_queue, devices) != 0) { if (camq_init(&devq->send_queue, devices) != 0)
return (1); return (1);
}
if (camq_init(&devq->send_queue, devices) != 0) {
camq_fini(&devq->alloc_queue);
return (1);
}
devq->alloc_openings = openings;
devq->alloc_active = 0;
devq->send_openings = openings; devq->send_openings = openings;
devq->send_active = 0; devq->send_active = 0;
return (0); return (0);
@ -247,7 +240,6 @@ cam_devq_init(struct cam_devq *devq, int devices, int openings)
void void
cam_devq_free(struct cam_devq *devq) cam_devq_free(struct cam_devq *devq)
{ {
camq_fini(&devq->alloc_queue);
camq_fini(&devq->send_queue); camq_fini(&devq->send_queue);
free(devq, M_CAMDEVQ); free(devq, M_CAMDEVQ);
} }
@ -257,11 +249,7 @@ cam_devq_resize(struct cam_devq *camq, int devices)
{ {
u_int32_t retval; u_int32_t retval;
retval = camq_resize(&camq->alloc_queue, devices); retval = camq_resize(&camq->send_queue, devices);
if (retval == CAM_REQ_CMP)
retval = camq_resize(&camq->send_queue, devices);
return (retval); return (retval);
} }
@ -328,11 +316,10 @@ int
cam_ccbq_init(struct cam_ccbq *ccbq, int openings) cam_ccbq_init(struct cam_ccbq *ccbq, int openings)
{ {
bzero(ccbq, sizeof(*ccbq)); bzero(ccbq, sizeof(*ccbq));
if (camq_init(&ccbq->queue, openings + (CAM_RL_VALUES - 1)) != 0) { if (camq_init(&ccbq->queue, openings + (CAM_RL_VALUES - 1)) != 0)
return (1); return (1);
}
ccbq->devq_openings = openings; ccbq->devq_openings = openings;
ccbq->dev_openings = openings; ccbq->dev_openings = openings;
return (0); return (0);
} }

View File

@ -48,7 +48,7 @@ struct camq {
int array_size; int array_size;
int entries; int entries;
u_int32_t generation; u_int32_t generation;
u_int32_t qfrozen_cnt[CAM_RL_VALUES]; u_int32_t qfrozen_cnt;
}; };
TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr); TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr);
@ -58,7 +58,8 @@ SLIST_HEAD(ccb_hdr_slist, ccb_hdr);
struct cam_ccbq { struct cam_ccbq {
struct camq queue; struct camq queue;
int devq_openings; int devq_openings;
int dev_openings; int devq_allocating;
int dev_openings;
int dev_active; int dev_active;
int held; int held;
}; };
@ -66,11 +67,7 @@ struct cam_ccbq {
struct cam_ed; struct cam_ed;
struct cam_devq { struct cam_devq {
struct camq alloc_queue;
struct camq send_queue; struct camq send_queue;
struct cam_ed *active_dev;
int alloc_openings;
int alloc_active;
int send_openings; int send_openings;
int send_active; int send_active;
}; };
@ -195,8 +192,7 @@ cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb)
{ {
ccbq->held--; ccbq->held--;
camq_insert(&ccbq->queue, &new_ccb->ccb_h.pinfo); camq_insert(&ccbq->queue, &new_ccb->ccb_h.pinfo);
if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL( if (ccbq->queue.qfrozen_cnt > 0) {
new_ccb->ccb_h.pinfo.priority)] > 0) {
ccbq->devq_openings++; ccbq->devq_openings++;
ccbq->held++; ccbq->held++;
return (1); return (1);
@ -208,8 +204,7 @@ static __inline int
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb) cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb)
{ {
camq_remove(&ccbq->queue, ccb->ccb_h.pinfo.index); camq_remove(&ccbq->queue, ccb->ccb_h.pinfo.index);
if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL( if (ccbq->queue.qfrozen_cnt > 0) {
ccb->ccb_h.pinfo.priority)] > 0) {
ccbq->devq_openings--; ccbq->devq_openings--;
ccbq->held--; ccbq->held--;
return (1); return (1);
@ -248,81 +243,5 @@ cam_ccbq_release_opening(struct cam_ccbq *ccbq)
ccbq->devq_openings++; ccbq->devq_openings++;
} }
static __inline int
cam_ccbq_freeze(struct cam_ccbq *ccbq, cam_rl rl, u_int32_t cnt)
{
int i, frozen = 0;
cam_rl p, n;
/* Find pevious run level. */
for (p = 0; p < CAM_RL_VALUES && ccbq->queue.qfrozen_cnt[p] == 0; p++);
/* Find new run level. */
n = min(rl, p);
/* Apply new run level. */
for (i = rl; i < CAM_RL_VALUES; i++)
ccbq->queue.qfrozen_cnt[i] += cnt;
/* Update ccbq statistics. */
if (n == p)
return (0);
for (i = CAMQ_HEAD; i <= ccbq->queue.entries; i++) {
cam_rl rrl =
CAM_PRIORITY_TO_RL(ccbq->queue.queue_array[i]->priority);
if (rrl < n)
continue;
if (rrl >= p)
break;
ccbq->devq_openings++;
ccbq->held++;
frozen++;
}
return (frozen);
}
static __inline int
cam_ccbq_release(struct cam_ccbq *ccbq, cam_rl rl, u_int32_t cnt)
{
int i, released = 0;
cam_rl p, n;
/* Apply new run level. */
for (i = rl; i < CAM_RL_VALUES; i++)
ccbq->queue.qfrozen_cnt[i] -= cnt;
/* Find new run level. */
for (n = 0; n < CAM_RL_VALUES && ccbq->queue.qfrozen_cnt[n] == 0; n++);
/* Find previous run level. */
p = min(rl, n);
/* Update ccbq statistics. */
if (n == p)
return (0);
for (i = CAMQ_HEAD; i <= ccbq->queue.entries; i++) {
cam_rl rrl =
CAM_PRIORITY_TO_RL(ccbq->queue.queue_array[i]->priority);
if (rrl < p)
continue;
if (rrl >= n)
break;
ccbq->devq_openings--;
ccbq->held--;
released++;
}
return (released);
}
static __inline u_int32_t
cam_ccbq_frozen(struct cam_ccbq *ccbq, cam_rl rl)
{
return (ccbq->queue.qfrozen_cnt[rl]);
}
static __inline u_int32_t
cam_ccbq_frozen_top(struct cam_ccbq *ccbq)
{
cam_rl rl;
rl = CAM_PRIORITY_TO_RL(CAMQ_GET_PRIO(&ccbq->queue));
return (ccbq->queue.qfrozen_cnt[rl]);
}
#endif /* _KERNEL */ #endif /* _KERNEL */
#endif /* _CAM_CAM_QUEUE_H */ #endif /* _CAM_CAM_QUEUE_H */

View File

@ -223,13 +223,13 @@ static void xpt_async_bcast(struct async_list *async_head,
static path_id_t xptnextfreepathid(void); static path_id_t xptnextfreepathid(void);
static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus); static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus);
static union ccb *xpt_get_ccb(struct cam_ed *device); static union ccb *xpt_get_ccb(struct cam_ed *device);
static void xpt_run_dev_allocq(struct cam_eb *bus); static void xpt_run_dev_allocq(struct cam_ed *device);
static void xpt_run_dev_sendq(struct cam_eb *bus); static void xpt_run_devq(struct cam_devq *devq);
static timeout_t xpt_release_devq_timeout; static timeout_t xpt_release_devq_timeout;
static void xpt_release_simq_timeout(void *arg) __unused; static void xpt_release_simq_timeout(void *arg) __unused;
static void xpt_release_bus(struct cam_eb *bus); static void xpt_release_bus(struct cam_eb *bus);
static void xpt_release_devq_device(struct cam_ed *dev, cam_rl rl, static void xpt_release_devq_device(struct cam_ed *dev, u_int count,
u_int count, int run_queue); int run_queue);
static struct cam_et* static struct cam_et*
xpt_alloc_target(struct cam_eb *bus, target_id_t target_id); xpt_alloc_target(struct cam_eb *bus, target_id_t target_id);
static void xpt_release_target(struct cam_et *target); static void xpt_release_target(struct cam_et *target);
@ -296,49 +296,24 @@ static xpt_busfunc_t xptsetasyncbusfunc;
static cam_status xptregister(struct cam_periph *periph, static cam_status xptregister(struct cam_periph *periph,
void *arg); void *arg);
static __inline int periph_is_queued(struct cam_periph *periph); static __inline int periph_is_queued(struct cam_periph *periph);
static __inline int device_is_alloc_queued(struct cam_ed *device); static __inline int device_is_queued(struct cam_ed *device);
static __inline int device_is_send_queued(struct cam_ed *device);
static __inline int static __inline int
xpt_schedule_dev_allocq(struct cam_eb *bus, struct cam_ed *dev) xpt_schedule_devq(struct cam_devq *devq, struct cam_ed *dev)
{
int retval;
if ((dev->drvq.entries > 0) &&
(dev->ccbq.devq_openings > 0) &&
(cam_ccbq_frozen(&dev->ccbq, CAM_PRIORITY_TO_RL(
CAMQ_GET_PRIO(&dev->drvq))) == 0)) {
/*
* The priority of a device waiting for CCB resources
* is that of the highest priority peripheral driver
* enqueued.
*/
retval = xpt_schedule_dev(&bus->sim->devq->alloc_queue,
&dev->alloc_ccb_entry.pinfo,
CAMQ_GET_PRIO(&dev->drvq));
} else {
retval = 0;
}
return (retval);
}
static __inline int
xpt_schedule_dev_sendq(struct cam_eb *bus, struct cam_ed *dev)
{ {
int retval; int retval;
if ((dev->ccbq.queue.entries > 0) && if ((dev->ccbq.queue.entries > 0) &&
(dev->ccbq.dev_openings > 0) && (dev->ccbq.dev_openings > 0) &&
(cam_ccbq_frozen_top(&dev->ccbq) == 0)) { (dev->ccbq.queue.qfrozen_cnt == 0)) {
/* /*
* The priority of a device waiting for controller * The priority of a device waiting for controller
* resources is that of the highest priority CCB * resources is that of the highest priority CCB
* enqueued. * enqueued.
*/ */
retval = retval =
xpt_schedule_dev(&bus->sim->devq->send_queue, xpt_schedule_dev(&devq->send_queue,
&dev->send_ccb_entry.pinfo, &dev->devq_entry.pinfo,
CAMQ_GET_PRIO(&dev->ccbq.queue)); CAMQ_GET_PRIO(&dev->ccbq.queue));
} else { } else {
retval = 0; retval = 0;
@ -353,15 +328,9 @@ periph_is_queued(struct cam_periph *periph)
} }
static __inline int static __inline int
device_is_alloc_queued(struct cam_ed *device) device_is_queued(struct cam_ed *device)
{ {
return (device->alloc_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX); return (device->devq_entry.pinfo.index != CAM_UNQUEUED_INDEX);
}
static __inline int
device_is_send_queued(struct cam_ed *device)
{
return (device->send_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX);
} }
static void static void
@ -2487,17 +2456,10 @@ xpt_action_default(union ccb *start_ccb)
case XPT_RESET_DEV: case XPT_RESET_DEV:
case XPT_ENG_EXEC: case XPT_ENG_EXEC:
case XPT_SMP_IO: case XPT_SMP_IO:
{ cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
int frozen; if (xpt_schedule_devq(path->bus->sim->devq, path->device))
xpt_run_devq(path->bus->sim->devq);
frozen = cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
path->device->sim->devq->alloc_openings += frozen;
if (frozen > 0)
xpt_run_dev_allocq(path->bus);
if (xpt_schedule_dev_sendq(path->bus, path->device))
xpt_run_dev_sendq(path->bus);
break; break;
}
case XPT_CALC_GEOMETRY: case XPT_CALC_GEOMETRY:
{ {
struct cam_sim *sim; struct cam_sim *sim;
@ -2546,8 +2508,7 @@ xpt_action_default(union ccb *start_ccb)
device = abort_ccb->ccb_h.path->device; device = abort_ccb->ccb_h.path->device;
ccbq = &device->ccbq; ccbq = &device->ccbq;
device->sim->devq->alloc_openings -= cam_ccbq_remove_ccb(ccbq, abort_ccb);
cam_ccbq_remove_ccb(ccbq, abort_ccb);
abort_ccb->ccb_h.status = abort_ccb->ccb_h.status =
CAM_REQ_ABORTED|CAM_DEV_QFRZN; CAM_REQ_ABORTED|CAM_DEV_QFRZN;
xpt_freeze_devq(abort_ccb->ccb_h.path, 1); xpt_freeze_devq(abort_ccb->ccb_h.path, 1);
@ -2928,13 +2889,9 @@ xpt_action_default(union ccb *start_ccb)
} }
} }
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) { if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0)
xpt_release_devq_rl(path, /*runlevel*/ xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE);
(crs->release_flags & RELSIM_RELEASE_RUNLEVEL) ? start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt;
crs->release_timeout : 0,
/*count*/1, /*run_queue*/TRUE);
}
start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt[0];
start_ccb->ccb_h.status = CAM_REQ_CMP; start_ccb->ccb_h.status = CAM_REQ_CMP;
break; break;
} }
@ -2977,16 +2934,6 @@ xpt_action_default(union ccb *start_ccb)
start_ccb->ccb_h.status = CAM_REQ_CMP; start_ccb->ccb_h.status = CAM_REQ_CMP;
break; break;
} }
case XPT_FREEZE_QUEUE:
{
struct ccb_relsim *crs = &start_ccb->crs;
xpt_freeze_devq_rl(path, /*runlevel*/
(crs->release_flags & RELSIM_RELEASE_RUNLEVEL) ?
crs->release_timeout : 0, /*count*/1);
start_ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
case XPT_NOOP: case XPT_NOOP:
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0) if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0)
xpt_freeze_devq(path, 1); xpt_freeze_devq(path, 1);
@ -3092,7 +3039,7 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
camq_change_priority(&device->drvq, camq_change_priority(&device->drvq,
perph->pinfo.index, perph->pinfo.index,
new_priority); new_priority);
runq = xpt_schedule_dev_allocq(perph->path->bus, device); runq = 1;
} }
} else { } else {
/* New entry on the queue */ /* New entry on the queue */
@ -3101,12 +3048,12 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
perph->pinfo.priority = new_priority; perph->pinfo.priority = new_priority;
perph->pinfo.generation = ++device->drvq.generation; perph->pinfo.generation = ++device->drvq.generation;
camq_insert(&device->drvq, &perph->pinfo); camq_insert(&device->drvq, &perph->pinfo);
runq = xpt_schedule_dev_allocq(perph->path->bus, device); runq = 1;
} }
if (runq != 0) { if (runq != 0) {
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE, CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
(" calling xpt_run_devq\n")); (" calling xpt_run_dev_allocq\n"));
xpt_run_dev_allocq(perph->path->bus); xpt_run_dev_allocq(device);
} }
} }
@ -3159,43 +3106,25 @@ xpt_schedule_dev(struct camq *queue, cam_pinfo *pinfo,
} }
static void static void
xpt_run_dev_allocq(struct cam_eb *bus) xpt_run_dev_allocq(struct cam_ed *device)
{ {
struct cam_devq *devq; struct camq *drvq;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq\n")); if (device->ccbq.devq_allocating)
devq = bus->sim->devq; return;
device->ccbq.devq_allocating = 1;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq(%p)\n", device));
(" qfrozen_cnt == 0x%x, entries == %d, " drvq = &device->drvq;
"openings == %d, active == %d\n", while ((drvq->entries > 0) &&
devq->alloc_queue.qfrozen_cnt[0], (device->ccbq.devq_openings > 0 ||
devq->alloc_queue.entries, CAMQ_GET_PRIO(drvq) <= CAM_PRIORITY_OOB) &&
devq->alloc_openings, (device->ccbq.queue.qfrozen_cnt == 0)) {
devq->alloc_active));
devq->alloc_queue.qfrozen_cnt[0]++;
while ((devq->alloc_queue.entries > 0)
&& (devq->alloc_openings > 0)
&& (devq->alloc_queue.qfrozen_cnt[0] <= 1)) {
struct cam_ed_qinfo *qinfo;
struct cam_ed *device;
union ccb *work_ccb; union ccb *work_ccb;
struct cam_periph *drv; struct cam_periph *drv;
struct camq *drvq;
qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->alloc_queue,
CAMQ_HEAD);
device = qinfo->device;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
("running device %p\n", device));
drvq = &device->drvq;
KASSERT(drvq->entries > 0, ("xpt_run_dev_allocq: " KASSERT(drvq->entries > 0, ("xpt_run_dev_allocq: "
"Device on queue without any work to do")); "Device on queue without any work to do"));
if ((work_ccb = xpt_get_ccb(device)) != NULL) { if ((work_ccb = xpt_get_ccb(device)) != NULL) {
devq->alloc_openings--;
devq->alloc_active++;
drv = (struct cam_periph*)camq_remove(drvq, CAMQ_HEAD); drv = (struct cam_periph*)camq_remove(drvq, CAMQ_HEAD);
xpt_setup_ccb(&work_ccb->ccb_h, drv->path, xpt_setup_ccb(&work_ccb->ccb_h, drv->path,
drv->pinfo.priority); drv->pinfo.priority);
@ -3214,27 +3143,21 @@ xpt_run_dev_allocq(struct cam_eb *bus)
*/ */
break; break;
} }
/* We may have more work. Attempt to reschedule. */
xpt_schedule_dev_allocq(bus, device);
} }
devq->alloc_queue.qfrozen_cnt[0]--; device->ccbq.devq_allocating = 0;
} }
static void static void
xpt_run_dev_sendq(struct cam_eb *bus) xpt_run_devq(struct cam_devq *devq)
{ {
struct cam_devq *devq;
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_sendq\n")); CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_devq\n"));
devq = bus->sim->devq; devq->send_queue.qfrozen_cnt++;
devq->send_queue.qfrozen_cnt[0]++;
while ((devq->send_queue.entries > 0) while ((devq->send_queue.entries > 0)
&& (devq->send_openings > 0) && (devq->send_openings > 0)
&& (devq->send_queue.qfrozen_cnt[0] <= 1)) { && (devq->send_queue.qfrozen_cnt <= 1)) {
struct cam_ed_qinfo *qinfo; struct cam_ed_qinfo *qinfo;
struct cam_ed *device; struct cam_ed *device;
union ccb *work_ccb; union ccb *work_ccb;
@ -3284,9 +3207,9 @@ xpt_run_dev_sendq(struct cam_eb *bus)
devq->send_openings--; devq->send_openings--;
devq->send_active++; devq->send_active++;
xpt_schedule_dev_sendq(bus, device); xpt_schedule_devq(devq, device);
if (work_ccb && (work_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0){ if ((work_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0) {
/* /*
* The client wants to freeze the queue * The client wants to freeze the queue
* after this CCB is sent. * after this CCB is sent.
@ -3336,7 +3259,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
sim = work_ccb->ccb_h.path->bus->sim; sim = work_ccb->ccb_h.path->bus->sim;
(*(sim->sim_action))(sim, work_ccb); (*(sim->sim_action))(sim, work_ccb);
} }
devq->send_queue.qfrozen_cnt[0]--; devq->send_queue.qfrozen_cnt--;
} }
/* /*
@ -3799,14 +3722,7 @@ xpt_release_ccb(union ccb *free_ccb)
SLIST_INSERT_HEAD(&sim->ccb_freeq, &free_ccb->ccb_h, SLIST_INSERT_HEAD(&sim->ccb_freeq, &free_ccb->ccb_h,
xpt_links.sle); xpt_links.sle);
} }
if (sim->devq == NULL) { xpt_run_dev_allocq(device);
return;
}
sim->devq->alloc_openings++;
sim->devq->alloc_active--;
if (device_is_alloc_queued(device) == 0)
xpt_schedule_dev_allocq(bus, device);
xpt_run_dev_allocq(bus);
} }
/* Functions accessed by SIM drivers */ /* Functions accessed by SIM drivers */
@ -4153,34 +4069,18 @@ xpt_dev_async_default(u_int32_t async_code, struct cam_eb *bus,
} }
u_int32_t u_int32_t
xpt_freeze_devq_rl(struct cam_path *path, cam_rl rl, u_int count) xpt_freeze_devq(struct cam_path *path, u_int count)
{ {
struct cam_ed *dev = path->device; struct cam_ed *dev = path->device;
mtx_assert(path->bus->sim->mtx, MA_OWNED); mtx_assert(path->bus->sim->mtx, MA_OWNED);
dev->sim->devq->alloc_openings += dev->ccbq.queue.qfrozen_cnt += count;
cam_ccbq_freeze(&dev->ccbq, rl, count);
/* Remove frozen device from allocq. */
if (device_is_alloc_queued(dev) &&
cam_ccbq_frozen(&dev->ccbq, CAM_PRIORITY_TO_RL(
CAMQ_GET_PRIO(&dev->drvq)))) {
camq_remove(&dev->sim->devq->alloc_queue,
dev->alloc_ccb_entry.pinfo.index);
}
/* Remove frozen device from sendq. */ /* Remove frozen device from sendq. */
if (device_is_send_queued(dev) && if (device_is_queued(dev)) {
cam_ccbq_frozen_top(&dev->ccbq)) {
camq_remove(&dev->sim->devq->send_queue, camq_remove(&dev->sim->devq->send_queue,
dev->send_ccb_entry.pinfo.index); dev->devq_entry.pinfo.index);
} }
return (dev->ccbq.queue.qfrozen_cnt[rl]); return (dev->ccbq.queue.qfrozen_cnt);
}
u_int32_t
xpt_freeze_devq(struct cam_path *path, u_int count)
{
return (xpt_freeze_devq_rl(path, 0, count));
} }
u_int32_t u_int32_t
@ -4188,8 +4088,8 @@ xpt_freeze_simq(struct cam_sim *sim, u_int count)
{ {
mtx_assert(sim->mtx, MA_OWNED); mtx_assert(sim->mtx, MA_OWNED);
sim->devq->send_queue.qfrozen_cnt[0] += count; sim->devq->send_queue.qfrozen_cnt += count;
return (sim->devq->send_queue.qfrozen_cnt[0]); return (sim->devq->send_queue.qfrozen_cnt);
} }
static void static void
@ -4198,45 +4098,30 @@ xpt_release_devq_timeout(void *arg)
struct cam_ed *device; struct cam_ed *device;
device = (struct cam_ed *)arg; device = (struct cam_ed *)arg;
xpt_release_devq_device(device, /*count*/1, /*run_queue*/TRUE);
xpt_release_devq_device(device, /*rl*/0, /*count*/1, /*run_queue*/TRUE);
} }
void void
xpt_release_devq(struct cam_path *path, u_int count, int run_queue) xpt_release_devq(struct cam_path *path, u_int count, int run_queue)
{ {
mtx_assert(path->bus->sim->mtx, MA_OWNED);
xpt_release_devq_device(path->device, /*rl*/0, count, run_queue); mtx_assert(path->bus->sim->mtx, MA_OWNED);
xpt_release_devq_device(path->device, count, run_queue);
} }
void void
xpt_release_devq_rl(struct cam_path *path, cam_rl rl, u_int count, int run_queue) xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue)
{
mtx_assert(path->bus->sim->mtx, MA_OWNED);
xpt_release_devq_device(path->device, rl, count, run_queue);
}
static void
xpt_release_devq_device(struct cam_ed *dev, cam_rl rl, u_int count, int run_queue)
{ {
if (count > dev->ccbq.queue.qfrozen_cnt[rl]) { if (count > dev->ccbq.queue.qfrozen_cnt) {
#ifdef INVARIANTS #ifdef INVARIANTS
printf("xpt_release_devq(%d): requested %u > present %u\n", printf("xpt_release_devq(): requested %u > present %u\n",
rl, count, dev->ccbq.queue.qfrozen_cnt[rl]); count, dev->ccbq.queue.qfrozen_cnt);
#endif #endif
count = dev->ccbq.queue.qfrozen_cnt[rl]; count = dev->ccbq.queue.qfrozen_cnt;
} }
dev->sim->devq->alloc_openings -= dev->ccbq.queue.qfrozen_cnt -= count;
cam_ccbq_release(&dev->ccbq, rl, count); if (dev->ccbq.queue.qfrozen_cnt == 0) {
if (cam_ccbq_frozen(&dev->ccbq, CAM_PRIORITY_TO_RL(
CAMQ_GET_PRIO(&dev->drvq))) == 0) {
if (xpt_schedule_dev_allocq(dev->target->bus, dev))
xpt_run_dev_allocq(dev->target->bus);
}
if (cam_ccbq_frozen_top(&dev->ccbq) == 0) {
/* /*
* No longer need to wait for a successful * No longer need to wait for a successful
* command completion. * command completion.
@ -4250,6 +4135,7 @@ xpt_release_devq_device(struct cam_ed *dev, cam_rl rl, u_int count, int run_queu
callout_stop(&dev->callout); callout_stop(&dev->callout);
dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING; dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING;
} }
xpt_run_dev_allocq(dev);
if (run_queue == 0) if (run_queue == 0)
return; return;
/* /*
@ -4257,8 +4143,8 @@ xpt_release_devq_device(struct cam_ed *dev, cam_rl rl, u_int count, int run_queu
* device so any pending transactions are * device so any pending transactions are
* run. * run.
*/ */
if (xpt_schedule_dev_sendq(dev->target->bus, dev)) if (xpt_schedule_devq(dev->sim->devq, dev))
xpt_run_dev_sendq(dev->target->bus); xpt_run_devq(dev->sim->devq);
} }
} }
@ -4269,14 +4155,14 @@ xpt_release_simq(struct cam_sim *sim, int run_queue)
mtx_assert(sim->mtx, MA_OWNED); mtx_assert(sim->mtx, MA_OWNED);
sendq = &(sim->devq->send_queue); sendq = &(sim->devq->send_queue);
if (sendq->qfrozen_cnt[0] <= 0) { if (sendq->qfrozen_cnt <= 0) {
#ifdef INVARIANTS #ifdef INVARIANTS
printf("xpt_release_simq: requested 1 > present %u\n", printf("xpt_release_simq: requested 1 > present %u\n",
sendq->qfrozen_cnt[0]); sendq->qfrozen_cnt);
#endif #endif
} else } else
sendq->qfrozen_cnt[0]--; sendq->qfrozen_cnt--;
if (sendq->qfrozen_cnt[0] == 0) { if (sendq->qfrozen_cnt == 0) {
/* /*
* If there is a timeout scheduled to release this * If there is a timeout scheduled to release this
* sim queue, remove it. The queue frozen count is * sim queue, remove it. The queue frozen count is
@ -4287,14 +4173,10 @@ xpt_release_simq(struct cam_sim *sim, int run_queue)
sim->flags &= ~CAM_SIM_REL_TIMEOUT_PENDING; sim->flags &= ~CAM_SIM_REL_TIMEOUT_PENDING;
} }
if (run_queue) { if (run_queue) {
struct cam_eb *bus;
/* /*
* Now that we are unfrozen run the send queue. * Now that we are unfrozen run the send queue.
*/ */
bus = xpt_find_bus(sim->path_id); xpt_run_devq(sim->devq);
xpt_run_dev_sendq(bus);
xpt_release_bus(bus);
} }
} }
} }
@ -4518,7 +4400,7 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
mtx_assert(target->bus->sim->mtx, MA_OWNED); mtx_assert(target->bus->sim->mtx, MA_OWNED);
/* Make space for us in the device queue on our bus */ /* Make space for us in the device queue on our bus */
devq = bus->sim->devq; devq = bus->sim->devq;
status = cam_devq_resize(devq, devq->alloc_queue.array_size + 1); status = cam_devq_resize(devq, devq->send_queue.array_size + 1);
if (status != CAM_REQ_CMP) if (status != CAM_REQ_CMP)
return (NULL); return (NULL);
@ -4527,10 +4409,8 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
if (device == NULL) if (device == NULL)
return (NULL); return (NULL);
cam_init_pinfo(&device->alloc_ccb_entry.pinfo); cam_init_pinfo(&device->devq_entry.pinfo);
device->alloc_ccb_entry.device = device; device->devq_entry.device = device;
cam_init_pinfo(&device->send_ccb_entry.pinfo);
device->send_ccb_entry.device = device;
device->target = target; device->target = target;
device->lun_id = lun_id; device->lun_id = lun_id;
device->sim = bus->sim; device->sim = bus->sim;
@ -4586,8 +4466,7 @@ xpt_release_device(struct cam_ed *device)
KASSERT(SLIST_EMPTY(&device->periphs), KASSERT(SLIST_EMPTY(&device->periphs),
("refcount is zero, but periphs list is not empty")); ("refcount is zero, but periphs list is not empty"));
if (device->alloc_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX if (device->devq_entry.pinfo.index != CAM_UNQUEUED_INDEX)
|| device->send_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX)
panic("Removing device while still queued for ccbs"); panic("Removing device while still queued for ccbs");
if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0)
@ -4598,7 +4477,7 @@ xpt_release_device(struct cam_ed *device)
device->target->bus->sim->max_ccbs -= device->ccbq.devq_openings; device->target->bus->sim->max_ccbs -= device->ccbq.devq_openings;
/* Release our slot in the devq */ /* Release our slot in the devq */
devq = device->target->bus->sim->devq; devq = device->target->bus->sim->devq;
cam_devq_resize(devq, devq->alloc_queue.array_size - 1); cam_devq_resize(devq, devq->send_queue.array_size - 1);
camq_fini(&device->drvq); camq_fini(&device->drvq);
cam_ccbq_fini(&device->ccbq); cam_ccbq_fini(&device->ccbq);
/* /*
@ -5064,9 +4943,9 @@ camisr_runqueue(void *V_queue)
if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
&& (--dev->tag_delay_count == 0)) && (--dev->tag_delay_count == 0))
xpt_start_tags(ccb_h->path); xpt_start_tags(ccb_h->path);
if (!device_is_send_queued(dev)) { if (!device_is_queued(dev)) {
(void)xpt_schedule_dev_sendq(ccb_h->path->bus, (void)xpt_schedule_devq(
dev); ccb_h->path->bus->sim->devq, dev);
} }
} }
@ -5083,7 +4962,7 @@ camisr_runqueue(void *V_queue)
/*run_queue*/TRUE); /*run_queue*/TRUE);
ccb_h->status &= ~CAM_DEV_QFRZN; ccb_h->status &= ~CAM_DEV_QFRZN;
} else if (runq) { } else if (runq) {
xpt_run_dev_sendq(ccb_h->path->bus); xpt_run_devq(ccb_h->path->bus->sim->devq);
} }
/* Call the peripheral driver's callback */ /* Call the peripheral driver's callback */

View File

@ -71,8 +71,7 @@ struct cam_ed_qinfo {
*/ */
struct cam_ed { struct cam_ed {
TAILQ_ENTRY(cam_ed) links; TAILQ_ENTRY(cam_ed) links;
struct cam_ed_qinfo alloc_ccb_entry; struct cam_ed_qinfo devq_entry;
struct cam_ed_qinfo send_ccb_entry;
struct cam_et *target; struct cam_et *target;
struct cam_sim *sim; struct cam_sim *sim;
lun_id_t lun_id; lun_id_t lun_id;

View File

@ -43,12 +43,8 @@ int32_t xpt_bus_deregister(path_id_t path_id);
u_int32_t xpt_freeze_simq(struct cam_sim *sim, u_int count); u_int32_t xpt_freeze_simq(struct cam_sim *sim, u_int count);
void xpt_release_simq(struct cam_sim *sim, int run_queue); void xpt_release_simq(struct cam_sim *sim, int run_queue);
u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count); u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
u_int32_t xpt_freeze_devq_rl(struct cam_path *path, cam_rl rl,
u_int count);
void xpt_release_devq(struct cam_path *path, void xpt_release_devq(struct cam_path *path,
u_int count, int run_queue); u_int count, int run_queue);
void xpt_release_devq_rl(struct cam_path *path, cam_rl rl,
u_int count, int run_queue);
void xpt_done(union ccb *done_ccb); void xpt_done(union ccb *done_ccb);
void xpt_batch_start(struct cam_sim *sim); void xpt_batch_start(struct cam_sim *sim);
void xpt_batch_done(struct cam_sim *sim); void xpt_batch_done(struct cam_sim *sim);

View File

@ -2060,7 +2060,6 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
static void static void
ctlfe_dump_sim(struct cam_sim *sim) ctlfe_dump_sim(struct cam_sim *sim)
{ {
int i;
printf("%s%d: max tagged openings: %d, max dev openings: %d\n", printf("%s%d: max tagged openings: %d, max dev openings: %d\n",
sim->sim_name, sim->unit_number, sim->sim_name, sim->unit_number,
@ -2071,14 +2070,6 @@ ctlfe_dump_sim(struct cam_sim *sim)
printf("%s%d: ccb_freeq is %sempty\n", printf("%s%d: ccb_freeq is %sempty\n",
sim->sim_name, sim->unit_number, sim->sim_name, sim->unit_number,
(SLIST_FIRST(&sim->ccb_freeq) == NULL) ? "" : "NOT "); (SLIST_FIRST(&sim->ccb_freeq) == NULL) ? "" : "NOT ");
printf("%s%d: alloc_queue.entries %d, alloc_openings %d\n",
sim->sim_name, sim->unit_number,
sim->devq->alloc_queue.entries, sim->devq->alloc_openings);
printf("%s%d: qfrozen_cnt:", sim->sim_name, sim->unit_number);
for (i = 0; i < CAM_RL_VALUES; i++) {
printf("%s%u", (i != 0) ? ":" : "",
sim->devq->alloc_queue.qfrozen_cnt[i]);
}
printf("\n"); printf("\n");
} }

View File

@ -464,7 +464,7 @@ cdcleanup(struct cam_periph *periph)
callout_stop(&softc->changer->short_handle); callout_stop(&softc->changer->short_handle);
softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED; softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED;
} }
softc->changer->devq.qfrozen_cnt[0]--; softc->changer->devq.qfrozen_cnt--;
softc->changer->flags |= CHANGER_MANUAL_CALL; softc->changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(softc->changer); cdrunchangerqueue(softc->changer);
} }
@ -1249,13 +1249,13 @@ cdrunchangerqueue(void *arg)
* If the changer queue is frozen, that means we have an active * If the changer queue is frozen, that means we have an active
* device. * device.
*/ */
if (changer->devq.qfrozen_cnt[0] > 0) { if (changer->devq.qfrozen_cnt > 0) {
/* /*
* We always need to reset the frozen count and clear the * We always need to reset the frozen count and clear the
* active flag. * active flag.
*/ */
changer->devq.qfrozen_cnt[0]--; changer->devq.qfrozen_cnt--;
changer->cur_device->flags &= ~CD_FLAG_ACTIVE; changer->cur_device->flags &= ~CD_FLAG_ACTIVE;
changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP; changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP;
@ -1290,7 +1290,7 @@ cdrunchangerqueue(void *arg)
changer->cur_device = softc; changer->cur_device = softc;
changer->devq.qfrozen_cnt[0]++; changer->devq.qfrozen_cnt++;
softc->flags |= CD_FLAG_ACTIVE; softc->flags |= CD_FLAG_ACTIVE;
/* Just in case this device is waiting */ /* Just in case this device is waiting */

View File

@ -613,8 +613,8 @@ passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
/* Compatibility for RL/priority-unaware code. */ /* Compatibility for RL/priority-unaware code. */
priority = inccb->ccb_h.pinfo.priority; priority = inccb->ccb_h.pinfo.priority;
if (priority < CAM_RL_TO_PRIORITY(CAM_RL_NORMAL)) if (priority <= CAM_PRIORITY_OOB)
priority += CAM_RL_TO_PRIORITY(CAM_RL_NORMAL); priority += CAM_PRIORITY_OOB + 1;
/* /*
* Non-immediate CCBs need a CCB from the per-device pool * Non-immediate CCBs need a CCB from the per-device pool

View File

@ -648,11 +648,6 @@ proberegister(struct cam_periph *periph, void *arg)
*/ */
cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset, cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
scsi_delay); scsi_delay);
/*
* Ensure nobody slip in until probe finish.
*/
cam_freeze_devq_arg(periph->path,
RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
probeschedule(periph); probeschedule(periph);
return(CAM_REQ_CMP); return(CAM_REQ_CMP);
} }
@ -981,6 +976,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
default: default:
panic("probestart: invalid action state 0x%x\n", softc->action); panic("probestart: invalid action state 0x%x\n", softc->action);
} }
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
xpt_action(start_ccb); xpt_action(start_ccb);
} }
@ -1127,8 +1123,12 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (cam_periph_error(done_ccb, 0, if (cam_periph_error(done_ccb, 0,
SF_NO_PRINT, NULL) == ERESTART) SF_NO_PRINT, NULL) == ERESTART) {
out:
/* Drop freeze taken due to CAM_DEV_QFREEZE */
cam_release_devq(path, 0, 0, 0, FALSE);
return; return;
}
else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, xpt_release_devq(done_ccb->ccb_h.path,
@ -1138,7 +1138,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
PROBE_SET_ACTION(softc, PROBE_INQUIRY); PROBE_SET_ACTION(softc, PROBE_INQUIRY);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
case PROBE_INQUIRY: case PROBE_INQUIRY:
case PROBE_FULL_INQUIRY: case PROBE_FULL_INQUIRY:
@ -1173,7 +1173,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY); PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
scsi_find_quirk(path->device); scsi_find_quirk(path->device);
@ -1203,7 +1203,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
} }
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} else if (path->device->lun_id == 0 && } else if (path->device->lun_id == 0 &&
SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 && SID_ANSI_REV(inq_buf) > SCSI_REV_SPC2 &&
(SCSI_QUIRK(path->device)->quirks & (SCSI_QUIRK(path->device)->quirks &
@ -1218,14 +1218,14 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
periph->path->target->rpl_size = 16; periph->path->target->rpl_size = 16;
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
} else if (cam_periph_error(done_ccb, 0, } else if (cam_periph_error(done_ccb, 0,
done_ccb->ccb_h.target_lun > 0 done_ccb->ccb_h.target_lun > 0
? SF_RETRY_UA|SF_QUIET_IR ? SF_RETRY_UA|SF_QUIET_IR
: SF_RETRY_UA, : SF_RETRY_UA,
&softc->saved_ccb) == ERESTART) { &softc->saved_ccb) == ERESTART) {
return; goto out;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@ -1266,7 +1266,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
done_ccb->ccb_h.target_lun > 0 ? done_ccb->ccb_h.target_lun > 0 ?
SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA, SF_RETRY_UA|SF_QUIET_IR : SF_RETRY_UA,
&softc->saved_ccb) == ERESTART) { &softc->saved_ccb) == ERESTART) {
return; goto out;
} }
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
xpt_release_devq(done_ccb->ccb_h.path, 1, xpt_release_devq(done_ccb->ccb_h.path, 1,
@ -1285,7 +1285,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
path->target->rpl_size = (nlun << 3) + 8; path->target->rpl_size = (nlun << 3) + 8;
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} else if (nlun == 0) { } else if (nlun == 0) {
/* /*
* If there don't appear to be any luns, bail. * If there don't appear to be any luns, bail.
@ -1358,7 +1358,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
PROBE_SUPPORTED_VPD_LIST); PROBE_SUPPORTED_VPD_LIST);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
if (lp) { if (lp) {
free(lp, M_CAMXPT); free(lp, M_CAMXPT);
@ -1383,7 +1383,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
} else if (cam_periph_error(done_ccb, 0, } else if (cam_periph_error(done_ccb, 0,
SF_RETRY_UA|SF_NO_PRINT, SF_RETRY_UA|SF_NO_PRINT,
&softc->saved_ccb) == ERESTART) { &softc->saved_ccb) == ERESTART) {
return; goto out;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, xpt_release_devq(done_ccb->ccb_h.path,
@ -1393,7 +1393,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
free(mode_hdr, M_CAMXPT); free(mode_hdr, M_CAMXPT);
PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST); PROBE_SET_ACTION(softc, PROBE_SUPPORTED_VPD_LIST);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
case PROBE_SUPPORTED_VPD_LIST: case PROBE_SUPPORTED_VPD_LIST:
{ {
@ -1422,11 +1422,11 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
PROBE_SET_ACTION(softc, PROBE_DEVICE_ID); PROBE_SET_ACTION(softc, PROBE_DEVICE_ID);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} else if (cam_periph_error(done_ccb, 0, } else if (cam_periph_error(done_ccb, 0,
SF_RETRY_UA|SF_NO_PRINT, SF_RETRY_UA|SF_NO_PRINT,
&softc->saved_ccb) == ERESTART) { &softc->saved_ccb) == ERESTART) {
return; goto out;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@ -1471,7 +1471,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
} else if (cam_periph_error(done_ccb, 0, } else if (cam_periph_error(done_ccb, 0,
SF_RETRY_UA, SF_RETRY_UA,
&softc->saved_ccb) == ERESTART) { &softc->saved_ccb) == ERESTART) {
return; goto out;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@ -1484,7 +1484,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM); PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
probe_device_check: probe_device_check:
@ -1526,7 +1526,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
} else if (cam_periph_error(done_ccb, 0, } else if (cam_periph_error(done_ccb, 0,
SF_RETRY_UA|SF_NO_PRINT, SF_RETRY_UA|SF_NO_PRINT,
&softc->saved_ccb) == ERESTART) { &softc->saved_ccb) == ERESTART) {
return; goto out;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */ /* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1, xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
@ -1585,7 +1585,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
*/ */
PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION); PROBE_SET_ACTION(softc, PROBE_TUR_FOR_NEGOTIATION);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
break; break;
@ -1615,7 +1615,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1); PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV1);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
if (softc->action == PROBE_DV_EXIT) { if (softc->action == PROBE_DV_EXIT) {
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
@ -1668,14 +1668,14 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
free(nbuf, M_CAMXPT); free(nbuf, M_CAMXPT);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
free(nbuf, M_CAMXPT); free(nbuf, M_CAMXPT);
if (softc->action == PROBE_INQUIRY_BASIC_DV1) { if (softc->action == PROBE_INQUIRY_BASIC_DV1) {
PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2); PROBE_SET_ACTION(softc, PROBE_INQUIRY_BASIC_DV2);
xpt_release_ccb(done_ccb); xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority); xpt_schedule(periph, priority);
return; goto out;
} }
if (softc->action == PROBE_INQUIRY_BASIC_DV2) { if (softc->action == PROBE_INQUIRY_BASIC_DV2) {
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, CAM_DEBUG(periph->path, CAM_DEBUG_PROBE,
@ -1707,12 +1707,13 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_done(done_ccb); xpt_done(done_ccb);
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n")); CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
/* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
cam_release_devq(path, 0, 0, 0, FALSE);
cam_periph_invalidate(periph); cam_periph_invalidate(periph);
cam_release_devq(periph->path,
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
cam_periph_release_locked(periph); cam_periph_release_locked(periph);
} else { } else {
probeschedule(periph); probeschedule(periph);
goto out;
} }
} }