aboutsummaryrefslogtreecommitdiff
path: root/lib/sg_pt_linux_nvme.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sg_pt_linux_nvme.c')
-rw-r--r--lib/sg_pt_linux_nvme.c100
1 files changed, 48 insertions, 52 deletions
diff --git a/lib/sg_pt_linux_nvme.c b/lib/sg_pt_linux_nvme.c
index 74453f74..094dc49c 100644
--- a/lib/sg_pt_linux_nvme.c
+++ b/lib/sg_pt_linux_nvme.c
@@ -41,7 +41,7 @@
* MA 02110-1301, USA.
*/
-/* sg_pt_linux_nvme version 1.15 20210102 */
+/* sg_pt_linux_nvme version 1.17 20210501 */
/* This file contains a small "SPC-only" SNTL to support the SES pass-through
* of SEND DIAGNOSTIC and RECEIVE DIAGNOSTIC RESULTS through NVME-MI
@@ -142,6 +142,7 @@
#define SG_NVME_AD_GET_FEATURE 0xa
#define SG_NVME_AD_SET_FEATURE 0x9
#define SG_NVME_AD_IDENTIFY 0x6 /* similar to SCSI INQUIRY */
+#define SG_NVME_AD_DEV_SELT_TEST 0x14
#define SG_NVME_AD_MI_RECEIVE 0x1e /* MI: Management Interface */
#define SG_NVME_AD_MI_SEND 0x1d /* hmmm, same opcode as SEND DIAG */
@@ -153,7 +154,7 @@
#define SG_NVME_NVM_WRITE 0x1
#define SG_NVME_NVM_WRITE_ZEROES 0x8 /* SCSI WRITE SAME */
-#define SG_NVME_NVM_CDW12_FUA (1 << 30) /* Force Unit Access bit */
+#define SG_NVME_RW_CDW12_FUA (1 << 30) /* Force Unit Access bit */
#if (HAVE_NVME && (! IGNORE_NVME))
@@ -318,7 +319,7 @@ sg_nvme_admin_cmd(struct sg_pt_linux_scsi * ptp,
if (vb > 2) {
pr2ws("NVMe Admin command: %s\n", nam);
hex2stderr((const uint8_t *)cmdp, cmd_len, 1);
- if ((vb > 3) && (! is_read) && dp) {
+ if ((vb > 4) && (! is_read) && dp) {
uint32_t len = sg_get_unaligned_le32(up + SG_NVME_PT_DATA_LEN);
if (len > 0) {
@@ -375,7 +376,7 @@ sg_nvme_admin_cmd(struct sg_pt_linux_scsi * ptp,
}
return SG_LIB_NVME_STATUS; /* == SCSI_PT_DO_NVME_STATUS */
}
- if ((vb > 3) && is_read && dp) {
+ if ((vb > 4) && is_read && dp) {
uint32_t len = sg_get_unaligned_le32(up + SG_NVME_PT_DATA_LEN);
if (len > 0) {
@@ -402,7 +403,7 @@ sntl_check_enclosure_override(struct sg_pt_linux_scsi * ptp, int vb)
if (NULL == up)
return;
nvmsr = up[253];
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: enter, nvmsr=%u\n", __func__, nvmsr);
ptp->dev_stat.id_ctl253 = nvmsr;
switch (ptp->dev_stat.enclosure_override) {
@@ -528,7 +529,7 @@ sntl_inq(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, int time_secs,
uint8_t * free_nvme_id_ns = NULL;
uint8_t inq_dout[256];
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: time_secs=%d\n", __func__, time_secs);
if (0x2 & cdbp[1]) { /* Reject CmdDt=1 */
@@ -677,7 +678,7 @@ sntl_rluns(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp, int time_secs,
uint8_t * rl_doutp;
uint8_t * up;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: time_secs=%d\n", __func__, time_secs);
sel_report = cdbp[2];
@@ -740,7 +741,7 @@ sntl_tur(struct sg_pt_linux_scsi * ptp, int time_secs, int vb)
int res;
uint32_t pow_state;
- if (vb > 4)
+ if (vb > 5)
pr2ws("%s: start\n", __func__);
if (NULL == ptp->nvme_id_ctlp) {
res = sntl_cache_identify(ptp, time_secs, vb);
@@ -760,7 +761,7 @@ sntl_tur(struct sg_pt_linux_scsi * ptp, int time_secs, int vb)
return res;
}
pow_state = (0x1f & ptp->nvme_result);
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: pow_state=%u\n", __func__, pow_state);
#if 0 /* pow_state bounces around too much on laptop */
if (pow_state)
@@ -779,7 +780,7 @@ sntl_req_sense(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
uint32_t pow_state, alloc_len, n;
uint8_t rs_dout[64];
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: time_secs=%d\n", __func__, time_secs);
if (NULL == ptp->nvme_id_ctlp) {
res = sntl_cache_identify(ptp, time_secs, vb);
@@ -802,7 +803,7 @@ sntl_req_sense(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
}
ptp->io_hdr.response_len = 0;
pow_state = (0x1f & ptp->nvme_result);
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: pow_state=%u\n", __func__, pow_state);
memset(rs_dout, 0, sizeof(rs_dout));
if (pow_state)
@@ -832,7 +833,7 @@ sntl_mode_ss(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
uint8_t * bp;
struct sg_sntl_result_t sntl_result;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: mode se%s\n", __func__, (is_msense ? "nse" : "lect"));
if (NULL == ptp->nvme_id_ctlp) {
res = sntl_cache_identify(ptp, time_secs, vb);
@@ -942,12 +943,12 @@ sntl_senddiag(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
st_cd = 0x7 & (cdbp[1] >> 5);
self_test = !! (0x4 & cdbp[1]);
pf = !! (0x10 & cdbp[1]);
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: pf=%d, self_test=%d (st_code=%d)\n", __func__, (int)pf,
(int)self_test, (int)st_cd);
if (self_test || st_cd) {
memset(cmd_up, 0, sizeof(cmd));
- cmd_up[SG_NVME_PT_OPCODE] = 0x14; /* Device self-test */
+ cmd_up[SG_NVME_PT_OPCODE] = SG_NVME_AD_DEV_SELT_TEST;
/* just this namespace (if there is one) and controller */
sg_put_unaligned_le32(ptp->nvme_nsid, cmd_up + SG_NVME_PT_NSID);
switch (st_cd) {
@@ -1057,7 +1058,7 @@ sntl_recvdiag(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
pcv = !! (0x1 & cdbp[1]);
dpg_cd = cdbp[2];
alloc_len = sg_get_unaligned_be16(cdbp + 3); /* parameter list length */
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: dpg_cd=0x%x, pcv=%d, alloc_len=0x%x\n", __func__,
dpg_cd, (int)pcv, alloc_len);
din_len = ptp->io_hdr.din_xfer_len;
@@ -1114,7 +1115,7 @@ sntl_rep_opcodes(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
uint8_t *arr;
uint8_t *free_arr;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: time_secs=%d\n", __func__, time_secs);
rctd = !!(cdbp[2] & 0x80); /* report command timeout desc. */
reporting_opts = cdbp[2] & 0x7;
@@ -1223,7 +1224,7 @@ sntl_rep_tmfs(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
uint32_t alloc_len, len;
uint8_t arr[16];
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: time_secs=%d\n", __func__, time_secs);
memset(arr, 0, sizeof(arr));
repd = !!(cdbp[2] & 0x80);
@@ -1269,7 +1270,7 @@ sntl_readcap(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
uint8_t * free_up = NULL;
uint8_t resp[32];
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: RCAP%d, time_secs=%d\n", __func__,
(is_rcap10 ? 10 : 16), time_secs);
up = sg_memalign(pg_sz, pg_sz, &free_up, false);
@@ -1348,7 +1349,7 @@ do_nvm_pt_low(struct sg_pt_linux_scsi * ptp,
if (vb > 2) {
pr2ws("NVMe NVM command: %s\n", nam);
hex2stderr((const uint8_t *)cmdp, cmd_len, 1);
- if ((vb > 3) && (! is_read) && dp) {
+ if ((vb > 4) && (! is_read) && dp) {
if (dlen > 0) {
n = dlen;
if ((dlen < 512) || (vb > 5))
@@ -1403,7 +1404,7 @@ do_nvm_pt_low(struct sg_pt_linux_scsi * ptp,
}
return SG_LIB_NVME_STATUS; /* == SCSI_PT_DO_NVME_STATUS */
}
- if ((vb > 3) && is_read && dp) {
+ if ((vb > 4) && is_read && dp) {
if (dlen > 0) {
n = dlen;
if ((dlen < 1024) || (vb > 5))
@@ -1445,17 +1446,17 @@ sntl_do_nvm_cmd(struct sg_pt_linux_scsi * ptp, struct sg_nvme_user_io * iop,
}
static int
-sntl_read(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
- int time_secs, int vb)
+sntl_rread(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
+ int time_secs, int vb)
{
bool is_read10 = (SCSI_READ10_OPC == cdbp[0]);
bool have_fua = !!(cdbp[1] & 0x8);
int res;
- int nblks_t10 = 0;
+ uint32_t nblks_t10 = 0;
struct sg_nvme_user_io io;
struct sg_nvme_user_io * iop = &io;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: fua=%d, time_secs=%d\n", __func__, (int)have_fua,
time_secs);
memset(iop, 0, sizeof(*iop));
@@ -1464,14 +1465,12 @@ sntl_read(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
iop->slba = sg_get_unaligned_be32(cdbp + 2);
nblks_t10 = sg_get_unaligned_be16(cdbp + 7);
} else {
- uint32_t num = sg_get_unaligned_be32(cdbp + 10);
-
iop->slba = sg_get_unaligned_be64(cdbp + 2);
- if (num > (UINT16_MAX + 1)) {
+ nblks_t10 = sg_get_unaligned_be32(cdbp + 10);
+ if (nblks_t10 > (UINT16_MAX + 1)) {
mk_sense_invalid_fld(ptp, true, 11, -1, vb);
return 0;
- } else
- nblks_t10 = num;
+ }
}
if (0 == nblks_t10) { /* NOP in SCSI */
if (vb > 4)
@@ -1481,7 +1480,7 @@ sntl_read(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
}
iop->nblocks = nblks_t10 - 1; /* crazy "0's based" */
if (have_fua)
- iop->nblocks |= SG_NVME_NVM_CDW12_FUA;
+ iop->nblocks |= SG_NVME_RW_CDW12_FUA;
iop->addr = (uint64_t)ptp->io_hdr.din_xferp;
res = sntl_do_nvm_cmd(ptp, iop, ptp->io_hdr.din_xfer_len,
true /* is_read */, time_secs, vb);
@@ -1499,11 +1498,11 @@ sntl_write(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
bool is_write10 = (SCSI_WRITE10_OPC == cdbp[0]);
bool have_fua = !!(cdbp[1] & 0x8);
int res;
- int nblks_t10 = 0;
+ uint32_t nblks_t10 = 0;
struct sg_nvme_user_io io;
struct sg_nvme_user_io * iop = &io;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: fua=%d, time_secs=%d\n", __func__, (int)have_fua,
time_secs);
memset(iop, 0, sizeof(*iop));
@@ -1512,14 +1511,12 @@ sntl_write(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
iop->slba = sg_get_unaligned_be32(cdbp + 2);
nblks_t10 = sg_get_unaligned_be16(cdbp + 7);
} else {
- uint32_t num = sg_get_unaligned_be32(cdbp + 10);
-
iop->slba = sg_get_unaligned_be64(cdbp + 2);
- if (num > (UINT16_MAX + 1)) {
+ nblks_t10 = sg_get_unaligned_be32(cdbp + 10);
+ if (nblks_t10 > (UINT16_MAX + 1)) {
mk_sense_invalid_fld(ptp, true, 11, -1, vb);
return 0;
- } else
- nblks_t10 = num;
+ }
}
if (0 == nblks_t10) { /* NOP in SCSI */
if (vb > 4)
@@ -1529,7 +1526,7 @@ sntl_write(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
}
iop->nblocks = nblks_t10 - 1;
if (have_fua)
- iop->nblocks |= SG_NVME_NVM_CDW12_FUA;
+ iop->nblocks |= SG_NVME_RW_CDW12_FUA;
iop->addr = (uint64_t)ptp->io_hdr.dout_xferp;
res = sntl_do_nvm_cmd(ptp, iop, ptp->io_hdr.dout_xfer_len, false,
time_secs, vb);
@@ -1548,30 +1545,28 @@ sntl_verify(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
uint8_t bytchk = (cdbp[1] >> 1) & 0x3;
uint32_t dlen = 0;
int res;
- int nblks_t10 = 0;
+ uint32_t nblks_t10 = 0;
struct sg_nvme_user_io io;
struct sg_nvme_user_io * iop = &io;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: bytchk=%d, time_secs=%d\n", __func__, bytchk, time_secs);
if (bytchk > 1) {
mk_sense_invalid_fld(ptp, true, 1, 2, vb);
return 0;
}
memset(iop, 0, sizeof(*iop));
- iop->opcode = bytchk ? SG_NVME_NVM_COMPARE : SG_NVME_NVM_WRITE;
+ iop->opcode = bytchk ? SG_NVME_NVM_COMPARE : SG_NVME_NVM_VERIFY;
if (is_verify10) {
iop->slba = sg_get_unaligned_be32(cdbp + 2);
nblks_t10 = sg_get_unaligned_be16(cdbp + 7);
} else {
- uint32_t num = sg_get_unaligned_be32(cdbp + 10);
-
iop->slba = sg_get_unaligned_be64(cdbp + 2);
- if (num > (UINT16_MAX + 1)) {
+ nblks_t10 = sg_get_unaligned_be32(cdbp + 10);
+ if (nblks_t10 > (UINT16_MAX + 1)) {
mk_sense_invalid_fld(ptp, true, 11, -1, vb);
return 0;
- } else
- nblks_t10 = num;
+ }
}
if (0 == nblks_t10) { /* NOP in SCSI */
if (vb > 4)
@@ -1603,7 +1598,7 @@ sntl_write_same(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
struct sg_nvme_user_io io;
struct sg_nvme_user_io * iop = &io;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: ndob=%d, time_secs=%d\n", __func__, (int)ndob, time_secs);
if (! ndob) {
int flbas, index, lbafx, lbads, lbsize;
@@ -1673,7 +1668,7 @@ sntl_sync_cache(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
struct sg_nvme_user_io * iop = &io;
int res;
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: immed=%d, time_secs=%d\n", __func__, (int)immed,
time_secs);
memset(iop, 0, sizeof(*iop));
@@ -1694,7 +1689,7 @@ sntl_start_stop(struct sg_pt_linux_scsi * ptp, const uint8_t * cdbp,
{
bool immed = !!(0x1 & cdbp[1]);
- if (vb > 3)
+ if (vb > 5)
pr2ws("%s: immed=%d, time_secs=%d, ignore\n", __func__, (int)immed,
time_secs);
if (ptp) { } /* suppress warning */
@@ -1739,7 +1734,7 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb)
}
n = ptp->io_hdr.request_len;
cdbp = (const uint8_t *)(sg_uintptr_t)ptp->io_hdr.request;
- if (vb > 3)
+ if (vb > 4)
pr2ws("%s: opcode=0x%x, fd=%d (dev_fd=%d), time_secs=%d\n", __func__,
cdbp[0], fd, hold_dev_fd, time_secs);
scsi_cdb = sg_is_scsi_cdb(cdbp, n);
@@ -1757,7 +1752,7 @@ sg_do_nvme_pt(struct sg_pt_base * vp, int fd, int time_secs, int vb)
return sntl_req_sense(ptp, cdbp, time_secs, vb);
case SCSI_READ10_OPC:
case SCSI_READ16_OPC:
- return sntl_read(ptp, cdbp, time_secs, vb);
+ return sntl_rread(ptp, cdbp, time_secs, vb);
case SCSI_WRITE10_OPC:
case SCSI_WRITE16_OPC:
return sntl_write(ptp, cdbp, time_secs, vb);
@@ -1908,7 +1903,7 @@ do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int vb)
#else /* (HAVE_NVME && (! IGNORE_NVME)) */
int
-do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose)
+do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int vb)
{
if (vb) {
pr2ws("%s: not supported, ", __func__);
@@ -1923,6 +1918,7 @@ do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose)
#else
pr2ws("don't IGNORE_NVME");
#endif
+ }
if (vp) { }
if (submq) { }
if (timeout_secs) { }