Re: [PATCH v1 5/9] ata: libata-core: detect support for depopulation capabilities

Hannes Reinecke <[email protected]> Mon, 13 Jul 2026 11:37:13 +0200
Newsgroups org.kernel.vger.linux-ide,org.kernel.vger.linux-scsi
Message-ID <[email protected]>
On 7/6/26 8:56 AM, Damien Le Moal wrote:
> 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 <[email protected]>
> ---
>   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 {

It's a bit of a mess, but not your fault...

Reviewed-by: Hannes Reinecke <[email protected]>

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
[email protected]                                +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