svn commit: r249941 - in head/sys/cam: ata scsi

Steven Hartland smh at FreeBSD.org
Fri Apr 26 16:31:04 UTC 2013


Author: smh
Date: Fri Apr 26 16:31:03 2013
New Revision: 249941
URL: http://svnweb.freebsd.org/changeset/base/249941

Log:
  Added automatic detection of non-rotating media which disables the
  use of BIO queue sorting, hence optimising performance for devices
  such as SSD's
  
  Reviewed by:	scottl
  Approved by:	pjd (mentor)
  MFC after:	2 weeks

Modified:
  head/sys/cam/ata/ata_da.c
  head/sys/cam/scsi/scsi_all.h
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c	Fri Apr 26 16:22:54 2013	(r249940)
+++ head/sys/cam/ata/ata_da.c	Fri Apr 26 16:31:03 2013	(r249941)
@@ -1155,7 +1155,11 @@ adaregister(struct cam_periph *periph, v
 	snprintf(announce_buf, sizeof(announce_buf),
 	    "kern.cam.ada.%d.write_cache", periph->unit_number);
 	TUNABLE_INT_FETCH(announce_buf, &softc->write_cache);
-	softc->sort_io_queue = -1;
+	/* Disable queue sorting for non-rotatational media by default */
+	if (cgd->ident_data.media_rotation_rate == 1)
+		softc->sort_io_queue = 0;
+	else
+		softc->sort_io_queue = -1;
 	adagetparams(periph, cgd);
 	softc->disk = disk_alloc();
 	softc->disk->d_devstat = devstat_new_entry(periph->periph_name,

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h	Fri Apr 26 16:22:54 2013	(r249940)
+++ head/sys/cam/scsi/scsi_all.h	Fri Apr 26 16:31:03 2013	(r249941)
@@ -1430,6 +1430,30 @@ struct scsi_diag_page {
 };
 
 /*
+ * Block Device Characteristics VPD Page based on
+ * T10/1799-D Revision 31
+ */
+struct scsi_vpd_block_characteristics
+{
+	u_int8_t device;
+	u_int8_t page_code;
+#define SVPD_BDC			0xB1
+	u_int8_t page_length[2];
+	u_int8_t medium_rotation_rate[2];
+#define SVPD_BDC_RATE_NOT_REPORTED	0x00
+#define SVPD_BDC_RATE_NONE_ROTATING	0x01
+	u_int8_t reserved1;
+	u_int8_t nominal_form_factor;
+#define SVPD_BDC_FORM_NOT_REPORTED	0x00
+#define SVPD_BDC_FORM_5_25INCH		0x01
+#define SVPD_BDC_FORM_3_5INCH		0x02
+#define SVPD_BDC_FORM_2_5INCH		0x03
+#define SVPD_BDC_FORM_1_5INCH		0x04
+#define SVPD_BDC_FORM_LESSTHAN_1_5INCH	0x05
+	u_int8_t reserved2[56];
+};
+
+/*
  * Logical Block Provisioning VPD Page based on
  * T10/1799-D Revision 31
  */

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c	Fri Apr 26 16:22:54 2013	(r249940)
+++ head/sys/cam/scsi/scsi_da.c	Fri Apr 26 16:31:03 2013	(r249941)
@@ -72,6 +72,7 @@ typedef enum {
 	DA_STATE_PROBE_RC16,
 	DA_STATE_PROBE_LBP,
 	DA_STATE_PROBE_BLK_LIMITS,
+	DA_STATE_PROBE_BDC,
 	DA_STATE_PROBE_ATA,
 	DA_STATE_NORMAL
 } da_state;
@@ -104,12 +105,13 @@ typedef enum {
 	DA_CCB_PROBE_RC16	= 0x02,
 	DA_CCB_PROBE_LBP	= 0x03,
 	DA_CCB_PROBE_BLK_LIMITS	= 0x04,
-	DA_CCB_PROBE_ATA	= 0x05,
-	DA_CCB_BUFFER_IO	= 0x06,
-	DA_CCB_WAITING		= 0x07,
-	DA_CCB_DUMP		= 0x08,
-	DA_CCB_DELETE		= 0x0A,
-	DA_CCB_TUR		= 0x0B,
+	DA_CCB_PROBE_BDC	= 0x05,
+	DA_CCB_PROBE_ATA	= 0x06,
+	DA_CCB_BUFFER_IO	= 0x07,
+	DA_CCB_WAITING		= 0x08,
+	DA_CCB_DUMP		= 0x0A,
+	DA_CCB_DELETE		= 0x0B,
+ 	DA_CCB_TUR		= 0x0C,
 	DA_CCB_TYPE_MASK	= 0x0F,
 	DA_CCB_RETRY_UA		= 0x10
 } da_ccb_state;
@@ -2424,6 +2426,39 @@ out:
 		xpt_action(start_ccb);
 		break;
 	}
+	case DA_STATE_PROBE_BDC:
+	{
+		struct scsi_vpd_block_characteristics *bdc;
+
+		if (!scsi_vpd_supported_page(periph, SVPD_BDC)) {
+			softc->state = DA_STATE_PROBE_ATA;
+			goto skipstate;
+		}
+
+		bdc = (struct scsi_vpd_block_characteristics *)
+			malloc(sizeof(*bdc), M_SCSIDA, M_NOWAIT|M_ZERO);
+
+		if (bdc == NULL) {
+			printf("dastart: Couldn't malloc bdc data\n");
+			/* da_free_periph??? */
+			break;
+		}
+
+		scsi_inquiry(&start_ccb->csio,
+			     /*retries*/da_retry_count,
+			     /*cbfcnp*/dadone,
+			     /*tag_action*/MSG_SIMPLE_Q_TAG,
+			     /*inq_buf*/(u_int8_t *)bdc,
+			     /*inq_len*/sizeof(*bdc),
+			     /*evpd*/TRUE,
+			     /*page_code*/SVPD_BDC,
+			     /*sense_len*/SSD_MIN_SIZE,
+			     /*timeout*/da_default_timeout * 1000);
+		start_ccb->ccb_h.ccb_bp = NULL;
+		start_ccb->ccb_h.ccb_state = DA_CCB_PROBE_BDC;
+		xpt_action(start_ccb);
+		break;
+	}
 	case DA_STATE_PROBE_ATA:
 	{
 		struct ata_params *ata_params;
@@ -2904,7 +2939,7 @@ dadone(struct cam_periph *periph, union 
 		}
 
 		xpt_release_ccb(done_ccb);
-		softc->state = DA_STATE_PROBE_ATA;
+		softc->state = DA_STATE_PROBE_BDC;
 		xpt_schedule(periph, priority);
 		return;
 	}
@@ -3027,6 +3062,40 @@ dadone(struct cam_periph *periph, union 
 		xpt_schedule(periph, priority);
 		return;
 	}
+	case DA_CCB_PROBE_BDC:
+	{
+		struct scsi_vpd_block_characteristics *bdc;
+
+		bdc = (struct scsi_vpd_block_characteristics *)csio->data_ptr;
+
+		if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+			if (scsi_2btoul(bdc->medium_rotation_rate) ==
+			    SVPD_BDC_RATE_NONE_ROTATING)
+				softc->sort_io_queue = 0;
+		} 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);
+				}
+			}
+		}
+
+		free(bdc, M_SCSIDA);
+		softc->state = DA_STATE_PROBE_ATA;
+		xpt_release_ccb(done_ccb);
+		xpt_schedule(periph, priority);
+		return;
+	}
 	case DA_CCB_PROBE_ATA:
 	{
 		int i;
@@ -3047,6 +3116,12 @@ dadone(struct cam_periph *periph, union 
 					  ata_params->max_dsm_blocks *
 					  ATA_DSM_BLK_RANGES);
 			}
+			/*
+			 * Disable queue sorting for non-rotatational media
+			 * by default
+			 */
+			if (ata_params->media_rotation_rate == 1)
+				softc->sort_io_queue = 0;
 		} else {
 			int error;
 			error = daerror(done_ccb, CAM_RETRY_SELTO,


More information about the svn-src-head mailing list