Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Damien Le Moal and committed by
Martin K. Petersen
eafe804b df60f9c6

+46 -5
+29 -3
drivers/ata/libata-core.c
··· 665 665 return block; 666 666 } 667 667 668 + /* 669 + * Set a taskfile command duration limit index. 670 + */ 671 + static inline void ata_set_tf_cdl(struct ata_queued_cmd *qc, int cdl) 672 + { 673 + struct ata_taskfile *tf = &qc->tf; 674 + 675 + if (tf->protocol == ATA_PROT_NCQ) 676 + tf->auxiliary |= cdl; 677 + else 678 + tf->feature |= cdl; 679 + 680 + /* Mark this command as having a CDL */ 681 + qc->flags |= ATA_QCFLAG_HAS_CDL; 682 + } 683 + 668 684 /** 669 685 * ata_build_rw_tf - Build ATA taskfile for given read/write request 670 686 * @qc: Metadata associated with the taskfile to build 671 687 * @block: Block address 672 688 * @n_block: Number of blocks 673 689 * @tf_flags: RW/FUA etc... 690 + * @cdl: Command duration limit index 674 691 * @class: IO priority class 675 692 * 676 693 * LOCKING: ··· 702 685 * -EINVAL if the request is invalid. 703 686 */ 704 687 int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, 705 - unsigned int tf_flags, int class) 688 + unsigned int tf_flags, int cdl, int class) 706 689 { 707 690 struct ata_taskfile *tf = &qc->tf; 708 691 struct ata_device *dev = qc->dev; ··· 741 724 if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED && 742 725 class == IOPRIO_CLASS_RT) 743 726 tf->hob_nsect |= ATA_PRIO_HIGH << ATA_SHIFT_PRIO; 727 + 728 + if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl) 729 + ata_set_tf_cdl(qc, cdl); 730 + 744 731 } else if (dev->flags & ATA_DFLAG_LBA) { 745 732 tf->flags |= ATA_TFLAG_LBA; 746 733 747 - /* We need LBA48 for FUA writes */ 748 - if (!(tf->flags & ATA_TFLAG_FUA) && lba_28_ok(block, n_block)) { 734 + if ((dev->flags & ATA_DFLAG_CDL_ENABLED) && cdl) 735 + ata_set_tf_cdl(qc, cdl); 736 + 737 + /* Both FUA writes and a CDL index require 48-bit commands */ 738 + if (!(tf->flags & ATA_TFLAG_FUA) && 739 + !(qc->flags & ATA_QCFLAG_HAS_CDL) && 740 + lba_28_ok(block, n_block)) { 749 741 /* use LBA28 */ 750 742 tf->device |= (block >> 24) & 0xf; 751 743 } else if (lba_48_ok(block, n_block)) {
+15 -1
drivers/ata/libata-scsi.c
··· 1381 1381 } 1382 1382 1383 1383 /** 1384 + * scsi_dld - Get duration limit descriptor index 1385 + * @cdb: SCSI command to translate 1386 + * 1387 + * Returns the dld bits indicating the index of a command duration limit 1388 + * descriptor. 1389 + */ 1390 + static inline int scsi_dld(const u8 *cdb) 1391 + { 1392 + return ((cdb[1] & 0x01) << 2) | ((cdb[14] >> 6) & 0x03); 1393 + } 1394 + 1395 + /** 1384 1396 * ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one 1385 1397 * @qc: Storage for translated ATA taskfile 1386 1398 * ··· 1560 1548 struct request *rq = scsi_cmd_to_rq(scmd); 1561 1549 int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); 1562 1550 unsigned int tf_flags = 0; 1551 + int dld = 0; 1563 1552 u64 block; 1564 1553 u32 n_block; 1565 1554 int rc; ··· 1611 1598 goto invalid_fld; 1612 1599 } 1613 1600 scsi_16_lba_len(cdb, &block, &n_block); 1601 + dld = scsi_dld(cdb); 1614 1602 if (cdb[1] & (1 << 3)) 1615 1603 tf_flags |= ATA_TFLAG_FUA; 1616 1604 if (!ata_check_nblocks(scmd, n_block)) ··· 1636 1622 qc->flags |= ATA_QCFLAG_IO; 1637 1623 qc->nbytes = n_block * scmd->device->sector_size; 1638 1624 1639 - rc = ata_build_rw_tf(qc, block, n_block, tf_flags, class); 1625 + rc = ata_build_rw_tf(qc, block, n_block, tf_flags, dld, class); 1640 1626 if (likely(rc == 0)) 1641 1627 return 0; 1642 1628
+1 -1
drivers/ata/libata.h
··· 45 45 extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); 46 46 extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); 47 47 extern int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, 48 - unsigned int tf_flags, int class); 48 + unsigned int tf_flags, int dld, int class); 49 49 extern u64 ata_tf_read_block(const struct ata_taskfile *tf, 50 50 struct ata_device *dev); 51 51 extern unsigned ata_exec_internal(struct ata_device *dev,
+1
include/linux/libata.h
··· 209 209 ATA_QCFLAG_CLEAR_EXCL = (1 << 5), /* clear excl_link on completion */ 210 210 ATA_QCFLAG_QUIET = (1 << 6), /* don't report device error */ 211 211 ATA_QCFLAG_RETRY = (1 << 7), /* retry after failure */ 212 + ATA_QCFLAG_HAS_CDL = (1 << 8), /* qc has CDL a descriptor set */ 212 213 213 214 ATA_QCFLAG_EH = (1 << 16), /* cmd aborted and owned by EH */ 214 215 ATA_QCFLAG_SENSE_VALID = (1 << 17), /* sense data valid */