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