svn commit: r266118 - in stable/8/sys/cam: . ata scsi
Marius Strobl
marius at FreeBSD.org
Thu May 15 09:55:25 UTC 2014
Author: marius
Date: Thu May 15 09:55:21 2014
New Revision: 266118
URL: http://svnweb.freebsd.org/changeset/base/266118
Log:
Revert the following MFCs done as part of r265147:
r249438, r249466, r249481, r250025, r253958
leaving the MFCs of r241028 and r241444 in place. While the CAM queuing
changes in question are pretty much self-contained and work fine with all
kinds of SAS, SATA and USB devices, for reasons unknown they cause a hang
with Initio INIC-1610P USB disks not seen with later branches containing
these rewrites. In turn, r241444 actually is sufficient to fix the panic
and problems I was seeing and that lead me to bringing CAM queuing up to
date.
Reported by: Scott Allendorf
Modified:
stable/8/sys/cam/ata/ata_da.c
stable/8/sys/cam/ata/ata_pmp.c
stable/8/sys/cam/ata/ata_xpt.c
stable/8/sys/cam/cam.h
stable/8/sys/cam/cam_ccb.h
stable/8/sys/cam/cam_periph.c
stable/8/sys/cam/cam_periph.h
stable/8/sys/cam/cam_queue.c
stable/8/sys/cam/cam_queue.h
stable/8/sys/cam/cam_xpt.c
stable/8/sys/cam/cam_xpt_internal.h
stable/8/sys/cam/cam_xpt_sim.h
stable/8/sys/cam/scsi/scsi_cd.c
stable/8/sys/cam/scsi/scsi_pass.c
stable/8/sys/cam/scsi/scsi_xpt.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/cam/ (props changed)
Modified: stable/8/sys/cam/ata/ata_da.c
==============================================================================
--- stable/8/sys/cam/ata/ata_da.c Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/ata/ata_da.c Thu May 15 09:55:21 2014 (r266118)
@@ -978,6 +978,8 @@ adaasync(void *callback_arg, u_int32_t c
else
break;
cam_periph_acquire(periph);
+ cam_freeze_devq_arg(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
xpt_schedule(periph, CAM_PRIORITY_DEV);
}
default:
@@ -1273,11 +1275,15 @@ adaregister(struct cam_periph *periph, v
cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) {
softc->state = ADA_STATE_RAHEAD;
cam_periph_acquire(periph);
+ cam_freeze_devq_arg(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
xpt_schedule(periph, CAM_PRIORITY_DEV);
} else if (ADA_WC >= 0 &&
cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) {
softc->state = ADA_STATE_WCACHE;
cam_periph_acquire(periph);
+ cam_freeze_devq_arg(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
xpt_schedule(periph, CAM_PRIORITY_DEV);
} else
softc->state = ADA_STATE_NORMAL;
@@ -1561,6 +1567,8 @@ out:
if (softc->flags & ADA_FLAG_PACK_INVALID) {
softc->state = ADA_STATE_NORMAL;
xpt_release_ccb(start_ccb);
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
adaschedule(periph);
cam_periph_release_locked(periph);
return;
@@ -1584,7 +1592,6 @@ out:
ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0);
start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE;
}
- start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
xpt_action(start_ccb);
break;
}
@@ -1597,13 +1604,11 @@ adadone(struct cam_periph *periph, union
struct ada_softc *softc;
struct ccb_ataio *ataio;
struct ccb_getdev *cgd;
- struct cam_path *path;
softc = (struct ada_softc *)periph->softc;
ataio = &done_ccb->ataio;
- path = done_ccb->ccb_h.path;
- CAM_DEBUG(path, CAM_DEBUG_TRACE, ("adadone\n"));
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adadone\n"));
switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) {
case ADA_CCB_BUFFER_IO:
@@ -1631,7 +1636,8 @@ adadone(struct cam_periph *periph, union
* XXX See if this is really a media
* XXX change first?
*/
- xpt_print(path, "Invalidating pack\n");
+ xpt_print(periph->path,
+ "Invalidating pack\n");
softc->flags |= ADA_FLAG_PACK_INVALID;
}
bp->bio_error = error;
@@ -1644,7 +1650,7 @@ adadone(struct cam_periph *periph, union
bp->bio_flags |= BIO_ERROR;
}
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
- cam_release_devq(path,
+ cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
@@ -1685,12 +1691,9 @@ adadone(struct cam_periph *periph, union
{
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
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;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- cam_release_devq(path,
+ cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
@@ -1707,7 +1710,7 @@ out:
* operation.
*/
cgd = (struct ccb_getdev *)done_ccb;
- xpt_setup_ccb(&cgd->ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cgd->ccb_h, periph->path, CAM_PRIORITY_NORMAL);
cgd->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action((union ccb *)cgd);
if (ADA_WC >= 0 &&
@@ -1715,12 +1718,12 @@ out:
softc->state = ADA_STATE_WCACHE;
xpt_release_ccb(done_ccb);
xpt_schedule(periph, CAM_PRIORITY_DEV);
- goto out;
+ return;
}
softc->state = ADA_STATE_NORMAL;
xpt_release_ccb(done_ccb);
- /* Drop freeze taken due to CAM_DEV_QFREEZE */
- cam_release_devq(path, 0, 0, 0, FALSE);
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
adaschedule(periph);
cam_periph_release_locked(periph);
return;
@@ -1729,9 +1732,9 @@ out:
{
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (adaerror(done_ccb, 0, 0) == ERESTART) {
- goto out;
+ return;
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
- cam_release_devq(path,
+ cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
@@ -1749,8 +1752,8 @@ out:
* operation.
*/
xpt_release_ccb(done_ccb);
- /* Drop freeze taken due to CAM_DEV_QFREEZE */
- cam_release_devq(path, 0, 0, 0, FALSE);
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
adaschedule(periph);
cam_periph_release_locked(periph);
return;
Modified: stable/8/sys/cam/ata/ata_pmp.c
==============================================================================
--- stable/8/sys/cam/ata/ata_pmp.c Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/ata/ata_pmp.c Thu May 15 09:55:21 2014 (r266118)
@@ -193,7 +193,8 @@ pmpfreeze(struct cam_periph *periph, int
i, 0) == CAM_REQ_CMP) {
softc->frozen |= (1 << i);
xpt_acquire_device(dpath->device);
- cam_freeze_devq(dpath);
+ cam_freeze_devq_arg(dpath,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_BUS + 1);
xpt_free_path(dpath);
}
}
@@ -214,7 +215,8 @@ pmprelease(struct cam_periph *periph, in
xpt_path_path_id(periph->path),
i, 0) == CAM_REQ_CMP) {
softc->frozen &= ~(1 << i);
- cam_release_devq(dpath, 0, 0, 0, FALSE);
+ cam_release_devq(dpath,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_BUS + 1, FALSE);
xpt_release_device(dpath->device);
xpt_free_path(dpath);
}
Modified: stable/8/sys/cam/ata/ata_xpt.c
==============================================================================
--- stable/8/sys/cam/ata/ata_xpt.c Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/ata/ata_xpt.c Thu May 15 09:55:21 2014 (r266118)
@@ -250,6 +250,12 @@ proberegister(struct cam_periph *periph,
return (status);
}
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);
return(CAM_REQ_CMP);
}
@@ -624,7 +630,6 @@ negotiate:
default:
panic("probestart: invalid action state 0x%x\n", softc->action);
}
- start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
xpt_action(start_ccb);
}
@@ -670,15 +675,12 @@ probedone(struct cam_periph *periph, uni
cam_error_print(done_ccb,
CAM_ESF_ALL, CAM_EPF_ALL);
}
- } else if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART) {
-out:
- /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
- cam_release_devq(path, 0, 0, 0, FALSE);
+ } else if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART)
return;
- }
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */
- xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE);
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
}
status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
if (softc->restart) {
@@ -771,7 +773,7 @@ noerror:
}
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
case PROBE_IDENTIFY:
{
@@ -806,7 +808,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_SPINUP);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
ident_buf = &path->device->ident_data;
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
@@ -879,7 +881,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_SETMODE);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
case PROBE_SPINUP:
if (bootverbose)
@@ -888,7 +890,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
case PROBE_SETMODE:
if (path->device->transport != XPORT_SATA)
goto notsata;
@@ -933,7 +935,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_SETPM);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
/* FALLTHROUGH */
case PROBE_SETPM:
@@ -944,7 +946,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_SETAPST);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
/* FALLTHROUGH */
case PROBE_SETAPST:
@@ -954,7 +956,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
/* FALLTHROUGH */
case PROBE_SETDMAAA:
@@ -964,7 +966,7 @@ noerror:
PROBE_SET_ACTION(softc, PROBE_SETAN);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
/* FALLTHROUGH */
case PROBE_SETAN:
@@ -976,14 +978,15 @@ notsata:
}
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
case PROBE_SET_MULTI:
if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb);
- xpt_async(AC_FOUND_DEVICE, path, done_ccb);
+ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
+ done_ccb);
}
PROBE_SET_ACTION(softc, PROBE_DONE);
break;
@@ -1018,7 +1021,7 @@ notsata:
PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
}
ata_device_transport(path);
@@ -1027,7 +1030,7 @@ notsata:
xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb);
- xpt_async(AC_FOUND_DEVICE, path, done_ccb);
+ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb);
}
PROBE_SET_ACTION(softc, PROBE_DONE);
break;
@@ -1045,7 +1048,7 @@ notsata:
PROBE_SET_ACTION(softc, PROBE_PM_PRV);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
- goto out;
+ return;
case PROBE_PM_PRV:
softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) +
(done_ccb->ataio.res.lba_mid << 16) +
@@ -1094,11 +1097,12 @@ notsata:
xpt_acquire_device(path->device);
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb);
- xpt_async(AC_FOUND_DEVICE, path, done_ccb);
+ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
+ done_ccb);
} else {
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb);
- xpt_async(AC_SCSI_AEN, path, done_ccb);
+ xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb);
}
PROBE_SET_ACTION(softc, PROBE_DONE);
break;
@@ -1110,7 +1114,7 @@ done:
softc->restart = 0;
xpt_release_ccb(done_ccb);
probeschedule(periph);
- goto out;
+ return;
}
xpt_release_ccb(done_ccb);
CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
@@ -1120,9 +1124,9 @@ done:
done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR;
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_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
cam_periph_release_locked(periph);
}
Modified: stable/8/sys/cam/cam.h
==============================================================================
--- stable/8/sys/cam/cam.h Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam.h Thu May 15 09:55:21 2014 (r266118)
@@ -80,15 +80,15 @@ typedef struct {
#define CAM_PRIORITY_BUS ((CAM_RL_BUS << 8) + 0x80)
#define CAM_PRIORITY_XPT ((CAM_RL_XPT << 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_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;
int index;
#define CAM_UNQUEUED_INDEX -1
#define CAM_ACTIVE_INDEX -2
#define CAM_DONEQ_INDEX -3
-#define CAM_EXTRAQ_INDEX INT_MAX
} cam_pinfo;
/*
Modified: stable/8/sys/cam/cam_ccb.h
==============================================================================
--- stable/8/sys/cam/cam_ccb.h Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam_ccb.h Thu May 15 09:55:21 2014 (r266118)
@@ -142,6 +142,8 @@ typedef enum {
/* Path statistics (error counts, etc.) */
XPT_GDEV_STATS = 0x0c,
/* Device statistics (error counts, etc.) */
+ XPT_FREEZE_QUEUE = 0x0d,
+ /* Freeze device queue */
/* SCSI Control Functions: 0x10->0x1F */
XPT_ABORT = 0x10,
/* Abort the specified CCB */
@@ -698,6 +700,7 @@ struct ccb_relsim {
#define RELSIM_RELEASE_AFTER_TIMEOUT 0x02
#define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04
#define RELSIM_RELEASE_AFTER_QEMPTY 0x08
+#define RELSIM_RELEASE_RUNLEVEL 0x10
u_int32_t openings;
u_int32_t release_timeout; /* Abstract argument. */
u_int32_t qfrozen_cnt;
Modified: stable/8/sys/cam/cam_periph.c
==============================================================================
--- stable/8/sys/cam/cam_periph.c Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam_periph.c Thu May 15 09:55:21 2014 (r266118)
@@ -998,12 +998,21 @@ cam_periph_runccb(union ccb *ccb,
void
cam_freeze_devq(struct cam_path *path)
{
- struct ccb_hdr ccb_h;
- xpt_setup_ccb(&ccb_h, path, /*priority*/1);
- ccb_h.func_code = XPT_NOOP;
- ccb_h.flags = CAM_DEV_QFREEZE;
- xpt_action((union ccb *)&ccb_h);
+ cam_freeze_devq_arg(path, 0, 0);
+}
+
+void
+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
Modified: stable/8/sys/cam/cam_periph.h
==============================================================================
--- stable/8/sys/cam/cam_periph.h Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam_periph.h Thu May 15 09:55:21 2014 (r266118)
@@ -169,6 +169,8 @@ int cam_periph_ioctl(struct cam_periph
cam_flags camflags,
u_int32_t sense_flags));
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 opening_reduction, u_int32_t arg,
int getcount_only);
Modified: stable/8/sys/cam/cam_queue.c
==============================================================================
--- stable/8/sys/cam/cam_queue.c Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam_queue.c Thu May 15 09:55:21 2014 (r266118)
@@ -230,8 +230,15 @@ int
cam_devq_init(struct cam_devq *devq, int devices, int openings)
{
bzero(devq, sizeof(*devq));
- if (camq_init(&devq->send_queue, devices) != 0)
+ if (camq_init(&devq->alloc_queue, devices) != 0) {
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_active = 0;
return (0);
@@ -240,6 +247,7 @@ cam_devq_init(struct cam_devq *devq, int
void
cam_devq_free(struct cam_devq *devq)
{
+ camq_fini(&devq->alloc_queue);
camq_fini(&devq->send_queue);
free(devq, M_CAMDEVQ);
}
@@ -249,7 +257,11 @@ cam_devq_resize(struct cam_devq *camq, i
{
u_int32_t retval;
- retval = camq_resize(&camq->send_queue, devices);
+ retval = camq_resize(&camq->alloc_queue, devices);
+
+ if (retval == CAM_REQ_CMP)
+ retval = camq_resize(&camq->send_queue, devices);
+
return (retval);
}
@@ -284,27 +296,43 @@ u_int32_t
cam_ccbq_resize(struct cam_ccbq *ccbq, int new_size)
{
int delta;
+ int space_left;
delta = new_size - (ccbq->dev_active + ccbq->dev_openings);
- ccbq->devq_openings += delta;
- ccbq->dev_openings += delta;
-
- new_size = imax(64, 1 << fls(new_size + new_size / 2));
- if (new_size > ccbq->queue.array_size)
- return (camq_resize(&ccbq->queue, new_size));
- else
+ space_left = new_size
+ - ccbq->queue.entries
+ - ccbq->held
+ - ccbq->dev_active;
+
+ /*
+ * Only attempt to change the underlying queue size if we are
+ * shrinking it and there is space for all outstanding entries
+ * in the new array or we have been requested to grow the array.
+ * We don't fail in the case where we can't reduce the array size,
+ * but clients that care that the queue be "garbage collected"
+ * should detect this condition and call us again with the
+ * same size once the outstanding entries have been processed.
+ */
+ if (space_left < 0
+ || camq_resize(&ccbq->queue, new_size + (CAM_RL_VALUES - 1)) ==
+ CAM_REQ_CMP) {
+ ccbq->devq_openings += delta;
+ ccbq->dev_openings += delta;
return (CAM_REQ_CMP);
+ } else {
+ return (CAM_RESRC_UNAVAIL);
+ }
}
int
cam_ccbq_init(struct cam_ccbq *ccbq, int openings)
{
bzero(ccbq, sizeof(*ccbq));
- if (camq_init(&ccbq->queue,
- imax(64, 1 << fls(openings + openings / 2))) != 0)
+ if (camq_init(&ccbq->queue, openings + (CAM_RL_VALUES - 1)) != 0) {
return (1);
+ }
ccbq->devq_openings = openings;
- ccbq->dev_openings = openings;
+ ccbq->dev_openings = openings;
return (0);
}
Modified: stable/8/sys/cam/cam_queue.h
==============================================================================
--- stable/8/sys/cam/cam_queue.h Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam_queue.h Thu May 15 09:55:21 2014 (r266118)
@@ -48,7 +48,7 @@ struct camq {
int array_size;
int entries;
u_int32_t generation;
- u_int32_t qfrozen_cnt;
+ u_int32_t qfrozen_cnt[CAM_RL_VALUES];
};
TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr);
@@ -57,11 +57,8 @@ SLIST_HEAD(ccb_hdr_slist, ccb_hdr);
struct cam_ccbq {
struct camq queue;
- struct ccb_hdr_tailq queue_extra_head;
- int queue_extra_entries;
int devq_openings;
- int devq_allocating;
- int dev_openings;
+ int dev_openings;
int dev_active;
int held;
};
@@ -69,7 +66,11 @@ struct cam_ccbq {
struct cam_ed;
struct cam_devq {
+ struct camq alloc_queue;
struct camq send_queue;
+ struct cam_ed *active_dev;
+ int alloc_openings;
+ int alloc_active;
int send_openings;
int send_active;
};
@@ -157,10 +158,10 @@ cam_ccbq_pending_ccb_count(struct cam_cc
static __inline void
cam_ccbq_take_opening(struct cam_ccbq *ccbq);
-static __inline void
+static __inline int
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb);
-static __inline void
+static __inline int
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb);
static __inline union ccb *
@@ -179,7 +180,7 @@ cam_ccbq_release_opening(struct cam_ccbq
static __inline int
cam_ccbq_pending_ccb_count(struct cam_ccbq *ccbq)
{
- return (ccbq->queue.entries + ccbq->queue_extra_entries);
+ return (ccbq->queue.entries);
}
static __inline void
@@ -189,64 +190,31 @@ cam_ccbq_take_opening(struct cam_ccbq *c
ccbq->held++;
}
-static __inline void
+static __inline int
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb)
{
- struct ccb_hdr *old_ccb;
- struct camq *queue = &ccbq->queue;
-
ccbq->held--;
-
- /*
- * If queue is already full, try to resize.
- * If resize fail, push CCB with lowest priority out to the TAILQ.
- */
- if (queue->entries == queue->array_size &&
- camq_resize(&ccbq->queue, queue->array_size * 2) != CAM_REQ_CMP) {
- old_ccb = (struct ccb_hdr *)camq_remove(queue, queue->entries);
- TAILQ_INSERT_HEAD(&ccbq->queue_extra_head, old_ccb,
- xpt_links.tqe);
- old_ccb->pinfo.index = CAM_EXTRAQ_INDEX;
- ccbq->queue_extra_entries++;
- }
-
- camq_insert(queue, &new_ccb->ccb_h.pinfo);
+ camq_insert(&ccbq->queue, &new_ccb->ccb_h.pinfo);
+ if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL(
+ new_ccb->ccb_h.pinfo.priority)] > 0) {
+ ccbq->devq_openings++;
+ ccbq->held++;
+ return (1);
+ } else
+ return (0);
}
-static __inline void
+static __inline int
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb)
{
- struct ccb_hdr *cccb, *bccb;
- struct camq *queue = &ccbq->queue;
-
- /* If the CCB is on the TAILQ, remove it from there. */
- if (ccb->ccb_h.pinfo.index == CAM_EXTRAQ_INDEX) {
- TAILQ_REMOVE(&ccbq->queue_extra_head, &ccb->ccb_h,
- xpt_links.tqe);
- ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX;
- ccbq->queue_extra_entries--;
- return;
- }
-
- camq_remove(queue, ccb->ccb_h.pinfo.index);
-
- /*
- * If there are some CCBs on TAILQ, find the best one and move it
- * to the emptied space in the queue.
- */
- bccb = TAILQ_FIRST(&ccbq->queue_extra_head);
- if (bccb == NULL)
- return;
- TAILQ_FOREACH(cccb, &ccbq->queue_extra_head, xpt_links.tqe) {
- if (bccb->pinfo.priority > cccb->pinfo.priority ||
- (bccb->pinfo.priority == cccb->pinfo.priority &&
- GENERATIONCMP(bccb->pinfo.generation, >,
- cccb->pinfo.generation)))
- bccb = cccb;
- }
- TAILQ_REMOVE(&ccbq->queue_extra_head, bccb, xpt_links.tqe);
- ccbq->queue_extra_entries--;
- camq_insert(queue, &bccb->pinfo);
+ camq_remove(&ccbq->queue, ccb->ccb_h.pinfo.index);
+ if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL(
+ ccb->ccb_h.pinfo.priority)] > 0) {
+ ccbq->devq_openings--;
+ ccbq->held--;
+ return (1);
+ } else
+ return (0);
}
static __inline union ccb *
@@ -280,5 +248,81 @@ cam_ccbq_release_opening(struct cam_ccbq
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 /* _CAM_CAM_QUEUE_H */
Modified: stable/8/sys/cam/cam_xpt.c
==============================================================================
--- stable/8/sys/cam/cam_xpt.c Thu May 15 05:35:00 2014 (r266117)
+++ stable/8/sys/cam/cam_xpt.c Thu May 15 09:55:21 2014 (r266118)
@@ -96,7 +96,7 @@ struct xpt_softc {
u_int32_t xpt_generation;
/* number of high powered commands that can go through right now */
- STAILQ_HEAD(highpowerlist, cam_ed) highpowerq;
+ STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq;
int num_highpower;
/* queue for handling async rescan requests. */
@@ -221,13 +221,13 @@ static void xpt_async_bcast(struct asyn
static path_id_t xptnextfreepathid(void);
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 void xpt_run_dev_allocq(struct cam_ed *device);
-static void xpt_run_devq(struct cam_devq *devq);
+static void xpt_run_dev_allocq(struct cam_eb *bus);
+static void xpt_run_dev_sendq(struct cam_eb *bus);
static timeout_t xpt_release_devq_timeout;
static void xpt_release_simq_timeout(void *arg) __unused;
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 void xpt_release_devq_device(struct cam_ed *dev, cam_rl rl,
+ 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_et *target);
@@ -297,24 +297,49 @@ static xpt_busfunc_t xptsetasyncbusfunc;
static cam_status xptregister(struct cam_periph *periph,
void *arg);
static __inline int periph_is_queued(struct cam_periph *periph);
-static __inline int device_is_queued(struct cam_ed *device);
+static __inline int device_is_alloc_queued(struct cam_ed *device);
+static __inline int device_is_send_queued(struct cam_ed *device);
static __inline int
-xpt_schedule_devq(struct cam_devq *devq, struct cam_ed *dev)
+xpt_schedule_dev_allocq(struct cam_eb *bus, 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;
if ((dev->ccbq.queue.entries > 0) &&
(dev->ccbq.dev_openings > 0) &&
- (dev->ccbq.queue.qfrozen_cnt == 0)) {
+ (cam_ccbq_frozen_top(&dev->ccbq) == 0)) {
/*
* The priority of a device waiting for controller
* resources is that of the highest priority CCB
* enqueued.
*/
retval =
- xpt_schedule_dev(&devq->send_queue,
- &dev->devq_entry.pinfo,
+ xpt_schedule_dev(&bus->sim->devq->send_queue,
+ &dev->send_ccb_entry.pinfo,
CAMQ_GET_PRIO(&dev->ccbq.queue));
} else {
retval = 0;
@@ -329,9 +354,15 @@ periph_is_queued(struct cam_periph *peri
}
static __inline int
-device_is_queued(struct cam_ed *device)
+device_is_alloc_queued(struct cam_ed *device)
{
- return (device->devq_entry.pinfo.index != CAM_UNQUEUED_INDEX);
+ return (device->alloc_ccb_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
@@ -2456,10 +2487,17 @@ xpt_action_default(union ccb *start_ccb)
/* FALLTHROUGH */
case XPT_RESET_DEV:
case XPT_ENG_EXEC:
- cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
- if (xpt_schedule_devq(path->bus->sim->devq, path->device))
- xpt_run_devq(path->bus->sim->devq);
+ {
+ int frozen;
+
+ 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;
+ }
case XPT_CALC_GEOMETRY:
{
struct cam_sim *sim;
@@ -2508,7 +2546,8 @@ xpt_action_default(union ccb *start_ccb)
device = abort_ccb->ccb_h.path->device;
ccbq = &device->ccbq;
- cam_ccbq_remove_ccb(ccbq, abort_ccb);
+ device->sim->devq->alloc_openings -=
+ 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);
@@ -2616,7 +2655,7 @@ xpt_action_default(union ccb *start_ccb)
cgds->dev_openings = dev->ccbq.dev_openings;
cgds->dev_active = dev->ccbq.dev_active;
cgds->devq_openings = dev->ccbq.devq_openings;
- cgds->devq_queued = cam_ccbq_pending_ccb_count(&dev->ccbq);
+ cgds->devq_queued = dev->ccbq.queue.entries;
cgds->held = dev->ccbq.held;
cgds->last_reset = tar->last_reset;
cgds->maxtags = dev->maxtags;
@@ -2883,9 +2922,13 @@ xpt_action_default(union ccb *start_ccb)
}
}
- if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0)
- xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE);
- start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt;
+ if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) {
+ xpt_release_devq_rl(path, /*runlevel*/
+ (crs->release_flags & RELSIM_RELEASE_RUNLEVEL) ?
+ 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;
break;
}
@@ -2920,6 +2963,16 @@ xpt_action_default(union ccb *start_ccb)
}
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:
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0)
xpt_freeze_devq(path, 1);
@@ -3023,7 +3076,7 @@ xpt_schedule(struct cam_periph *perph, u
camq_change_priority(&device->drvq,
perph->pinfo.index,
new_priority);
- runq = 1;
+ runq = xpt_schedule_dev_allocq(perph->path->bus, device);
}
} else {
/* New entry on the queue */
@@ -3032,12 +3085,12 @@ xpt_schedule(struct cam_periph *perph, u
perph->pinfo.priority = new_priority;
perph->pinfo.generation = ++device->drvq.generation;
camq_insert(&device->drvq, &perph->pinfo);
- runq = 1;
+ runq = xpt_schedule_dev_allocq(perph->path->bus, device);
}
if (runq != 0) {
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
- (" calling xpt_run_dev_allocq\n"));
- xpt_run_dev_allocq(device);
+ (" calling xpt_run_devq\n"));
+ xpt_run_dev_allocq(perph->path->bus);
}
}
@@ -3090,25 +3143,43 @@ xpt_schedule_dev(struct camq *queue, cam
}
static void
-xpt_run_dev_allocq(struct cam_ed *device)
+xpt_run_dev_allocq(struct cam_eb *bus)
{
- struct camq *drvq;
+ struct cam_devq *devq;
- if (device->ccbq.devq_allocating)
- return;
- device->ccbq.devq_allocating = 1;
- CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq(%p)\n", device));
- drvq = &device->drvq;
- while ((drvq->entries > 0) &&
- (device->ccbq.devq_openings > 0 ||
- CAMQ_GET_PRIO(drvq) <= CAM_PRIORITY_OOB) &&
- (device->ccbq.queue.qfrozen_cnt == 0)) {
+ CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq\n"));
+ devq = bus->sim->devq;
+
+ CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
+ (" qfrozen_cnt == 0x%x, entries == %d, "
+ "openings == %d, active == %d\n",
+ devq->alloc_queue.qfrozen_cnt[0],
+ devq->alloc_queue.entries,
+ devq->alloc_openings,
+ 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;
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));
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable
mailing list