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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to