summaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
authorDamien Le Moal <dlemoal@kernel.org>2023-05-11 03:13:51 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2023-05-22 17:05:20 -0400
commiteafe804bda7ba01da562c43351068b8a76a579af (patch)
tree2914ef0556797d082d55b501090a891e032b22af /drivers/ata/libata-scsi.c
parentdf60f9c64576d6d05b59ec5c34addcd61ef1efb0 (diff)
downloadlinux-eafe804bda7ba01da562c43351068b8a76a579af.tar.gz
linux-eafe804bda7ba01da562c43351068b8a76a579af.tar.bz2
linux-eafe804bda7ba01da562c43351068b8a76a579af.zip
scsi: ata: libata: Set read/write commands CDL index
For devices supporting the command duration limits feature, translate the dld field of read and write operation to set the command duration limit index field of the command task file when the duration limit feature is enabled. The function ata_set_tf_cdl() is introduced to do this. For unqueued (non NCQ) read and write operations, this function sets the command duration limit index set as the lower 3 bits of the feature field. For queued NCQ read/write commands, the index is set as the lower 3 bits of the auxiliary field. The flag ATA_QCFLAG_HAS_CDL is introduced to indicate that a command taskfile has a non zero cdl field. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Igor Pylypiv <ipylypiv@google.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Co-developed-by: Niklas Cassel <niklas.cassel@wdc.com> Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com> Link: https://lore.kernel.org/r/20230511011356.227789-19-nks@flawful.org Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 91db4e7f4906..69fc0d2c2123 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1381,6 +1381,18 @@ static inline void scsi_16_lba_len(const u8 *cdb, u64 *plba, u32 *plen)
}
/**
+ * scsi_dld - Get duration limit descriptor index
+ * @cdb: SCSI command to translate
+ *
+ * Returns the dld bits indicating the index of a command duration limit
+ * descriptor.
+ */
+static inline int scsi_dld(const u8 *cdb)
+{
+ return ((cdb[1] & 0x01) << 2) | ((cdb[14] >> 6) & 0x03);
+}
+
+/**
* ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
* @qc: Storage for translated ATA taskfile
*
@@ -1548,6 +1560,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
struct request *rq = scsi_cmd_to_rq(scmd);
int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
unsigned int tf_flags = 0;
+ int dld = 0;
u64 block;
u32 n_block;
int rc;
@@ -1598,6 +1611,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
goto invalid_fld;
}
scsi_16_lba_len(cdb, &block, &n_block);
+ dld = scsi_dld(cdb);
if (cdb[1] & (1 << 3))
tf_flags |= ATA_TFLAG_FUA;
if (!ata_check_nblocks(scmd, n_block))
@@ -1622,7 +1636,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_IO;
qc->nbytes = n_block * scmd->device->sector_size;
- rc = ata_build_rw_tf(qc, block, n_block, tf_flags, class);
+ rc = ata_build_rw_tf(qc, block, n_block, tf_flags, dld, class);
if (likely(rc == 0))
return 0;