scsi: ata: libata: Detect support for command duration limits
Use the supported capabilities identify device data log page to detect if a device supports the command duration limits feature. For devices supporting this feature, set the device flag ATA_DFLAG_CDL. To support SCSI-ATA translation, retrieve the command duration limits log page 18h and cache this page content using the cdl array added to the ata_device data structure. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Christoph Hellwig <hch@lst.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-15-nks@flawful.org Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
24aeebbf8e
commit
62e4a60e0c
@ -2367,6 +2367,54 @@ static void ata_dev_config_trusted(struct ata_device *dev)
|
||||
dev->flags |= ATA_DFLAG_TRUSTED;
|
||||
}
|
||||
|
||||
static void ata_dev_config_cdl(struct ata_device *dev)
|
||||
{
|
||||
struct ata_port *ap = dev->link->ap;
|
||||
unsigned int err_mask;
|
||||
u64 val;
|
||||
|
||||
if (ata_id_major_version(dev->id) < 12)
|
||||
goto not_supported;
|
||||
|
||||
if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
|
||||
!ata_identify_page_supported(dev, ATA_LOG_SUPPORTED_CAPABILITIES))
|
||||
goto not_supported;
|
||||
|
||||
err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
|
||||
ATA_LOG_SUPPORTED_CAPABILITIES,
|
||||
ap->sector_buf, 1);
|
||||
if (err_mask)
|
||||
goto not_supported;
|
||||
|
||||
/* Check Command Duration Limit Supported bits */
|
||||
val = get_unaligned_le64(&ap->sector_buf[168]);
|
||||
if (!(val & BIT_ULL(63)) || !(val & BIT_ULL(0)))
|
||||
goto not_supported;
|
||||
|
||||
/* Warn the user if command duration guideline is not supported */
|
||||
if (!(val & BIT_ULL(1)))
|
||||
ata_dev_warn(dev,
|
||||
"Command duration guideline is not supported\n");
|
||||
|
||||
/*
|
||||
* Command duration limits is supported: cache the CDL log page 18h
|
||||
* (command duration descriptors).
|
||||
*/
|
||||
err_mask = ata_read_log_page(dev, ATA_LOG_CDL, 0, ap->sector_buf, 1);
|
||||
if (err_mask) {
|
||||
ata_dev_warn(dev, "Read Command Duration Limits log failed\n");
|
||||
goto not_supported;
|
||||
}
|
||||
|
||||
memcpy(dev->cdl, ap->sector_buf, ATA_LOG_CDL_SIZE);
|
||||
dev->flags |= ATA_DFLAG_CDL;
|
||||
|
||||
return;
|
||||
|
||||
not_supported:
|
||||
dev->flags &= ~ATA_DFLAG_CDL;
|
||||
}
|
||||
|
||||
static int ata_dev_config_lba(struct ata_device *dev)
|
||||
{
|
||||
const u16 *id = dev->id;
|
||||
@ -2534,13 +2582,14 @@ static void ata_dev_print_features(struct ata_device *dev)
|
||||
return;
|
||||
|
||||
ata_dev_info(dev,
|
||||
"Features:%s%s%s%s%s%s%s\n",
|
||||
"Features:%s%s%s%s%s%s%s%s\n",
|
||||
dev->flags & ATA_DFLAG_FUA ? " FUA" : "",
|
||||
dev->flags & ATA_DFLAG_TRUSTED ? " Trust" : "",
|
||||
dev->flags & ATA_DFLAG_DA ? " Dev-Attention" : "",
|
||||
dev->flags & ATA_DFLAG_DEVSLP ? " Dev-Sleep" : "",
|
||||
dev->flags & ATA_DFLAG_NCQ_SEND_RECV ? " NCQ-sndrcv" : "",
|
||||
dev->flags & ATA_DFLAG_NCQ_PRIO ? " NCQ-prio" : "",
|
||||
dev->flags & ATA_DFLAG_CDL ? " CDL" : "",
|
||||
dev->cpr_log ? " CPR" : "");
|
||||
}
|
||||
|
||||
@ -2702,6 +2751,7 @@ int ata_dev_configure(struct ata_device *dev)
|
||||
ata_dev_config_zac(dev);
|
||||
ata_dev_config_trusted(dev);
|
||||
ata_dev_config_cpr(dev);
|
||||
ata_dev_config_cdl(dev);
|
||||
dev->cdb_len = 32;
|
||||
|
||||
if (print_info)
|
||||
|
@ -47,15 +47,14 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
|
||||
static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
|
||||
const struct scsi_device *scsidev);
|
||||
|
||||
#define RW_RECOVERY_MPAGE 0x1
|
||||
#define RW_RECOVERY_MPAGE_LEN 12
|
||||
#define CACHE_MPAGE 0x8
|
||||
#define CACHE_MPAGE_LEN 20
|
||||
#define CONTROL_MPAGE 0xa
|
||||
#define CONTROL_MPAGE_LEN 12
|
||||
#define ALL_MPAGES 0x3f
|
||||
#define ALL_SUB_MPAGES 0xff
|
||||
|
||||
#define RW_RECOVERY_MPAGE 0x1
|
||||
#define RW_RECOVERY_MPAGE_LEN 12
|
||||
#define CACHE_MPAGE 0x8
|
||||
#define CACHE_MPAGE_LEN 20
|
||||
#define CONTROL_MPAGE 0xa
|
||||
#define CONTROL_MPAGE_LEN 12
|
||||
#define ALL_MPAGES 0x3f
|
||||
#define ALL_SUB_MPAGES 0xff
|
||||
|
||||
static const u8 def_rw_recovery_mpage[RW_RECOVERY_MPAGE_LEN] = {
|
||||
RW_RECOVERY_MPAGE,
|
||||
|
@ -322,15 +322,18 @@ enum {
|
||||
ATA_LOG_SATA_NCQ = 0x10,
|
||||
ATA_LOG_NCQ_NON_DATA = 0x12,
|
||||
ATA_LOG_NCQ_SEND_RECV = 0x13,
|
||||
ATA_LOG_CDL = 0x18,
|
||||
ATA_LOG_CDL_SIZE = ATA_SECT_SIZE,
|
||||
ATA_LOG_IDENTIFY_DEVICE = 0x30,
|
||||
ATA_LOG_CONCURRENT_POSITIONING_RANGES = 0x47,
|
||||
|
||||
/* Identify device log pages: */
|
||||
ATA_LOG_SUPPORTED_CAPABILITIES = 0x03,
|
||||
ATA_LOG_SECURITY = 0x06,
|
||||
ATA_LOG_SATA_SETTINGS = 0x08,
|
||||
ATA_LOG_ZONED_INFORMATION = 0x09,
|
||||
|
||||
/* Identify device SATA settings log:*/
|
||||
/* Identify device SATA settings log: */
|
||||
ATA_LOG_DEVSLP_OFFSET = 0x30,
|
||||
ATA_LOG_DEVSLP_SIZE = 0x08,
|
||||
ATA_LOG_DEVSLP_MDAT = 0x00,
|
||||
|
@ -94,17 +94,18 @@ enum {
|
||||
ATA_DFLAG_DMADIR = (1 << 10), /* device requires DMADIR */
|
||||
ATA_DFLAG_NCQ_SEND_RECV = (1 << 11), /* device supports NCQ SEND and RECV */
|
||||
ATA_DFLAG_NCQ_PRIO = (1 << 12), /* device supports NCQ priority */
|
||||
ATA_DFLAG_CFG_MASK = (1 << 13) - 1,
|
||||
ATA_DFLAG_CDL = (1 << 13), /* supports cmd duration limits */
|
||||
ATA_DFLAG_CFG_MASK = (1 << 14) - 1,
|
||||
|
||||
ATA_DFLAG_PIO = (1 << 13), /* device limited to PIO mode */
|
||||
ATA_DFLAG_NCQ_OFF = (1 << 14), /* device limited to non-NCQ mode */
|
||||
ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
|
||||
ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */
|
||||
ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */
|
||||
ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */
|
||||
ATA_DFLAG_INIT_MASK = (1 << 19) - 1,
|
||||
ATA_DFLAG_PIO = (1 << 14), /* device limited to PIO mode */
|
||||
ATA_DFLAG_NCQ_OFF = (1 << 15), /* device limited to non-NCQ mode */
|
||||
ATA_DFLAG_SLEEPING = (1 << 16), /* device is sleeping */
|
||||
ATA_DFLAG_DUBIOUS_XFER = (1 << 17), /* data transfer not verified */
|
||||
ATA_DFLAG_NO_UNLOAD = (1 << 18), /* device doesn't support unload */
|
||||
ATA_DFLAG_UNLOCK_HPA = (1 << 19), /* unlock HPA */
|
||||
ATA_DFLAG_INIT_MASK = (1 << 20) - 1,
|
||||
|
||||
ATA_DFLAG_NCQ_PRIO_ENABLED = (1 << 19), /* Priority cmds sent to dev */
|
||||
ATA_DFLAG_NCQ_PRIO_ENABLED = (1 << 20), /* Priority cmds sent to dev */
|
||||
ATA_DFLAG_DETACH = (1 << 24),
|
||||
ATA_DFLAG_DETACHED = (1 << 25),
|
||||
ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */
|
||||
@ -115,7 +116,8 @@ enum {
|
||||
|
||||
ATA_DFLAG_FEATURES_MASK = (ATA_DFLAG_TRUSTED | ATA_DFLAG_DA | \
|
||||
ATA_DFLAG_DEVSLP | ATA_DFLAG_NCQ_SEND_RECV | \
|
||||
ATA_DFLAG_NCQ_PRIO | ATA_DFLAG_FUA),
|
||||
ATA_DFLAG_NCQ_PRIO | ATA_DFLAG_FUA | \
|
||||
ATA_DFLAG_CDL),
|
||||
|
||||
ATA_DEV_UNKNOWN = 0, /* unknown device */
|
||||
ATA_DEV_ATA = 1, /* ATA device */
|
||||
@ -709,6 +711,9 @@ struct ata_device {
|
||||
/* Concurrent positioning ranges */
|
||||
struct ata_cpr_log *cpr_log;
|
||||
|
||||
/* Command Duration Limits log support */
|
||||
u8 cdl[ATA_LOG_CDL_SIZE];
|
||||
|
||||
/* error history */
|
||||
int spdn_cnt;
|
||||
/* ering is CLEAR_END, read comment above CLEAR_END */
|
||||
|
Loading…
x
Reference in New Issue
Block a user