svn commit: r265147 - in stable/8/sys/cam: . ata scsi

Marius Strobl marius at FreeBSD.org
Wed Apr 30 14:09:29 UTC 2014


Author: marius
Date: Wed Apr 30 14:09:26 2014
New Revision: 265147
URL: http://svnweb.freebsd.org/changeset/base/265147

Log:
  MFC: r241028
  
  Change queue overflow checks from DIAGNOSTIC+panic() to KASSERT() to make
  them enabled on HEAD by default. It is probably better to do single compare
  then hunt for unexpected memory corruption.
  
  MFC: r241444
  
  Increase device CCB queue array size by CAM_RL_VALUES - 1 (4) elements.
  It is required to store extra recovery requests in case of bus resets.
  On ATA/SATA this fixes assertion panics on HEAD with INVARIANTS enabled or
  possible memory corruptions otherwise if timeout/reset happens when device
  CCB queue is already full.
  
  MFC: r249466 (partial), r249438, r249481, r250025 (partial)
  
  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.
  
  MFC: r253958
  
  Change CCB queue resize logic to be able safely handle overallocations:
   - (re)allocate queue space in power of 2 chunks with 64 elements minimum
  and never shrink it; with only 4/8 bytes per element size is insignificant.
   - automatically reallocate the queue to double size if it is overflowed.
   - if queue reallocation failed, store extra CCBs in unsorted TAILQ,
  fetching them back as soon as some queue element is freed.
  
  To free space in CCB for TAILQ linking, change highpowerq from keeping
  high-power CCBs to keeping devices frozen due to high-power CCBs.
  
  This encloses all pieces of queue resize logic inside of cam_queue.[ch],
  removing some not obvious duties from xpt_release_ccb().

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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/ata/ata_da.c	Wed Apr 30 14:09:26 2014	(r265147)
@@ -978,8 +978,6 @@ 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:
@@ -1275,15 +1273,11 @@ 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;
@@ -1567,8 +1561,6 @@ 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;
@@ -1592,6 +1584,7 @@ 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;
 	}
@@ -1604,11 +1597,13 @@ 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(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) {
 	case ADA_CCB_BUFFER_IO:
@@ -1636,8 +1631,7 @@ adadone(struct cam_periph *periph, union
 					 * XXX See if this is really a media
 					 * XXX change first?
 					 */
-					xpt_print(periph->path,
-					    "Invalidating pack\n");
+					xpt_print(path, "Invalidating pack\n");
 					softc->flags |= ADA_FLAG_PACK_INVALID;
 				}
 				bp->bio_error = error;
@@ -1650,7 +1644,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(done_ccb->ccb_h.path,
+				cam_release_devq(path,
 						 /*relsim_flags*/0,
 						 /*reduction*/0,
 						 /*timeout*/0,
@@ -1691,9 +1685,12 @@ 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(done_ccb->ccb_h.path,
+				cam_release_devq(path,
 				    /*relsim_flags*/0,
 				    /*reduction*/0,
 				    /*timeout*/0,
@@ -1710,7 +1707,7 @@ adadone(struct cam_periph *periph, union
 		 * operation.
 		 */
 		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;
 		xpt_action((union ccb *)cgd);
 		if (ADA_WC >= 0 &&
@@ -1718,12 +1715,12 @@ adadone(struct cam_periph *periph, union
 			softc->state = ADA_STATE_WCACHE;
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, CAM_PRIORITY_DEV);
-			return;
+			goto out;
 		}
 		softc->state = ADA_STATE_NORMAL;
 		xpt_release_ccb(done_ccb);
-		cam_release_devq(periph->path,
-		    RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
+		/* Drop freeze taken due to CAM_DEV_QFREEZE */
+		cam_release_devq(path, 0, 0, 0, FALSE);
 		adaschedule(periph);
 		cam_periph_release_locked(periph);
 		return;
@@ -1732,9 +1729,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) {
-				return;
+				goto out;
 			} 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,
 				    /*reduction*/0,
 				    /*timeout*/0,
@@ -1752,8 +1749,8 @@ adadone(struct cam_periph *periph, union
 		 * operation.
 		 */
 		xpt_release_ccb(done_ccb);
-		cam_release_devq(periph->path,
-		    RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
+		/* Drop freeze taken due to CAM_DEV_QFREEZE */
+		cam_release_devq(path, 0, 0, 0, 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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/ata/ata_pmp.c	Wed Apr 30 14:09:26 2014	(r265147)
@@ -193,8 +193,7 @@ pmpfreeze(struct cam_periph *periph, int
 		    i, 0) == CAM_REQ_CMP) {
 			softc->frozen |= (1 << i);
 			xpt_acquire_device(dpath->device);
-			cam_freeze_devq_arg(dpath,
-			    RELSIM_RELEASE_RUNLEVEL, CAM_RL_BUS + 1);
+			cam_freeze_devq(dpath);
 			xpt_free_path(dpath);
 		}
 	}
@@ -215,8 +214,7 @@ 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,
-			    RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_BUS + 1, FALSE);
+			cam_release_devq(dpath, 0, 0, 0, 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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/ata/ata_xpt.c	Wed Apr 30 14:09:26 2014	(r265147)
@@ -250,12 +250,6 @@ 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);
 }
@@ -630,6 +624,7 @@ negotiate:
 	default:
 		panic("probestart: invalid action state 0x%x\n", softc->action);
 	}
+	start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
 	xpt_action(start_ccb);
 }
 
@@ -675,12 +670,15 @@ 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)
+		} 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);
 			return;
+		}
 		if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
 			/* Don't wedge the queue */
-			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
-					 /*run_queue*/TRUE);
+			xpt_release_devq(path, /*count*/1, /*run_queue*/TRUE);
 		}
 		status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
 		if (softc->restart) {
@@ -773,7 +771,7 @@ noerror:
 		}
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
-		return;
+		goto out;
 	}
 	case PROBE_IDENTIFY:
 	{
@@ -808,7 +806,7 @@ noerror:
 			PROBE_SET_ACTION(softc, PROBE_SPINUP);
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, priority);
-			return;
+			goto out;
 		}
 		ident_buf = &path->device->ident_data;
 		if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
@@ -881,7 +879,7 @@ noerror:
 		PROBE_SET_ACTION(softc, PROBE_SETMODE);
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
-		return;
+		goto out;
 	}
 	case PROBE_SPINUP:
 		if (bootverbose)
@@ -890,7 +888,7 @@ noerror:
 		PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
-		return;
+		goto out;
 	case PROBE_SETMODE:
 		if (path->device->transport != XPORT_SATA)
 			goto notsata;
@@ -935,7 +933,7 @@ noerror:
 			PROBE_SET_ACTION(softc, PROBE_SETPM);
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, priority);
-			return;
+			goto out;
 		}
 		/* FALLTHROUGH */
 	case PROBE_SETPM:
@@ -946,7 +944,7 @@ noerror:
 			PROBE_SET_ACTION(softc, PROBE_SETAPST);
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, priority);
-			return;
+			goto out;
 		}
 		/* FALLTHROUGH */
 	case PROBE_SETAPST:
@@ -956,7 +954,7 @@ noerror:
 			PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, priority);
-			return;
+			goto out;
 		}
 		/* FALLTHROUGH */
 	case PROBE_SETDMAAA:
@@ -966,7 +964,7 @@ noerror:
 			PROBE_SET_ACTION(softc, PROBE_SETAN);
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, priority);
-			return;
+			goto out;
 		}
 		/* FALLTHROUGH */
 	case PROBE_SETAN:
@@ -978,15 +976,14 @@ notsata:
 		}
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
-		return;
+		goto out;
 	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, done_ccb->ccb_h.path,
-			    done_ccb);
+			xpt_async(AC_FOUND_DEVICE, path, done_ccb);
 		}
 		PROBE_SET_ACTION(softc, PROBE_DONE);
 		break;
@@ -1021,7 +1018,7 @@ notsata:
 			PROBE_SET_ACTION(softc, PROBE_FULL_INQUIRY);
 			xpt_release_ccb(done_ccb);
 			xpt_schedule(periph, priority);
-			return;
+			goto out;
 		}
 
 		ata_device_transport(path);
@@ -1030,7 +1027,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, done_ccb->ccb_h.path, done_ccb);
+			xpt_async(AC_FOUND_DEVICE, path, done_ccb);
 		}
 		PROBE_SET_ACTION(softc, PROBE_DONE);
 		break;
@@ -1048,7 +1045,7 @@ notsata:
 		PROBE_SET_ACTION(softc, PROBE_PM_PRV);
 		xpt_release_ccb(done_ccb);
 		xpt_schedule(periph, priority);
-		return;
+		goto out;
 	case PROBE_PM_PRV:
 		softc->pm_prv = (done_ccb->ataio.res.lba_high << 24) +
 		    (done_ccb->ataio.res.lba_mid << 16) +
@@ -1097,12 +1094,11 @@ notsata:
 			xpt_acquire_device(path->device);
 			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
 			xpt_action(done_ccb);
-			xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
-			    done_ccb);
+			xpt_async(AC_FOUND_DEVICE, path, done_ccb);
 		} else {
 			done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
 			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);
 		break;
@@ -1114,7 +1110,7 @@ done:
 		softc->restart = 0;
 		xpt_release_ccb(done_ccb);
 		probeschedule(periph);
-		return;
+		goto out;
 	}
 	xpt_release_ccb(done_ccb);
 	CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
@@ -1124,9 +1120,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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam.h	Wed Apr 30 14:09:26 2014	(r265147)
@@ -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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam_ccb.h	Wed Apr 30 14:09:26 2014	(r265147)
@@ -142,8 +142,6 @@ 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 */
@@ -700,7 +698,6 @@ 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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam_periph.c	Wed Apr 30 14:09:26 2014	(r265147)
@@ -998,21 +998,12 @@ cam_periph_runccb(union ccb *ccb,
 void
 cam_freeze_devq(struct cam_path *path)
 {
+	struct ccb_hdr 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);
+	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);
 }
 
 u_int32_t

Modified: stable/8/sys/cam/cam_periph.h
==============================================================================
--- stable/8/sys/cam/cam_periph.h	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam_periph.h	Wed Apr 30 14:09:26 2014	(r265147)
@@ -169,8 +169,6 @@ 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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam_queue.c	Wed Apr 30 14:09:26 2014	(r265147)
@@ -121,11 +121,9 @@ camq_resize(struct camq *queue, int new_
 {
 	cam_pinfo **new_array;
 
-#ifdef DIAGNOSTIC
-	if (new_size < queue->entries)
-		panic("camq_resize: New queue size can't accomodate "
-		      "queued entries.");
-#endif
+	KASSERT(new_size >= queue->entries, ("camq_resize: "
+	    "New queue size can't accomodate queued entries (%d < %d).",
+	    new_size, queue->entries));
 	new_array = (cam_pinfo **)malloc(new_size * sizeof(cam_pinfo *),
 					 M_CAMQ, M_NOWAIT);
 	if (new_array == NULL) {
@@ -156,10 +154,10 @@ camq_resize(struct camq *queue, int new_
 void
 camq_insert(struct camq *queue, cam_pinfo *new_entry)
 {
-#ifdef DIAGNOSTIC
-	if (queue->entries >= queue->array_size)
-		panic("camq_insert: Attempt to insert into a full queue");
-#endif
+
+	KASSERT(queue->entries < queue->array_size,
+	    ("camq_insert: Attempt to insert into a full queue (%d >= %d)",
+	    queue->entries, queue->array_size));
 	queue->entries++;
 	queue->queue_array[queue->entries] = new_entry;
 	new_entry->index = queue->entries;
@@ -232,15 +230,8 @@ int
 cam_devq_init(struct cam_devq *devq, int devices, int openings)
 {
 	bzero(devq, sizeof(*devq));
-	if (camq_init(&devq->alloc_queue, devices) != 0) {
-		return (1);
-	}
-	if (camq_init(&devq->send_queue, devices) != 0) {
-		camq_fini(&devq->alloc_queue);
+	if (camq_init(&devq->send_queue, devices) != 0)
 		return (1);
-	}
-	devq->alloc_openings = openings;
-	devq->alloc_active = 0;
 	devq->send_openings = openings;
 	devq->send_active = 0;	
 	return (0);	
@@ -249,7 +240,6 @@ 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);
 }
@@ -259,11 +249,7 @@ cam_devq_resize(struct cam_devq *camq, i
 {
 	u_int32_t retval;
 
-	retval = camq_resize(&camq->alloc_queue, devices);
-
-	if (retval == CAM_REQ_CMP)
-		retval = camq_resize(&camq->send_queue, devices);
-
+	retval = camq_resize(&camq->send_queue, devices);
 	return (retval);
 }
 
@@ -298,42 +284,27 @@ 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);
-	space_left = new_size
-	    - ccbq->queue.entries
-	    - ccbq->held
-	    - ccbq->dev_active;
+	ccbq->devq_openings += delta;
+	ccbq->dev_openings += delta;
 
-	/*
-	 * 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_REQ_CMP) {
-		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
 		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, openings) != 0) {
+	if (camq_init(&ccbq->queue,
+	    imax(64, 1 << fls(openings + openings / 2))) != 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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam_queue.h	Wed Apr 30 14:09:26 2014	(r265147)
@@ -48,7 +48,7 @@ struct camq {
 	int	   array_size;
 	int	   entries;
 	u_int32_t  generation;
-	u_int32_t  qfrozen_cnt[CAM_RL_VALUES];
+	u_int32_t  qfrozen_cnt;
 };
 
 TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr);
@@ -57,8 +57,11 @@ 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	dev_openings;	
+	int	devq_allocating;
+	int	dev_openings;
 	int	dev_active;
 	int	held;
 };
@@ -66,11 +69,7 @@ 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;
 };
@@ -158,10 +157,10 @@ cam_ccbq_pending_ccb_count(struct cam_cc
 static __inline void
 cam_ccbq_take_opening(struct cam_ccbq *ccbq);
 
-static __inline int
+static __inline void
 cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb);
 
-static __inline int
+static __inline void
 cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb);
 
 static __inline union ccb *
@@ -180,7 +179,7 @@ cam_ccbq_release_opening(struct cam_ccbq
 static __inline int
 cam_ccbq_pending_ccb_count(struct cam_ccbq *ccbq)
 {
-	return (ccbq->queue.entries);
+	return (ccbq->queue.entries + ccbq->queue_extra_entries);
 }
 
 static __inline void
@@ -190,31 +189,64 @@ cam_ccbq_take_opening(struct cam_ccbq *c
 	ccbq->held++;
 }
 
-static __inline int
+static __inline void
 cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb)
 {
+	struct ccb_hdr *old_ccb;
+	struct camq *queue = &ccbq->queue;
+
 	ccbq->held--;
-	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);
+
+	/*
+	 * 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);
 }
 
-static __inline int
+static __inline void
 cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb)
 {
-	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);
+	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);
 }
 
 static __inline union ccb *
@@ -248,81 +280,5 @@ 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	Wed Apr 30 11:06:02 2014	(r265146)
+++ stable/8/sys/cam/cam_xpt.c	Wed Apr 30 14:09:26 2014	(r265147)
@@ -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, ccb_hdr)	highpowerq;
+	STAILQ_HEAD(highpowerlist, cam_ed)	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_eb *bus);
-static void	 xpt_run_dev_sendq(struct cam_eb *bus);
+static void	 xpt_run_dev_allocq(struct cam_ed *device);
+static void	 xpt_run_devq(struct cam_devq *devq);
 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, cam_rl rl,
-		    u_int count, int run_queue);
+static void	 xpt_release_devq_device(struct cam_ed *dev, u_int count,
+		    int run_queue);
 static struct cam_et*
 		 xpt_alloc_target(struct cam_eb *bus, target_id_t target_id);
 static void	 xpt_release_target(struct cam_et *target);
@@ -297,49 +297,24 @@ 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_alloc_queued(struct cam_ed *device);
-static __inline int device_is_send_queued(struct cam_ed *device);
+static __inline int device_is_queued(struct cam_ed *device);
 
 static __inline int
-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)
+xpt_schedule_devq(struct cam_devq *devq, struct cam_ed *dev)
 {
 	int	retval;
 
 	if ((dev->ccbq.queue.entries > 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
 		 * resources is that of the highest priority CCB
 		 * enqueued.
 		 */
 		retval =
-		    xpt_schedule_dev(&bus->sim->devq->send_queue,
-				     &dev->send_ccb_entry.pinfo,
+		    xpt_schedule_dev(&devq->send_queue,
+				     &dev->devq_entry.pinfo,
 				     CAMQ_GET_PRIO(&dev->ccbq.queue));
 	} else {
 		retval = 0;
@@ -354,15 +329,9 @@ periph_is_queued(struct cam_periph *peri
 }
 
 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);
-}
-
-static __inline int
-device_is_send_queued(struct cam_ed *device)
-{
-	return (device->send_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX);
+	return (device->devq_entry.pinfo.index != CAM_UNQUEUED_INDEX);
 }
 
 static void
@@ -2487,17 +2456,10 @@ xpt_action_default(union ccb *start_ccb)
 		/* FALLTHROUGH */
 	case XPT_RESET_DEV:
 	case XPT_ENG_EXEC:
-	{
-		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);
+		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);
 		break;
-	}
 	case XPT_CALC_GEOMETRY:
 	{
 		struct cam_sim *sim;
@@ -2546,8 +2508,7 @@ xpt_action_default(union ccb *start_ccb)
 
 				device = abort_ccb->ccb_h.path->device;
 				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 =
 				    CAM_REQ_ABORTED|CAM_DEV_QFRZN;
 				xpt_freeze_devq(abort_ccb->ccb_h.path, 1);
@@ -2655,7 +2616,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 = dev->ccbq.queue.entries;
+			cgds->devq_queued = cam_ccbq_pending_ccb_count(&dev->ccbq);
 			cgds->held = dev->ccbq.held;
 			cgds->last_reset = tar->last_reset;
 			cgds->maxtags = dev->maxtags;
@@ -2922,13 +2883,9 @@ xpt_action_default(union ccb *start_ccb)
 			}
 		}
 
-		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];
+		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;
 		start_ccb->ccb_h.status = CAM_REQ_CMP;
 		break;
 	}
@@ -2963,16 +2920,6 @@ 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);
@@ -3076,7 +3023,7 @@ xpt_schedule(struct cam_periph *perph, u
 			camq_change_priority(&device->drvq,
 					     perph->pinfo.index,
 					     new_priority);
-			runq = xpt_schedule_dev_allocq(perph->path->bus, device);
+			runq = 1;
 		}
 	} else {
 		/* New entry on the queue */
@@ -3085,12 +3032,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 = xpt_schedule_dev_allocq(perph->path->bus, device);
+		runq = 1;
 	}
 	if (runq != 0) {
 		CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
-			  ("   calling xpt_run_devq\n"));
-		xpt_run_dev_allocq(perph->path->bus);
+			  ("   calling xpt_run_dev_allocq\n"));
+		xpt_run_dev_allocq(device);
 	}
 }
 
@@ -3143,43 +3090,25 @@ xpt_schedule_dev(struct camq *queue, cam
 }
 
 static void
-xpt_run_dev_allocq(struct cam_eb *bus)
+xpt_run_dev_allocq(struct cam_ed *device)
 {
-	struct	cam_devq *devq;
-
-	CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq\n"));
-	devq = bus->sim->devq;
+	struct camq	*drvq;
 
-	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,

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list