projects/linux·commit faabe2db

Merge tag 'ata-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

faabe2db · Linus Torvalds <[email protected]> · 2026-08-19 12:31:50 -07:00

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
  ...
Commit
faabe2db712e8310dbe38fb81d33e5313ff0f059
Parents
59e6295f · 73b6bf3c

Merge commit. Changes below are compared with the first parent: 59e6295f.

Changes

20 files changed · +915 −345

Only the first 600 diff lines are shown. Download the complete patch.

drivers/ata/ahci_da850.c

View file
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index f97566c..4e53ff9 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,

drivers/ata/ahci_platform.c

View file
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 4fbcaff..8724b24 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);

drivers/ata/ahci_qoriq.c

View file
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 0dec1a1..9649215 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);

drivers/ata/ahci_seattle.c

View file
diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c
index 3f16c16..9758fa0 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);

drivers/ata/ahci_xgene.c

View file
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index 98c99b5..2ebfe86 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

drivers/ata/libata-core.c

View file
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 59e87b9..f482c0a 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)

drivers/ata/libata-eh.c

View file
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index c154103..c93c24b 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);

drivers/ata/libata-scsi.c

View file
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d2160ee..a7d667c 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,

This diff is incomplete. Download the complete patch.

drivers/ata/libata-sff.c

View file

This diff is incomplete. Download the complete patch.

drivers/ata/libata.h

View file

This diff is incomplete. Download the complete patch.

drivers/ata/pata_ep93xx.c

View file

This diff is incomplete. Download the complete patch.

drivers/ata/pata_mpc52xx.c

View file

This diff is incomplete. Download the complete patch.

drivers/ata/pata_pxa.c

View file

This diff is incomplete. Download the complete patch.

drivers/ata/pata_rb532_cf.c

View file

This diff is incomplete. Download the complete patch.

drivers/ata/sata_highbank.c

View file

This diff is incomplete. Download the complete patch.

drivers/ata/sata_mv.c

View file

This diff is incomplete. Download the complete patch.

drivers/scsi/scsi_debug.c

View file

This diff is incomplete. Download the complete patch.

include/linux/ata.h

View file

This diff is incomplete. Download the complete patch.

include/linux/libata.h

View file

This diff is incomplete. Download the complete patch.

include/scsi/scsi_proto.h

View file

This diff is incomplete. Download the complete patch.