svn commit: r333154 - head/sys/cam/scsi

Scott Long scottl at FreeBSD.org
Tue May 1 21:42:28 UTC 2018


Author: scottl
Date: Tue May  1 21:42:27 2018
New Revision: 333154
URL: https://svnweb.freebsd.org/changeset/base/333154

Log:
  Refactor dadone().  There was no useful code sharing in it; it was just
  a 1500 line switch statement.  Callers now specify a discrete completion
  handler, though they're still welcome to track state via ccb_state.
  
  Sponsored by:	Netflix

Modified:
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c	Tue May  1 20:17:22 2018	(r333153)
+++ head/sys/cam/scsi/scsi_da.c	Tue May  1 21:42:27 2018	(r333154)
@@ -163,7 +163,7 @@ typedef enum {
 	DA_CCB_PROBE_ATA_ZONE	= 0x11,
 	DA_CCB_PROBE_WP		= 0x12,
 	DA_CCB_TYPE_MASK	= 0x1F,
-	DA_CCB_RETRY_UA		= 0x20
+	DA_CCB_RETRY_UA		= 0x20 
 } da_ccb_state;
 
 /*
@@ -358,7 +358,7 @@ struct da_softc {
 	u_int	timeouts;
 	u_int	invalidations;
 #endif
-#define DA_ANNOUNCETMP_SZ 80
+#define DA_ANNOUNCETMP_SZ 160
 	char			announce_temp[DA_ANNOUNCETMP_SZ];
 #define DA_ANNOUNCE_SZ 400
 	char			announcebuf[DA_ANNOUNCE_SZ];
@@ -1405,6 +1405,30 @@ static	periph_oninv_t	daoninvalidate;
 static	void		dazonedone(struct cam_periph *periph, union ccb *ccb);
 static	void		dadone(struct cam_periph *periph,
 			       union ccb *done_ccb);
+static void		dadone_probewp(struct cam_periph *periph,
+				       union ccb *done_ccb);
+static void		dadone_proberc(struct cam_periph *periph,
+				       union ccb *done_ccb);
+static void		dadone_probelbp(struct cam_periph *periph,
+					union ccb *done_ccb);
+static void		dadone_probeblklimits(struct cam_periph *periph,
+					      union ccb *done_ccb);
+static void		dadone_probebdc(struct cam_periph *periph,
+					union ccb *done_ccb);
+static void		dadone_probeata(struct cam_periph *periph,
+					union ccb *done_ccb);
+static void		dadone_probeatalogdir(struct cam_periph *periph,
+					      union ccb *done_ccb);
+static void		dadone_probeataiddir(struct cam_periph *periph,
+					     union ccb *done_ccb);
+static void		dadone_probeatasup(struct cam_periph *periph,
+					   union ccb *done_ccb);
+static void		dadone_probeatazone(struct cam_periph *periph,
+					    union ccb *done_ccb);
+static void		dadone_probezone(struct cam_periph *periph,
+					 union ccb *done_ccb);
+static void		dadone_tur(struct cam_periph *periph,
+				   union ccb *done_ccb);
 static  int		daerror(union ccb *ccb, u_int32_t cam_flags,
 				u_int32_t sense_flags);
 static void		daprevent(struct cam_periph *periph, int action);
@@ -3114,12 +3138,14 @@ skipstate:
 more:
 		bp = cam_iosched_next_bio(softc->cam_iosched);
 		if (bp == NULL) {
-			if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
+			if (cam_iosched_has_work_flags(softc->cam_iosched,
+			    DA_WORK_TUR)) {
 				softc->flags |= DA_FLAG_TUR_PENDING;
-				cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR);
+				cam_iosched_clr_work_flags(softc->cam_iosched,
+				    DA_WORK_TUR);
 				scsi_test_unit_ready(&start_ccb->csio,
 				     /*retries*/ da_retry_count,
-				     dadone,
+				     dadone_tur,
 				     MSG_SIMPLE_Q_TAG,
 				     SSD_FULL_SIZE,
 				     da_default_timeout * 1000);
@@ -3136,14 +3162,19 @@ more:
 				softc->delete_func(periph, start_ccb, bp);
 				goto out;
 			} else {
-				/* Not sure this is possible, but failsafe by lying and saying "sure, done." */
+				/*
+				 * Not sure this is possible, but failsafe by
+				 * lying and saying "sure, done."
+				 */
 				biofinish(bp, NULL, 0);
 				goto more;
 			}
 		}
 
-		if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
-			cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR);
+		if (cam_iosched_has_work_flags(softc->cam_iosched,
+		    DA_WORK_TUR)) {
+			cam_iosched_clr_work_flags(softc->cam_iosched,
+			    DA_WORK_TUR);
 			da_periph_release_locked(periph, DA_REF_TUR);
 		}
 
@@ -3201,7 +3232,7 @@ more:
 			/*
 			 * If we don't support sync cache, or the disk
 			 * isn't dirty, FLUSH is a no-op.  Use the
-			 * allocated * CCB for the next bio if one is
+			 * allocated CCB for the next bio if one is
 			 * available.
 			 */
 			if ((softc->quirks & DA_Q_NO_SYNC_CACHE) != 0 ||
@@ -3290,7 +3321,7 @@ out:
 		}
 		scsi_mode_sense_len(&start_ccb->csio,
 				    /*retries*/ da_retry_count,
-				    /*cbfcnp*/ dadone,
+				    /*cbfcnp*/ dadone_probewp,
 				    /*tag_action*/ MSG_SIMPLE_Q_TAG,
 				    /*dbd*/ FALSE,
 				    /*pc*/ SMS_PAGE_CTRL_CURRENT,
@@ -3318,7 +3349,7 @@ out:
 		}
 		scsi_read_capacity(&start_ccb->csio,
 				   /*retries*/da_retry_count,
-				   dadone,
+				   dadone_proberc,
 				   MSG_SIMPLE_Q_TAG,
 				   rcap,
 				   SSD_FULL_SIZE,
@@ -3341,7 +3372,7 @@ out:
 		}
 		scsi_read_capacity_16(&start_ccb->csio,
 				      /*retries*/ da_retry_count,
-				      /*cbfcnp*/ dadone,
+				      /*cbfcnp*/ dadone_proberc,
 				      /*tag_action*/ MSG_SIMPLE_Q_TAG,
 				      /*lba*/ 0,
 				      /*reladr*/ 0,
@@ -3384,7 +3415,7 @@ out:
 
 		scsi_inquiry(&start_ccb->csio,
 			     /*retries*/da_retry_count,
-			     /*cbfcnp*/dadone,
+			     /*cbfcnp*/dadone_probelbp,
 			     /*tag_action*/MSG_SIMPLE_Q_TAG,
 			     /*inq_buf*/(u_int8_t *)lbp,
 			     /*inq_len*/sizeof(*lbp),
@@ -3418,7 +3449,7 @@ out:
 
 		scsi_inquiry(&start_ccb->csio,
 			     /*retries*/da_retry_count,
-			     /*cbfcnp*/dadone,
+			     /*cbfcnp*/dadone_probeblklimits,
 			     /*tag_action*/MSG_SIMPLE_Q_TAG,
 			     /*inq_buf*/(u_int8_t *)block_limits,
 			     /*inq_len*/sizeof(*block_limits),
@@ -3451,7 +3482,7 @@ out:
 
 		scsi_inquiry(&start_ccb->csio,
 			     /*retries*/da_retry_count,
-			     /*cbfcnp*/dadone,
+			     /*cbfcnp*/dadone_probebdc,
 			     /*tag_action*/MSG_SIMPLE_Q_TAG,
 			     /*inq_buf*/(u_int8_t *)bdc,
 			     /*inq_len*/sizeof(*bdc),
@@ -3497,7 +3528,7 @@ out:
 
 		scsi_ata_identify(&start_ccb->csio,
 				  /*retries*/da_retry_count,
-				  /*cbfcnp*/dadone,
+				  /*cbfcnp*/dadone_probeata,
                                   /*tag_action*/MSG_SIMPLE_Q_TAG,
 				  /*data_ptr*/(u_int8_t *)ata_params,
 				  /*dxfer_len*/sizeof(*ata_params),
@@ -3540,7 +3571,7 @@ out:
 
 		retval = scsi_ata_read_log(&start_ccb->csio,
 		    /*retries*/ da_retry_count,
-		    /*cbfcnp*/ dadone,
+		    /*cbfcnp*/ dadone_probeatalogdir,
 		    /*tag_action*/ MSG_SIMPLE_Q_TAG,
 		    /*log_address*/ ATA_LOG_DIRECTORY,
 		    /*page_number*/ 0,
@@ -3590,7 +3621,7 @@ out:
 
 		retval = scsi_ata_read_log(&start_ccb->csio,
 		    /*retries*/ da_retry_count,
-		    /*cbfcnp*/ dadone,
+		    /*cbfcnp*/ dadone_probeataiddir,
 		    /*tag_action*/ MSG_SIMPLE_Q_TAG,
 		    /*log_address*/ ATA_IDENTIFY_DATA_LOG,
 		    /*page_number*/ ATA_IDL_PAGE_LIST,
@@ -3639,7 +3670,7 @@ out:
 
 		retval = scsi_ata_read_log(&start_ccb->csio,
 		    /*retries*/ da_retry_count,
-		    /*cbfcnp*/ dadone,
+		    /*cbfcnp*/ dadone_probeatasup,
 		    /*tag_action*/ MSG_SIMPLE_Q_TAG,
 		    /*log_address*/ ATA_IDENTIFY_DATA_LOG,
 		    /*page_number*/ ATA_IDL_SUP_CAP,
@@ -3691,7 +3722,7 @@ out:
 
 		retval = scsi_ata_read_log(&start_ccb->csio,
 		    /*retries*/ da_retry_count,
-		    /*cbfcnp*/ dadone,
+		    /*cbfcnp*/ dadone_probeatazone,
 		    /*tag_action*/ MSG_SIMPLE_Q_TAG,
 		    /*log_address*/ ATA_IDENTIFY_DATA_LOG,
 		    /*page_number*/ ATA_IDL_ZDI,
@@ -3741,7 +3772,7 @@ out:
 		}
 		scsi_inquiry(&start_ccb->csio,
 			     /*retries*/da_retry_count,
-			     /*cbfcnp*/dadone,
+			     /*cbfcnp*/dadone_probezone,
 			     /*tag_action*/MSG_SIMPLE_Q_TAG,
 			     /*inq_buf*/(u_int8_t *)bdc,
 			     /*inq_len*/sizeof(*bdc),
@@ -3830,7 +3861,8 @@ da_delete_unmap(struct cam_periph *periph, union ccb *
 					totalcount -= c;
 					lastlba -= c;
 					lastcount -= c;
-					scsi_ulto4b(lastcount, d[ranges - 1].length);
+					scsi_ulto4b(lastcount,
+					    d[ranges - 1].length);
 				}
 			}
 			/* Align beginning of the new range. */
@@ -4301,1296 +4333,1360 @@ dazonedone(struct cam_periph *periph, union ccb *ccb)
 static void
 dadone(struct cam_periph *periph, union ccb *done_ccb)
 {
+	struct bio *bp, *bp1;
 	struct da_softc *softc;
 	struct ccb_scsiio *csio;
 	u_int32_t  priority;
 	da_ccb_state state;
 
-	softc = (struct da_softc *)periph->softc;
-	priority = done_ccb->ccb_h.pinfo.priority;
-
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
 
+	softc = (struct da_softc *)periph->softc;
+	priority = done_ccb->ccb_h.pinfo.priority;
 	csio = &done_ccb->csio;
+
 #if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
 	if (csio->bio != NULL)
 		biotrack(csio->bio, __func__);
 #endif
 	state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
-	switch (state) {
-	case DA_CCB_BUFFER_IO:
-	case DA_CCB_DELETE:
-	{
-		struct bio *bp, *bp1;
 
-		cam_periph_lock(periph);
+	cam_periph_lock(periph);
+	bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
+	if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		int error;
+		int sf;
+
+		if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
+			sf = SF_RETRY_UA;
+		else
+			sf = 0;
+
+		error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
+		if (error == ERESTART) {
+			/* A retry was scheduled, so just return. */
+			cam_periph_unlock(periph);
+			return;
+		}
 		bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
-		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
-			int error;
-			int sf;
+		if (error != 0) {
+			int queued_error;
 
-			if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
-				sf = SF_RETRY_UA;
-			else
-				sf = 0;
+			/*
+			 * return all queued I/O with EIO, so that
+			 * the client can retry these I/Os in the
+			 * proper order should it attempt to recover.
+			 */
+			queued_error = EIO;
 
-			error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
-			if (error == ERESTART) {
+			if (error == ENXIO
+			 && (softc->flags & DA_FLAG_PACK_INVALID)== 0) {
 				/*
-				 * A retry was scheduled, so
-				 * just return.
+				 * Catastrophic error.  Mark our pack as
+				 * invalid.
+				 *
+				 * XXX See if this is really a media
+				 * XXX change first?
 				 */
-				cam_periph_unlock(periph);
-				return;
-			}
-			bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
-			if (error != 0) {
-				int queued_error;
-
-				/*
-				 * return all queued I/O with EIO, so that
-				 * the client can retry these I/Os in the
-				 * proper order should it attempt to recover.
-				 */
-				queued_error = EIO;
-
-				if (error == ENXIO
-				 && (softc->flags & DA_FLAG_PACK_INVALID)== 0) {
-					/*
-					 * Catastrophic error.  Mark our pack as
-					 * invalid.
-					 */
-					/*
-					 * XXX See if this is really a media
-					 * XXX change first?
-					 */
-					xpt_print(periph->path,
-					    "Invalidating pack\n");
-					softc->flags |= DA_FLAG_PACK_INVALID;
+				xpt_print(periph->path, "Invalidating pack\n");
+				softc->flags |= DA_FLAG_PACK_INVALID;
 #ifdef CAM_IO_STATS
-					softc->invalidations++;
+				softc->invalidations++;
 #endif
-					queued_error = ENXIO;
-				}
-				cam_iosched_flush(softc->cam_iosched, NULL,
-					   queued_error);
-				if (bp != NULL) {
-					bp->bio_error = error;
-					bp->bio_resid = bp->bio_bcount;
-					bp->bio_flags |= BIO_ERROR;
-				}
-			} else if (bp != NULL) {
-				if (state == DA_CCB_DELETE)
-					bp->bio_resid = 0;
-				else
-					bp->bio_resid = csio->resid;
-				bp->bio_error = 0;
-				if (bp->bio_resid != 0)
-					bp->bio_flags |= BIO_ERROR;
+				queued_error = ENXIO;
 			}
-			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
-				cam_release_devq(done_ccb->ccb_h.path,
-						 /*relsim_flags*/0,
-						 /*reduction*/0,
-						 /*timeout*/0,
-						 /*getcount_only*/0);
+			cam_iosched_flush(softc->cam_iosched, NULL,
+			   queued_error);
+			if (bp != NULL) {
+				bp->bio_error = error;
+				bp->bio_resid = bp->bio_bcount;
+				bp->bio_flags |= BIO_ERROR;
+			}
 		} else if (bp != NULL) {
-			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
-				panic("REQ_CMP with QFRZN");
-			if (bp->bio_cmd == BIO_ZONE)
-				dazonedone(periph, done_ccb);
-			else if (state == DA_CCB_DELETE)
+			if (state == DA_CCB_DELETE)
 				bp->bio_resid = 0;
 			else
 				bp->bio_resid = csio->resid;
-			if ((csio->resid > 0)
-			 && (bp->bio_cmd != BIO_ZONE))
+			bp->bio_error = 0;
+			if (bp->bio_resid != 0)
 				bp->bio_flags |= BIO_ERROR;
-			if (softc->error_inject != 0) {
-				bp->bio_error = softc->error_inject;
-				bp->bio_resid = bp->bio_bcount;
-				bp->bio_flags |= BIO_ERROR;
-				softc->error_inject = 0;
-			}
 		}
+		if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
+			cam_release_devq(done_ccb->ccb_h.path,
+					 /*relsim_flags*/0,
+					 /*reduction*/0,
+					 /*timeout*/0,
+					 /*getcount_only*/0);
+	} else if (bp != NULL) {
+		if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
+			panic("REQ_CMP with QFRZN");
+		if (bp->bio_cmd == BIO_ZONE)
+			dazonedone(periph, done_ccb);
+		else if (state == DA_CCB_DELETE)
+			bp->bio_resid = 0;
+		else
+			bp->bio_resid = csio->resid;
+		if ((csio->resid > 0) && (bp->bio_cmd != BIO_ZONE))
+			bp->bio_flags |= BIO_ERROR;
+		if (softc->error_inject != 0) {
+			bp->bio_error = softc->error_inject;
+			bp->bio_resid = bp->bio_bcount;
+			bp->bio_flags |= BIO_ERROR;
+			softc->error_inject = 0;
+		}
+	}
 
-		if (bp != NULL)
-			biotrack(bp, __func__);
-		LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
-		if (LIST_EMPTY(&softc->pending_ccbs))
-			softc->flags |= DA_FLAG_WAS_OTAG;
+	if (bp != NULL)
+		biotrack(bp, __func__);
+	LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
+	if (LIST_EMPTY(&softc->pending_ccbs))
+		softc->flags |= DA_FLAG_WAS_OTAG;
 
+	/*
+	 * We need to call cam_iosched before we call biodone so that we
+	 * don't measure any activity that happens in the completion
+	 * routine, which in the case of sendfile can be quite
+	 * extensive.
+	 */
+	cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb);
+	xpt_release_ccb(done_ccb);
+	if (state == DA_CCB_DELETE) {
+		TAILQ_HEAD(, bio) queue;
+
+		TAILQ_INIT(&queue);
+		TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue);
+		softc->delete_run_queue.insert_point = NULL;
 		/*
-		 * We need to call cam_iosched before we call biodone so that we
-		 * don't measure any activity that happens in the completion
-		 * routine, which in the case of sendfile can be quite
-		 * extensive.
+		 * Normally, the xpt_release_ccb() above would make sure
+		 * that when we have more work to do, that work would
+		 * get kicked off. However, we specifically keep
+		 * delete_running set to 0 before the call above to
+		 * allow other I/O to progress when many BIO_DELETE
+		 * requests are pushed down. We set delete_running to 0
+		 * and call daschedule again so that we don't stall if
+		 * there are no other I/Os pending apart from BIO_DELETEs.
 		 */
-		cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb);
-		xpt_release_ccb(done_ccb);
-		if (state == DA_CCB_DELETE) {
-			TAILQ_HEAD(, bio) queue;
-
-			TAILQ_INIT(&queue);
-			TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue);
-			softc->delete_run_queue.insert_point = NULL;
-			/*
-			 * Normally, the xpt_release_ccb() above would make sure
-			 * that when we have more work to do, that work would
-			 * get kicked off. However, we specifically keep
-			 * delete_running set to 0 before the call above to
-			 * allow other I/O to progress when many BIO_DELETE
-			 * requests are pushed down. We set delete_running to 0
-			 * and call daschedule again so that we don't stall if
-			 * there are no other I/Os pending apart from BIO_DELETEs.
-			 */
-			cam_iosched_trim_done(softc->cam_iosched);
-			daschedule(periph);
-			cam_periph_unlock(periph);
-			while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
-				TAILQ_REMOVE(&queue, bp1, bio_queue);
-				bp1->bio_error = bp->bio_error;
-				if (bp->bio_flags & BIO_ERROR) {
-					bp1->bio_flags |= BIO_ERROR;
-					bp1->bio_resid = bp1->bio_bcount;
-				} else
-					bp1->bio_resid = 0;
-				biodone(bp1);
-			}
-		} else {
-			daschedule(periph);
-			cam_periph_unlock(periph);
+		cam_iosched_trim_done(softc->cam_iosched);
+		daschedule(periph);
+		cam_periph_unlock(periph);
+		while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
+			TAILQ_REMOVE(&queue, bp1, bio_queue);
+			bp1->bio_error = bp->bio_error;
+			if (bp->bio_flags & BIO_ERROR) {
+				bp1->bio_flags |= BIO_ERROR;
+				bp1->bio_resid = bp1->bio_bcount;
+			} else
+				bp1->bio_resid = 0;
+			biodone(bp1);
 		}
-		if (bp != NULL)
-			biodone(bp);
-		return;
+	} else {
+		daschedule(periph);
+		cam_periph_unlock(periph);
 	}
-	case DA_CCB_PROBE_WP:
-	{
-		struct scsi_mode_header_6 *mode_hdr6;
-		struct scsi_mode_header_10 *mode_hdr10;
-		uint8_t dev_spec;
+	if (bp != NULL)
+		biodone(bp);
+	return;
+}
 
-		if (softc->minimum_cmd_size > 6) {
-			mode_hdr10 = (struct scsi_mode_header_10 *)csio->data_ptr;
-			dev_spec = mode_hdr10->dev_spec;
-		} else {
-			mode_hdr6 = (struct scsi_mode_header_6 *)csio->data_ptr;
-			dev_spec = mode_hdr6->dev_spec;
-		}
-		if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) {
-			if ((dev_spec & 0x80) != 0)
-				softc->disk->d_flags |= DISKFLAG_WRITE_PROTECT;
-			else
-				softc->disk->d_flags &= ~DISKFLAG_WRITE_PROTECT;
-		} else {
-			int error;
+static void
+dadone_probewp(struct cam_periph *periph, union ccb *done_ccb)
+{
+	struct scsi_mode_header_6 *mode_hdr6;
+	struct scsi_mode_header_10 *mode_hdr10;
+	struct da_softc *softc;
+	struct ccb_scsiio *csio;
+	u_int32_t  priority;
+	uint8_t dev_spec;
 
-			error = daerror(done_ccb, CAM_RETRY_SELTO,
-					SF_RETRY_UA|SF_NO_PRINT);
-			if (error == ERESTART)
-				return;
-			else if (error != 0) {
-				if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
-					/* Don't wedge this device's queue */
-					cam_release_devq(done_ccb->ccb_h.path,
-							 /*relsim_flags*/0,
-							 /*reduction*/0,
-							 /*timeout*/0,
-							 /*getcount_only*/0);
-				}
-			}
-		}
+	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone_probewp\n"));
 
-		free(csio->data_ptr, M_SCSIDA);
-		xpt_release_ccb(done_ccb);
-		if ((softc->flags & DA_FLAG_CAN_RC16) != 0)
-			softc->state = DA_STATE_PROBE_RC16;
+	softc = (struct da_softc *)periph->softc;
+	priority = done_ccb->ccb_h.pinfo.priority;
+	csio = &done_ccb->csio;
+
+	if (softc->minimum_cmd_size > 6) {
+		mode_hdr10 = (struct scsi_mode_header_10 *)csio->data_ptr;
+		dev_spec = mode_hdr10->dev_spec;
+	} else {
+		mode_hdr6 = (struct scsi_mode_header_6 *)csio->data_ptr;
+		dev_spec = mode_hdr6->dev_spec;
+	}
+	if (cam_ccb_status(done_ccb) == CAM_REQ_CMP) {
+		if ((dev_spec & 0x80) != 0)
+			softc->disk->d_flags |= DISKFLAG_WRITE_PROTECT;
 		else
-			softc->state = DA_STATE_PROBE_RC;
-		xpt_schedule(periph, priority);
-		return;
+			softc->disk->d_flags &= ~DISKFLAG_WRITE_PROTECT;
+	} else {
+		int error;
+
+		error = daerror(done_ccb, CAM_RETRY_SELTO,
+				SF_RETRY_UA|SF_NO_PRINT);
+		if (error == ERESTART)
+			return;
+		else if (error != 0) {
+			if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+				/* Don't wedge this device's queue */
+				cam_release_devq(done_ccb->ccb_h.path,
+						 /*relsim_flags*/0,
+						 /*reduction*/0,
+						 /*timeout*/0,
+						 /*getcount_only*/0);
+			}
+		}
 	}
-	case DA_CCB_PROBE_RC:
-	case DA_CCB_PROBE_RC16:
-	{
-		struct	   scsi_read_capacity_data *rdcap;
-		struct     scsi_read_capacity_data_long *rcaplong;
-		char	   *announce_buf;
-		int	   lbp;
 
-		lbp = 0;
-		rdcap = NULL;
-		rcaplong = NULL;
-		/* XXX TODO: can this be a malloc? */
-		announce_buf = softc->announce_temp;
-		bzero(announce_buf, DA_ANNOUNCETMP_SZ);
+	free(csio->data_ptr, M_SCSIDA);
+	xpt_release_ccb(done_ccb);
+	if ((softc->flags & DA_FLAG_CAN_RC16) != 0)
+		softc->state = DA_STATE_PROBE_RC16;
+	else
+		softc->state = DA_STATE_PROBE_RC;
+	xpt_schedule(periph, priority);
+	return;
+}
 
-		if (state == DA_CCB_PROBE_RC)
-			rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
-		else
-			rcaplong = (struct scsi_read_capacity_data_long *)
-				csio->data_ptr;
+static void
+dadone_proberc(struct cam_periph *periph, union ccb *done_ccb)
+{
+	struct scsi_read_capacity_data *rdcap;
+	struct scsi_read_capacity_data_long *rcaplong;
+	struct da_softc *softc;
+	struct ccb_scsiio *csio;
+	da_ccb_state state;
+	char *announce_buf;
+	u_int32_t  priority;
+	int lbp;
 
-		if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
-			struct disk_params *dp;
-			uint32_t block_size;
-			uint64_t maxsector;
-			u_int lalba;	/* Lowest aligned LBA. */
+	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone_proberc\n"));
 
-			if (state == DA_CCB_PROBE_RC) {
-				block_size = scsi_4btoul(rdcap->length);
-				maxsector = scsi_4btoul(rdcap->addr);
-				lalba = 0;
+	softc = (struct da_softc *)periph->softc;
+	priority = done_ccb->ccb_h.pinfo.priority;
+	csio = &done_ccb->csio;
+	state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
 
-				/*
-				 * According to SBC-2, if the standard 10
-				 * byte READ CAPACITY command returns 2^32,
-				 * we should issue the 16 byte version of
-				 * the command, since the device in question
-				 * has more sectors than can be represented
-				 * with the short version of the command.
-				 */
-				if (maxsector == 0xffffffff) {
-					free(rdcap, M_SCSIDA);
-					xpt_release_ccb(done_ccb);
-					softc->state = DA_STATE_PROBE_RC16;
-					xpt_schedule(periph, priority);
-					return;
-				}
-			} else {
-				block_size = scsi_4btoul(rcaplong->length);
-				maxsector = scsi_8btou64(rcaplong->addr);
-				lalba = scsi_2btoul(rcaplong->lalba_lbp);
-			}
+	lbp = 0;
+	rdcap = NULL;
+	rcaplong = NULL;
+	/* XXX TODO: can this be a malloc? */
+	announce_buf = softc->announce_temp;
+	bzero(announce_buf, DA_ANNOUNCETMP_SZ);
 
+	if (state == DA_CCB_PROBE_RC)
+		rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
+	else
+		rcaplong = (struct scsi_read_capacity_data_long *)
+			csio->data_ptr;
+
+	if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+		struct disk_params *dp;
+		uint32_t block_size;
+		uint64_t maxsector;
+		u_int lalba;	/* Lowest aligned LBA. */
+
+		if (state == DA_CCB_PROBE_RC) {
+			block_size = scsi_4btoul(rdcap->length);
+			maxsector = scsi_4btoul(rdcap->addr);
+			lalba = 0;
+
 			/*
-			 * Because GEOM code just will panic us if we
-			 * give them an 'illegal' value we'll avoid that
-			 * here.
+			 * According to SBC-2, if the standard 10
+			 * byte READ CAPACITY command returns 2^32,
+			 * we should issue the 16 byte version of
+			 * the command, since the device in question
+			 * has more sectors than can be represented
+			 * with the short version of the command.
 			 */
-			if (block_size == 0) {
-				block_size = 512;
-				if (maxsector == 0)
-					maxsector = -1;
+			if (maxsector == 0xffffffff) {
+				free(rdcap, M_SCSIDA);
+				xpt_release_ccb(done_ccb);
+				softc->state = DA_STATE_PROBE_RC16;
+				xpt_schedule(periph, priority);
+				return;
 			}
-			if (block_size >= MAXPHYS) {
-				xpt_print(periph->path,
-				    "unsupportable block size %ju\n",
-				    (uintmax_t) block_size);
-				announce_buf = NULL;
-				cam_periph_invalidate(periph);
-			} else {
-				/*
-				 * We pass rcaplong into dasetgeom(),
-				 * because it will only use it if it is
-				 * non-NULL.
-				 */
-				dasetgeom(periph, block_size, maxsector,
-					  rcaplong, sizeof(*rcaplong));
-				lbp = (lalba & SRC16_LBPME_A);
-				dp = &softc->params;
-				snprintf(announce_buf, DA_ANNOUNCETMP_SZ,
-				    "%juMB (%ju %u byte sectors)",
-				    ((uintmax_t)dp->secsize * dp->sectors) /
-				     (1024 * 1024),
-				    (uintmax_t)dp->sectors, dp->secsize);
-			}
 		} else {
-			int	error;
+			block_size = scsi_4btoul(rcaplong->length);
+			maxsector = scsi_8btou64(rcaplong->addr);
+			lalba = scsi_2btoul(rcaplong->lalba_lbp);
+		}
 
+		/*
+		 * Because GEOM code just will panic us if we
+		 * give them an 'illegal' value we'll avoid that
+		 * here.
+		 */
+		if (block_size == 0) {
+			block_size = 512;
+			if (maxsector == 0)
+				maxsector = -1;
+		}
+		if (block_size >= MAXPHYS) {
+			xpt_print(periph->path,
+			    "unsupportable block size %ju\n",
+			    (uintmax_t) block_size);
+			announce_buf = NULL;
+			cam_periph_invalidate(periph);
+		} else {
 			/*
-			 * Retry any UNIT ATTENTION type errors.  They
-			 * are expected at boot.
+			 * We pass rcaplong into dasetgeom(),
+			 * because it will only use it if it is
+			 * non-NULL.
 			 */
-			error = daerror(done_ccb, CAM_RETRY_SELTO,
-					SF_RETRY_UA|SF_NO_PRINT);
-			if (error == ERESTART) {
-				/*
-				 * A retry was scheuled, so
-				 * just return.
-				 */
-				return;
-			} else if (error != 0) {
-				int asc, ascq;
-				int sense_key, error_code;
-				int have_sense;
-				cam_status status;
-				struct ccb_getdev cgd;
+			dasetgeom(periph, block_size, maxsector,
+				  rcaplong, sizeof(*rcaplong));
+			lbp = (lalba & SRC16_LBPME_A);
+			dp = &softc->params;
+			snprintf(announce_buf, DA_ANNOUNCETMP_SZ,
+			    "%juMB (%ju %u byte sectors)",
+			    ((uintmax_t)dp->secsize * dp->sectors) /
+			     (1024 * 1024),
+			    (uintmax_t)dp->sectors, dp->secsize);
+		}
+	} else {
+		int error;
 
-				/* Don't wedge this device's queue */
-				status = done_ccb->ccb_h.status;
-				if ((status & CAM_DEV_QFRZN) != 0)
-					cam_release_devq(done_ccb->ccb_h.path,
-							 /*relsim_flags*/0,
-							 /*reduction*/0,
-							 /*timeout*/0,
-							 /*getcount_only*/0);
+		/*
+		 * Retry any UNIT ATTENTION type errors.  They
+		 * are expected at boot.
+		 */
+		error = daerror(done_ccb, CAM_RETRY_SELTO,
+				SF_RETRY_UA|SF_NO_PRINT);
+		if (error == ERESTART) {
+			/*
+			 * A retry was scheuled, so
+			 * just return.
+			 */
+			return;
+		} else if (error != 0) {
+			int asc, ascq;
+			int sense_key, error_code;
+			int have_sense;
+			cam_status status;
+			struct ccb_getdev cgd;
 
+			/* Don't wedge this device's queue */
+			status = done_ccb->ccb_h.status;
+			if ((status & CAM_DEV_QFRZN) != 0)
+				cam_release_devq(done_ccb->ccb_h.path,
+						 /*relsim_flags*/0,
+						 /*reduction*/0,
+						 /*timeout*/0,
+						 /*getcount_only*/0);
 
-				xpt_setup_ccb(&cgd.ccb_h, 
-					      done_ccb->ccb_h.path,
-					      CAM_PRIORITY_NORMAL);
-				cgd.ccb_h.func_code = XPT_GDEV_TYPE;
-				xpt_action((union ccb *)&cgd);
 
-				if (scsi_extract_sense_ccb(done_ccb,
-				    &error_code, &sense_key, &asc, &ascq))
-					have_sense = TRUE;
-				else
-					have_sense = FALSE;
+			xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path,
+				      CAM_PRIORITY_NORMAL);
+			cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+			xpt_action((union ccb *)&cgd);
 
-				/*
-				 * If we tried READ CAPACITY(16) and failed,
-				 * fallback to READ CAPACITY(10).
-				 */
-				if ((state == DA_CCB_PROBE_RC16) &&
-				    (softc->flags & DA_FLAG_CAN_RC16) &&
-				    (((csio->ccb_h.status & CAM_STATUS_MASK) ==
-					CAM_REQ_INVALID) ||
-				     ((have_sense) &&
-				      (error_code == SSD_CURRENT_ERROR ||
-				       error_code == SSD_DESC_CURRENT_ERROR) &&
-				      (sense_key == SSD_KEY_ILLEGAL_REQUEST)))) {
-					cam_periph_assert(periph, MA_OWNED);
-					softc->flags &= ~DA_FLAG_CAN_RC16;
-					free(rdcap, M_SCSIDA);
-					xpt_release_ccb(done_ccb);
-					softc->state = DA_STATE_PROBE_RC;
-					xpt_schedule(periph, priority);
-					return;
-				}
+			if (scsi_extract_sense_ccb(done_ccb,
+			    &error_code, &sense_key, &asc, &ascq))
+				have_sense = TRUE;
+			else
+				have_sense = FALSE;
 
-				/*
-				 * Attach to anything that claims to be a
-				 * direct access or optical disk device,
-				 * as long as it doesn't return a "Logical
-				 * unit not supported" (0x25) error.
-				 * "Internal Target Failure" (0x44) is also
-				 * special and typically means that the
-				 * device is a SATA drive behind a SATL
-				 * translation that's fallen into a
-				 * terminally fatal state.
-				 */
-				if ((have_sense)
-				 && (asc != 0x25) && (asc != 0x44)
-				 && (error_code == SSD_CURRENT_ERROR
-				  || error_code == SSD_DESC_CURRENT_ERROR)) {
-					const char *sense_key_desc;
-					const char *asc_desc;
-
-					dasetgeom(periph, 512, -1, NULL, 0);
-					scsi_sense_desc(sense_key, asc, ascq,
-							&cgd.inq_data,
-							&sense_key_desc,
-							&asc_desc);
-					snprintf(announce_buf,
-					    DA_ANNOUNCETMP_SZ,
-					    "Attempt to query device "
-					    "size failed: %s, %s",
-					    sense_key_desc, asc_desc);
-				} else { 
-					if (have_sense)
-						scsi_sense_print(
-							&done_ccb->csio);
-					else {
-						xpt_print(periph->path,
-						    "got CAM status %#x\n",
-						    done_ccb->ccb_h.status);
-					}
-
-					xpt_print(periph->path, "fatal error, "
-					    "failed to attach to device\n");
-
-					announce_buf = NULL;
-
-					/*
-					 * Free up resources.
-					 */
-					cam_periph_invalidate(periph);
-				} 
+			/*
+			 * If we tried READ CAPACITY(16) and failed,
+			 * fallback to READ CAPACITY(10).
+			 */
+			if ((state == DA_CCB_PROBE_RC16) &&
+			    (softc->flags & DA_FLAG_CAN_RC16) &&
+			    (((csio->ccb_h.status & CAM_STATUS_MASK) ==
+				CAM_REQ_INVALID) ||
+			     ((have_sense) &&
+			      (error_code == SSD_CURRENT_ERROR ||
+			       error_code == SSD_DESC_CURRENT_ERROR) &&
+			      (sense_key == SSD_KEY_ILLEGAL_REQUEST)))) {
+				cam_periph_assert(periph, MA_OWNED);
+				softc->flags &= ~DA_FLAG_CAN_RC16;
+				free(rdcap, M_SCSIDA);
+				xpt_release_ccb(done_ccb);
+				softc->state = DA_STATE_PROBE_RC;
+				xpt_schedule(periph, priority);
+				return;
 			}
-		}
-		free(csio->data_ptr, M_SCSIDA);
-		if (announce_buf != NULL &&
-		    ((softc->flags & DA_FLAG_ANNOUNCED) == 0)) {
-			struct sbuf sb;
 
-			sbuf_new(&sb, softc->announcebuf, DA_ANNOUNCE_SZ,
-			    SBUF_FIXEDLEN);
-			xpt_announce_periph_sbuf(periph, &sb, announce_buf);
-			xpt_announce_quirks_sbuf(periph, &sb, softc->quirks,
-			    DA_Q_BIT_STRING);
-			sbuf_finish(&sb);
-			sbuf_putbuf(&sb);
-
 			/*
-			 * Create our sysctl variables, now that we know
-			 * we have successfully attached.
+			 * Attach to anything that claims to be a
+			 * direct access or optical disk device,
+			 * as long as it doesn't return a "Logical
+			 * unit not supported" (0x25) error.
+			 * "Internal Target Failure" (0x44) is also
+			 * special and typically means that the
+			 * device is a SATA drive behind a SATL
+			 * translation that's fallen into a
+			 * terminally fatal state.
 			 */
-			/* increase the refcount */
-			if (da_periph_acquire(periph, DA_REF_SYSCTL) == 0) {
+			if ((have_sense)
+			 && (asc != 0x25) && (asc != 0x44)
+			 && (error_code == SSD_CURRENT_ERROR
+			  || error_code == SSD_DESC_CURRENT_ERROR)) {
+				const char *sense_key_desc;
+				const char *asc_desc;
 
-				taskqueue_enqueue(taskqueue_thread,
-						  &softc->sysctl_task);
-			} else {
-				/* XXX This message is useless! */
+				dasetgeom(periph, 512, -1, NULL, 0);
+				scsi_sense_desc(sense_key, asc, ascq,
+						&cgd.inq_data, &sense_key_desc,
+						&asc_desc);
+				snprintf(announce_buf, DA_ANNOUNCETMP_SZ,
+				    "Attempt to query device "
+				    "size failed: %s, %s",
+				    sense_key_desc, asc_desc);
+			} else { 
+				if (have_sense)
+					scsi_sense_print(&done_ccb->csio);
+				else {
+					xpt_print(periph->path,
+					    "got CAM status %#x\n",
+					    done_ccb->ccb_h.status);
+				}

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


More information about the svn-src-all mailing list