diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-19 12:31:50 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-19 12:31:50 -0700 |
| commit | faabe2db712e8310dbe38fb81d33e5313ff0f059 (patch) | |
| tree | 8f917cb0126f652d041e8b2ed03f5aa6fa5a1e54 | |
| parent | 59e6295fac26b8e85c1ea859cdd89fa1e47519d7 (diff) | |
| parent | 73b6bf3c314ad34a9fd389f84de6e8dbfc204880 (diff) | |
Merge tag 'ata-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux
Pull ata updates from Damien Le Moal:
- Some code cleanups to rename the function used to identify ZAC
devices and declare some local functions static (me)
- Refactoring and improvement of the translation of the SCSI REPORT
SUPPORTED OPCODES command to allow users access to the entire list of
supported commands (me)
- Fix the translation of the WRITE SAME command with UNMAP bit set (DSM
TRIM) for devices with a sector size larger than 2K and devices that
support multiple TRIM segments (Niklas)
- Add support detecting support for and translating the SCSI commands
related to the storage elements depopulation feature (GET PHYSICAL
ELEMENT STATUS, REMOVE ELEMENT AND TRUCATE, REMOVE ELEMENT AND MODIFY
ZONES and RESTORE ELEMENTS AND REBUILD) (me)
- Improvements to the sata_mv driver probe code (clocks and IRQ
initialization) (Rosen)
- Improve resource initialization in the pata_rb532_cf, pata_pxa,
sata_highbank and ahci_da850 drivers (Rosen)
- Improve PIO data-in command completions to better hndle slow devices,
e.g. CF cards (Richard)
- Improve the DMA channel management using device resources in the
pata_pxa driver (Rosen)
- Fix the pata_ep93xx driver to correctly fallback to PIO mode if DMA
initialization fails (Rosen)
- Use named initializers to define the match tables of the ahci_xgene,
ahci_qoriq and ahci_platform drivers (Pawel)
* tag 'ata-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux: (28 commits)
ata: use named initializers for acpi_device_id
ata: pata_ep93xx: fix PIO fallback when DMA init fails
ata: pata_pxa: use devres for DMA channel management
ata: libata-sff: don't busy-wait for PIO data-in command completion
ata: ahci_da850: use devm_platform_ioremap_resource()
ata: sata_highbank: use devm_platform_ioremap_resource
ata: pata_pxa: use devm_platform_ioremap_resource
ata: pata_rb532_cf: use devm_platform_ioremap_resource()
ata: sata_mv: use devm clock helpers
ata: sata_mv: Use platform_get_irq() to get interrupt
ata: pata_mpc52xx: Remove redundant dev_err()
ata: libata-eh: make ata_eh_qc_complete() and ata_eh_qc_retry() static
ata: libata-scsi: add support for the REMOVE ELEMENT AND MODIFY ZONES command
ata: libata-scsi: add support for the RESTORE ELEMENTS AND REBUILD command
ata: libata-scsi: add support for the REMOVE ELEMENT AND TRUNCATE command
ata: libata-scsi: add support for the GET PHYSICAL ELEMENT STATUS command
ata: libata-core: detect support for depopulation capabilities
ata: libata-scsi: improve ata_get_xlat_func
ata: libata: improve the definition of device flags
scsi: define depopulation capabilities related service actions
...
| -rw-r--r-- | drivers/ata/ahci_da850.c | 17 | ||||
| -rw-r--r-- | drivers/ata/ahci_platform.c | 4 | ||||
| -rw-r--r-- | drivers/ata/ahci_qoriq.c | 2 | ||||
| -rw-r--r-- | drivers/ata/ahci_seattle.c | 4 | ||||
| -rw-r--r-- | drivers/ata/ahci_xgene.c | 6 | ||||
| -rw-r--r-- | drivers/ata/libata-core.c | 79 | ||||
| -rw-r--r-- | drivers/ata/libata-eh.c | 6 | ||||
| -rw-r--r-- | drivers/ata/libata-scsi.c | 714 | ||||
| -rw-r--r-- | drivers/ata/libata-sff.c | 24 | ||||
| -rw-r--r-- | drivers/ata/libata.h | 2 | ||||
| -rw-r--r-- | drivers/ata/pata_ep93xx.c | 30 | ||||
| -rw-r--r-- | drivers/ata/pata_mpc52xx.c | 4 | ||||
| -rw-r--r-- | drivers/ata/pata_pxa.c | 52 | ||||
| -rw-r--r-- | drivers/ata/pata_rb532_cf.c | 16 | ||||
| -rw-r--r-- | drivers/ata/sata_highbank.c | 18 | ||||
| -rw-r--r-- | drivers/ata/sata_mv.c | 52 | ||||
| -rw-r--r-- | drivers/scsi/scsi_debug.c | 46 | ||||
| -rw-r--r-- | include/linux/ata.h | 17 | ||||
| -rw-r--r-- | include/linux/libata.h | 93 | ||||
| -rw-r--r-- | include/scsi/scsi_proto.h | 74 |
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, |
