All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] libata: ZAC support
@ 2016-04-04  9:47 Hannes Reinecke
  2016-04-04  9:47 ` [PATCH 1/4] libata: implement ZBC IN translation Hannes Reinecke
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04  9:47 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash, Hannes Reinecke

Hi all,

here's a patchset implementing ZAC support for libata.

This is the second part of a larger patchset for ZAC/ZBC support;
it requires the scsi trace fixes queued for in mkp/4.7/scsi-queue and
the patchset 'libata: SATL update' I've posted earlier.
The full patchset can be found at:

git.kernel.org/hare/scsi-devel/h/zbc.v3

As usual, comments and reviews are welcome.

Hannes Reinecke (4):
  libata: implement ZBC IN translation
  libata: Implement ZBC OUT translation
  libata: support device-managed ZAC devices
  libata: support host-aware and host-managed ZAC devices

 drivers/ata/libata-core.c     |  50 ++++++++
 drivers/ata/libata-eh.c       |   2 +
 drivers/ata/libata-scsi.c     | 274 ++++++++++++++++++++++++++++++++++++++++--
 include/linux/ata.h           |  17 +++
 include/linux/libata.h        |   7 ++
 include/trace/events/libata.h |   2 +
 6 files changed, 341 insertions(+), 11 deletions(-)

-- 
1.8.5.6


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

* [PATCH 1/4] libata: implement ZBC IN translation
  2016-04-04  9:47 [PATCH 0/4] libata: ZAC support Hannes Reinecke
@ 2016-04-04  9:47 ` Hannes Reinecke
  2016-04-04 15:49   ` Tejun Heo
  2016-04-04 16:26   ` Shaun Tancheff
  2016-04-04  9:47 ` [PATCH 2/4] libata: Implement ZBC OUT translation Hannes Reinecke
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04  9:47 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash, Hannes Reinecke

ZAC drives implement 'zac management in' command template,
which maps onto the ZBC IN command.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-eh.c       |   1 +
 drivers/ata/libata-scsi.c     | 144 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/ata.h           |   4 ++
 include/trace/events/libata.h |   1 +
 4 files changed, 150 insertions(+)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e6b16f4..e947bd5 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2480,6 +2480,7 @@ const char *ata_get_cmd_descript(u8 command)
 		{ ATA_CMD_CFA_WRITE_MULT_NE,	"CFA WRITE MULTIPLE WITHOUT ERASE" },
 		{ ATA_CMD_REQ_SENSE_DATA,	"REQUEST SENSE DATA EXT" },
 		{ ATA_CMD_SANITIZE_DEVICE,	"SANITIZE DEVICE" },
+		{ ATA_CMD_ZAC_MGMT_IN,		"ZAC MANAGEMENT IN" },
 		{ ATA_CMD_READ_LONG,		"READ LONG (with retries)" },
 		{ ATA_CMD_READ_LONG_ONCE,	"READ LONG (without retries)" },
 		{ ATA_CMD_WRITE_LONG,		"WRITE LONG (with retries)" },
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index d29832f..21c2b40 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3310,6 +3310,147 @@ invalid_opcode:
 	return 1;
 }
 
+/*
+ * ata_scsi_report_zones_complete
+ *
+ * Convert T-13 little-endian field representation into
+ * T-10 big-endian field representation.
+ */
+static void ata_scsi_report_zones_complete(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	struct sg_mapping_iter miter;
+	unsigned long flags;
+	unsigned int bytes = 0;
+
+	sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
+		       SG_MITER_TO_SG | SG_MITER_ATOMIC);
+
+	local_irq_save(flags);
+	while (sg_miter_next(&miter)) {
+		unsigned int offset = 0;
+
+		if (bytes == 0) {
+			char *hdr;
+			u32 list_length;
+			u64 max_lba, opt_lba;
+			u16 same;
+
+			/* Swizzle header */
+			hdr = miter.addr;
+			list_length = get_unaligned_le32(&hdr[0]);
+			same = get_unaligned_le16(&hdr[4]);
+			max_lba = get_unaligned_le64(&hdr[8]);
+			opt_lba = get_unaligned_le64(&hdr[16]);
+			put_unaligned_be32(list_length, &hdr[0]);
+			hdr[4] = same & 0xf;
+			put_unaligned_be64(max_lba, &hdr[8]);
+			put_unaligned_be64(opt_lba, &hdr[16]);
+			offset += 64;
+			bytes += 64;
+		}
+		while (offset < miter.length) {
+			char *rec;
+			u8 cond, type, non_seq, reset;
+			u64 size, start, wp;
+
+			/* Swizzle zone descriptor */
+			rec = miter.addr + offset;
+			type = rec[0] & 0xf;
+			cond = (rec[1] >> 4) & 0xf;
+			non_seq = (rec[1] & 2);
+			reset = (rec[1] & 1);
+			size = get_unaligned_le64(&rec[8]);
+			start = get_unaligned_le64(&rec[16]);
+			wp = get_unaligned_le64(&rec[24]);
+			rec[0] = type;
+			rec[1] = (cond << 4) | non_seq | reset;
+			put_unaligned_be64(size, &rec[8]);
+			put_unaligned_be64(start, &rec[16]);
+			put_unaligned_be64(wp, &rec[24]);
+			WARN_ON(offset + 64 > miter.length);
+			offset += 64;
+			bytes += 64;
+		}
+	}
+	sg_miter_stop(&miter);
+	local_irq_restore(flags);
+
+	ata_scsi_qc_complete(qc);
+}
+
+static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	const u8 *cdb = scmd->cmnd;
+	u16 sect, fp = (u16)-1;
+	u8 sa, options, bp = 0xff;
+	u64 block;
+	u32 n_block;
+
+	if (unlikely(scmd->cmd_len < 16)) {
+		ata_dev_warn(qc->dev, "invalid cdb length %d\n",
+			     scmd->cmd_len);
+		fp = 15;
+		goto invalid_fld;
+	}
+	scsi_16_lba_len(cdb, &block, &n_block);
+	if (n_block != scsi_bufflen(scmd)) {
+		ata_dev_warn(qc->dev, "non-matching transfer count (%d/%d)\n",
+			     n_block, scsi_bufflen(scmd));
+		goto invalid_param_len;
+	}
+	sa = cdb[1] & 0x1f;
+	if (sa != ZI_REPORT_ZONES) {
+		ata_dev_warn(qc->dev, "invalid service action %d\n", sa);
+		fp = 1;
+		goto invalid_fld;
+	}
+	/*
+	 * ZAC allows only for transfers in 512 byte blocks,
+	 * and uses a 16 bit value for the transfer count.
+	 */
+	if ((n_block / 512) > 0xffff || n_block < 512 || (n_block % 512)) {
+		ata_dev_warn(qc->dev, "invalid transfer count %d\n", n_block);
+		goto invalid_param_len;
+	}
+	sect = n_block / 512;
+	options = cdb[14];
+
+	tf->command = ATA_CMD_ZAC_MGMT_IN;
+	tf->feature = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES;
+	tf->protocol = ATA_PROT_DMA;
+	tf->hob_feature = options & 0x3f;
+	tf->hob_nsect = (sect >> 8) & 0xff;
+	tf->nsect = sect & 0xff;
+	tf->device = ATA_LBA;
+	tf->lbah = (block >> 16) & 0xff;
+	tf->lbam = (block >> 8) & 0xff;
+	tf->lbal = block & 0xff;
+	tf->hob_lbah = (block >> 40) & 0xff;
+	tf->hob_lbam = (block >> 32) & 0xff;
+	tf->hob_lbal = (block >> 24) & 0xff;
+
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+
+	ata_qc_set_pc_nbytes(qc);
+
+	qc->complete_fn = ata_scsi_report_zones_complete;
+
+	return 0;
+
+invalid_fld:
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
+	return 1;
+
+invalid_param_len:
+	/* "Parameter list length error" */
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
+	return 1;
+}
+
 /**
  *	ata_mselect_caching - Simulate MODE SELECT for caching info page
  *	@qc: Storage for translated ATA taskfile
@@ -3623,6 +3764,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 		return ata_scsi_mode_select_xlat;
 		break;
 
+	case ZBC_IN:
+		return ata_scsi_zbc_in_xlat;
+
 	case START_STOP:
 		return ata_scsi_start_stop_xlat;
 	}
diff --git a/include/linux/ata.h b/include/linux/ata.h
index e402cb3..2e4a6af 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -301,6 +301,7 @@ enum {
 	ATA_CMD_CFA_WRITE_MULT_NE = 0xCD,
 	ATA_CMD_REQ_SENSE_DATA  = 0x0B,
 	ATA_CMD_SANITIZE_DEVICE = 0xB4,
+	ATA_CMD_ZAC_MGMT_IN	= 0x4A,
 
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
@@ -309,6 +310,9 @@ enum {
 	ATA_SUBCMD_FPDMA_SEND_DSM            = 0x00,
 	ATA_SUBCMD_FPDMA_SEND_WR_LOG_DMA_EXT = 0x02,
 
+	/* Subcmds for ATA_CMD_ZAC_MGMT_IN */
+	ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES = 0x00,
+
 	/* READ_LOG_EXT pages */
 	ATA_LOG_SATA_NCQ	= 0x10,
 	ATA_LOG_NCQ_SEND_RECV	  = 0x13,
diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h
index 8b0fbd9..02ec4e5 100644
--- a/include/trace/events/libata.h
+++ b/include/trace/events/libata.h
@@ -97,6 +97,7 @@
 		 ata_opcode_name(ATA_CMD_CFA_WRITE_MULT_NE),	\
 		 ata_opcode_name(ATA_CMD_REQ_SENSE_DATA),	\
 		 ata_opcode_name(ATA_CMD_SANITIZE_DEVICE),	\
+		 ata_opcode_name(ATA_CMD_ZAC_MGMT_IN),		\
 		 ata_opcode_name(ATA_CMD_RESTORE),		\
 		 ata_opcode_name(ATA_CMD_READ_LONG),		\
 		 ata_opcode_name(ATA_CMD_READ_LONG_ONCE),	\
-- 
1.8.5.6


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

* [PATCH 2/4] libata: Implement ZBC OUT translation
  2016-04-04  9:47 [PATCH 0/4] libata: ZAC support Hannes Reinecke
  2016-04-04  9:47 ` [PATCH 1/4] libata: implement ZBC IN translation Hannes Reinecke
@ 2016-04-04  9:47 ` Hannes Reinecke
  2016-04-04 13:08   ` Shaun Tancheff
  2016-04-04  9:47 ` [PATCH 3/4] libata: support device-managed ZAC devices Hannes Reinecke
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04  9:47 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash, Hannes Reinecke

ZAC drives implement a 'zac management out' command template,
which maps onto the ZBC OUT command.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-eh.c       |  1 +
 drivers/ata/libata-scsi.c     | 73 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/ata.h           |  7 +++++
 include/trace/events/libata.h |  1 +
 4 files changed, 82 insertions(+)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e947bd5..ee984f9 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2481,6 +2481,7 @@ const char *ata_get_cmd_descript(u8 command)
 		{ ATA_CMD_REQ_SENSE_DATA,	"REQUEST SENSE DATA EXT" },
 		{ ATA_CMD_SANITIZE_DEVICE,	"SANITIZE DEVICE" },
 		{ ATA_CMD_ZAC_MGMT_IN,		"ZAC MANAGEMENT IN" },
+		{ ATA_CMD_ZAC_MGMT_OUT,		"ZAC MANAGEMENT OUT" },
 		{ ATA_CMD_READ_LONG,		"READ LONG (with retries)" },
 		{ ATA_CMD_READ_LONG_ONCE,	"READ LONG (without retries)" },
 		{ ATA_CMD_WRITE_LONG,		"WRITE LONG (with retries)" },
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 21c2b40..6db2aaf 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3451,6 +3451,76 @@ invalid_param_len:
 	return 1;
 }
 
+static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	struct ata_device *dev = qc->dev;
+	const u8 *cdb = scmd->cmnd;
+	u8 reset_all, sa;
+	u64 block;
+	u32 n_block;
+	u16 fp = (u16)-1;
+
+	if (unlikely(scmd->cmd_len < 16)) {
+		fp = 15;
+		goto invalid_fld;
+	}
+
+	/*
+	 * The service action definition got moved from
+	 * 0x00 to 0x04 with zbc-r02, so accept both.
+	 */
+	sa = cdb[1] & 0x1f;
+	/* Compatibility with ZBC r01 */
+	if (!sa)
+		sa = ZO_RESET_WRITE_POINTER;
+	if (sa != ZO_RESET_WRITE_POINTER) {
+		fp = 1;
+		goto invalid_fld;
+	}
+
+	scsi_16_lba_len(cdb, &block, &n_block);
+	if (n_block) {
+		/*
+		 * ZAC MANAGEMENT OUT doesn't define any length
+		 */
+		goto invalid_param_len;
+	}
+	if (block > dev->n_sectors)
+		goto out_of_range;
+
+	reset_all = cdb[14] & 0x1;
+
+	tf->protocol = ATA_PROT_NODATA;
+	tf->command = ATA_CMD_ZAC_MGMT_OUT;
+	tf->feature = sa;
+	tf->hob_feature = reset_all & 0x1;
+
+	tf->lbah = (block >> 16) & 0xff;
+	tf->lbam = (block >> 8) & 0xff;
+	tf->lbal = block & 0xff;
+	tf->hob_lbah = (block >> 40) & 0xff;
+	tf->hob_lbam = (block >> 32) & 0xff;
+	tf->hob_lbal = (block >> 24) & 0xff;
+	tf->device = ATA_LBA;
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+
+	return 0;
+
+ invalid_fld:
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
+	return 1;
+ out_of_range:
+	/* "Logical Block Address out of range" */
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x00);
+	return 1;
+invalid_param_len:
+	/* "Parameter list length error" */
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
+	return 1;
+}
+
 /**
  *	ata_mselect_caching - Simulate MODE SELECT for caching info page
  *	@qc: Storage for translated ATA taskfile
@@ -3767,6 +3837,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 	case ZBC_IN:
 		return ata_scsi_zbc_in_xlat;
 
+	case ZBC_OUT:
+		return ata_scsi_zbc_out_xlat;
+
 	case START_STOP:
 		return ata_scsi_start_stop_xlat;
 	}
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 2e4a6af..eef9d80 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -302,6 +302,7 @@ enum {
 	ATA_CMD_REQ_SENSE_DATA  = 0x0B,
 	ATA_CMD_SANITIZE_DEVICE = 0xB4,
 	ATA_CMD_ZAC_MGMT_IN	= 0x4A,
+	ATA_CMD_ZAC_MGMT_OUT	= 0x9F,
 
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
@@ -313,6 +314,12 @@ enum {
 	/* Subcmds for ATA_CMD_ZAC_MGMT_IN */
 	ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES = 0x00,
 
+	/* Subcmds for ATA_CMD_ZAC_MGMT_OUT */
+	ATA_SUBCMD_ZAC_MGMT_OUT_CLOSE_ZONE = 0x01,
+	ATA_SUBCMD_ZAC_MGMT_OUT_FINISH_ZONE = 0x02,
+	ATA_SUBCMD_ZAC_MGMT_OUT_OPEN_ZONE = 0x03,
+	ATA_SUBCMD_ZAC_MGMT_OUT_RESET_WRITE_POINTER = 0x04,
+
 	/* READ_LOG_EXT pages */
 	ATA_LOG_SATA_NCQ	= 0x10,
 	ATA_LOG_NCQ_SEND_RECV	  = 0x13,
diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h
index 02ec4e5..24dcd43 100644
--- a/include/trace/events/libata.h
+++ b/include/trace/events/libata.h
@@ -98,6 +98,7 @@
 		 ata_opcode_name(ATA_CMD_REQ_SENSE_DATA),	\
 		 ata_opcode_name(ATA_CMD_SANITIZE_DEVICE),	\
 		 ata_opcode_name(ATA_CMD_ZAC_MGMT_IN),		\
+		 ata_opcode_name(ATA_CMD_ZAC_MGMT_OUT),		\
 		 ata_opcode_name(ATA_CMD_RESTORE),		\
 		 ata_opcode_name(ATA_CMD_READ_LONG),		\
 		 ata_opcode_name(ATA_CMD_READ_LONG_ONCE),	\
-- 
1.8.5.6


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

* [PATCH 3/4] libata: support device-managed ZAC devices
  2016-04-04  9:47 [PATCH 0/4] libata: ZAC support Hannes Reinecke
  2016-04-04  9:47 ` [PATCH 1/4] libata: implement ZBC IN translation Hannes Reinecke
  2016-04-04  9:47 ` [PATCH 2/4] libata: Implement ZBC OUT translation Hannes Reinecke
@ 2016-04-04  9:47 ` Hannes Reinecke
  2016-04-04 11:13   ` Sergei Shtylyov
  2016-04-04  9:47 ` [PATCH 4/4] libata: support host-aware and host-managed " Hannes Reinecke
  2016-04-04 15:50 ` [PATCH 0/4] libata: ZAC support Tejun Heo
  4 siblings, 1 reply; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04  9:47 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash, Hannes Reinecke

Device-managed ZAC devices just set the zoned capabilities field
in INQUIRY byte 69 (cf ACS-4). This corresponds to the 'zoned'
field in the block device characteristics VPD page.
As this is only defined in SPC-5/SBC-4 we also need to update
the supported SCSI version descriptor.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-scsi.c | 19 ++++++++++---------
 include/linux/ata.h       |  5 +++++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 6db2aaf..ff95ef6 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2076,14 +2076,14 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
 		0x00,
 		0xA0,	/* SAM-5 (no version claimed) */
 
-		0x04,
-		0xC0,	/* SBC-3 (no version claimed) */
+		0x06,
+		0x00,	/* SBC-4 (no version claimed) */
 
-		0x04,
-		0x60,	/* SPC-4 (no version claimed) */
+		0x05,
+		0xC0,	/* SPC-5 (no version claimed) */
 
 		0x60,
-		0x20,   /* ZBC (no version claimed) */
+		0x24,   /* ZBC r05 */
 	};
 
 	u8 hdr[] = {
@@ -2103,10 +2103,8 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
 	    (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL))
 		hdr[1] |= (1 << 7);
 
-	if (args->dev->class == ATA_DEV_ZAC) {
+	if (args->dev->class == ATA_DEV_ZAC)
 		hdr[0] = TYPE_ZBC;
-		hdr[2] = 0x6; /* ZBC is defined in SPC-4 */
-	}
 
 	memcpy(rbuf, hdr, sizeof(hdr));
 	memcpy(&rbuf[8], "ATA     ", 8);
@@ -2120,7 +2118,7 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
 	if (rbuf[32] == 0 || rbuf[32] == ' ')
 		memcpy(&rbuf[32], "n/a ", 4);
 
-	if (args->dev->class == ATA_DEV_ZAC)
+	if (ata_id_zoned_cap(args->id) || args->dev->class == ATA_DEV_ZAC)
 		memcpy(rbuf + 58, versions_zbc, sizeof(versions_zbc));
 	else
 		memcpy(rbuf + 58, versions, sizeof(versions));
@@ -2316,12 +2314,15 @@ static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
 {
 	int form_factor = ata_id_form_factor(args->id);
 	int media_rotation_rate = ata_id_rotation_rate(args->id);
+	u8 zoned = ata_id_zoned_cap(args->id);
 
 	rbuf[1] = 0xb1;
 	rbuf[3] = 0x3c;
 	rbuf[4] = media_rotation_rate >> 8;
 	rbuf[5] = media_rotation_rate;
 	rbuf[7] = form_factor;
+	if (zoned)
+		rbuf[8] = (zoned << 4);
 
 	return 0;
 }
diff --git a/include/linux/ata.h b/include/linux/ata.h
index eef9d80..4ad7363 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -900,6 +900,11 @@ static inline bool ata_id_is_ssd(const u16 *id)
 	return id[ATA_ID_ROT_SPEED] == 0x01;
 }
 
+static inline u8 ata_id_zoned_cap(const u16 *id)
+{
+	return (id[ATA_ID_ADDITIONAL_SUPP] & 0x3);
+}
+
 static inline bool ata_id_pio_need_iordy(const u16 *id, const u8 pio)
 {
 	/* CF spec. r4.1 Table 22 says no IORDY on PIO5 and PIO6. */
-- 
1.8.5.6


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

* [PATCH 4/4] libata: support host-aware and host-managed ZAC devices
  2016-04-04  9:47 [PATCH 0/4] libata: ZAC support Hannes Reinecke
                   ` (2 preceding siblings ...)
  2016-04-04  9:47 ` [PATCH 3/4] libata: support device-managed ZAC devices Hannes Reinecke
@ 2016-04-04  9:47 ` Hannes Reinecke
  2016-04-04 15:50 ` [PATCH 0/4] libata: ZAC support Tejun Heo
  4 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04  9:47 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash, Hannes Reinecke

Byte 69 bits 0:1 in the IDENTIFY DEVICE data indicate a
host-aware ZAC device.
Host-managed ZAC devices have their own individual signature,
and to not set the bits in the IDENTIFY DEVICE data.
And whenever we detect a ZAC-compatible device we should
be displaying the zoned block characteristics VPD page.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libata-core.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/ata/libata-scsi.c | 38 +++++++++++++++++++++++++++++++++--
 include/linux/ata.h       |  1 +
 include/linux/libata.h    |  7 +++++++
 4 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index a8d6336..3ec2bbd 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -66,6 +66,7 @@
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 #include <linux/cdrom.h>
 #include <linux/ratelimit.h>
 #include <linux/pm_runtime.h>
@@ -2166,6 +2167,54 @@ static void ata_dev_config_sense_reporting(struct ata_device *dev)
 	}
 }
 
+static void ata_dev_config_zac(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->link->ap;
+	unsigned int err_mask;
+	u8 *identify_buf = ap->sector_buf;
+
+	dev->zac_zones_optimal_open = (u32)-1;
+	dev->zac_zones_optimal_nonseq = (u32)-1;
+	dev->zac_zones_max_open = (u32)-1;
+
+	/*
+	 * Always set the 'ZAC' flag for Host-managed devices.
+	 */
+	if (dev->class == ATA_DEV_ZAC)
+		dev->flags |= ATA_DFLAG_ZAC;
+	else if (ata_id_zoned_cap(dev->id) == 0x01)
+		/*
+		 * Check for host-aware devices.
+		 */
+		dev->flags |= ATA_DFLAG_ZAC;
+
+	if (!(dev->flags & ATA_DFLAG_ZAC))
+		return;
+
+	/*
+	 * Read IDENTIFY DEVICE data log, page 9 (Zoned-device information)
+	 */
+	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA,
+				     ATA_LOG_ZONED_INFORMATION,
+				     identify_buf, 1);
+	if (!err_mask) {
+		u64 zoned_cap, opt_open, opt_nonseq, max_open;
+
+		zoned_cap = get_unaligned_le64(&identify_buf[8]);
+		if ((zoned_cap >> 63))
+			dev->zac_zoned_cap = (zoned_cap & 1);
+		opt_open = get_unaligned_le64(&identify_buf[24]);
+		if ((opt_open >> 63))
+			dev->zac_zones_optimal_open = (u32)opt_open;
+		opt_nonseq = get_unaligned_le64(&identify_buf[32]);
+		if ((opt_nonseq >> 63))
+			dev->zac_zones_optimal_nonseq = (u32)opt_nonseq;
+		max_open = get_unaligned_le64(&identify_buf[40]);
+		if ((max_open >> 63))
+			dev->zac_zones_max_open = (u32)max_open;
+	}
+}
+
 /**
  *	ata_dev_configure - Configure the specified ATA/ATAPI device
  *	@dev: Target device to configure
@@ -2389,6 +2438,7 @@ int ata_dev_configure(struct ata_device *dev)
 				}
 		}
 		ata_dev_config_sense_reporting(dev);
+		ata_dev_config_zac(dev);
 		dev->cdb_len = 16;
 	}
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index ff95ef6..9b84155 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2138,6 +2138,7 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
  */
 static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
 {
+	int num_pages;
 	const u8 pages[] = {
 		0x00,	/* page 0x00, this page */
 		0x80,	/* page 0x80, unit serial no page */
@@ -2146,10 +2147,14 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
 		0xb0,	/* page 0xb0, block limits page */
 		0xb1,	/* page 0xb1, block device characteristics page */
 		0xb2,	/* page 0xb2, thin provisioning page */
+		0xb6,	/* page 0xb6, zoned block device characteristics */
 	};
 
-	rbuf[3] = sizeof(pages);	/* number of supported VPD pages */
-	memcpy(rbuf + 4, pages, sizeof(pages));
+	num_pages = sizeof(pages);
+	if (!(args->dev->flags & ATA_DFLAG_ZAC))
+		num_pages--;
+	rbuf[3] = num_pages;	/* number of supported VPD pages */
+	memcpy(rbuf + 4, pages, num_pages);
 	return 0;
 }
 
@@ -2337,6 +2342,26 @@ static unsigned int ata_scsiop_inq_b2(struct ata_scsi_args *args, u8 *rbuf)
 	return 0;
 }
 
+static unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf)
+{
+	/*
+	 * zbc-r05 SCSI Zoned Block device characteristics VPD page
+	 */
+	rbuf[1] = 0xb6;
+	rbuf[3] = 0x3C;
+
+	/*
+	 * URSWRZ bit is only meaningful for host-managed ZAC drives
+	 */
+	if (args->dev->zac_zoned_cap & 1)
+		rbuf[4] |= 1;
+	put_unaligned_be32(args->dev->zac_zones_optimal_open, &rbuf[8]);
+	put_unaligned_be32(args->dev->zac_zones_optimal_nonseq, &rbuf[12]);
+	put_unaligned_be32(args->dev->zac_zones_max_open, &rbuf[16]);
+
+	return 0;
+}
+
 /**
  *	ata_scsiop_noop - Command handler that simply returns success.
  *	@args: device IDENTIFY data / SCSI command of interest.
@@ -2654,6 +2679,9 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
 				rbuf[14] |= 0x40; /* LBPRZ */
 			}
 		}
+		if (ata_id_zoned_cap(args->id) ||
+		    args->dev->class == ATA_DEV_ZAC)
+			rbuf[12] = (1 << 4); /* RC_BASIS */
 	}
 	return 0;
 }
@@ -4022,6 +4050,12 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
 		case 0xb2:
 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
 			break;
+		case 0xb6:
+			if (dev->flags & ATA_DFLAG_ZAC) {
+				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6);
+				break;
+			}
+			/* Fallthrough */
 		default:
 			ata_scsi_invalid_field(dev, cmd, 2);
 			break;
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 4ad7363..e4b120d 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -325,6 +325,7 @@ enum {
 	ATA_LOG_NCQ_SEND_RECV	  = 0x13,
 	ATA_LOG_SATA_ID_DEV_DATA  = 0x30,
 	ATA_LOG_SATA_SETTINGS	  = 0x08,
+	ATA_LOG_ZONED_INFORMATION = 0x09,
 	ATA_LOG_DEVSLP_OFFSET	  = 0x30,
 	ATA_LOG_DEVSLP_SIZE	  = 0x08,
 	ATA_LOG_DEVSLP_MDAT	  = 0x00,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a418bca..13da8f2 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -181,6 +181,7 @@ enum {
 	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_ZAC		= (1 << 30), /* ZAC device */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -729,6 +730,12 @@ struct ata_device {
 	/* NCQ send and receive log subcommand support */
 	u8			ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_SIZE];
 
+	/* ZAC zone configuration */
+	u32			zac_zoned_cap;
+	u32			zac_zones_optimal_open;
+	u32			zac_zones_optimal_nonseq;
+	u32			zac_zones_max_open;
+
 	/* error history */
 	int			spdn_cnt;
 	/* ering is CLEAR_END, read comment above CLEAR_END */
-- 
1.8.5.6


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

* Re: [PATCH 3/4] libata: support device-managed ZAC devices
  2016-04-04  9:47 ` [PATCH 3/4] libata: support device-managed ZAC devices Hannes Reinecke
@ 2016-04-04 11:13   ` Sergei Shtylyov
  2016-04-04 14:15     ` Hannes Reinecke
  0 siblings, 1 reply; 13+ messages in thread
From: Sergei Shtylyov @ 2016-04-04 11:13 UTC (permalink / raw)
  To: Hannes Reinecke, Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash

Hello.

On 4/4/2016 12:47 PM, Hannes Reinecke wrote:

> Device-managed ZAC devices just set the zoned capabilities field
> in INQUIRY byte 69 (cf ACS-4). This corresponds to the 'zoned'
> field in the block device characteristics VPD page.
> As this is only defined in SPC-5/SBC-4 we also need to update
> the supported SCSI version descriptor.
>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>   drivers/ata/libata-scsi.c | 19 ++++++++++---------
>   include/linux/ata.h       |  5 +++++
>   2 files changed, 15 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 6db2aaf..ff95ef6 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
[...]
> @@ -2316,12 +2314,15 @@ static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
>   {
>   	int form_factor = ata_id_form_factor(args->id);
>   	int media_rotation_rate = ata_id_rotation_rate(args->id);
> +	u8 zoned = ata_id_zoned_cap(args->id);
>
>   	rbuf[1] = 0xb1;
>   	rbuf[3] = 0x3c;
>   	rbuf[4] = media_rotation_rate >> 8;
>   	rbuf[5] = media_rotation_rate;
>   	rbuf[7] = form_factor;
> +	if (zoned)
> +		rbuf[8] = (zoned << 4);

    Parens not needed here.

[...]

MBR, Sergei


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

* Re: [PATCH 2/4] libata: Implement ZBC OUT translation
  2016-04-04  9:47 ` [PATCH 2/4] libata: Implement ZBC OUT translation Hannes Reinecke
@ 2016-04-04 13:08   ` Shaun Tancheff
  2016-04-04 13:18     ` Hannes Reinecke
  0 siblings, 1 reply; 13+ messages in thread
From: Shaun Tancheff @ 2016-04-04 13:08 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Tejun Heo, linux-ide, Martin K. Petersen, Christoph Hellwig,
	Damien Le Moal, linux-scsi, Sathya Prakash

On Mon, Apr 4, 2016 at 4:47 PM, Hannes Reinecke <hare@suse.de> wrote:
> ZAC drives implement a 'zac management out' command template,
> which maps onto the ZBC OUT command.
>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/ata/libata-eh.c       |  1 +
>  drivers/ata/libata-scsi.c     | 73 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/ata.h           |  7 +++++
>  include/trace/events/libata.h |  1 +
>  4 files changed, 82 insertions(+)
>
> diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
> index e947bd5..ee984f9 100644
> --- a/drivers/ata/libata-eh.c
> +++ b/drivers/ata/libata-eh.c
> @@ -2481,6 +2481,7 @@ const char *ata_get_cmd_descript(u8 command)
>                 { ATA_CMD_REQ_SENSE_DATA,       "REQUEST SENSE DATA EXT" },
>                 { ATA_CMD_SANITIZE_DEVICE,      "SANITIZE DEVICE" },
>                 { ATA_CMD_ZAC_MGMT_IN,          "ZAC MANAGEMENT IN" },
> +               { ATA_CMD_ZAC_MGMT_OUT,         "ZAC MANAGEMENT OUT" },
>                 { ATA_CMD_READ_LONG,            "READ LONG (with retries)" },
>                 { ATA_CMD_READ_LONG_ONCE,       "READ LONG (without retries)" },
>                 { ATA_CMD_WRITE_LONG,           "WRITE LONG (with retries)" },
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index 21c2b40..6db2aaf 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -3451,6 +3451,76 @@ invalid_param_len:
>         return 1;
>  }
>
> +static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
> +{
> +       struct ata_taskfile *tf = &qc->tf;
> +       struct scsi_cmnd *scmd = qc->scsicmd;
> +       struct ata_device *dev = qc->dev;
> +       const u8 *cdb = scmd->cmnd;
> +       u8 reset_all, sa;
> +       u64 block;
> +       u32 n_block;
> +       u16 fp = (u16)-1;
> +
> +       if (unlikely(scmd->cmd_len < 16)) {
> +               fp = 15;
> +               goto invalid_fld;
> +       }
> +
> +       /*
> +        * The service action definition got moved from
> +        * 0x00 to 0x04 with zbc-r02, so accept both.
> +        */
> +       sa = cdb[1] & 0x1f;
> +       /* Compatibility with ZBC r01 */
> +       if (!sa)
> +               sa = ZO_RESET_WRITE_POINTER;

I think we can support the remaining zone commands here:

if (!(sa == ZO_CLOSE_ZONE || sa == ZO_FINISH_ZONE ||
     sa == ZO_OPEN_ZONE || sa == ZO_RESET_WRITE_POINTER)) {
...

> +       if (sa != ZO_RESET_WRITE_POINTER) {
> +               fp = 1;
> +               goto invalid_fld;
> +       }
> +
> +       scsi_16_lba_len(cdb, &block, &n_block);
> +       if (n_block) {
> +               /*
> +                * ZAC MANAGEMENT OUT doesn't define any length
> +                */
> +               goto invalid_param_len;
> +       }
> +       if (block > dev->n_sectors)
> +               goto out_of_range;
> +
> +       reset_all = cdb[14] & 0x1;
> +
> +       tf->protocol = ATA_PROT_NODATA;
> +       tf->command = ATA_CMD_ZAC_MGMT_OUT;
> +       tf->feature = sa;
> +       tf->hob_feature = reset_all & 0x1;
> +
> +       tf->lbah = (block >> 16) & 0xff;
> +       tf->lbam = (block >> 8) & 0xff;
> +       tf->lbal = block & 0xff;
> +       tf->hob_lbah = (block >> 40) & 0xff;
> +       tf->hob_lbam = (block >> 32) & 0xff;
> +       tf->hob_lbal = (block >> 24) & 0xff;
> +       tf->device = ATA_LBA;
> +       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
> +
> +       return 0;
> +
> + invalid_fld:
> +       ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
> +       return 1;
> + out_of_range:
> +       /* "Logical Block Address out of range" */
> +       ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x00);
> +       return 1;
> +invalid_param_len:
> +       /* "Parameter list length error" */
> +       ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
> +       return 1;
> +}
> +
>  /**
>   *     ata_mselect_caching - Simulate MODE SELECT for caching info page
>   *     @qc: Storage for translated ATA taskfile
> @@ -3767,6 +3837,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
>         case ZBC_IN:
>                 return ata_scsi_zbc_in_xlat;
>
> +       case ZBC_OUT:
> +               return ata_scsi_zbc_out_xlat;
> +
>         case START_STOP:
>                 return ata_scsi_start_stop_xlat;
>         }
> diff --git a/include/linux/ata.h b/include/linux/ata.h
> index 2e4a6af..eef9d80 100644
> --- a/include/linux/ata.h
> +++ b/include/linux/ata.h
> @@ -302,6 +302,7 @@ enum {
>         ATA_CMD_REQ_SENSE_DATA  = 0x0B,
>         ATA_CMD_SANITIZE_DEVICE = 0xB4,
>         ATA_CMD_ZAC_MGMT_IN     = 0x4A,
> +       ATA_CMD_ZAC_MGMT_OUT    = 0x9F,
>
>         /* marked obsolete in the ATA/ATAPI-7 spec */
>         ATA_CMD_RESTORE         = 0x10,
> @@ -313,6 +314,12 @@ enum {
>         /* Subcmds for ATA_CMD_ZAC_MGMT_IN */
>         ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES = 0x00,
>
> +       /* Subcmds for ATA_CMD_ZAC_MGMT_OUT */
> +       ATA_SUBCMD_ZAC_MGMT_OUT_CLOSE_ZONE = 0x01,
> +       ATA_SUBCMD_ZAC_MGMT_OUT_FINISH_ZONE = 0x02,
> +       ATA_SUBCMD_ZAC_MGMT_OUT_OPEN_ZONE = 0x03,
> +       ATA_SUBCMD_ZAC_MGMT_OUT_RESET_WRITE_POINTER = 0x04,
> +
>         /* READ_LOG_EXT pages */
>         ATA_LOG_SATA_NCQ        = 0x10,
>         ATA_LOG_NCQ_SEND_RECV     = 0x13,
> diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h
> index 02ec4e5..24dcd43 100644
> --- a/include/trace/events/libata.h
> +++ b/include/trace/events/libata.h
> @@ -98,6 +98,7 @@
>                  ata_opcode_name(ATA_CMD_REQ_SENSE_DATA),       \
>                  ata_opcode_name(ATA_CMD_SANITIZE_DEVICE),      \
>                  ata_opcode_name(ATA_CMD_ZAC_MGMT_IN),          \
> +                ata_opcode_name(ATA_CMD_ZAC_MGMT_OUT),         \
>                  ata_opcode_name(ATA_CMD_RESTORE),              \
>                  ata_opcode_name(ATA_CMD_READ_LONG),            \
>                  ata_opcode_name(ATA_CMD_READ_LONG_ONCE),       \
> --
> 1.8.5.6
>



-- 
Shaun Tancheff

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

* Re: [PATCH 2/4] libata: Implement ZBC OUT translation
  2016-04-04 13:08   ` Shaun Tancheff
@ 2016-04-04 13:18     ` Hannes Reinecke
  0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04 13:18 UTC (permalink / raw)
  To: Shaun Tancheff
  Cc: Tejun Heo, linux-ide, Martin K. Petersen, Christoph Hellwig,
	Damien Le Moal, linux-scsi, Sathya Prakash

On 04/04/2016 03:08 PM, Shaun Tancheff wrote:
> On Mon, Apr 4, 2016 at 4:47 PM, Hannes Reinecke <hare@suse.de> wrote:
>> ZAC drives implement a 'zac management out' command template,
>> which maps onto the ZBC OUT command.
>>
>> Signed-off-by: Hannes Reinecke <hare@suse.de>
>> ---
>>  drivers/ata/libata-eh.c       |  1 +
>>  drivers/ata/libata-scsi.c     | 73 +++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/ata.h           |  7 +++++
>>  include/trace/events/libata.h |  1 +
>>  4 files changed, 82 insertions(+)
>>
>> diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
>> index e947bd5..ee984f9 100644
>> --- a/drivers/ata/libata-eh.c
>> +++ b/drivers/ata/libata-eh.c
>> @@ -2481,6 +2481,7 @@ const char *ata_get_cmd_descript(u8 command)
>>                 { ATA_CMD_REQ_SENSE_DATA,       "REQUEST SENSE DATA EXT" },
>>                 { ATA_CMD_SANITIZE_DEVICE,      "SANITIZE DEVICE" },
>>                 { ATA_CMD_ZAC_MGMT_IN,          "ZAC MANAGEMENT IN" },
>> +               { ATA_CMD_ZAC_MGMT_OUT,         "ZAC MANAGEMENT OUT" },
>>                 { ATA_CMD_READ_LONG,            "READ LONG (with retries)" },
>>                 { ATA_CMD_READ_LONG_ONCE,       "READ LONG (without retries)" },
>>                 { ATA_CMD_WRITE_LONG,           "WRITE LONG (with retries)" },
>> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
>> index 21c2b40..6db2aaf 100644
>> --- a/drivers/ata/libata-scsi.c
>> +++ b/drivers/ata/libata-scsi.c
>> @@ -3451,6 +3451,76 @@ invalid_param_len:
>>         return 1;
>>  }
>>
>> +static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
>> +{
>> +       struct ata_taskfile *tf = &qc->tf;
>> +       struct scsi_cmnd *scmd = qc->scsicmd;
>> +       struct ata_device *dev = qc->dev;
>> +       const u8 *cdb = scmd->cmnd;
>> +       u8 reset_all, sa;
>> +       u64 block;
>> +       u32 n_block;
>> +       u16 fp = (u16)-1;
>> +
>> +       if (unlikely(scmd->cmd_len < 16)) {
>> +               fp = 15;
>> +               goto invalid_fld;
>> +       }
>> +
>> +       /*
>> +        * The service action definition got moved from
>> +        * 0x00 to 0x04 with zbc-r02, so accept both.
>> +        */
>> +       sa = cdb[1] & 0x1f;
>> +       /* Compatibility with ZBC r01 */
>> +       if (!sa)
>> +               sa = ZO_RESET_WRITE_POINTER;
> 
> I think we can support the remaining zone commands here:
> 
> if (!(sa == ZO_CLOSE_ZONE || sa == ZO_FINISH_ZONE ||
>      sa == ZO_OPEN_ZONE || sa == ZO_RESET_WRITE_POINTER)) {
> ...
> 
Sure, I just didn't do it for now as none of the drives I have
actually supports this.
But yes, will be fixing it up for the next round of submissions.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)

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

* Re: [PATCH 3/4] libata: support device-managed ZAC devices
  2016-04-04 11:13   ` Sergei Shtylyov
@ 2016-04-04 14:15     ` Hannes Reinecke
  0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-04 14:15 UTC (permalink / raw)
  To: Sergei Shtylyov, Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash

On 04/04/2016 01:13 PM, Sergei Shtylyov wrote:
> Hello.
> 
> On 4/4/2016 12:47 PM, Hannes Reinecke wrote:
> 
>> Device-managed ZAC devices just set the zoned capabilities field
>> in INQUIRY byte 69 (cf ACS-4). This corresponds to the 'zoned'
>> field in the block device characteristics VPD page.
>> As this is only defined in SPC-5/SBC-4 we also need to update
>> the supported SCSI version descriptor.
>>
>> Signed-off-by: Hannes Reinecke <hare@suse.de>
>> ---
>>   drivers/ata/libata-scsi.c | 19 ++++++++++---------
>>   include/linux/ata.h       |  5 +++++
>>   2 files changed, 15 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
>> index 6db2aaf..ff95ef6 100644
>> --- a/drivers/ata/libata-scsi.c
>> +++ b/drivers/ata/libata-scsi.c
> [...]
>> @@ -2316,12 +2314,15 @@ static unsigned int
>> ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
>>   {
>>       int form_factor = ata_id_form_factor(args->id);
>>       int media_rotation_rate = ata_id_rotation_rate(args->id);
>> +    u8 zoned = ata_id_zoned_cap(args->id);
>>
>>       rbuf[1] = 0xb1;
>>       rbuf[3] = 0x3c;
>>       rbuf[4] = media_rotation_rate >> 8;
>>       rbuf[5] = media_rotation_rate;
>>       rbuf[7] = form_factor;
>> +    if (zoned)
>> +        rbuf[8] = (zoned << 4);
> 
>    Parens not needed here.
> 
> [...]
> 
> MBR, Sergei
> 
Thanks, will be fixing it up with the next round of submissions.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/4] libata: implement ZBC IN translation
  2016-04-04  9:47 ` [PATCH 1/4] libata: implement ZBC IN translation Hannes Reinecke
@ 2016-04-04 15:49   ` Tejun Heo
  2016-04-06  7:51     ` Hannes Reinecke
  2016-04-04 16:26   ` Shaun Tancheff
  1 sibling, 1 reply; 13+ messages in thread
From: Tejun Heo @ 2016-04-04 15:49 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash

On Mon, Apr 04, 2016 at 11:47:48AM +0200, Hannes Reinecke wrote:
> +/*

/**

> + * ata_scsi_report_zones_complete
> + *
> + * Convert T-13 little-endian field representation into
> + * T-10 big-endian field representation.
> + */
> +static void ata_scsi_report_zones_complete(struct ata_queued_cmd *qc)
> +{
> +	struct scsi_cmnd *scmd = qc->scsicmd;
> +	struct sg_mapping_iter miter;
> +	unsigned long flags;
> +	unsigned int bytes = 0;
> +
> +	sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
> +		       SG_MITER_TO_SG | SG_MITER_ATOMIC);
> +
> +	local_irq_save(flags);
> +	while (sg_miter_next(&miter)) {
> +		unsigned int offset = 0;

Not this patch's fault but ugh........  :(

Thanks.

-- 
tejun

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

* Re: [PATCH 0/4] libata: ZAC support
  2016-04-04  9:47 [PATCH 0/4] libata: ZAC support Hannes Reinecke
                   ` (3 preceding siblings ...)
  2016-04-04  9:47 ` [PATCH 4/4] libata: support host-aware and host-managed " Hannes Reinecke
@ 2016-04-04 15:50 ` Tejun Heo
  4 siblings, 0 replies; 13+ messages in thread
From: Tejun Heo @ 2016-04-04 15:50 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash

Hello, Hannes.

Except for the minor nits, looks good to me.  Will wait for refresh
and apply to libata/for-4.7-zac.

Thanks.

-- 
tejun

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

* Re: [PATCH 1/4] libata: implement ZBC IN translation
  2016-04-04  9:47 ` [PATCH 1/4] libata: implement ZBC IN translation Hannes Reinecke
  2016-04-04 15:49   ` Tejun Heo
@ 2016-04-04 16:26   ` Shaun Tancheff
  1 sibling, 0 replies; 13+ messages in thread
From: Shaun Tancheff @ 2016-04-04 16:26 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Tejun Heo, linux-ide, Martin K. Petersen, Christoph Hellwig,
	Damien Le Moal, linux-scsi, Sathya Prakash

On Mon, Apr 4, 2016 at 4:47 PM, Hannes Reinecke <hare@suse.de> wrote:
> ZAC drives implement 'zac management in' command template,
> which maps onto the ZBC IN command.
>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/ata/libata-eh.c       |   1 +
>  drivers/ata/libata-scsi.c     | 144 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/ata.h           |   4 ++
>  include/trace/events/libata.h |   1 +
>  4 files changed, 150 insertions(+)
>
> diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
> index e6b16f4..e947bd5 100644
> --- a/drivers/ata/libata-eh.c
> +++ b/drivers/ata/libata-eh.c
> @@ -2480,6 +2480,7 @@ const char *ata_get_cmd_descript(u8 command)
>                 { ATA_CMD_CFA_WRITE_MULT_NE,    "CFA WRITE MULTIPLE WITHOUT ERASE" },
>                 { ATA_CMD_REQ_SENSE_DATA,       "REQUEST SENSE DATA EXT" },
>                 { ATA_CMD_SANITIZE_DEVICE,      "SANITIZE DEVICE" },
> +               { ATA_CMD_ZAC_MGMT_IN,          "ZAC MANAGEMENT IN" },
>                 { ATA_CMD_READ_LONG,            "READ LONG (with retries)" },
>                 { ATA_CMD_READ_LONG_ONCE,       "READ LONG (without retries)" },
>                 { ATA_CMD_WRITE_LONG,           "WRITE LONG (with retries)" },
> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> index d29832f..21c2b40 100644
> --- a/drivers/ata/libata-scsi.c
> +++ b/drivers/ata/libata-scsi.c
> @@ -3310,6 +3310,147 @@ invalid_opcode:
>         return 1;
>  }
>
> +/*
> + * ata_scsi_report_zones_complete
> + *
> + * Convert T-13 little-endian field representation into
> + * T-10 big-endian field representation.
> + */
> +static void ata_scsi_report_zones_complete(struct ata_queued_cmd *qc)
> +{
> +       struct scsi_cmnd *scmd = qc->scsicmd;
> +       struct sg_mapping_iter miter;
> +       unsigned long flags;
> +       unsigned int bytes = 0;
> +
> +       sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
> +                      SG_MITER_TO_SG | SG_MITER_ATOMIC);
> +
> +       local_irq_save(flags);
> +       while (sg_miter_next(&miter)) {
> +               unsigned int offset = 0;
> +
> +               if (bytes == 0) {
> +                       char *hdr;
> +                       u32 list_length;
> +                       u64 max_lba, opt_lba;
> +                       u16 same;
> +
> +                       /* Swizzle header */
> +                       hdr = miter.addr;
> +                       list_length = get_unaligned_le32(&hdr[0]);
> +                       same = get_unaligned_le16(&hdr[4]);
> +                       max_lba = get_unaligned_le64(&hdr[8]);
> +                       opt_lba = get_unaligned_le64(&hdr[16]);
> +                       put_unaligned_be32(list_length, &hdr[0]);
> +                       hdr[4] = same & 0xf;
> +                       put_unaligned_be64(max_lba, &hdr[8]);
> +                       put_unaligned_be64(opt_lba, &hdr[16]);
> +                       offset += 64;
> +                       bytes += 64;
> +               }
> +               while (offset < miter.length) {
> +                       char *rec;
> +                       u8 cond, type, non_seq, reset;
> +                       u64 size, start, wp;
> +
> +                       /* Swizzle zone descriptor */
> +                       rec = miter.addr + offset;
> +                       type = rec[0] & 0xf;
> +                       cond = (rec[1] >> 4) & 0xf;
> +                       non_seq = (rec[1] & 2);
> +                       reset = (rec[1] & 1);
> +                       size = get_unaligned_le64(&rec[8]);
> +                       start = get_unaligned_le64(&rec[16]);
> +                       wp = get_unaligned_le64(&rec[24]);
> +                       rec[0] = type;
> +                       rec[1] = (cond << 4) | non_seq | reset;

The bit munging around rec[0] and rec[1] look unnecessary to me.

Does the top nibble of re[0] and bits 2 and 3 of rec[1] really
need these cleanups?

> +                       put_unaligned_be64(size, &rec[8]);
> +                       put_unaligned_be64(start, &rec[16]);
> +                       put_unaligned_be64(wp, &rec[24]);
> +                       WARN_ON(offset + 64 > miter.length);
> +                       offset += 64;
> +                       bytes += 64;
> +               }
> +       }
> +       sg_miter_stop(&miter);
> +       local_irq_restore(flags);
> +
> +       ata_scsi_qc_complete(qc);
> +}
> +
> +static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc)
> +{
> +       struct ata_taskfile *tf = &qc->tf;
> +       struct scsi_cmnd *scmd = qc->scsicmd;
> +       const u8 *cdb = scmd->cmnd;
> +       u16 sect, fp = (u16)-1;
> +       u8 sa, options, bp = 0xff;
> +       u64 block;
> +       u32 n_block;
> +
> +       if (unlikely(scmd->cmd_len < 16)) {
> +               ata_dev_warn(qc->dev, "invalid cdb length %d\n",
> +                            scmd->cmd_len);
> +               fp = 15;
> +               goto invalid_fld;
> +       }
> +       scsi_16_lba_len(cdb, &block, &n_block);
> +       if (n_block != scsi_bufflen(scmd)) {
> +               ata_dev_warn(qc->dev, "non-matching transfer count (%d/%d)\n",
> +                            n_block, scsi_bufflen(scmd));
> +               goto invalid_param_len;
> +       }
> +       sa = cdb[1] & 0x1f;
> +       if (sa != ZI_REPORT_ZONES) {
> +               ata_dev_warn(qc->dev, "invalid service action %d\n", sa);
> +               fp = 1;
> +               goto invalid_fld;
> +       }
> +       /*
> +        * ZAC allows only for transfers in 512 byte blocks,
> +        * and uses a 16 bit value for the transfer count.
> +        */
> +       if ((n_block / 512) > 0xffff || n_block < 512 || (n_block % 512)) {
> +               ata_dev_warn(qc->dev, "invalid transfer count %d\n", n_block);
> +               goto invalid_param_len;
> +       }
> +       sect = n_block / 512;
> +       options = cdb[14];
> +
> +       tf->command = ATA_CMD_ZAC_MGMT_IN;
> +       tf->feature = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES;
> +       tf->protocol = ATA_PROT_DMA;
> +       tf->hob_feature = options & 0x3f;
> +       tf->hob_nsect = (sect >> 8) & 0xff;
> +       tf->nsect = sect & 0xff;
> +       tf->device = ATA_LBA;
> +       tf->lbah = (block >> 16) & 0xff;
> +       tf->lbam = (block >> 8) & 0xff;
> +       tf->lbal = block & 0xff;
> +       tf->hob_lbah = (block >> 40) & 0xff;
> +       tf->hob_lbam = (block >> 32) & 0xff;
> +       tf->hob_lbal = (block >> 24) & 0xff;
> +
> +       tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
> +       qc->flags |= ATA_QCFLAG_RESULT_TF;
> +
> +       ata_qc_set_pc_nbytes(qc);
> +
> +       qc->complete_fn = ata_scsi_report_zones_complete;
> +
> +       return 0;
> +
> +invalid_fld:
> +       ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
> +       return 1;
> +
> +invalid_param_len:
> +       /* "Parameter list length error" */
> +       ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
> +       return 1;
> +}
> +
>  /**
>   *     ata_mselect_caching - Simulate MODE SELECT for caching info page
>   *     @qc: Storage for translated ATA taskfile
> @@ -3623,6 +3764,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
>                 return ata_scsi_mode_select_xlat;
>                 break;
>
> +       case ZBC_IN:
> +               return ata_scsi_zbc_in_xlat;
> +
>         case START_STOP:
>                 return ata_scsi_start_stop_xlat;
>         }
> diff --git a/include/linux/ata.h b/include/linux/ata.h
> index e402cb3..2e4a6af 100644
> --- a/include/linux/ata.h
> +++ b/include/linux/ata.h
> @@ -301,6 +301,7 @@ enum {
>         ATA_CMD_CFA_WRITE_MULT_NE = 0xCD,
>         ATA_CMD_REQ_SENSE_DATA  = 0x0B,
>         ATA_CMD_SANITIZE_DEVICE = 0xB4,
> +       ATA_CMD_ZAC_MGMT_IN     = 0x4A,
>
>         /* marked obsolete in the ATA/ATAPI-7 spec */
>         ATA_CMD_RESTORE         = 0x10,
> @@ -309,6 +310,9 @@ enum {
>         ATA_SUBCMD_FPDMA_SEND_DSM            = 0x00,
>         ATA_SUBCMD_FPDMA_SEND_WR_LOG_DMA_EXT = 0x02,
>
> +       /* Subcmds for ATA_CMD_ZAC_MGMT_IN */
> +       ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES = 0x00,
> +
>         /* READ_LOG_EXT pages */
>         ATA_LOG_SATA_NCQ        = 0x10,
>         ATA_LOG_NCQ_SEND_RECV     = 0x13,
> diff --git a/include/trace/events/libata.h b/include/trace/events/libata.h
> index 8b0fbd9..02ec4e5 100644
> --- a/include/trace/events/libata.h
> +++ b/include/trace/events/libata.h
> @@ -97,6 +97,7 @@
>                  ata_opcode_name(ATA_CMD_CFA_WRITE_MULT_NE),    \
>                  ata_opcode_name(ATA_CMD_REQ_SENSE_DATA),       \
>                  ata_opcode_name(ATA_CMD_SANITIZE_DEVICE),      \
> +                ata_opcode_name(ATA_CMD_ZAC_MGMT_IN),          \
>                  ata_opcode_name(ATA_CMD_RESTORE),              \
>                  ata_opcode_name(ATA_CMD_READ_LONG),            \
>                  ata_opcode_name(ATA_CMD_READ_LONG_ONCE),       \
> --
> 1.8.5.6
>

The zone report looks good.

Tested-by: Shaun Tancheff <shaun.tancheff@seagate.com>

-- 
Shaun Tancheff

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

* Re: [PATCH 1/4] libata: implement ZBC IN translation
  2016-04-04 15:49   ` Tejun Heo
@ 2016-04-06  7:51     ` Hannes Reinecke
  0 siblings, 0 replies; 13+ messages in thread
From: Hannes Reinecke @ 2016-04-06  7:51 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-ide, Martin K. Petersen, Christoph Hellwig, Shaun Tancheff,
	Damien Le Moal, linux-scsi, Sathya Prakash

On 04/04/2016 05:49 PM, Tejun Heo wrote:
> On Mon, Apr 04, 2016 at 11:47:48AM +0200, Hannes Reinecke wrote:
>> +/*
> 
> /**
> 
>> + * ata_scsi_report_zones_complete
>> + *
>> + * Convert T-13 little-endian field representation into
>> + * T-10 big-endian field representation.
>> + */
>> +static void ata_scsi_report_zones_complete(struct ata_queued_cmd *qc)
>> +{
>> +	struct scsi_cmnd *scmd = qc->scsicmd;
>> +	struct sg_mapping_iter miter;
>> +	unsigned long flags;
>> +	unsigned int bytes = 0;
>> +
>> +	sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
>> +		       SG_MITER_TO_SG | SG_MITER_ATOMIC);
>> +
>> +	local_irq_save(flags);
>> +	while (sg_miter_next(&miter)) {
>> +		unsigned int offset = 0;
> 
> Not this patch's fault but ugh........  :(
> 
I know. I've been asking the very same questions to T-13.
But apparently it's by design ... gnaa.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare@suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2016-04-06  7:51 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-04  9:47 [PATCH 0/4] libata: ZAC support Hannes Reinecke
2016-04-04  9:47 ` [PATCH 1/4] libata: implement ZBC IN translation Hannes Reinecke
2016-04-04 15:49   ` Tejun Heo
2016-04-06  7:51     ` Hannes Reinecke
2016-04-04 16:26   ` Shaun Tancheff
2016-04-04  9:47 ` [PATCH 2/4] libata: Implement ZBC OUT translation Hannes Reinecke
2016-04-04 13:08   ` Shaun Tancheff
2016-04-04 13:18     ` Hannes Reinecke
2016-04-04  9:47 ` [PATCH 3/4] libata: support device-managed ZAC devices Hannes Reinecke
2016-04-04 11:13   ` Sergei Shtylyov
2016-04-04 14:15     ` Hannes Reinecke
2016-04-04  9:47 ` [PATCH 4/4] libata: support host-aware and host-managed " Hannes Reinecke
2016-04-04 15:50 ` [PATCH 0/4] libata: ZAC support Tejun Heo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.