diff options
author | mav <mav@FreeBSD.org> | 2014-05-08 07:13:22 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2014-05-08 07:13:22 +0000 |
commit | 8c4230087267cddda71bf6da3df6f9fd04d46b5e (patch) | |
tree | 08e754a64423293f2df0bf2f3fcce509a3d624b2 | |
parent | 878513ca7de9e1d7eac37951bb6895c636b49c91 (diff) | |
download | FreeBSD-src-8c4230087267cddda71bf6da3df6f9fd04d46b5e.zip FreeBSD-src-8c4230087267cddda71bf6da3df6f9fd04d46b5e.tar.gz |
MFC r265159:
Respect MAXIMUM TRANSFER LENGTH field of Block Limits VPD page.
Nobody yet reported disk supporting I/Os less then our MAXPHYS value, but
since we any way have code to read Block Limits VPD page, that is easy.
-rw-r--r-- | sys/cam/scsi/scsi_da.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 6f7b5c4..fc52c0d 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -212,6 +212,7 @@ struct da_softc { int trim_max_ranges; int delete_running; int delete_available; /* Delete methods possibly available */ + u_int maxio; uint32_t unmap_max_ranges; uint32_t unmap_max_lba; /* Max LBAs in UNMAP req */ uint64_t ws_max_blks; @@ -2135,11 +2136,12 @@ daregister(struct cam_periph *periph, void *arg) softc->disk->d_name = "da"; softc->disk->d_drv1 = periph; if (cpi.maxio == 0) - softc->disk->d_maxsize = DFLTPHYS; /* traditional default */ + softc->maxio = DFLTPHYS; /* traditional default */ else if (cpi.maxio > MAXPHYS) - softc->disk->d_maxsize = MAXPHYS; /* for safety */ + softc->maxio = MAXPHYS; /* for safety */ else - softc->disk->d_maxsize = cpi.maxio; + softc->maxio = cpi.maxio; + softc->disk->d_maxsize = softc->maxio; softc->disk->d_unit = periph->unit_number; softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION; if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) @@ -3279,14 +3281,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) (lbp->flags & SVPD_LBP_WS10)); dadeleteflag(softc, DA_DELETE_UNMAP, (lbp->flags & SVPD_LBP_UNMAP)); - - if (lbp->flags & SVPD_LBP_UNMAP) { - free(lbp, M_SCSIDA); - xpt_release_ccb(done_ccb); - softc->state = DA_STATE_PROBE_BLK_LIMITS; - xpt_schedule(periph, priority); - return; - } } else { int error; error = daerror(done_ccb, CAM_RETRY_SELTO, @@ -3312,7 +3306,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) free(lbp, M_SCSIDA); xpt_release_ccb(done_ccb); - softc->state = DA_STATE_PROBE_BDC; + softc->state = DA_STATE_PROBE_BLK_LIMITS; xpt_schedule(periph, priority); return; } @@ -3323,12 +3317,20 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) block_limits = (struct scsi_vpd_block_limits *)csio->data_ptr; if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) { + uint32_t max_txfer_len = scsi_4btoul( + block_limits->max_txfer_len); uint32_t max_unmap_lba_cnt = scsi_4btoul( block_limits->max_unmap_lba_cnt); uint32_t max_unmap_blk_cnt = scsi_4btoul( block_limits->max_unmap_blk_cnt); uint64_t ws_max_blks = scsi_8btou64( block_limits->max_write_same_length); + + if (max_txfer_len != 0) { + softc->disk->d_maxsize = MIN(softc->maxio, + (off_t)max_txfer_len * softc->params.secsize); + } + /* * We should already support UNMAP but we check lba * and block count to be sure |