linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Add support for Write Same via SCT
@ 2016-06-06 17:58 Shaun Tancheff
  2016-06-06 17:58 ` [PATCH] Add support for SCT Write Same Shaun Tancheff
  0 siblings, 1 reply; 4+ messages in thread
From: Shaun Tancheff @ 2016-06-06 17:58 UTC (permalink / raw)
  To: linux-ide, linux-scsi
  Cc: Shaun Tancheff, James E.J. Bottomley, Martin K. Petersen,
	Tejun Heo

At some point the method of issuing Write Same for ATA drives changed.
Currently write same is commonly available via SCT so expose the SCT
capabilities and use SCT Write Same if available.

This is useful for zoned based media that prefers to support discard
with lbprz set, aka discard zeroes data by mapping discard operations to 
reset write pointer operations. Conventional zones that do not support 
reset write pointer can still honor the discard zeroes data by issuing
a write same over the zone.

Cc: "James E.J. Bottomley" <jejb@linux.vnet.ibm.com>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Cc: Tejun Heo <tj@kernel.org>

Shaun Tancheff (1):
  Add support for SCT Write Same

 drivers/ata/libata-scsi.c  | 32 ++++++++++++++++++++++++++++++++
 drivers/scsi/sd.c          | 21 +++++++++++++--------
 include/linux/ata.h        | 43 +++++++++++++++++++++++++++++++++++++++++++
 include/scsi/scsi_device.h |  1 +
 4 files changed, 89 insertions(+), 8 deletions(-)

-- 
2.8.1


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

* [PATCH] Add support for SCT Write Same
  2016-06-06 17:58 [PATCH] Add support for Write Same via SCT Shaun Tancheff
@ 2016-06-06 17:58 ` Shaun Tancheff
  2016-06-09  3:39   ` Martin K. Petersen
  0 siblings, 1 reply; 4+ messages in thread
From: Shaun Tancheff @ 2016-06-06 17:58 UTC (permalink / raw)
  To: linux-ide, linux-scsi; +Cc: Shaun Tancheff, Shaun Tancheff

SATA drives may support write same via SCT. This is useful
for setting the drive contents to a specific pattern (0's).

Signed-off-by: Shaun Tancheff <shaun.tancheff@seagate.com>
---
 drivers/ata/libata-scsi.c  | 31 +++++++++++++++++++++++++
 drivers/scsi/sd.c          | 25 +++++++++++---------
 include/linux/ata.h        | 58 ++++++++++++++++++++++++++++++++++++++++++++++
 include/scsi/scsi_device.h |  1 +
 4 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index bfec66f..4f1a97b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3305,6 +3305,37 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
 		goto invalid_param_len;
 
 	buf = page_address(sg_page(scsi_sglist(scmd)));
+
+	if (ata_id_sct_write_same(dev->id)) {
+		u16 *sctpg = buf;
+
+		put_unaligned_le16(0x0002,  &sctpg[0]); /* SCT_ACT_WRITE_SAME */
+		put_unaligned_le16(0x0101,  &sctpg[1]); /* WRITE PTRN FG */
+		put_unaligned_le64(block,   &sctpg[2]);
+		put_unaligned_le64(n_block, &sctpg[6]);
+		put_unaligned_le32(0u,      &sctpg[10]);
+
+		tf->hob_feature = 0;
+		tf->feature = 0;
+		tf->hob_nsect = 0;
+		tf->nsect = 1;
+		tf->lbah = 0;
+		tf->lbam = 0;
+		tf->lbal = ATA_CMD_STANDBYNOW1;
+		tf->hob_lbah = 0;
+		tf->hob_lbam = 0;
+		tf->hob_lbal = 0;
+		tf->device = ATA_CMD_STANDBYNOW1;
+		tf->protocol = ATA_PROT_DMA;
+		tf->command = ATA_CMD_WRITE_LOG_DMA_EXT;
+		tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE |
+			     ATA_TFLAG_LBA48 | ATA_TFLAG_WRITE;
+
+		ata_qc_set_pc_nbytes(qc);
+
+		return 0;
+	}
+
 	size = ata_set_lba_range_entries(buf, 512, block, n_block);
 
 	if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) {
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 428c03e..c5c8424 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -52,6 +52,7 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/pr.h>
+#include <linux/ata.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
@@ -794,7 +795,7 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
 	struct request_queue *q = sdkp->disk->queue;
 	unsigned int logical_block_size = sdkp->device->sector_size;
 
-	if (sdkp->device->no_write_same) {
+	if (sdkp->device->no_write_same && !sdkp->device->sct_write_same) {
 		sdkp->max_ws_blocks = 0;
 		goto out;
 	}
@@ -2761,24 +2762,26 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
 	struct scsi_device *sdev = sdkp->device;
 
-	if (sdev->host->no_write_same) {
-		sdev->no_write_same = 1;
-
-		return;
-	}
-
 	if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
-		/* too large values might cause issues with arcmsr */
-		int vpd_buf_len = 64;
-
 		sdev->no_report_opcodes = 1;
 
 		/* Disable WRITE SAME if REPORT SUPPORTED OPERATION
 		 * CODES is unsupported and the device has an ATA
 		 * Information VPD page (SAT).
 		 */
-		if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len))
+		if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE)) {
 			sdev->no_write_same = 1;
+			if (ata_id_sct_write_same((u16 *)&buffer[60])) {
+				sdev->sct_write_same = 1;
+				sdkp->max_ws_blocks = SD_MAX_WS16_BLOCKS;
+			}
+		}
+	}
+
+	if (sdev->host->no_write_same) {
+		sdev->no_write_same = 1;
+
+		return;
 	}
 
 	if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 99346be..cdffe1f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -104,6 +104,7 @@ enum {
 	ATA_ID_CFA_KEY_MGMT	= 162,
 	ATA_ID_CFA_MODES	= 163,
 	ATA_ID_DATA_SET_MGMT	= 169,
+	ATA_ID_SCT_CMD_XPORT	= 206,
 	ATA_ID_ROT_SPEED	= 217,
 	ATA_ID_PIO4		= (1 << 1),
 
@@ -778,6 +779,48 @@ static inline bool ata_id_sense_reporting_enabled(const u16 *id)
 }
 
 /**
+ *
+ * Word: 206 - SCT Command Transport
+ *    15:12 - Vendor Specific
+ *     11:6 - Reserved
+ *        5 - SCT Command Transport Data Tables supported
+ *        4 - SCT Command Transport Features Control supported
+ *        3 - SCT Command Transport Error Recovery Control supported
+ *        2 - SCT Command Transport Write Same supported
+ *        1 - SCT Command Transport Long Sector Access supported
+ *        0 - SCT Command Transport supported
+ */
+static inline bool ata_id_sct_data_tables(const u16 *id)
+{
+	return id[ATA_ID_SCT_CMD_XPORT] & (1 << 5) ? true : false;
+}
+
+static inline bool ata_id_sct_features_ctrl(const u16 *id)
+{
+	return id[ATA_ID_SCT_CMD_XPORT] & (1 << 4) ? true : false;
+}
+
+static inline bool ata_id_sct_error_recovery_ctrl(const u16 *id)
+{
+	return id[ATA_ID_SCT_CMD_XPORT] & (1 << 3) ? true : false;
+}
+
+static inline bool ata_id_sct_write_same(const u16 *id)
+{
+	return id[ATA_ID_SCT_CMD_XPORT] & (1 << 2) ? true : false;
+}
+
+static inline bool ata_id_sct_long_sector_access(const u16 *id)
+{
+	return id[ATA_ID_SCT_CMD_XPORT] & (1 << 1) ? true : false;
+}
+
+static inline bool ata_id_sct_supported(const u16 *id)
+{
+	return id[ATA_ID_SCT_CMD_XPORT] & (1 << 0) ? true : false;
+}
+
+/**
  *	ata_id_major_version	-	get ATA level of drive
  *	@id: Identify data
  *
@@ -1060,6 +1103,21 @@ static inline void ata_id_to_hd_driveid(u16 *id)
 #endif
 }
 
+/**
+ * _lba_to_cmd_ata() - Copy lba48 to ATA command
+ * @cmd: ATA command as an array of bytes
+ * @_lba: lba48 in the low 48 bits
+ */
+static inline void _lba_to_cmd_ata(u8 *cmd, u64 _lba)
+{
+	cmd[1] =  _lba	      & 0xff;
+	cmd[3] = (_lba >>  8) & 0xff;
+	cmd[5] = (_lba >> 16) & 0xff;
+	cmd[0] = (_lba >> 24) & 0xff;
+	cmd[2] = (_lba >> 32) & 0xff;
+	cmd[4] = (_lba >> 40) & 0xff;
+}
+
 /*
  * Write LBA Range Entries to the buffer that will cover the extent from
  * sector to sector + count.  This is used for TRIM and for ADD LBA(S)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index a6c346d..66f5af7 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -157,6 +157,7 @@ struct scsi_device {
 	unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
 	unsigned no_report_opcodes:1;	/* no REPORT SUPPORTED OPERATION CODES */
 	unsigned no_write_same:1;	/* no WRITE SAME command */
+	unsigned sct_write_same:1;	/* Has WRITE SAME via SCT Command */
 	unsigned use_16_for_rw:1; /* Use read/write(16) over read/write(10) */
 	unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
 	unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
-- 
2.8.1


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

* Re: [PATCH] Add support for SCT Write Same
  2016-06-06 17:58 ` [PATCH] Add support for SCT Write Same Shaun Tancheff
@ 2016-06-09  3:39   ` Martin K. Petersen
  2016-06-09  6:32     ` Shaun Tancheff
  0 siblings, 1 reply; 4+ messages in thread
From: Martin K. Petersen @ 2016-06-09  3:39 UTC (permalink / raw)
  To: Shaun Tancheff; +Cc: linux-ide, linux-scsi, Shaun Tancheff

>>>>> "Shaun" == Shaun Tancheff <shaun@tancheff.com> writes:

Shaun,

Shaun> SATA drives may support write same via SCT. This is useful for
Shaun> setting the drive contents to a specific pattern (0's).

index 428c03e..c5c8424 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -52,6 +52,7 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/pr.h>
+#include <linux/ata.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
No ATA stuff in sd.c, please.


@@ -2761,24 +2762,26 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
 	struct scsi_device *sdev = sdkp->device;
 
-	if (sdev->host->no_write_same) {
-		sdev->no_write_same = 1;
-
-		return;
-	}
-
 	if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
-		/* too large values might cause issues with arcmsr */
-		int vpd_buf_len = 64;
-
 		sdev->no_report_opcodes = 1;
 
 		/* Disable WRITE SAME if REPORT SUPPORTED OPERATION
 		 * CODES is unsupported and the device has an ATA
 		 * Information VPD page (SAT).
 		 */

The above comment tells you how to enable WRITE SAME in libata's
SCSI-ATA translation.


-		if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len))
+		if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE))

That vpd_buf_len is intentional.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH] Add support for SCT Write Same
  2016-06-09  3:39   ` Martin K. Petersen
@ 2016-06-09  6:32     ` Shaun Tancheff
  0 siblings, 0 replies; 4+ messages in thread
From: Shaun Tancheff @ 2016-06-09  6:32 UTC (permalink / raw)
  To: Martin K. Petersen; +Cc: Shaun Tancheff, linux-ide, linux-scsi

On Wed, Jun 8, 2016 at 10:39 PM, Martin K. Petersen
<martin.petersen@oracle.com> wrote:
>
> >>>>> "Shaun" == Shaun Tancheff <shaun@tancheff.com> writes:
>
> Shaun,
>
> Shaun> SATA drives may support write same via SCT. This is useful for
> Shaun> setting the drive contents to a specific pattern (0's).
>
> index 428c03e..c5c8424 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -52,6 +52,7 @@
>  #include <linux/slab.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/pr.h>
> +#include <linux/ata.h>
>  #include <asm/uaccess.h>
>  #include <asm/unaligned.h>
>
> No ATA stuff in sd.c, please.
>
>
> @@ -2761,24 +2762,26 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
>  {
>         struct scsi_device *sdev = sdkp->device;
>
> -       if (sdev->host->no_write_same) {
> -               sdev->no_write_same = 1;
> -
> -               return;
> -       }
> -
>         if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
> -               /* too large values might cause issues with arcmsr */
> -               int vpd_buf_len = 64;
> -
>                 sdev->no_report_opcodes = 1;
>
>                 /* Disable WRITE SAME if REPORT SUPPORTED OPERATION
>                  * CODES is unsupported and the device has an ATA
>                  * Information VPD page (SAT).
>                  */
>
> The above comment tells you how to enable WRITE SAME in libata's
> SCSI-ATA translation.
>
>
> -               if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len))
> +               if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE))
>
> That vpd_buf_len is intentional.



Got it. Looking at it again all of hacking here is not required.
Posting a cleaner v2 without this.

Thanks!

>
>
> --
> Martin K. Petersen      Oracle Linux Engineering




-- 
Shaun Tancheff

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

end of thread, other threads:[~2016-06-09  6:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-06 17:58 [PATCH] Add support for Write Same via SCT Shaun Tancheff
2016-06-06 17:58 ` [PATCH] Add support for SCT Write Same Shaun Tancheff
2016-06-09  3:39   ` Martin K. Petersen
2016-06-09  6:32     ` Shaun Tancheff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).