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,
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to