summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/ahci_da850.c17
-rw-r--r--drivers/ata/ahci_platform.c4
-rw-r--r--drivers/ata/ahci_qoriq.c2
-rw-r--r--drivers/ata/ahci_seattle.c4
-rw-r--r--drivers/ata/ahci_xgene.c6
-rw-r--r--drivers/ata/libata-core.c79
-rw-r--r--drivers/ata/libata-eh.c6
-rw-r--r--drivers/ata/libata-scsi.c714
-rw-r--r--drivers/ata/libata-sff.c24
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--drivers/ata/pata_ep93xx.c30
-rw-r--r--drivers/ata/pata_mpc52xx.c4
-rw-r--r--drivers/ata/pata_pxa.c52
-rw-r--r--drivers/ata/pata_rb532_cf.c16
-rw-r--r--drivers/ata/sata_highbank.c18
-rw-r--r--drivers/ata/sata_mv.c52
-rw-r--r--drivers/scsi/scsi_debug.c46
-rw-r--r--include/linux/ata.h17
-rw-r--r--include/linux/libata.h93
-rw-r--r--include/scsi/scsi_proto.h74
20 files changed, 915 insertions, 345 deletions
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index f97566c420f8..4e53ff96d712 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -162,7 +162,6 @@ static int ahci_da850_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv;
void __iomem *pwrdn_reg;
- struct resource *res;
u32 mpy;
int rc;
@@ -198,22 +197,14 @@ static int ahci_da850_probe(struct platform_device *pdev)
return -EINVAL;
}
+ pwrdn_reg = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(pwrdn_reg))
+ return PTR_ERR(pwrdn_reg);
+
rc = ahci_platform_enable_resources(hpriv);
if (rc)
return rc;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res) {
- rc = -ENODEV;
- goto disable_resources;
- }
-
- pwrdn_reg = devm_ioremap(dev, res->start, resource_size(res));
- if (!pwrdn_reg) {
- rc = -ENOMEM;
- goto disable_resources;
- }
-
da850_sata_init(dev, pwrdn_reg, hpriv->mmio, mpy);
rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info,
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 4fbcaff3283c..8724b242640e 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -87,9 +87,9 @@ static const struct of_device_id ahci_of_match[] = {
MODULE_DEVICE_TABLE(of, ahci_of_match);
static const struct acpi_device_id ahci_acpi_match[] = {
- { "APMC0D33", (unsigned long)&ahci_port_info_nolpm },
+ { .id = "APMC0D33", .driver_data = (unsigned long)&ahci_port_info_nolpm },
{ ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) },
- {},
+ { }
};
MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 0dec1a17e5b1..96492159fa7c 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -80,7 +80,7 @@ static const struct of_device_id ahci_qoriq_of_match[] = {
MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
static const struct acpi_device_id ahci_qoriq_acpi_match[] = {
- {"NXP0004", .driver_data = (kernel_ulong_t)AHCI_LX2160A},
+ { .id = "NXP0004", .driver_data = (kernel_ulong_t)AHCI_LX2160A },
{ }
};
MODULE_DEVICE_TABLE(acpi, ahci_qoriq_acpi_match);
diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c
index 3f16c1678402..9758fa0260ac 100644
--- a/drivers/ata/ahci_seattle.c
+++ b/drivers/ata/ahci_seattle.c
@@ -178,8 +178,8 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
ahci_platform_resume);
static const struct acpi_device_id ahci_acpi_match[] = {
- { "AMDI0600", 0 },
- {}
+ { .id = "AMDI0600" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 98c99b5a8242..2ebfe86e429b 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -710,9 +710,9 @@ static const struct scsi_host_template ahci_platform_sht = {
#ifdef CONFIG_ACPI
static const struct acpi_device_id xgene_ahci_acpi_match[] = {
- { "APMC0D0D", XGENE_AHCI_V1},
- { "APMC0D32", XGENE_AHCI_V2},
- {},
+ { .id = "APMC0D0D", .driver_data = XGENE_AHCI_V1 },
+ { .id = "APMC0D32", .driver_data = XGENE_AHCI_V2 },
+ { }
};
MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
#endif
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 59e87b987d73..f482c0a6d7e9 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2488,7 +2488,7 @@ static void ata_dev_config_sense_reporting(struct ata_device *dev)
}
}
-static void ata_dev_config_zac(struct ata_device *dev)
+static void ata_dev_config_zoned(struct ata_device *dev)
{
unsigned int err_mask;
u8 *identify_buf = dev->sector_buf;
@@ -2497,7 +2497,7 @@ static void ata_dev_config_zac(struct ata_device *dev)
dev->zac_zones_optimal_nonseq = U32_MAX;
dev->zac_zones_max_open = U32_MAX;
- if (!ata_dev_is_zac(dev))
+ if (!ata_dev_is_zoned(dev))
return;
if (!ata_identify_page_supported(dev, ATA_LOG_ZONED_INFORMATION)) {
@@ -2705,6 +2705,71 @@ not_supported:
ata_dev_cleanup_cdl_resources(dev);
}
+static void ata_dev_config_depop(struct ata_device *dev)
+{
+ unsigned int err_mask;
+ u64 val;
+
+ /* Ignore old drives. */
+ if (ata_id_major_version(dev->id) < 11)
+ goto not_supported;
+
+ /* NCQ Autosense is required. */
+ if (!ata_identify_page_supported(dev, ATA_LOG_SUPPORTED_CAPABILITIES) ||
+ !ata_id_has_ncq_autosense(dev->id))
+ goto not_supported;
+
+ err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
+ ATA_LOG_SUPPORTED_CAPABILITIES,
+ dev->sector_buf, 1);
+ if (err_mask)
+ goto not_supported;
+
+ /* Check depopulation capabilities bits. */
+ val = get_unaligned_le64(&dev->sector_buf[152]);
+ if (!(val & BIT_ULL(63)))
+ goto not_supported;
+
+ /*
+ * Support for at least the GET PHYSICAL ELEMENT STATUS and
+ * REMOVE ELEMENT AND TRUNCATE commands is mandated.
+ */
+ if (!(val & BIT_ULL(0)) || !(val & BIT_ULL(1)))
+ goto not_supported;
+
+ dev->flags |= ATA_DFLAG_DEPOP;
+
+ /* Check if RESTORE ELEMENTS AND REBUILD is supported. */
+ if (val & BIT_ULL(2))
+ dev->flags |= ATA_DFLAG_DEPOP_RESTORE;
+
+ /*
+ * For ZAC devices, check if REMOVE ELEMENT AND MODIFY ZONES is
+ * supported.
+ */
+ if (dev->class != ATA_DEV_ZAC)
+ return;
+
+ err_mask = ata_read_log_page(dev, ATA_LOG_IDENTIFY_DEVICE,
+ ATA_LOG_ZONED_INFORMATION,
+ dev->sector_buf, 1);
+ if (err_mask)
+ return;
+
+ val = get_unaligned_le64(&dev->sector_buf[8]);
+ if (!(val & BIT_ULL(63)))
+ return;
+
+ if (val & BIT_ULL(1))
+ dev->flags |= ATA_DFLAG_DEPOP_MODIFY;
+
+ return;
+
+not_supported:
+ dev->flags &= ~(ATA_DFLAG_DEPOP | ATA_DFLAG_DEPOP_RESTORE |
+ ATA_DFLAG_DEPOP_MODIFY);
+}
+
static int ata_dev_config_lba(struct ata_device *dev)
{
const u16 *id = dev->id;
@@ -2942,7 +3007,7 @@ static void ata_dev_print_features(struct ata_device *dev)
return;
ata_dev_info(dev,
- "Features:%s%s%s%s%s%s%s%s%s%s\n",
+ "Features:%s%s%s%s%s%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" : "",
@@ -2952,7 +3017,10 @@ static void ata_dev_print_features(struct ata_device *dev)
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" : "");
+ dev->cpr_log ? " CPR" : "",
+ dev->flags & ATA_DFLAG_DEPOP ? " Depop" : "",
+ dev->flags & ATA_DFLAG_DEPOP_RESTORE ? " Depop-Restore" : "",
+ dev->flags & ATA_DFLAG_DEPOP_MODIFY ? " Depop-Modify" : "");
}
/**
@@ -3111,10 +3179,11 @@ int ata_dev_configure(struct ata_device *dev)
ata_dev_config_fua(dev);
ata_dev_config_devslp(dev);
ata_dev_config_sense_reporting(dev);
- ata_dev_config_zac(dev);
+ ata_dev_config_zoned(dev);
ata_dev_config_trusted(dev);
ata_dev_config_cpr(dev);
ata_dev_config_cdl(dev);
+ ata_dev_config_depop(dev);
dev->cdb_len = 32;
if (print_info)
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index c154103d892c..c93c24b22d9c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1221,9 +1221,10 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
* Indicate to the mid and upper layers that an ATA command has
* completed. To be used from EH.
*/
-void ata_eh_qc_complete(struct ata_queued_cmd *qc)
+static void ata_eh_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
+
scmd->retries = scmd->allowed;
__ata_eh_qc_complete(qc);
}
@@ -1239,9 +1240,10 @@ void ata_eh_qc_complete(struct ata_queued_cmd *qc)
* scmd->allowed is incremented for commands which get retried
* due to unrelated failures (qc->err_mask is zero).
*/
-void ata_eh_qc_retry(struct ata_queued_cmd *qc)
+static void ata_eh_qc_retry(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *scmd = qc->scsicmd;
+
if (!qc->err_mask)
scmd->allowed++;
__ata_eh_qc_complete(qc);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d2160ee7ca7d..a7d667cfcfec 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2106,7 +2106,7 @@ static unsigned int ata_scsiop_inq_std(struct ata_device *dev,
if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4);
- if (ata_id_zoned_cap(dev->id) || dev->class == ATA_DEV_ZAC)
+ if (ata_dev_is_zoned(dev))
memcpy(rbuf + 58, versions_zbc, sizeof(versions_zbc));
else
memcpy(rbuf + 58, versions, sizeof(versions));
@@ -2146,7 +2146,7 @@ static unsigned int ata_scsiop_inq_00(struct ata_device *dev,
};
for (i = 0; i < sizeof(pages); i++) {
- if (pages[i] == 0xb6 && !ata_dev_is_zac(dev))
+ if (pages[i] == 0xb6 && !ata_dev_is_zoned(dev))
continue;
rbuf[num_pages + 4] = pages[i];
num_pages++;
@@ -2285,6 +2285,39 @@ static unsigned int ata_scsiop_inq_89(struct ata_device *dev,
}
/**
+ * ata_dsm_trim_pages - maximum DSM TRIM payload for a device, in 512-byte pages
+ * @dev: ATA device the DATA SET MANAGEMENT TRIM command will be sent to
+ *
+ * A DATA SET MANAGEMENT TRIM payload is a list of 512-byte pages, each holding
+ * up to ATA_MAX_TRIM_RNUM (64) LBA Range Entries; the format is page-based and
+ * unrelated to the logical sector size.
+ *
+ * The logical sector size still bounds it, though: the descriptor is written
+ * directly into the WRITE SAME data-out buffer, which sd sizes to a single
+ * logical block, so it can hold at most sector_size / 512 pages.
+ *
+ * Return: the maximum number of 512-byte pages a single translated WRITE SAME
+ * command may send to @dev (never less than one), that is the smaller of:
+ * - MAX PAGES PER DSM COMMAND (IDENTIFY DEVICE word 105), when the device
+ * reports a non-zero limit; and
+ * - the logical sector size expressed in 512-byte pages (see above).
+ */
+static unsigned int ata_dsm_trim_pages(struct ata_device *dev)
+{
+ unsigned int sector_size = ata_id_logical_sector_size(dev->id);
+ unsigned int max_pages = ata_id_dsm_max_pages(dev->id);
+ unsigned int pages = sector_size / ATA_SECT_SIZE;
+
+ /* If the device does not specify a limit, assume only a single page. */
+ if (!max_pages)
+ max_pages = 1;
+
+ pages = min_not_zero(pages, max_pages);
+
+ return pages;
+}
+
+/**
* ata_scsiop_inq_b0 - Simulate INQUIRY VPD page B0, Block Limits
* @dev: Target device.
* @cmd: SCSI command of interest.
@@ -2323,7 +2356,8 @@ static unsigned int ata_scsiop_inq_b0(struct ata_device *dev,
* with the unmap bit set.
*/
if (ata_id_has_trim(dev->id)) {
- u64 max_blocks = 65535 * ATA_MAX_TRIM_RNUM;
+ unsigned int max_pages = ata_dsm_trim_pages(dev);
+ u64 max_blocks = max_pages * ATA_MAX_TRIM_RNUM * (u64)U16_MAX;
if (dev->quirks & ATA_QUIRK_MAX_TRIM_128M)
max_blocks = 128 << (20 - SECTOR_SHIFT);
@@ -2403,7 +2437,7 @@ static unsigned int ata_scsiop_inq_b2(struct ata_device *dev,
static unsigned int ata_scsiop_inq_b6(struct ata_device *dev,
struct scsi_cmnd *cmd, u8 *rbuf)
{
- if (!ata_dev_is_zac(dev)) {
+ if (!ata_dev_is_zoned(dev)) {
ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
return 0;
}
@@ -2934,7 +2968,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev,
rbuf[10] = sector_size >> (8 * 1);
rbuf[11] = sector_size;
- if (ata_id_zoned_cap(dev->id) || dev->class == ATA_DEV_ZAC)
+ if (ata_dev_is_zoned(dev))
rbuf[12] = (1 << 4); /* RC_BASIS */
rbuf[13] = log2_per_phys;
rbuf[14] = (lowest_aligned >> 8) & 0x3f;
@@ -3524,14 +3558,14 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
/**
* ata_format_dsm_trim_descr() - SATL Write Same to DSM Trim
* @cmd: SCSI command being translated
- * @trmax: Maximum number of entries that will fit in sector_size bytes.
+ * @size: DSM TRIM payload size in bytes (a multiple of 512)
* @sector: Starting sector
* @count: Total Range of request in logical sectors
*
* Rewrite the WRITE SAME descriptor to be a DSM TRIM little-endian formatted
* descriptor.
*
- * Upto 64 entries of the format:
+ * The payload is a list of @size / 8 entries of the format:
* 63:48 Range Length
* 47:0 LBA
*
@@ -3540,39 +3574,45 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
*
* NOTE: this is the same format as ADD LBA(S) TO NV CACHE PINNED SET
*
- * Return: Number of bytes copied into sglist.
+ * The descriptor is written straight into the WRITE SAME data-out buffer;
+ * ata_dsm_trim_pages() guarantees @size does not exceed that buffer (one
+ * logical block). An atomic sg_miter mapping is used so this works from the
+ * command submission path and, unlike page_address(), copes with a high
+ * memory payload.
+ *
+ * Return: Number of bytes written into the data-out buffer.
*/
-static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, u32 trmax,
+static size_t ata_format_dsm_trim_descr(struct scsi_cmnd *cmd, size_t size,
u64 sector, u32 count)
{
- struct scsi_device *sdp = cmd->device;
- size_t len = sdp->sector_size;
- size_t r;
- __le64 *buf;
- u32 i = 0;
- unsigned long flags;
+ struct sg_mapping_iter miter;
+ size_t offset = 0;
+
+ sg_miter_start(&miter, scsi_sglist(cmd), scsi_sg_count(cmd),
+ SG_MITER_TO_SG | SG_MITER_ATOMIC);
+ while (offset < size && sg_miter_next(&miter)) {
+ __le64 *buf = miter.addr;
+ size_t chunk = min_t(size_t, miter.length, size - offset);
+ unsigned int n = chunk / sizeof(__le64);
+ unsigned int i;
- WARN_ON(len > ATA_SCSI_RBUF_SIZE);
+ for (i = 0; i < n; i++) {
+ u64 entry = 0;
- if (len > ATA_SCSI_RBUF_SIZE)
- len = ATA_SCSI_RBUF_SIZE;
+ if (count) {
+ u32 rlen = min_t(u32, count, 0xffff);
- spin_lock_irqsave(&ata_scsi_rbuf_lock, flags);
- buf = ((void *)ata_scsi_rbuf);
- memset(buf, 0, len);
- while (i < trmax) {
- u64 entry = sector |
- ((u64)(count > 0xffff ? 0xffff : count) << 48);
- buf[i++] = __cpu_to_le64(entry);
- if (count <= 0xffff)
- break;
- count -= 0xffff;
- sector += 0xffff;
+ entry = sector | ((u64)rlen << 48);
+ sector += rlen;
+ count -= rlen;
+ }
+ buf[i] = cpu_to_le64(entry);
+ }
+ offset += n * sizeof(__le64);
}
- r = sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), buf, len);
- spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags);
+ sg_miter_stop(&miter);
- return r;
+ return offset;
}
/**
@@ -3590,14 +3630,13 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
{
struct ata_taskfile *tf = &qc->tf;
struct scsi_cmnd *scmd = qc->scsicmd;
- struct scsi_device *sdp = scmd->device;
- size_t len = sdp->sector_size;
struct ata_device *dev = qc->dev;
const u8 *cdb = scmd->cmnd;
+ unsigned int max_pages = ata_dsm_trim_pages(dev);
+ unsigned int n_pages;
+ size_t size;
u64 block;
u32 n_block;
- const u32 trmax = len >> 3;
- u32 size;
u16 fp;
u8 bp = 0xff;
u8 unmap = cdb[1] & 0x8;
@@ -3627,7 +3666,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
goto invalid_fld;
}
/* If the request is too large the cmd is invalid */
- if (n_block > 0xffff * trmax) {
+ if (n_block > max_pages * ATA_MAX_TRIM_RNUM * (u64)U16_MAX) {
fp = 2;
goto invalid_fld;
}
@@ -3640,31 +3679,39 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
goto invalid_param_len;
/*
- * size must match sector size in bytes
- * For DATA SET MANAGEMENT TRIM in ACS-2 nsect (aka count)
- * is defined as number of 512 byte blocks to be transferred.
+ * The DATA SET MANAGEMENT TRIM payload is a whole number of 512-byte
+ * pages (each holding up to ATA_MAX_TRIM_RNUM LBA Range Entries),
+ * independent of the logical sector size. Only use as many pages as
+ * are needed to describe the request, capped at max_pages.
*/
+ n_pages = DIV_ROUND_UP(DIV_ROUND_UP(n_block, U16_MAX),
+ ATA_MAX_TRIM_RNUM);
+ n_pages = clamp(n_pages, 1U, max_pages);
+ size = (size_t)n_pages * ATA_SECT_SIZE;
- size = ata_format_dsm_trim_descr(scmd, trmax, block, n_block);
- if (size != len)
+ if (ata_format_dsm_trim_descr(scmd, size, block, n_block) != size)
goto invalid_param_len;
+ /*
+ * For DATA SET MANAGEMENT TRIM the COUNT field (aka nsect) is the
+ * number of 512-byte pages to be transferred.
+ */
if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) {
/* Newer devices support queued TRIM commands */
tf->protocol = ATA_PROT_NCQ;
tf->command = ATA_CMD_FPDMA_SEND;
tf->hob_nsect = ATA_SUBCMD_FPDMA_SEND_DSM & 0x1f;
tf->nsect = qc->hw_tag << 3;
- tf->hob_feature = (size / 512) >> 8;
- tf->feature = size / 512;
+ tf->hob_feature = n_pages >> 8;
+ tf->feature = n_pages;
tf->auxiliary = 1;
} else {
tf->protocol = ATA_PROT_DMA;
tf->hob_feature = 0;
tf->feature = ATA_DSM_TRIM;
- tf->hob_nsect = (size / 512) >> 8;
- tf->nsect = size / 512;
+ tf->hob_nsect = n_pages >> 8;
+ tf->nsect = n_pages;
tf->command = ATA_CMD_DSM;
}
@@ -3672,6 +3719,12 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
ATA_TFLAG_WRITE;
ata_qc_set_pc_nbytes(qc);
+ /*
+ * The DSM TRIM payload (size) may be smaller than the WRITE SAME
+ * data-out buffer (one logical block); only transfer the pages that
+ * were actually built so the transfer length matches the COUNT field.
+ */
+ qc->nbytes = size;
return 0;
@@ -3688,88 +3741,286 @@ invalid_opcode:
return 1;
}
-static unsigned int ata_scsi_report_supported_opcodes(struct ata_device *dev,
- struct scsi_cmnd *cmd,
- u8 *rbuf)
+struct ata_scsi_cmd {
+ u8 op;
+ u8 cdb_len;
+ bool sa_valid;
+ u16 sa;
+};
+
+/*
+ * Array of commands supported with translation or emulation, sorted in
+ * ascending opcode and service action order. All of these commands are
+ * processed either in ata_xlat_func() or in ata_scsi_simulate();
+ *
+ * Note: commands that are not fully supported may be left out of this array
+ * so that they are not reported as supported for passthrough but still
+ * available through the block layer. For now, this includes the following
+ * commands:
+ * - WRITE_SAME_16: ata_scsi_write_same_xlat() forbids passthrough commands
+ */
+static const struct ata_scsi_cmd ata_supported_cmds[] = {
+ { .op = TEST_UNIT_READY, .cdb_len = 6 },
+ { .op = REZERO_UNIT, .cdb_len = 6 },
+ { .op = REQUEST_SENSE, .cdb_len = 6 },
+ { .op = READ_6, .cdb_len = 6 },
+ { .op = WRITE_6, .cdb_len = 6 },
+ { .op = SEEK_6, .cdb_len = 6 },
+ { .op = INQUIRY, .cdb_len = 6 },
+ { .op = MODE_SELECT, .cdb_len = 6 },
+ { .op = MODE_SENSE, .cdb_len = 6 },
+ { .op = START_STOP, .cdb_len = 6 },
+ { .op = SEND_DIAGNOSTIC, .cdb_len = 6 },
+ { .op = READ_CAPACITY, .cdb_len = 10 },
+ { .op = READ_10, .cdb_len = 10 },
+ { .op = WRITE_10, .cdb_len = 10 },
+ { .op = SEEK_10, .cdb_len = 10 },
+ { .op = VERIFY, .cdb_len = 10 },
+ { .op = SYNCHRONIZE_CACHE, .cdb_len = 10 },
+ { .op = MODE_SELECT_10, .cdb_len = 10 },
+ { .op = MODE_SENSE_10, .cdb_len = 10 },
+ {
+ .op = VARIABLE_LENGTH_CMD, .cdb_len = 32,
+ .sa_valid = true,
+ .sa = ATA_32
+ },
+ { .op = ATA_16, .cdb_len = 16 },
+ { .op = READ_16, .cdb_len = 16 },
+ { .op = WRITE_16, .cdb_len = 16 },
+ { .op = VERIFY_16, .cdb_len = 16 },
+ { .op = SYNCHRONIZE_CACHE_16, .cdb_len = 16 },
+ {
+ .op = ZBC_OUT, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = ZO_CLOSE_ZONE
+ },
+ {
+ .op = ZBC_OUT, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = ZO_FINISH_ZONE
+ },
+ {
+ .op = ZBC_OUT, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = ZO_OPEN_ZONE
+ },
+ {
+ .op = ZBC_OUT, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = ZO_RESET_WRITE_POINTER
+ },
+ {
+ .op = ZBC_IN, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = ZI_REPORT_ZONES
+ },
+ {
+ .op = SERVICE_ACTION_IN_16, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = SAI_READ_CAPACITY_16
+ },
+ {
+ .op = SERVICE_ACTION_IN_16, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = SAI_GET_PHYSICAL_ELEMENT_STATUS
+ },
+ {
+ .op = SERVICE_ACTION_IN_16, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = SAI_REMOVE_ELEMENT_AND_TRUNCATE
+ },
+ {
+ .op = SERVICE_ACTION_IN_16, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = SAI_RESTORE_ELEMENTS_AND_REBUILD
+ },
+ {
+ .op = SERVICE_ACTION_IN_16, .cdb_len = 16,
+ .sa_valid = true,
+ .sa = SAI_REMOVE_ELEMENT_AND_MODIFY_ZONES
+ },
+ { .op = REPORT_LUNS, .cdb_len = 12 },
+ { .op = ATA_12, .cdb_len = 12 },
+ { .op = SECURITY_PROTOCOL_IN, .cdb_len = 12 },
+ {
+ .op = MAINTENANCE_IN, .cdb_len = 12,
+ .sa_valid = true,
+ .sa = MI_REPORT_SUPPORTED_OPERATION_CODES
+ },
+ { .op = SECURITY_PROTOCOL_OUT, .cdb_len = 12 },
+};
+
+static const struct ata_scsi_cmd *ata_scsi_get_supported_cmd(u8 op, u16 sa)
{
- u8 *cdb = cmd->cmnd;
- u8 supported = 0, cdlp = 0, rwcdlp = 0;
+ const struct ata_scsi_cmd *cmd;
+ int i;
- if (cdb[2] != 1 && cdb[2] != 3) {
- ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
- ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
- return 0;
+ for (i = 0; i < ARRAY_SIZE(ata_supported_cmds); i++) {
+ cmd = &ata_supported_cmds[i];
+ if (cmd->op == op && cmd->sa == sa)
+ return cmd;
}
- switch (cdb[3]) {
- case INQUIRY:
- case MODE_SENSE:
- case MODE_SENSE_10:
- case READ_CAPACITY:
- case SERVICE_ACTION_IN_16:
- case REPORT_LUNS:
- case REQUEST_SENSE:
- case SYNCHRONIZE_CACHE:
- case SYNCHRONIZE_CACHE_16:
- case REZERO_UNIT:
- case SEEK_6:
- case SEEK_10:
- case TEST_UNIT_READY:
- case SEND_DIAGNOSTIC:
- case MAINTENANCE_IN:
- case READ_6:
- case READ_10:
- case WRITE_6:
- case WRITE_10:
- case ATA_12:
- case ATA_16:
- case VERIFY:
- case VERIFY_16:
- case MODE_SELECT:
- case MODE_SELECT_10:
- case START_STOP:
- supported = 3;
- break;
+ return NULL;
+}
+
+static bool ata_scsi_supported_cmd_use_sa(u8 op)
+{
+ const struct ata_scsi_cmd *cmd;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ata_supported_cmds); i++) {
+ cmd = &ata_supported_cmds[i];
+ if (cmd->op == op)
+ return cmd->sa_valid;
+ }
+
+ return false;
+}
+
+struct ata_scsi_cmd_support {
+ u8 cdlp;
+ u8 rwcdlp;
+};
+
+static bool ata_scsi_cmd_is_supported(struct ata_device *dev, u8 op, u16 sa,
+ struct ata_scsi_cmd_support *sup)
+{
+ const struct ata_scsi_cmd *cmd;
+
+ /* First, see if we support the command. */
+ cmd = ata_scsi_get_supported_cmd(op, sa);
+ if (!cmd)
+ return false;
+
+ /* Now refine the support report depending on the device features. */
+ memset(sup, 0, sizeof(*sup));
+ switch (op) {
case READ_16:
- supported = 3;
if (dev->flags & ATA_DFLAG_CDL) {
/*
* CDL read descriptors map to the T2A page, that is,
* rwcdlp = 0x01 and cdlp = 0x01
*/
- rwcdlp = 0x01;
- cdlp = 0x01 << 3;
+ sup->rwcdlp = 0x01;
+ sup->cdlp = 0x01;
}
break;
case WRITE_16:
- supported = 3;
if (dev->flags & ATA_DFLAG_CDL) {
/*
* CDL write descriptors map to the T2B page, that is,
* rwcdlp = 0x01 and cdlp = 0x02
*/
- rwcdlp = 0x01;
- cdlp = 0x02 << 3;
+ sup->rwcdlp = 0x01;
+ sup->cdlp = 0x02;
}
break;
case ZBC_IN:
case ZBC_OUT:
- if (ata_id_zoned_cap(dev->id) ||
- dev->class == ATA_DEV_ZAC)
- supported = 3;
+ return ata_dev_is_zoned(dev);
+ case SERVICE_ACTION_IN_16:
+ switch (sa) {
+ case SAI_GET_PHYSICAL_ELEMENT_STATUS:
+ case SAI_REMOVE_ELEMENT_AND_TRUNCATE:
+ return dev->flags & ATA_DFLAG_DEPOP;
+ case SAI_RESTORE_ELEMENTS_AND_REBUILD:
+ return dev->flags & ATA_DFLAG_DEPOP_RESTORE;
+ case SAI_REMOVE_ELEMENT_AND_MODIFY_ZONES:
+ return dev->flags & ATA_DFLAG_DEPOP_MODIFY;
+ default:
+ return true;
+ }
break;
case SECURITY_PROTOCOL_IN:
case SECURITY_PROTOCOL_OUT:
- if (dev->flags & ATA_DFLAG_TRUSTED)
- supported = 3;
- break;
+ return dev->flags & ATA_DFLAG_TRUSTED;
default:
break;
}
+ return true;
+}
+
+static unsigned int
+ata_scsi_report_all_supported_opcodes(struct ata_device *dev, u8 *rbuf)
+{
+ struct ata_scsi_cmd_support sup;
+ const struct ata_scsi_cmd *cmd;
+ unsigned int len = 4;
+ u8 *buf = &rbuf[len];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ata_supported_cmds); i++) {
+ if (len > ATA_SCSI_RBUF_SIZE - 8)
+ break;
+
+ cmd = &ata_supported_cmds[i];
+
+ /* All command format */
+ if (!ata_scsi_cmd_is_supported(dev, cmd->op, cmd->sa, &sup))
+ continue;
+
+ buf[0] = cmd->op;
+ put_unaligned_be16(cmd->sa, &buf[2]);
+ buf[5] = (sup.rwcdlp << 6) | (sup.cdlp << 2);
+ if (cmd->sa_valid)
+ buf[5] |= 0x01;
+ put_unaligned_be16(cmd->cdb_len, &buf[6]);
+
+ /* CTDP == 0 */
+ len += 8;
+ buf += 8;
+ }
+
+ put_unaligned_be32(len - 4, &rbuf[0]);
+
+ return len;
+}
+
+static unsigned int ata_scsi_report_supported_opcodes(struct ata_device *dev,
+ struct scsi_cmnd *cmd,
+ u8 *rbuf)
+{
+ struct ata_scsi_cmd_support sup;
+ u8 *cdb = cmd->cmnd;
+ u16 sa = 0;
+
+ switch (cdb[2]) {
+ case 0:
+ /* All command format */
+ return ata_scsi_report_all_supported_opcodes(dev, rbuf);
+ case 1:
+ /* One command format with command support data, ignore sa. */
+ if (ata_scsi_supported_cmd_use_sa(cdb[3])) {
+ ata_scsi_set_invalid_field(dev, cmd, 3, 0xff);
+ return 0;
+ }
+ break;
+ case 2:
+ /* One command format, must have sa. */
+ if (!ata_scsi_supported_cmd_use_sa(cdb[3])) {
+ ata_scsi_set_invalid_field(dev, cmd, 3, 0xff);
+ return 0;
+ }
+ fallthrough;
+ case 3:
+ /* One command format */
+ sa = get_unaligned_be16(&cdb[4]);
+ break;
+ default:
+ ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
+ ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
+ return 0;
+ }
+
/* One command format */
- rbuf[0] = rwcdlp;
- rbuf[1] = cdlp | supported;
+ if (ata_scsi_cmd_is_supported(dev, cdb[3], sa, &sup)) {
+ rbuf[0] = sup.rwcdlp;
+ rbuf[1] = (sup.cdlp << 3) | 0x03;
+ } else {
+ rbuf[1] = 0x01;
+ }
return 4;
}
@@ -4452,6 +4703,245 @@ static unsigned int ata_scsi_security_inout_xlat(struct ata_queued_cmd *qc)
return 0;
}
+/*
+ * Convert T-13 little-endian field representation of GET PHYSICAL ELEMENT
+ * STATUS DMA command reply into T-10 big-endian field representation.
+ */
+static void ata_scsi_get_phys_element_status_complete(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ struct sg_mapping_iter miter;
+ unsigned int bytes = 0;
+
+ lockdep_assert_held(qc->ap->lock);
+
+ sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
+ SG_MITER_TO_SG | SG_MITER_ATOMIC);
+
+ while (sg_miter_next(&miter)) {
+ unsigned int offset = 0;
+
+ if (bytes == 0) {
+ u32 num_desc, num_desc_returned, id;
+ u16 max_depop, cur_depop;
+ char *hdr;
+
+ /* Swizzle the header */
+ hdr = miter.addr;
+ num_desc = get_unaligned_le32(&hdr[0]);
+ num_desc_returned = get_unaligned_le32(&hdr[4]);
+ id = get_unaligned_le32(&hdr[8]);
+ max_depop = get_unaligned_le16(&hdr[12]);
+ cur_depop = get_unaligned_le16(&hdr[14]);
+
+ put_unaligned_be32(num_desc, &hdr[0]);
+ put_unaligned_be32(num_desc_returned, &hdr[4]);
+ put_unaligned_be32(id, &hdr[8]);
+ put_unaligned_be16(max_depop, &hdr[12]);
+ put_unaligned_be16(cur_depop, &hdr[14]);
+
+ offset += 32;
+ bytes += 32;
+ }
+
+ /* Swizzle the descriptors. */
+ while (offset < miter.length) {
+ char *desc;
+ u32 id;
+ u8 type;
+
+ desc = miter.addr + offset;
+ id = get_unaligned_le32(&desc[4]);
+ put_unaligned_be32(id, &desc[4]);
+
+ type = desc[14];
+ if (type == SCSI_PHYS_ELEM_TYPE_ALL_ACCESS_STORAGE) {
+ u64 capacity = get_unaligned_le64(&desc[16]);
+
+ put_unaligned_be64(capacity, &desc[16]);
+ } else {
+ u64 num_zones;
+
+ id = get_unaligned_le32(&desc[16]);
+ num_zones = get_unaligned_le64(&desc[24]);
+
+ put_unaligned_be32(id, &desc[16]);
+ put_unaligned_be64(num_zones, &desc[24]);
+ }
+
+ offset += 32;
+ bytes += 32;
+ }
+ }
+ sg_miter_stop(&miter);
+
+ ata_scsi_qc_complete(qc);
+}
+
+static unsigned int
+ata_scsi_get_phys_element_status_xlat(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ const u8 *cdb = scmd->cmnd;
+ struct ata_device *dev = qc->dev;
+ struct ata_taskfile *tf = &qc->tf;
+ u32 starting_element, len;
+
+ /* ATA_CMD_GET_PHYS_ELEMENT_STATUS is a DMA command. */
+ if (!(dev->flags & ATA_DFLAG_DEPOP) || !ata_dma_enabled(dev)) {
+ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ return 1;
+ }
+
+ len = get_unaligned_be32(&cdb[10]) / ATA_SECT_SIZE;
+ if (!len || len > U16_MAX) {
+ ata_scsi_set_invalid_field(dev, scmd, 10, 0);
+ return 1;
+ }
+
+ tf->protocol = ATA_PROT_DMA;
+ tf->command = ATA_CMD_GET_PHYS_ELEMENT_STATUS;
+ tf->hob_feature = cdb[14];
+ tf->hob_nsect = (len >> 8) & 0xff;
+ tf->nsect = len & 0xff;
+
+ starting_element = get_unaligned_be32(&cdb[6]);
+ if (starting_element) {
+ tf->hob_lbal = (starting_element >> 24) & 0xff;
+ tf->lbah = (starting_element >> 16) & 0xff;
+ tf->lbam = (starting_element >> 8) & 0xff;
+ tf->lbal = starting_element & 0xff;
+ }
+ tf->device = ATA_LBA;
+ tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+
+ ata_qc_set_pc_nbytes(qc);
+
+ qc->flags |= ATA_QCFLAG_RESULT_TF;
+ qc->complete_fn = ata_scsi_get_phys_element_status_complete;
+
+ return 0;
+}
+
+static void ata_scsi_depop_ua_cap_changed_complete(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ u8 *cdb = scmd->cmnd;
+ bool is_ata_passthru = cdb[0] == ATA_16 || cdb[0] == ATA_12;
+ bool is_success = qc->err_mask == 0;
+
+ /*
+ * For successful non-passthrough commands, raise a UNIT ATTENTION with
+ * the additional sense code set to CAPACITY DATA HAS CHANGED to be
+ * raised. Note that this should be done only if the capacity has
+ * actually changed, which may not be the case if the element that was
+ * specified for depopulation was already depopulated, or we did not
+ * restore any removed element. But a capacity change unit attention is
+ * harmless, so always raise the unit attention.
+ */
+ if (is_success && !is_ata_passthru)
+ ata_scsi_set_sense(qc->dev, scmd, UNIT_ATTENTION,
+ UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
+ ata_scsi_qc_complete(qc);
+}
+
+static unsigned int
+ata_scsi_remove_element_and_truncate_xlat(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ const u8 *cdb = scmd->cmnd;
+ struct ata_device *dev = qc->dev;
+ struct ata_taskfile *tf = &qc->tf;
+ u64 req_capacity;
+ u32 id;
+
+ if (!(dev->flags & ATA_DFLAG_DEPOP)) {
+ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ return 1;
+ }
+
+ req_capacity = get_unaligned_be64(&cdb[2]);
+ if (req_capacity == 1) {
+ ata_scsi_set_invalid_field(dev, scmd, 2, 0);
+ return 1;
+ }
+
+ id = get_unaligned_be32(&cdb[10]);
+
+ tf->protocol = ATA_PROT_NODATA;
+ tf->command = ATA_CMD_REMOVE_ELEMENT_AND_TRUNCATE;
+ tf->hob_feature = (id >> 24) & 0xff;
+ tf->feature = (id >> 16) & 0xff;
+ tf->hob_nsect = (id >> 8) & 0xff;
+ tf->nsect = id & 0xff;
+ tf->hob_lbah = (req_capacity >> 40) & 0xff;
+ tf->hob_lbam = (req_capacity >> 32) & 0xff;
+ tf->hob_lbal = (req_capacity >> 24) & 0xff;
+ tf->lbah = (req_capacity >> 16) & 0xff;
+ tf->lbam = (req_capacity >> 8) & 0xff;
+ tf->lbal = req_capacity & 0xff;
+ tf->device = ATA_LBA;
+ tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+
+ qc->flags |= ATA_QCFLAG_RESULT_TF;
+ qc->complete_fn = ata_scsi_depop_ua_cap_changed_complete;
+
+ return 0;
+}
+
+static unsigned int
+ata_scsi_remove_element_and_modify_zones_xlat(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ const u8 *cdb = scmd->cmnd;
+ struct ata_device *dev = qc->dev;
+ struct ata_taskfile *tf = &qc->tf;
+ u32 id;
+
+ if (!(dev->flags & ATA_DFLAG_DEPOP_MODIFY)) {
+ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ return 1;
+ }
+
+ id = get_unaligned_be32(&cdb[10]);
+
+ tf->protocol = ATA_PROT_NODATA;
+ tf->command = ATA_CMD_REMOVE_ELEMENT_AND_MODIFY_ZONES;
+ tf->hob_feature = (id >> 24) & 0xff;
+ tf->feature = (id >> 16) & 0xff;
+ tf->hob_nsect = (id >> 8) & 0xff;
+ tf->nsect = id & 0xff;
+ tf->device = ATA_LBA;
+ tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+
+ qc->flags |= ATA_QCFLAG_RESULT_TF;
+
+ return 0;
+}
+
+static unsigned int
+ata_scsi_restore_elements_and_rebuild_xlat(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *scmd = qc->scsicmd;
+ struct ata_device *dev = qc->dev;
+ struct ata_taskfile *tf = &qc->tf;
+
+ if (!(dev->flags & ATA_DFLAG_DEPOP_RESTORE)) {
+ ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0);
+ return 1;
+ }
+
+ tf->protocol = ATA_PROT_NODATA;
+ tf->command = ATA_CMD_RESTORE_ELEMENTS_AND_REBUILD;
+ tf->device = ATA_LBA;
+ tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+
+ qc->flags |= ATA_QCFLAG_RESULT_TF;
+ qc->complete_fn = ata_scsi_depop_ua_cap_changed_complete;
+
+ return 0;
+}
+
/**
* ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler
* @qc: Command to be translated
@@ -4483,7 +4973,7 @@ static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc)
/**
* ata_get_xlat_func - check if SCSI to ATA translation is possible
* @dev: ATA device
- * @cmd: SCSI command opcode to consider
+ * @cdb: CDB of the SCSI command to consider
*
* Look up the SCSI command given, and determine whether the
* SCSI command is to be translated or simulated.
@@ -4492,9 +4982,12 @@ static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc)
* Pointer to translation function if possible, %NULL if not.
*/
-static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
+static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev,
+ u8 *cdb)
{
- switch (cmd) {
+ u8 sa;
+
+ switch (cdb[0]) {
case READ_6:
case READ_10:
case READ_16:
@@ -4528,6 +5021,18 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
case MODE_SELECT_10:
return ata_scsi_mode_select_xlat;
+ case SERVICE_ACTION_IN_16:
+ sa = cdb[1] & 0x1f;
+ if (sa == SAI_GET_PHYSICAL_ELEMENT_STATUS)
+ return ata_scsi_get_phys_element_status_xlat;
+ if (sa == SAI_REMOVE_ELEMENT_AND_TRUNCATE)
+ return ata_scsi_remove_element_and_truncate_xlat;
+ if (sa == SAI_REMOVE_ELEMENT_AND_MODIFY_ZONES)
+ return ata_scsi_remove_element_and_modify_zones_xlat;
+ if (sa == SAI_RESTORE_ELEMENTS_AND_REBUILD)
+ return ata_scsi_restore_elements_and_rebuild_xlat;
+ break;
+
case ZBC_IN:
return ata_scsi_zbc_in_xlat;
@@ -4625,7 +5130,8 @@ enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
struct ata_port *ap)
__must_hold(ap->lock)
{
- u8 scsi_op = scmd->cmnd[0];
+ u8 *cdb = scmd->cmnd;
+ u8 scsi_op = cdb[0];
ata_xlat_func_t xlat_func;
/*
@@ -4645,7 +5151,7 @@ enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
if (unlikely(scmd->cmd_len > dev->cdb_len))
goto bad_cdb_len;
- xlat_func = ata_get_xlat_func(dev, scsi_op);
+ xlat_func = ata_get_xlat_func(dev, cdb);
} else if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
/* relay SCSI command to ATAPI device */
int len = COMMAND_SIZE(scsi_op);
@@ -4661,7 +5167,7 @@ enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
if (unlikely(scmd->cmd_len > 16))
goto bad_cdb_len;
- xlat_func = ata_get_xlat_func(dev, scsi_op);
+ xlat_func = ata_get_xlat_func(dev, cdb);
}
if (xlat_func)
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 734e7c88439a..976e4e160494 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1114,8 +1114,14 @@ fsm_start:
if (ap->hsm_task_state == HSM_ST_LAST &&
(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
- /* all data read */
- status = ata_wait_idle(ap);
+ status = ata_sff_busy_wait(ap,
+ ATA_BUSY | ATA_DRQ, 10);
+ if (status != 0xff &&
+ (status & (ATA_BUSY | ATA_DRQ))) {
+ qc->tf.flags |= ATA_TFLAG_POLLING;
+ ata_sff_queue_pio_task(link, 0);
+ return 0;
+ }
goto fsm_start;
}
}
@@ -1213,7 +1219,7 @@ static void ata_sff_pio_task(struct work_struct *work)
container_of(work, struct ata_port, sff_pio_task.work);
struct ata_link *link = ap->sff_pio_task_link;
struct ata_queued_cmd *qc;
- u8 status;
+ u8 status, wait_mask;
int poll_next;
spin_lock_irq(ap->lock);
@@ -1229,6 +1235,10 @@ static void ata_sff_pio_task(struct work_struct *work)
fsm_start:
WARN_ON_ONCE(ap->hsm_task_state == HSM_ST_IDLE);
+ wait_mask = ATA_BUSY;
+ if (ap->hsm_task_state == HSM_ST_LAST)
+ wait_mask |= ATA_DRQ;
+
/*
* This is purely heuristic. This is a fast path.
* Sometimes when we enter, BSY will be cleared in
@@ -1236,14 +1246,14 @@ fsm_start:
* or something. Snooze for a couple msecs, then
* chk-status again. If still busy, queue delayed work.
*/
- status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
- if (status & ATA_BUSY) {
+ status = ata_sff_busy_wait(ap, wait_mask, 5);
+ if (status & wait_mask) {
spin_unlock_irq(ap->lock);
ata_msleep(ap, 2);
spin_lock_irq(ap->lock);
- status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
- if (status & ATA_BUSY) {
+ status = ata_sff_busy_wait(ap, wait_mask, 10);
+ if (status & wait_mask) {
ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
goto out_unlock;
}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 8dacc1daabf0..48274691cd0e 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -44,7 +44,7 @@ static inline bool ata_sstatus_online(u32 sstatus)
return (sstatus & 0xf) == 0x3;
}
-static inline bool ata_dev_is_zac(struct ata_device *dev)
+static inline bool ata_dev_is_zoned(struct ata_device *dev)
{
/* Host managed device or host aware device */
return dev->class == ATA_DEV_ZAC ||
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index 42a24dc51d26..339ee5e43e9f 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -656,14 +656,22 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
* start of new transfer.
*/
drv_data->dma_rx_channel = dma_request_chan(dev, "rx");
- if (IS_ERR(drv_data->dma_rx_channel))
- return dev_err_probe(dev, PTR_ERR(drv_data->dma_rx_channel),
- "rx DMA setup failed\n");
+ if (IS_ERR(drv_data->dma_rx_channel)) {
+ ret = PTR_ERR(drv_data->dma_rx_channel);
+ drv_data->dma_rx_channel = NULL;
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ dev_warn(dev, "rx DMA unavailable, using PIO\n");
+ return 0;
+ }
drv_data->dma_tx_channel = dma_request_chan(&pdev->dev, "tx");
if (IS_ERR(drv_data->dma_tx_channel)) {
- ret = dev_err_probe(dev, PTR_ERR(drv_data->dma_tx_channel),
- "tx DMA setup failed\n");
+ ret = PTR_ERR(drv_data->dma_tx_channel);
+ drv_data->dma_tx_channel = NULL;
+ if (ret == -EPROBE_DEFER)
+ goto fail_release_rx;
+ dev_warn(dev, "tx DMA unavailable, using PIO\n");
goto fail_release_rx;
}
@@ -674,7 +682,7 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ret = dmaengine_slave_config(drv_data->dma_rx_channel, &conf);
if (ret) {
- dev_err_probe(dev, ret, "failed to configure rx dma channel");
+ dev_warn(dev, "failed to configure rx dma channel, using PIO\n");
goto fail_release_dma;
}
@@ -685,7 +693,7 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ret = dmaengine_slave_config(drv_data->dma_tx_channel, &conf);
if (ret) {
- dev_err_probe(dev, ret, "failed to configure tx dma channel");
+ dev_warn(dev, "failed to configure tx dma channel, using PIO\n");
goto fail_release_dma;
}
@@ -693,10 +701,14 @@ static int ep93xx_pata_dma_init(struct ep93xx_pata_data *drv_data)
fail_release_rx:
dma_release_channel(drv_data->dma_rx_channel);
+ drv_data->dma_rx_channel = NULL;
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ return 0;
+
fail_release_dma:
ep93xx_pata_release_dma(drv_data);
-
- return ret;
+ return 0;
}
static void ep93xx_pata_dma_start(struct ata_queued_cmd *qc)
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 210a63283f62..1739743427cf 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -769,10 +769,8 @@ static int mpc52xx_ata_probe(struct platform_device *op)
task_irq = bcom_get_task_irq(dmatsk);
rv = devm_request_irq(&op->dev, task_irq, &mpc52xx_ata_task_irq, 0,
"ATA task", priv);
- if (rv) {
- dev_err(&op->dev, "error requesting DMA IRQ\n");
+ if (rv)
goto err2;
- }
priv->dmatsk = dmatsk;
/* Init the hw */
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 9f63bdfb8576..a694f6a178e3 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -161,8 +161,6 @@ static int pxa_ata_probe(struct platform_device *pdev)
struct ata_host *host;
struct ata_port *ap;
struct pata_pxa_data *data;
- struct resource *cmd_res;
- struct resource *ctl_res;
struct resource *dma_res;
struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev);
struct dma_slave_config config;
@@ -182,20 +180,6 @@ static int pxa_ata_probe(struct platform_device *pdev)
}
/*
- * CMD port base address
- */
- cmd_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(cmd_res == NULL))
- return -EINVAL;
-
- /*
- * CTL port base address
- */
- ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (unlikely(ctl_res == NULL))
- return -EINVAL;
-
- /*
* DMA port base address
*/
dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -221,14 +205,12 @@ static int pxa_ata_probe(struct platform_device *pdev)
ap->pio_mask = ATA_PIO4;
ap->mwdma_mask = ATA_MWDMA2;
- ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, cmd_res->start,
- resource_size(cmd_res));
- if (!ap->ioaddr.cmd_addr)
- return -ENOMEM;
- ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
- resource_size(ctl_res));
- if (!ap->ioaddr.ctl_addr)
- return -ENOMEM;
+ ap->ioaddr.cmd_addr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ap->ioaddr.cmd_addr))
+ return PTR_ERR(ap->ioaddr.cmd_addr);
+ ap->ioaddr.ctl_addr = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(ap->ioaddr.ctl_addr))
+ return PTR_ERR(ap->ioaddr.ctl_addr);
ap->ioaddr.bmdma_addr = devm_ioremap(&pdev->dev, dma_res->start,
resource_size(dma_res));
if (!ap->ioaddr.bmdma_addr)
@@ -280,40 +262,26 @@ static int pxa_ata_probe(struct platform_device *pdev)
/*
* Request the DMA channel
*/
- data->dma_chan = dma_request_chan(&pdev->dev, "data");
+ data->dma_chan = devm_dma_request_chan(&pdev->dev, "data");
if (IS_ERR(data->dma_chan))
return PTR_ERR(data->dma_chan);
+
ret = dmaengine_slave_config(data->dma_chan, &config);
if (ret < 0) {
dev_err(&pdev->dev, "dma configuration failed: %d\n", ret);
- dma_release_channel(data->dma_chan);
return ret;
}
/*
* Activate the ATA host
*/
- ret = ata_host_activate(host, irq, ata_sff_interrupt,
+ return ata_host_activate(host, irq, ata_sff_interrupt,
pdata->irq_flags, &pxa_ata_sht);
- if (ret)
- dma_release_channel(data->dma_chan);
-
- return ret;
-}
-
-static void pxa_ata_remove(struct platform_device *pdev)
-{
- struct ata_host *host = platform_get_drvdata(pdev);
- struct pata_pxa_data *data = host->ports[0]->private_data;
-
- dma_release_channel(data->dma_chan);
-
- ata_host_detach(host);
}
static struct platform_driver pxa_ata_driver = {
.probe = pxa_ata_probe,
- .remove = pxa_ata_remove,
+ .remove = ata_platform_remove_one,
.driver = {
.name = DRV_NAME,
},
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index fd81e75c9402..0144e597707e 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -103,16 +103,14 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
{
int irq;
struct gpio_desc *gpiod;
- struct resource *res;
struct ata_host *ah;
struct rb532_cf_info *info;
+ void __iomem *iobase;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "no IOMEM resource found\n");
- return -EINVAL;
- }
+ iobase = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(iobase))
+ return PTR_ERR(iobase);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -139,11 +137,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
ah->private_data = info;
info->gpio_line = gpiod;
info->irq = irq;
-
- info->iobase = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!info->iobase)
- return -ENOMEM;
+ info->iobase = iobase;
rb532_pata_setup_ports(ah);
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 3421039f4bae..a0b6e197cfb5 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -455,7 +455,7 @@ static int ahci_highbank_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
struct ecx_plat_data *pdata;
struct ata_host *host;
- struct resource *mem;
+ void __iomem *mmio;
int irq;
int i;
int rc;
@@ -463,11 +463,9 @@ static int ahci_highbank_probe(struct platform_device *pdev)
struct ata_port_info pi = ahci_highbank_port_info;
const struct ata_port_info *ppi[] = { &pi, NULL };
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(dev, "no mmio space\n");
- return -EINVAL;
- }
+ mmio = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(mmio))
+ return PTR_ERR(mmio);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -488,12 +486,7 @@ static int ahci_highbank_probe(struct platform_device *pdev)
hpriv->irq = irq;
hpriv->flags |= (unsigned long)pi.private_data;
-
- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
- if (!hpriv->mmio) {
- dev_err(dev, "can't map %pR\n", mem);
- return -ENOMEM;
- }
+ hpriv->mmio = mmio;
rc = highbank_initialize_phys(dev, hpriv->mmio);
if (rc)
@@ -537,7 +530,6 @@ static int ahci_highbank_probe(struct platform_device *pdev)
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
- ata_port_desc(ap, "mmio %pR", mem);
ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
/* set enclosure management message type */
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 365454390d7e..d260f04e6384 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4054,17 +4054,13 @@ static int mv_platform_probe(struct platform_device *pdev)
n_ports);
return -EINVAL;
}
-
- irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
} else {
mv_platform_data = dev_get_platdata(&pdev->dev);
n_ports = mv_platform_data->n_ports;
- irq = platform_get_irq(pdev, 0);
}
+ irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
- if (!irq)
- return -EINVAL;
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
@@ -4092,21 +4088,19 @@ static int mv_platform_probe(struct platform_device *pdev)
hpriv->base -= SATAHC0_REG_BASE;
- hpriv->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(hpriv->clk)) {
- dev_notice(&pdev->dev, "cannot get optional clkdev\n");
- } else {
- rc = clk_prepare_enable(hpriv->clk);
- if (rc)
- goto err;
- }
+ hpriv->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+ if (IS_ERR(hpriv->clk))
+ return PTR_ERR(hpriv->clk);
for (port = 0; port < n_ports; port++) {
char port_number[16];
sprintf(port_number, "%d", port);
- hpriv->port_clks[port] = clk_get(&pdev->dev, port_number);
- if (!IS_ERR(hpriv->port_clks[port]))
- clk_prepare_enable(hpriv->port_clks[port]);
+ hpriv->port_clks[port] = devm_clk_get_optional_enabled(&pdev->dev, port_number);
+ if (IS_ERR(hpriv->port_clks[port])) {
+ rc = PTR_ERR(hpriv->port_clks[port]);
+ hpriv->n_ports = port;
+ goto err;
+ }
sprintf(port_number, "port%d", port);
hpriv->port_phys[port] = devm_phy_optional_get(&pdev->dev,
@@ -4120,8 +4114,8 @@ static int mv_platform_probe(struct platform_device *pdev)
/* Cleanup only the initialized ports */
hpriv->n_ports = port;
goto err;
- } else
- phy_power_on(hpriv->port_phys[port]);
+ }
+ phy_power_on(hpriv->port_phys[port]);
}
/* All the ports have been initialized */
@@ -4160,17 +4154,8 @@ static int mv_platform_probe(struct platform_device *pdev)
return 0;
err:
- if (!IS_ERR(hpriv->clk)) {
- clk_disable_unprepare(hpriv->clk);
- clk_put(hpriv->clk);
- }
- for (port = 0; port < hpriv->n_ports; port++) {
- if (!IS_ERR(hpriv->port_clks[port])) {
- clk_disable_unprepare(hpriv->port_clks[port]);
- clk_put(hpriv->port_clks[port]);
- }
+ for (port = 0; port < hpriv->n_ports; port++)
phy_power_off(hpriv->port_phys[port]);
- }
return rc;
}
@@ -4190,17 +4175,8 @@ static void mv_platform_remove(struct platform_device *pdev)
int port;
ata_host_detach(host);
- if (!IS_ERR(hpriv->clk)) {
- clk_disable_unprepare(hpriv->clk);
- clk_put(hpriv->clk);
- }
- for (port = 0; port < host->n_ports; port++) {
- if (!IS_ERR(hpriv->port_clks[port])) {
- clk_disable_unprepare(hpriv->port_clks[port]);
- clk_put(hpriv->port_clks[port]);
- }
+ for (port = 0; port < host->n_ports; port++)
phy_power_off(hpriv->port_phys[port]);
- }
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 4fb2dc403962..3346562275f8 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -67,52 +67,6 @@ static const char *sdebug_version_date = "20210520";
#define MY_NAME "scsi_debug"
-/* Additional Sense Code (ASC) */
-#define NO_ADDITIONAL_SENSE 0x0
-#define OVERLAP_ATOMIC_COMMAND_ASC 0x0
-#define OVERLAP_ATOMIC_COMMAND_ASCQ 0x23
-#define FILEMARK_DETECTED_ASCQ 0x1
-#define EOP_EOM_DETECTED_ASCQ 0x2
-#define BEGINNING_OF_P_M_DETECTED_ASCQ 0x4
-#define EOD_DETECTED_ASCQ 0x5
-#define LOGICAL_UNIT_NOT_READY 0x4
-#define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8
-#define UNRECOVERED_READ_ERR 0x11
-#define PARAMETER_LIST_LENGTH_ERR 0x1a
-#define INVALID_OPCODE 0x20
-#define LBA_OUT_OF_RANGE 0x21
-#define INVALID_FIELD_IN_CDB 0x24
-#define INVALID_FIELD_IN_PARAM_LIST 0x26
-#define WRITE_PROTECTED 0x27
-#define UA_READY_ASC 0x28
-#define UA_RESET_ASC 0x29
-#define UA_CHANGED_ASC 0x2a
-#define TOO_MANY_IN_PARTITION_ASC 0x3b
-#define TARGET_CHANGED_ASC 0x3f
-#define LUNS_CHANGED_ASCQ 0x0e
-#define INSUFF_RES_ASC 0x55
-#define INSUFF_RES_ASCQ 0x3
-#define POWER_ON_RESET_ASCQ 0x0
-#define POWER_ON_OCCURRED_ASCQ 0x1
-#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */
-#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */
-#define CAPACITY_CHANGED_ASCQ 0x9
-#define SAVING_PARAMS_UNSUP 0x39
-#define TRANSPORT_PROBLEM 0x4b
-#define THRESHOLD_EXCEEDED 0x5d
-#define LOW_POWER_COND_ON 0x5e
-#define MISCOMPARE_VERIFY_ASC 0x1d
-#define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */
-#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
-#define WRITE_ERROR_ASC 0xc
-#define UNALIGNED_WRITE_ASCQ 0x4
-#define WRITE_BOUNDARY_ASCQ 0x5
-#define READ_INVDATA_ASCQ 0x6
-#define READ_BOUNDARY_ASCQ 0x7
-#define ATTEMPT_ACCESS_GAP 0x9
-#define INSUFF_ZONE_ASCQ 0xe
-/* see drivers/scsi/sense_codes.h */
-
/* Additional Sense Code Qualifier (ASCQ) */
#define ACK_NAK_TO 0x3
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 7daad4cad985..c4fac5f8d480 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -75,6 +75,7 @@ enum {
ATA_ID_HW_CONFIG = 93,
ATA_ID_SPG = 98,
ATA_ID_LBA_CAPACITY_2 = 100,
+ ATA_ID_MAX_PAGES_PER_DSM = 105,
ATA_ID_SECTOR_SIZE = 106,
ATA_ID_WWN = 108,
ATA_ID_LOGICAL_SECTOR_SIZE = 117, /* and 118 */
@@ -288,6 +289,10 @@ enum {
ATA_CMD_SANITIZE_DEVICE = 0xB4,
ATA_CMD_ZAC_MGMT_IN = 0x4A,
ATA_CMD_ZAC_MGMT_OUT = 0x9F,
+ ATA_CMD_GET_PHYS_ELEMENT_STATUS = 0x12,
+ ATA_CMD_REMOVE_ELEMENT_AND_TRUNCATE = 0x7c,
+ ATA_CMD_RESTORE_ELEMENTS_AND_REBUILD = 0x7d,
+ ATA_CMD_REMOVE_ELEMENT_AND_MODIFY_ZONES = 0x7e,
/* marked obsolete in the ATA/ATAPI-7 spec */
ATA_CMD_RESTORE = 0x10,
@@ -928,6 +933,18 @@ static inline bool ata_id_has_trim(const u16 *id)
return false;
}
+static inline u16 ata_id_dsm_max_pages(const u16 *id)
+{
+ /*
+ * IDENTIFY DEVICE word 105: MAX PAGES PER DSM COMMAND. Maximum number
+ * of 512-byte pages of LBA Range Entries the device accepts in a
+ * single DATA SET MANAGEMENT command. Zero means the device does not
+ * specify a limit. The field is reserved unless TRIM is supported, so
+ * callers must gate on ata_id_has_trim().
+ */
+ return id[ATA_ID_MAX_PAGES_PER_DSM];
+}
+
static inline bool ata_id_has_zero_after_trim(const u16 *id)
{
/* DSM supported, deterministic read, and read zero after trim set */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 1827502b9cf2..313e96173b19 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -121,6 +121,55 @@ enum {
ATA_QUIRK_NO_FUA = BIT_ULL(__ATA_QUIRK_NO_FUA),
};
+/*
+ * struct ata_device flags
+ */
+enum {
+ ATA_DFLAG_LBA = (1UL << 0), /* device supports LBA */
+ ATA_DFLAG_LBA48 = (1UL << 1), /* device supports LBA48 */
+ ATA_DFLAG_CDB_INTR = (1UL << 2), /* device asserts INTRQ when ready for CDB */
+ ATA_DFLAG_NCQ = (1UL << 3), /* device supports NCQ */
+ ATA_DFLAG_FLUSH_EXT = (1UL << 4), /* do FLUSH_EXT instead of FLUSH */
+ ATA_DFLAG_ACPI_PENDING = (1UL << 5), /* ACPI resume action pending */
+ ATA_DFLAG_ACPI_FAILED = (1UL << 6), /* ACPI on devcfg has failed */
+ ATA_DFLAG_AN = (1UL << 7), /* AN configured */
+ ATA_DFLAG_TRUSTED = (1UL << 8), /* device supports trusted send/recv */
+ ATA_DFLAG_FUA = (1UL << 9), /* device supports FUA */
+ ATA_DFLAG_DMADIR = (1UL << 10), /* device requires DMADIR */
+ ATA_DFLAG_NCQ_SEND_RECV = (1UL << 11), /* device supports NCQ SEND and RECV */
+ ATA_DFLAG_NCQ_PRIO = (1UL << 12), /* device supports NCQ priority */
+ ATA_DFLAG_CDL = (1UL << 13), /* supports cmd duration limits */
+ ATA_DFLAG_DEPOP = (1UL << 14), /* supports depopulation capability */
+ ATA_DFLAG_DEPOP_RESTORE = (1UL << 15), /* supports depopulation restoration */
+ ATA_DFLAG_DEPOP_MODIFY = (1UL << 16), /* supports zoned depopulation */
+ ATA_DFLAG_CFG_MASK = (1UL << 17) - 1,
+
+ ATA_DFLAG_PIO = (1UL << 17), /* device limited to PIO mode */
+ ATA_DFLAG_NCQ_OFF = (1UL << 18), /* device limited to non-NCQ mode */
+ ATA_DFLAG_SLEEPING = (1UL << 19), /* device is sleeping */
+ ATA_DFLAG_DUBIOUS_XFER = (1UL << 20), /* data transfer not verified */
+ ATA_DFLAG_NO_UNLOAD = (1UL << 21), /* device doesn't support unload */
+ ATA_DFLAG_UNLOCK_HPA = (1UL << 22), /* unlock HPA */
+ ATA_DFLAG_INIT_MASK = (1UL << 23) - 1,
+
+ ATA_DFLAG_NCQ_PRIO_ENABLED = (1UL << 23), /* Priority cmds sent to dev */
+ ATA_DFLAG_CDL_ENABLED = (1UL << 24), /* cmd duration limits is enabled */
+ ATA_DFLAG_RESUMING = (1UL << 25), /* Device is resuming */
+ ATA_DFLAG_DETACH = (1UL << 26),
+ ATA_DFLAG_DETACHED = (1UL << 27),
+ ATA_DFLAG_DA = (1UL << 28), /* device supports Device Attention */
+ ATA_DFLAG_DEVSLP = (1UL << 29), /* device supports Device Sleep */
+ ATA_DFLAG_ACPI_DISABLED = (1UL << 30), /* ACPI for the device is disabled */
+ ATA_DFLAG_D_SENSE = (1UL << 31), /* Descriptor sense requested */
+
+ 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_CDL | ATA_DFLAG_DEPOP | \
+ ATA_DFLAG_DEPOP_RESTORE |
+ ATA_DFLAG_DEPOP_MODIFY)
+};
+
enum {
/* various global constants */
LIBATA_MAX_PRD = ATA_MAX_PRD / 2,
@@ -146,46 +195,7 @@ enum {
ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */
- /* struct ata_device stuff */
- ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */
- ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */
- ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */
- ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */
- ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
- ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
- ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
- ATA_DFLAG_AN = (1 << 7), /* AN configured */
- ATA_DFLAG_TRUSTED = (1 << 8), /* device supports trusted send/recv */
- ATA_DFLAG_FUA = (1 << 9), /* device supports FUA */
- 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_CDL = (1 << 13), /* supports cmd duration limits */
- ATA_DFLAG_CFG_MASK = (1 << 14) - 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 << 20), /* Priority cmds sent to dev */
- ATA_DFLAG_CDL_ENABLED = (1 << 21), /* cmd duration limits is enabled */
- ATA_DFLAG_RESUMING = (1 << 22), /* Device is resuming */
- ATA_DFLAG_DETACH = (1 << 24),
- ATA_DFLAG_DETACHED = (1 << 25),
- ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */
- ATA_DFLAG_DEVSLP = (1 << 27), /* device supports Device Sleep */
- ATA_DFLAG_ACPI_DISABLED = (1 << 28), /* ACPI for the device is disabled */
- ATA_DFLAG_D_SENSE = (1 << 29), /* Descriptor sense requested */
-
- 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_CDL),
-
+ /* sturct ata_device class. */
ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */
ATA_DEV_ATA_UNSUP = 2, /* ATA device (unsupported) */
@@ -1421,9 +1431,6 @@ extern int ata_port_freeze(struct ata_port *ap);
extern void ata_eh_freeze_port(struct ata_port *ap);
extern void ata_eh_thaw_port(struct ata_port *ap);
-extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
-extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
-
extern void ata_std_error_handler(struct ata_port *ap)
__must_hold(&ap->host->eh_mutex);
extern void ata_std_sched_eh(struct ata_port *ap);
diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index f64385cde5b9..c6b4a4dc8d9c 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -129,6 +129,10 @@
#define SAI_GET_LBA_STATUS 0x12
#define SAI_REPORT_REFERRALS 0x13
#define SAI_GET_STREAM_STATUS 0x16
+#define SAI_GET_PHYSICAL_ELEMENT_STATUS 0x17
+#define SAI_REMOVE_ELEMENT_AND_TRUNCATE 0x18
+#define SAI_RESTORE_ELEMENTS_AND_REBUILD 0x19
+#define SAI_REMOVE_ELEMENT_AND_MODIFY_ZONES 0x1a
/* values for maintenance in */
#define MI_REPORT_IDENTIFYING_INFORMATION 0x05
#define MI_REPORT_TARGET_PGS 0x0a
@@ -234,6 +238,57 @@ enum sam_status {
#define COMPLETED 0x0f
/*
+ * Additional Sense Codes (ASC).
+ */
+#define NO_ADDITIONAL_SENSE 0x00
+#define OVERLAP_ATOMIC_COMMAND_ASC 0x00
+#define LOGICAL_UNIT_NOT_READY 0x04
+#define LOGICAL_UNIT_COMMUNICATION_FAILURE 0x8
+#define WRITE_ERROR_ASC 0x0c
+#define UNRECOVERED_READ_ERR 0x11
+#define PARAMETER_LIST_LENGTH_ERR 0x1a
+#define MISCOMPARE_VERIFY_ASC 0x1d
+#define INVALID_OPCODE 0x20
+#define LBA_OUT_OF_RANGE 0x21
+#define INVALID_FIELD_IN_CDB 0x24
+#define INVALID_FIELD_IN_PARAM_LIST 0x26
+#define WRITE_PROTECTED 0x27
+#define UA_READY_ASC 0x28
+#define UA_RESET_ASC 0x29
+#define UA_CHANGED_ASC 0x2a
+#define TOO_MANY_IN_PARTITION_ASC 0x3b
+#define TARGET_CHANGED_ASC 0x3f
+#define SAVING_PARAMS_UNSUP 0x39
+#define TRANSPORT_PROBLEM 0x4b
+#define INSUFF_RES_ASC 0x55
+#define LOW_POWER_COND_ON 0x5e
+#define THRESHOLD_EXCEEDED 0x5d
+
+/*
+ * Additional Sense Code Qualifiers (ASCQ).
+ */
+#define POWER_ON_RESET_ASCQ 0x00
+#define MODE_CHANGED_ASCQ 0x01 /* mode parameters changed */
+#define FILEMARK_DETECTED_ASCQ 0x01
+#define POWER_ON_OCCURRED_ASCQ 0x01
+#define MICROCODE_CHANGED_ASCQ 0x01 /* with TARGET_CHANGED_ASC */
+#define BUS_RESET_ASCQ 0x02 /* scsi bus reset occurred */
+#define EOP_EOM_DETECTED_ASCQ 0x02
+#define INSUFF_RES_ASCQ 0x03
+#define BEGINNING_OF_P_M_DETECTED_ASCQ 0x04
+#define UNALIGNED_WRITE_ASCQ 0x04
+#define EOD_DETECTED_ASCQ 0x05
+#define WRITE_BOUNDARY_ASCQ 0x05
+#define READ_INVDATA_ASCQ 0x06
+#define READ_BOUNDARY_ASCQ 0x07
+#define CAPACITY_CHANGED_ASCQ 0x09
+#define ATTEMPT_ACCESS_GAP 0x09
+#define LUNS_CHANGED_ASCQ 0x0e
+#define INSUFF_ZONE_ASCQ 0x0e
+#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
+#define OVERLAP_ATOMIC_COMMAND_ASCQ 0x23
+
+/*
* DEVICE TYPES
* Please keep them in 0x%02x format for $MODALIAS to work
*/
@@ -413,6 +468,25 @@ enum zbc_zone_alignment_method {
ZBC_CONSTANT_ZONE_START_OFFSET = 0x8,
};
+/* SCSI physical element types */
+enum scsi_phys_element_type {
+ SCSI_PHYS_ELEM_TYPE_ALL_ACCESS_STORAGE = 0x1,
+ SCSI_PHYS_ELEM_TYPE_FRAC_ACCESS_STORAGE = 0x2,
+};
+
+/* SCSI physical element health. */
+enum scsi_phys_element_health {
+ SCSI_PHYS_ELEM_HEALTH_NOT_REPORTED = 0x00,
+ SCSI_PHYS_ELEM_HEALTH_WITHIN_SPEC_LIMITS = 0x01,
+ SCSI_PHYS_ELEM_HEALTH_AT_SPEC_LIMITS = 0x64,
+ SCSI_PHYS_ELEM_HEALTH_OUTSIDE_SPEC_LIMITS = 0x65,
+ SCSI_PHYS_ELEM_HEALTH_DEPOP_REVOKE_ERR = 0xFB,
+ SCSI_PHYS_ELEM_HEALTH_DEPOP_REVOKE_IN_PROGRESS = 0xFC,
+ SCSI_PHYS_ELEM_HEALTH_DEPOP_ERR = 0xFD,
+ SCSI_PHYS_ELEM_HEALTH_DEPOP_IN_PROGRESS = 0xFE,
+ SCSI_PHYS_ELEM_HEALTH_DEPOP_OK = 0xFF,
+};
+
/* Version descriptor values for INQUIRY */
enum scsi_version_descriptor {
SCSI_VERSION_DESCRIPTOR_FCP4 = 0x0a40,