Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [PATCH v1 0/9] ATA support for storage element management commands
@ 2026-07-06  6:56 Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h Damien Le Moal
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

This patch series adds support to libata for translating all storage
element management commands:
 - GET PHYSICAL ELEMENT STATUS
 - REMOVE ELEMENT AND TRUNCATE
 - RESTORE ELEMENTS AND REBUILD
 - REMOVE ELEMENT AND MODIFY ZONES

The first 2 patches add definitions to scsi_proto.h related to the
depopulation feature. The remaining patches modify libata to detect
support for this feature and add command translation support.

Martin,

I have more patches for sd and scsi_debug (depop emulation) that depend on
patch 1 & 2. So I am not sure how we should handle this series. Maybe we
should create a "depop" topic branch in the scsi or libata tree ? I am
open to suggestions.

Damien Le Moal (9):
  scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h
  scsi: define depopulation capabilities related service actions
  ata: libata: improve the definition of device flags
  ata: libata-scsi: improve ata_get_xlat_func
  ata: libata-core: detect support for depopulation capabilities
  ata: libata-scsi: add support for the GET PHYSICAL ELEMENT STATUS
    command
  ata: libata-scsi: add support for the REMOVE ELEMENT AND TRUNCATE
    command
  ata: libata-scsi: add support for the RESTORE ELEMENTS AND REBUILD
    command
  ata: libata-scsi: add support for the REMOVE ELEMENT AND MODIFY ZONES
    command

 drivers/ata/libata-core.c |  73 +++++++++-
 drivers/ata/libata-scsi.c | 300 +++++++++++++++++++++++++++++++++++++-
 drivers/scsi/scsi_debug.c |  46 ------
 include/linux/ata.h       |   4 +
 include/linux/libata.h    |  90 +++++++-----
 include/scsi/scsi_proto.h |  74 ++++++++++
 6 files changed, 493 insertions(+), 94 deletions(-)

-- 
2.54.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  8:29   ` Hannes Reinecke
  2026-07-06  8:44   ` Hannes Reinecke
  2026-07-06  6:56 ` [PATCH v1 2/9] scsi: define depopulation capabilities related service actions Damien Le Moal
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

The scsi_debug driver internally defines lots of SCSI additional sense
codes (ASC) and additional sense code qualifiers (ASCQ). Move these
definitions to include/scsi/scsi_proto.h so that they can be reused
elsewhere in the SCSI and ATA code. This also makes the scsi_debug.c file
a little smaller.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/scsi/scsi_debug.c | 46 -----------------------------------
 include/scsi/scsi_proto.h | 51 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 46 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 9d1c9c41d0f9..4a95e6bae38b 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/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index f64385cde5b9..965cde7ebc5b 100644
--- a/include/scsi/scsi_proto.h
+++ b/include/scsi/scsi_proto.h
@@ -233,6 +233,57 @@ enum sam_status {
 #define MISCOMPARE          0x0e
 #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
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 2/9] scsi: define depopulation capabilities related service actions
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 3/9] ata: libata: improve the definition of device flags Damien Le Moal
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

Add to include/scsi/scsi_proto.h the definition of the four service
actions of the SERVICE ACTION IN (16) command for the storage element
depopulation and restoration capabilities, as defined in the SBC5 and
ZBC2 specifications. These are:
 - SAI_GET_PHYSICAL_ELEMENT_STATUS (GET PHYSICAL ELEMENT STATUS command)
 - SAI_REMOVE_ELEMENT_AND_TRUNCATE (REMOVE ELEMENT AND TRUNCATE command)
 - SAI_RESTORE_ELEMENTS_AND_REBUILD (RESTORE ELEMENTS AND REBUILD command)
 - SAI_REMOVE_ELEMENT_AND_MODIFY_ZONES (REMOVE ELEMENT AND MODIFY ZONES
   command)

The physical element types and physical element health values reported by
the GET PHYSICAL ELEMENT STATUS command are also defined.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 include/scsi/scsi_proto.h | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
index 965cde7ebc5b..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
@@ -464,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,
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 3/9] ata: libata: improve the definition of device flags
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 2/9] scsi: define depopulation capabilities related service actions Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 4/9] ata: libata-scsi: improve ata_get_xlat_func Damien Le Moal
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

The flags field of struct ata_device has the unsigned long type. Define
all the ATA_DFLAG_XXX flags using a 1UL bit shift to match this type, thus
avoiding flags to become signed values (e.g. for bit 31 flag).

To avoid all other values defined in the same enum as the ATA_DFLAG_XXX
flags to implicitly also become unsigned long values, move the device
flags definition to a separate enum.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 include/linux/libata.h | 85 ++++++++++++++++++++++--------------------
 1 file changed, 45 insertions(+), 40 deletions(-)

diff --git a/include/linux/libata.h b/include/linux/libata.h
index 96e626d6a7ca..736ba8a6a77b 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -121,6 +121,50 @@ 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_CFG_MASK	= (1UL << 14) - 1,
+
+	ATA_DFLAG_PIO		= (1UL << 14), /* device limited to PIO mode */
+	ATA_DFLAG_NCQ_OFF	= (1UL << 15), /* device limited to non-NCQ mode */
+	ATA_DFLAG_SLEEPING	= (1UL << 16), /* device is sleeping */
+	ATA_DFLAG_DUBIOUS_XFER	= (1UL << 17), /* data transfer not verified */
+	ATA_DFLAG_NO_UNLOAD	= (1UL << 18), /* device doesn't support unload */
+	ATA_DFLAG_UNLOCK_HPA	= (1UL << 19), /* unlock HPA */
+	ATA_DFLAG_INIT_MASK	= (1UL << 20) - 1,
+
+	ATA_DFLAG_NCQ_PRIO_ENABLED = (1UL << 20), /* Priority cmds sent to dev */
+	ATA_DFLAG_CDL_ENABLED	= (1UL << 21), /* cmd duration limits is enabled */
+	ATA_DFLAG_RESUMING	= (1UL << 22),  /* Device is resuming */
+	ATA_DFLAG_DETACH	= (1UL << 24),
+	ATA_DFLAG_DETACHED	= (1UL << 25),
+	ATA_DFLAG_DA		= (1UL << 26), /* device supports Device Attention */
+	ATA_DFLAG_DEVSLP	= (1UL << 27), /* device supports Device Sleep */
+	ATA_DFLAG_ACPI_DISABLED = (1UL << 28), /* ACPI for the device is disabled */
+	ATA_DFLAG_D_SENSE	= (1UL << 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)
+};
+
 enum {
 	/* various global constants */
 	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
@@ -146,46 +190,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) */
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 4/9] ata: libata-scsi: improve ata_get_xlat_func
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
                   ` (2 preceding siblings ...)
  2026-07-06  6:56 ` [PATCH v1 3/9] ata: libata: improve the definition of device flags Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 5/9] ata: libata-core: detect support for depopulation capabilities Damien Le Moal
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

ata_get_xlat_func() is given only the opcode of a SCSI command to
determine the ATA command to translate to. This makes it impossible to
translate SCSI commands such as SERVICE ACTION IN which need a service
action field to fully specify the command.

In preparation for supporting the translation of the SERVICE ACTION IN
command with service actions different from the SAI_READ_CAPACITY_16 (READ
CAPACITY 16), change ata_get_xlat_func() to take a pointer to a SCSI
command CDB so that all fields of the SCSI command to translate can be
easily inspected.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-scsi.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 5cddb63a6bc6..f5c838ca0ce9 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -4606,7 +4606,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.
@@ -4615,9 +4615,10 @@ 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) {
+	switch (cdb[0]) {
 	case READ_6:
 	case READ_10:
 	case READ_16:
@@ -4748,7 +4749,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;
 
 	/*
@@ -4768,7 +4770,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);
@@ -4784,7 +4786,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)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 5/9] ata: libata-core: detect support for depopulation capabilities
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
                   ` (3 preceding siblings ...)
  2026-07-06  6:56 ` [PATCH v1 4/9] ata: libata-scsi: improve ata_get_xlat_func Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 6/9] ata: libata-scsi: add support for the GET PHYSICAL ELEMENT STATUS command Damien Le Moal
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

Introduce the device flags ATA_DFLAG_DEPOP to indicate support by a device
for the basic commands of the storage element depopulation feature set,
that is, the GET PHYSICAL ELEMENT STATUS and REMOVE ELEMENT AND TRUNCATE
commands. The device flag ATA_DFLAG_DEPOP_RESTORE flag is introduced to
indicate support for the RESTORE ELEMENTS AND REBUILD command. Both flags
are obtained from the command support bits of the qword at bytes 152 to
159 of the supported capabilities log page.

For ZAC devices, the device flag ATA_DFLAG_DEPOP_MODIFY is introduced to
indicate support for the REMOVE ELEMENT AND MODIFY ZONES command. This
support is indicated by the REMOVE ELEMENT AND MODIFY ZONES SUPPORTED bit
in the qword at byte 8 to 15 of the zoned device information log page.

The function ata_dev_config_depop() is introduced to set these flags
based on the content of the supported capabilities log and zoned device
information log. As per the ACS specifications, NCQ autosense support is
also mandatory if these flags are set.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-core.c | 73 +++++++++++++++++++++++++++++++++++++--
 include/linux/libata.h    | 45 +++++++++++++-----------
 2 files changed, 96 insertions(+), 22 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5121faf9738e..d893c916df0b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2705,6 +2705,71 @@ static void ata_dev_config_cdl(struct ata_device *dev)
 	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" : "");
 }
 
 /**
@@ -3115,6 +3183,7 @@ int ata_dev_configure(struct ata_device *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/include/linux/libata.h b/include/linux/libata.h
index 736ba8a6a77b..3703ef433bd4 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -139,30 +139,35 @@ enum {
 	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_CFG_MASK	= (1UL << 14) - 1,
-
-	ATA_DFLAG_PIO		= (1UL << 14), /* device limited to PIO mode */
-	ATA_DFLAG_NCQ_OFF	= (1UL << 15), /* device limited to non-NCQ mode */
-	ATA_DFLAG_SLEEPING	= (1UL << 16), /* device is sleeping */
-	ATA_DFLAG_DUBIOUS_XFER	= (1UL << 17), /* data transfer not verified */
-	ATA_DFLAG_NO_UNLOAD	= (1UL << 18), /* device doesn't support unload */
-	ATA_DFLAG_UNLOCK_HPA	= (1UL << 19), /* unlock HPA */
-	ATA_DFLAG_INIT_MASK	= (1UL << 20) - 1,
-
-	ATA_DFLAG_NCQ_PRIO_ENABLED = (1UL << 20), /* Priority cmds sent to dev */
-	ATA_DFLAG_CDL_ENABLED	= (1UL << 21), /* cmd duration limits is enabled */
-	ATA_DFLAG_RESUMING	= (1UL << 22),  /* Device is resuming */
-	ATA_DFLAG_DETACH	= (1UL << 24),
-	ATA_DFLAG_DETACHED	= (1UL << 25),
-	ATA_DFLAG_DA		= (1UL << 26), /* device supports Device Attention */
-	ATA_DFLAG_DEVSLP	= (1UL << 27), /* device supports Device Sleep */
-	ATA_DFLAG_ACPI_DISABLED = (1UL << 28), /* ACPI for the device is disabled */
-	ATA_DFLAG_D_SENSE	= (1UL << 29), /* Descriptor sense requested */
+	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_CDL | ATA_DFLAG_DEPOP | \
+				   ATA_DFLAG_DEPOP_RESTORE |
+				   ATA_DFLAG_DEPOP_MODIFY)
 };
 
 enum {
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 6/9] ata: libata-scsi: add support for the GET PHYSICAL ELEMENT STATUS command
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
                   ` (4 preceding siblings ...)
  2026-07-06  6:56 ` [PATCH v1 5/9] ata: libata-core: detect support for depopulation capabilities Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 7/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND TRUNCATE command Damien Le Moal
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

Define the translation for the GET PHYSICAL ELEMENT STATUS command
(SERVICE ACTION IN command with service action
SAI_GET_PHYSICAL_ELEMENT_STATUS) into the ATA command
ATA_CMD_GET_PHYS_ELEMENT_STATUS with the new function
ata_scsi_get_phys_element_status_xlat(). The reply of this function also
needs translation from little endian to big endian. This is done with the
completion callback ata_scsi_get_phys_element_status_complete().

The array of supported commands ata_supported_cmds is modified to add a
new entry for this command. ata_scsi_cmd_is_supported() is also modified
to correctly handle this new entry depending on the target device flag
ATA_DFLAG_DEPOP being set.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-scsi.c | 141 ++++++++++++++++++++++++++++++++++++++
 include/linux/ata.h       |   1 +
 2 files changed, 142 insertions(+)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f5c838ca0ce9..8723faa96c48 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3724,6 +3724,11 @@ static const struct ata_scsi_cmd ata_supported_cmds[] = {
 		.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 = REPORT_LUNS,		.cdb_len = 12	},
 	{	.op = ATA_12,			.cdb_len = 12	},
 	{	.op = SECURITY_PROTOCOL_IN,	.cdb_len = 12	},
@@ -3804,6 +3809,14 @@ static bool ata_scsi_cmd_is_supported(struct ata_device *dev, u8 op, u16 sa,
 	case ZBC_IN:
 	case ZBC_OUT:
 		return ata_dev_is_zoned(dev);
+	case SERVICE_ACTION_IN_16:
+		switch (sa) {
+		case SAI_GET_PHYSICAL_ELEMENT_STATUS:
+			return dev->flags & ATA_DFLAG_DEPOP;
+		default:
+			return true;
+		}
+		break;
 	case SECURITY_PROTOCOL_IN:
 	case SECURITY_PROTOCOL_OUT:
 		return dev->flags & ATA_DFLAG_TRUSTED;
@@ -4575,6 +4588,126 @@ 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;
+}
+
 /**
  *	ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler
  *	@qc: Command to be translated
@@ -4618,6 +4751,8 @@ static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc)
 static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev,
 						u8 *cdb)
 {
+	u8 sa;
+
 	switch (cdb[0]) {
 	case READ_6:
 	case READ_10:
@@ -4652,6 +4787,12 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev,
 	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;
+		break;
+
 	case ZBC_IN:
 		return ata_scsi_zbc_in_xlat;
 
diff --git a/include/linux/ata.h b/include/linux/ata.h
index ac5616a9668b..8b726d9bdda3 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -289,6 +289,7 @@ 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,
 
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 7/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND TRUNCATE command
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
                   ` (5 preceding siblings ...)
  2026-07-06  6:56 ` [PATCH v1 6/9] ata: libata-scsi: add support for the GET PHYSICAL ELEMENT STATUS command Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 8/9] ata: libata-scsi: add support for the RESTORE ELEMENTS AND REBUILD command Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 9/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND MODIFY ZONES command Damien Le Moal
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

Define the translation for the REMOVE ELEMENT AND TRUNCATE command
(SERVICE ACTION IN command with service action
SAI_REMOVE_ELEMENT_AND_TRUNCATE) into the ATA command
ATA_CMD_REMOVE_ELEMENT_AND_TRUNCATE with the new function
ata_scsi_remove_element_and_truncate_xlat()

The array of supported commands ata_supported_cmds is modified to add a
new entry for this command. ata_scsi_cmd_is_supported() is also modify to
correctly handle this new entry depending on the target device flag
ATA_DFLAG_DEPOP being set.

The ATA command completion is handled using the function
ata_scsi_depop_ua_cap_changed_complete() so that on a successful
completion, a UNIT ATTENTION with the additional sense code set to
CAPACITY DATA HAS CHANGED is raised.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-scsi.c | 73 +++++++++++++++++++++++++++++++++++++++
 include/linux/ata.h       |  1 +
 2 files changed, 74 insertions(+)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8723faa96c48..49beefa46cf3 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3729,6 +3729,11 @@ static const struct ata_scsi_cmd ata_supported_cmds[] = {
 		.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 = REPORT_LUNS,		.cdb_len = 12	},
 	{	.op = ATA_12,			.cdb_len = 12	},
 	{	.op = SECURITY_PROTOCOL_IN,	.cdb_len = 12	},
@@ -3812,6 +3817,7 @@ static bool ata_scsi_cmd_is_supported(struct ata_device *dev, u8 op, u16 sa,
 	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;
 		default:
 			return true;
@@ -4708,6 +4714,71 @@ ata_scsi_get_phys_element_status_xlat(struct ata_queued_cmd *qc)
 	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. 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;
+}
+
 /**
  *	ata_scsi_var_len_cdb_xlat - SATL variable length CDB to Handler
  *	@qc: Command to be translated
@@ -4791,6 +4862,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev,
 		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;
 		break;
 
 	case ZBC_IN:
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 8b726d9bdda3..89ac27743f50 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -290,6 +290,7 @@ enum {
 	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,
 
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 8/9] ata: libata-scsi: add support for the RESTORE ELEMENTS AND REBUILD command
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
                   ` (6 preceding siblings ...)
  2026-07-06  6:56 ` [PATCH v1 7/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND TRUNCATE command Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  2026-07-06  6:56 ` [PATCH v1 9/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND MODIFY ZONES command Damien Le Moal
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

Define the translation for the RESTORE ELEMENTS AND REBUILD command
(SERVICE ACTION IN command with service action
SAI_RESTORE_ELEMENTS_AND_REBUILD) into the ATA command
ATA_CMD_RESTORE_ELEMENTS_AND_REBUILD with the new function
ata_scsi_restore_elements_and_rebuild_xlat()

The array of supported commands ata_supported_cmds is modified to add a
new entry for this command. ata_scsi_cmd_is_supported() is also modify to
correctly handle this new entry depending on the target device flag
ATA_DFLAG_DEPOP_RESTORE being set.

The ATA command completion is handled using the function
ata_scsi_depop_ua_cap_changed_complete() so that on a successful
completion, a UNIT ATTENTION with the additional sense code set to
CAPACITY DATA HAS CHANGED is raised.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-scsi.c | 37 +++++++++++++++++++++++++++++++++++--
 include/linux/ata.h       |  1 +
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 49beefa46cf3..5bdf54a9e9b1 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3734,6 +3734,11 @@ static const struct ata_scsi_cmd ata_supported_cmds[] = {
 		.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 = REPORT_LUNS,		.cdb_len = 12	},
 	{	.op = ATA_12,			.cdb_len = 12	},
 	{	.op = SECURITY_PROTOCOL_IN,	.cdb_len = 12	},
@@ -3819,6 +3824,8 @@ static bool ata_scsi_cmd_is_supported(struct ata_device *dev, u8 op, u16 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;
 		default:
 			return true;
 		}
@@ -4726,8 +4733,9 @@ static void ata_scsi_depop_ua_cap_changed_complete(struct ata_queued_cmd *qc)
 	 * 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. But a capacity
-	 * change unit attention is harmless, so always raise the unit attention.
+	 * 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,
@@ -4779,6 +4787,29 @@ ata_scsi_remove_element_and_truncate_xlat(struct ata_queued_cmd *qc)
 	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
@@ -4864,6 +4895,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev,
 			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_RESTORE_ELEMENTS_AND_REBUILD)
+			return ata_scsi_restore_elements_and_rebuild_xlat;
 		break;
 
 	case ZBC_IN:
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 89ac27743f50..a1cd68cfb44f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -291,6 +291,7 @@ enum {
 	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,
 
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v1 9/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND MODIFY ZONES command
  2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
                   ` (7 preceding siblings ...)
  2026-07-06  6:56 ` [PATCH v1 8/9] ata: libata-scsi: add support for the RESTORE ELEMENTS AND REBUILD command Damien Le Moal
@ 2026-07-06  6:56 ` Damien Le Moal
  8 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  6:56 UTC (permalink / raw)
  To: linux-ide, Niklas Cassel, linux-scsi, Martin K . Petersen

Define the translation for the REMOVE ELEMENT AND MODIFY ZONES command
(SERVICE ACTION IN command with service action
SAI_REMOVE_ELEMENT_AND_MODIFY_ZONES) into the ATA command
ATA_CMD_REMOVE_ELEMENT_AND_MODIFY_ZONES with the new function
ata_scsi_remove_element_and_modify_zones_xlat()

The array of supported commands ata_supported_cmds is modified to add a
new entry for this command. ata_scsi_cmd_is_supported() is also modify to
correctly handle this new entry depending on the target device flag
ATA_DFLAG_DEPOP being set, and the target device being a ZAC zoned device.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/ata/libata-scsi.c | 39 +++++++++++++++++++++++++++++++++++++++
 include/linux/ata.h       |  1 +
 2 files changed, 40 insertions(+)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 5bdf54a9e9b1..1d225ee9eb86 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3739,6 +3739,11 @@ static const struct ata_scsi_cmd ata_supported_cmds[] = {
 		.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	},
@@ -3826,6 +3831,8 @@ static bool ata_scsi_cmd_is_supported(struct ata_device *dev, u8 op, u16 sa,
 			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;
 		}
@@ -4787,6 +4794,36 @@ ata_scsi_remove_element_and_truncate_xlat(struct ata_queued_cmd *qc)
 	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)
 {
@@ -4895,6 +4932,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev,
 			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;
diff --git a/include/linux/ata.h b/include/linux/ata.h
index a1cd68cfb44f..fc21a2417b25 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -292,6 +292,7 @@ enum {
 	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,
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h
  2026-07-06  6:56 ` [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h Damien Le Moal
@ 2026-07-06  8:29   ` Hannes Reinecke
  2026-07-06  8:55     ` Damien Le Moal
  2026-07-06  8:44   ` Hannes Reinecke
  1 sibling, 1 reply; 14+ messages in thread
From: Hannes Reinecke @ 2026-07-06  8:29 UTC (permalink / raw)
  To: Damien Le Moal, linux-ide, Niklas Cassel, linux-scsi,
	Martin K . Petersen

On 7/6/26 8:56 AM, Damien Le Moal wrote:
> The scsi_debug driver internally defines lots of SCSI additional sense
> codes (ASC) and additional sense code qualifiers (ASCQ). Move these
> definitions to include/scsi/scsi_proto.h so that they can be reused
> elsewhere in the SCSI and ATA code. This also makes the scsi_debug.c file
> a little smaller.
> 
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> ---
>   drivers/scsi/scsi_debug.c | 46 -----------------------------------
>   include/scsi/scsi_proto.h | 51 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 51 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
> index 9d1c9c41d0f9..4a95e6bae38b 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/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
> index f64385cde5b9..965cde7ebc5b 100644
> --- a/include/scsi/scsi_proto.h
> +++ b/include/scsi/scsi_proto.h
> @@ -233,6 +233,57 @@ enum sam_status {
>   #define MISCOMPARE          0x0e
>   #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

While at it, would you mind converting the raw asc/ascq numbers
in drivers/scsi/scsi_lib.c to use these definitions?
That will make the code in there _so much_ more readable ...

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h
  2026-07-06  6:56 ` [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h Damien Le Moal
  2026-07-06  8:29   ` Hannes Reinecke
@ 2026-07-06  8:44   ` Hannes Reinecke
  2026-07-06  9:00     ` Damien Le Moal
  1 sibling, 1 reply; 14+ messages in thread
From: Hannes Reinecke @ 2026-07-06  8:44 UTC (permalink / raw)
  To: Damien Le Moal, linux-ide, Niklas Cassel, linux-scsi,
	Martin K . Petersen

On 7/6/26 8:56 AM, Damien Le Moal wrote:
> The scsi_debug driver internally defines lots of SCSI additional sense
> codes (ASC) and additional sense code qualifiers (ASCQ). Move these
> definitions to include/scsi/scsi_proto.h so that they can be reused
> elsewhere in the SCSI and ATA code. This also makes the scsi_debug.c file
> a little smaller.
> 
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
> ---
>   drivers/scsi/scsi_debug.c | 46 -----------------------------------
>   include/scsi/scsi_proto.h | 51 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 51 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
> index 9d1c9c41d0f9..4a95e6bae38b 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/scsi/scsi_proto.h b/include/scsi/scsi_proto.h
> index f64385cde5b9..965cde7ebc5b 100644
> --- a/include/scsi/scsi_proto.h
> +++ b/include/scsi/scsi_proto.h
> @@ -233,6 +233,57 @@ enum sam_status {
>   #define MISCOMPARE          0x0e
>   #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

Weelll ... _technically_ the ASC/ASCQ codes have to be evaluated
together, and the individual definitions only make sense for a
combination of ASC/ASCQ codes.
EG SPC-5 defines the ASC/ASCQ 0x20/0x00 as 'Invalid command opcode',
but with this we would deocde it as 'INVALID_OPCODE'/'POWER_ON_RESET_ASCQ',
but 'POWER ON RESET OCCURRED' is ASC/ASCQ 0x29/0x00.
So if we were to define ASCQ codes we would need to define the
ASCQ codes for each ASC to avoid these issues.

Makes me wonder if we shouldn't introduce u16 for sense code
handling ...

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h
  2026-07-06  8:29   ` Hannes Reinecke
@ 2026-07-06  8:55     ` Damien Le Moal
  0 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  8:55 UTC (permalink / raw)
  To: Hannes Reinecke, linux-ide, Niklas Cassel, linux-scsi,
	Martin K . Petersen

On 7/6/26 5:29 PM, Hannes Reinecke wrote:
> While at it, would you mind converting the raw asc/ascq numbers
> in drivers/scsi/scsi_lib.c to use these definitions?
> That will make the code in there _so much_ more readable ...

100% agree. And not just scsi_lib, but also sd.c, libata, etc. We have so many
places where ASC/ASCQ are hardcoded/hard to understand, that this will be a
great cleanup.

BUT, that's too much for this series. I was planning such cleanup as a follow-up.

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h
  2026-07-06  8:44   ` Hannes Reinecke
@ 2026-07-06  9:00     ` Damien Le Moal
  0 siblings, 0 replies; 14+ messages in thread
From: Damien Le Moal @ 2026-07-06  9:00 UTC (permalink / raw)
  To: Hannes Reinecke, linux-ide, Niklas Cassel, linux-scsi,
	Martin K . Petersen

On 7/6/26 5:44 PM, Hannes Reinecke wrote:
> Weelll ... _technically_ the ASC/ASCQ codes have to be evaluated
> together, and the individual definitions only make sense for a
> combination of ASC/ASCQ codes.

Yes, I am well aware.

> EG SPC-5 defines the ASC/ASCQ 0x20/0x00 as 'Invalid command opcode',
> but with this we would deocde it as 'INVALID_OPCODE'/'POWER_ON_RESET_ASCQ',
> but 'POWER ON RESET OCCURRED' is ASC/ASCQ 0x29/0x00.
> So if we were to define ASCQ codes we would need to define the
> ASCQ codes for each ASC to avoid these issues.

Yes, this is messy. But re-check the specs. There are plenty of places that say
"with additional sense code XXX" without actually specifying the exact
combination of ASC/ASCQ as they are defined on the T10 site
(https://www.t10.org/lists/asc-num.htm).

> Makes me wonder if we shouldn't introduce u16 for sense code
> handling ...

Maybe, but that will be more work as we have many functions and code that
handle asc and ascq separatly. Which I kind of like.

The main benefit of having the macros and using them is code readability: the
values used/tested for ASC & ASCQ become self explanatory, making it far easier
to match code and specs.

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-07-06  9:01 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06  6:56 [PATCH v1 0/9] ATA support for storage element management commands Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 1/9] scsi: scsi_debug: move ASC and ASCQ definitions to scsi_proto.h Damien Le Moal
2026-07-06  8:29   ` Hannes Reinecke
2026-07-06  8:55     ` Damien Le Moal
2026-07-06  8:44   ` Hannes Reinecke
2026-07-06  9:00     ` Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 2/9] scsi: define depopulation capabilities related service actions Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 3/9] ata: libata: improve the definition of device flags Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 4/9] ata: libata-scsi: improve ata_get_xlat_func Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 5/9] ata: libata-core: detect support for depopulation capabilities Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 6/9] ata: libata-scsi: add support for the GET PHYSICAL ELEMENT STATUS command Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 7/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND TRUNCATE command Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 8/9] ata: libata-scsi: add support for the RESTORE ELEMENTS AND REBUILD command Damien Le Moal
2026-07-06  6:56 ` [PATCH v1 9/9] ata: libata-scsi: add support for the REMOVE ELEMENT AND MODIFY ZONES command Damien Le Moal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox