From: sunad.s@samsung.com (Sunad Bhandary)
Subject: [PATCHv3] NVMe: write_long SCSI to NVMe translation implementation
Date: Tue, 24 Mar 2015 17:27:31 +0530 [thread overview]
Message-ID: <006501d06629$b8397550$28ac5ff0$@samsung.com> (raw)
In-Reply-To: <1427118493-29227-1-git-send-email-sunad.s@samsung.com>
Hi Keith,
I think this patch suffices for the shortcomings of the previous versions.
Does anything else seem amiss ?
If I am to submit a version of the patch for the legacy-nvme , the SCSI
macro SERVICE_ACTION _OUT_16 is not present in the kernel.
Is it alright to define a Macro SAO_16(0x9f) exclusive to nvme-scsi to
support WRITE_LONG_16?
Regards,
Sunad
-----Original Message-----
From: Linux-nvme [mailto:linux-nvme-bounces@lists.infradead.org] On Behalf
Of Sunad Bhandary S
Sent: Monday, March 23, 2015 7:18 PM
To: linux-nvme at lists.infradead.org; keith.busch at intel.com
Cc: Sunad Bhandary S
Subject: [PATCHv3] NVMe: write_long SCSI to NVMe translation implementation
From: Sunad Bhandary S <sunad.s@samsung.com>
This patch implements the SCSI to NVMe translation for write_long.
write_long is translated to the NVMe command write_uncorrectable as defined
by the translation specification version 1.4.
This patch also indicates the device support for write_uncorrectable method
in the response of extended inquiry as defined in the translation spec.
This patch is based on for-linus branch.
Changes:
v1 -> v2 : __le32 nlb field changed to __le16 nlb followed by __u16 rsvd.
v2 -> v3 : Check for SAO16 value for write_long_16.
Signed-off-by: Sunad Bhandary S <sunad.s at samsung.com>
---
drivers/block/nvme-scsi.c | 78
+++++++++++++++++++++++++++++++++++++++++++++--
include/uapi/linux/nvme.h | 13 ++++++++
2 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/drivers/block/nvme-scsi.c b/drivers/block/nvme-scsi.c index
e10196e..3b778e4 100644
--- a/drivers/block/nvme-scsi.c
+++ b/drivers/block/nvme-scsi.c
@@ -245,6 +245,17 @@ static int sg_version_num = 30534; /* 2 digits for each
component */
/* Report LUNs defines */
#define REPORT_LUNS_FIRST_LUN_OFFSET 8
+/*Write Long defines */
+#define WRITE_LONG_CDB_COR_DIS_OFFSET 1
+#define WRITE_LONG_CDB_COR_DIS_MASK 0x80
+#define WRITE_LONG_CDB_WR_UNCOR_OFFSET 1
+#define WRITE_LONG_CDB_WR_UNCOR_MASK 0x40
+#define WRITE_LONG_CDB_PBLOCK_OFFSET 1
+#define WRITE_LONG_CDB_PBLOCK_MASK 0x20
+#define WRITE_LONG_CDB_LBA_OFFSET 2
+#define WRITE_LONG_SAO_MASK 0x1F
+#define SAO_WRITE_LONG_16 0x11
+
/* SCSI ADDITIONAL SENSE Codes */
#define SCSI_ASC_NO_SENSE 0x00
@@ -331,6 +342,10 @@ INQUIRY_EVPD_BIT_MASK) ? 1 : 0)
#define IS_READ_CAP_16(cdb) \
((cdb[0] == SERVICE_ACTION_IN_16 && cdb[1] == SAI_READ_CAPACITY_16) ? 1 :
0)
+#define IS_WRITE_LONG_16(cdb) \
+((cdb[0] == SERVICE_ACTION_OUT_16 && \
+(cdb[1] & WRITE_LONG_SAO_MASK) == SAO_WRITE_LONG_16) ? 1 : 0)
+
/* Request Sense Helper Macros */
#define GET_REQUEST_SENSE_ALLOC_LENGTH(cdb) \
(GET_U8_FROM_CDB(cdb, REQUEST_SENSE_CDB_ALLOC_LENGTH_OFFSET))
@@ -871,7 +886,7 @@ static int nvme_trans_ext_inq_page(struct nvme_ns *ns,
struct sg_io_hdr *hdr,
u8 spt_lut[8] = {0, 0, 2, 1, 4, 6, 5, 7};
u8 grd_chk, app_chk, ref_chk, protect;
u8 uask_sup = 0x20;
- u8 v_sup;
+ u8 v_sup, wrt_uncor, wu_sup, cd_sup;
u8 luiclr = 0x01;
inq_response = kmalloc(EXTENDED_INQUIRY_DATA_PAGE_LENGTH,
GFP_KERNEL); @@ -914,6 +929,10 @@ static int nvme_trans_ext_inq_page(struct
nvme_ns *ns, struct sg_io_hdr *hdr,
}
id_ctrl = mem;
v_sup = id_ctrl->vwc;
+ wrt_uncor = (id_ctrl->oncs &
+ NVME_CTRL_ONCS_WRITE_UNCORRECTABLE) ? 1 : 0;
+ wu_sup = wrt_uncor << 3;
+ cd_sup = wrt_uncor << 2;
memset(inq_response, 0, EXTENDED_INQUIRY_DATA_PAGE_LENGTH);
inq_response[1] = INQ_EXTENDED_INQUIRY_DATA_PAGE; /* Page Code */
@@ -921,7 +940,7 @@ static int nvme_trans_ext_inq_page(struct nvme_ns *ns,
struct sg_io_hdr *hdr,
inq_response[3] = 0x3C; /* Page Length LSB */
inq_response[4] = microcode | spt | grd_chk | app_chk | ref_chk;
inq_response[5] = uask_sup;
- inq_response[6] = v_sup;
+ inq_response[6] = wu_sup | cd_sup | v_sup;
inq_response[7] = luiclr;
inq_response[8] = 0;
inq_response[9] = 0;
@@ -2916,6 +2935,52 @@ static int nvme_trans_unmap(struct nvme_ns *ns,
struct sg_io_hdr *hdr,
return res;
}
+static int nvme_trans_write_long(struct nvme_ns *ns, struct sg_io_hdr *hdr,
+ u8 *cmd)
+{
+ int res = SNTI_TRANSLATION_SUCCESS;
+ int nvme_sc;
+ struct nvme_command c;
+ u64 slba;
+ u8 cor_dis, wr_uncor, pblock;
+
+ cor_dis = GET_U8_FROM_CDB(cmd, WRITE_LONG_CDB_COR_DIS_OFFSET) &
+ WRITE_LONG_CDB_COR_DIS_MASK;
+ wr_uncor = GET_U8_FROM_CDB(cmd, WRITE_LONG_CDB_WR_UNCOR_OFFSET) &
+ WRITE_LONG_CDB_WR_UNCOR_MASK;
+ pblock = GET_U8_FROM_CDB(cmd, WRITE_LONG_CDB_PBLOCK_OFFSET) &
+ WRITE_LONG_CDB_PBLOCK_MASK;
+
+ if (!cor_dis || !wr_uncor || pblock) {
+ res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
+ ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_CDB,
+ SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
+ goto out;
+ }
+
+ if (cmd[0] == WRITE_LONG)
+ slba = GET_U32_FROM_CDB(cmd, WRITE_LONG_CDB_LBA_OFFSET);
+ else
+ slba = GET_U64_FROM_CDB(cmd, WRITE_LONG_CDB_LBA_OFFSET);
+
+ memset(&c, 0, sizeof(c));
+ c.wu.opcode = nvme_cmd_write_uncor;
+ c.wu.nsid = cpu_to_le32(ns->ns_id);
+ c.wu.slba = cpu_to_le64(slba);
+ c.wu.nlb = 0;
+
+ nvme_sc = nvme_submit_io_cmd(ns->dev, ns, &c, NULL);
+ res = nvme_trans_status_code(hdr, nvme_sc);
+ if (res)
+ goto out;
+ if (nvme_sc)
+ res = nvme_sc;
+
+out:
+ return res;
+}
+
static int nvme_scsi_translate(struct nvme_ns *ns, struct sg_io_hdr *hdr)
{
u8 cmd[BLK_MAX_CDB];
@@ -3001,6 +3066,15 @@ static int nvme_scsi_translate(struct nvme_ns *ns,
struct sg_io_hdr *hdr)
case UNMAP:
retcode = nvme_trans_unmap(ns, hdr, cmd);
break;
+ case WRITE_LONG:
+ retcode = nvme_trans_write_long(ns, hdr, cmd);
+ break;
+ case SERVICE_ACTION_OUT_16:
+ if (IS_WRITE_LONG_16(cmd))
+ retcode = nvme_trans_write_long(ns, hdr, cmd);
+ else
+ goto out;
+ break;
default:
out:
retcode = nvme_trans_completion(hdr,
SAM_STAT_CHECK_CONDITION, diff --git a/include/uapi/linux/nvme.h
b/include/uapi/linux/nvme.h index aef9a81..068db6d 100644
--- a/include/uapi/linux/nvme.h
+++ b/include/uapi/linux/nvme.h
@@ -310,6 +310,18 @@ struct nvme_dsm_range {
__le64 slba;
};
+struct nvme_write_uncor_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 nsid;
+ __u32 rsvd2[8];
+ __le64 slba;
+ __le16 nlb;
+ __u16 rsvd;
+ __u32 rsvd13[3];
+};
+
/* Admin commands */
enum nvme_admin_opcode {
@@ -469,6 +481,7 @@ struct nvme_command {
struct nvme_download_firmware dlfw;
struct nvme_format_cmd format;
struct nvme_dsm_cmd dsm;
+ struct nvme_write_uncor_cmd wu;
struct nvme_abort_cmd abort;
};
};
--
1.8.3.2
_______________________________________________
Linux-nvme mailing list
Linux-nvme at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
next prev parent reply other threads:[~2015-03-24 11:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-23 13:48 [PATCHv3] NVMe: write_long SCSI to NVMe translation implementation Sunad Bhandary S
2015-03-24 11:57 ` Sunad Bhandary [this message]
2015-03-24 13:54 ` Keith Busch
2015-04-16 12:04 ` Sunad Bhandary
2015-04-16 14:27 ` Keith Busch
2015-03-24 16:23 ` Matthew Wilcox
2015-03-24 16:36 ` Keith Busch
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='006501d06629$b8397550$28ac5ff0$@samsung.com' \
--to=sunad.s@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.