aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-04-19 18:15:45 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-04-19 18:15:45 +0000
commit7dff7ae9433763457872082271aac0487e14d158 (patch)
treeb58832a541c07f160176b8a789f7e1110c0e743b
parentf55a523cb14c613b30b6d63fe78c892e8a414e3a (diff)
downloadsg3_utils-7dff7ae9433763457872082271aac0487e14d158.tar.gz
spelling and testing for sg v4 driver
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@819 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog4
-rw-r--r--src/sg_ses_microcode.c6
-rw-r--r--testing/sg_tst_ioctl.c66
-rw-r--r--testing/sgh_dd.cpp67
-rw-r--r--testing/uapi_sg.h8
5 files changed, 96 insertions, 55 deletions
diff --git a/ChangeLog b/ChangeLog
index 6d0d0d3a..21688d03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.45 [20190414] [svn: r818]
+Changelog for sg3_utils-1.45 [20190419] [svn: r819]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
- sg_opcodes: expand MLU (spc5r20)
@@ -17,7 +17,7 @@ Changelog for sg3_utils-1.45 [20190414] [svn: r818]
- sg_scan (win32): expand limits for big arrays
- sg_modes: placeholders for Command duration limit
T2A and T2B mpages (sbc4r17)
- - sg_logs: placeholder for Commmand duration limits
+ - sg_logs: placeholder for Command duration limits
statistics lpage (sbc4r17)
- sg_lib: add sg_t10_uuid_desig2str()
- tweak sg_pt interface to better handle bidi
diff --git a/src/sg_ses_microcode.c b/src/sg_ses_microcode.c
index 25011d5c..44e79b70 100644
--- a/src/sg_ses_microcode.c
+++ b/src/sg_ses_microcode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018 Douglas Gilbert.
+ * Copyright (c) 2014-2019 Douglas Gilbert.
* All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the BSD_LICENSE file.
@@ -44,7 +44,7 @@
* RESULTS commands in order to send microcode to the given SES device.
*/
-static const char * version_str = "1.16 20180628"; /* ses4r02 */
+static const char * version_str = "1.17 20190416"; /* ses4r02 */
#define ME "sg_ses_microcode: "
#define MAX_XFER_LEN (128 * 1024 * 1024)
@@ -935,7 +935,7 @@ fini:
}
}
if (0 == op->verbose) {
- if (! sg_if_can2stderr("sg_ses_mocrocode failed: ", ret))
+ if (! sg_if_can2stderr("sg_ses_microcode failed: ", ret))
pr2serr("Some error occurred, try again with '-v' "
"or '-vv' for more information\n");
}
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index fb21bcb2..063fe94a 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -56,7 +56,7 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.08 20190406";
+static const char * version_str = "Version: 1.08 20190419";
#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
@@ -84,6 +84,7 @@ static bool ioctl_only = false;
static bool q_at_tail = false;
static bool write_only = false;
static bool mrq_immed = false; /* if set, also sets mrq_iosubmit */
+static bool mrq_half_immed = false;
static bool mrq_iosubmit = false;
static int childs_pid = 0;
@@ -111,6 +112,8 @@ usage(void)
"the letter\n"
" 'I' is appended after a comma, then do "
"IMMED mrq;\n"
+ " 'i' IMMED on submission, non-IMMED on "
+ "receive;\n"
" 'S' is appended, then use "
"ioctl(SG_IOSUBMIT)\n"
" -o ioctls only, then exit\n"
@@ -362,28 +365,6 @@ tst_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_READ_VAL;
seip->sei_rd_mask |= SG_SEIM_READ_VAL;
- seip->read_value = SG_SEIRV_TRC_SZ;
- if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
- pr2serr("ioctl(SG_SET_GET_EXTENDED) failed, errno=%d %s\n", errno,
- strerror(errno));
- return 1;
- }
- printf(" %sread_value[SG_SEIRV_TRC_SZ]= %u\n", cp, seip->read_value);
-
- memset(seip, 0, sizeof(*seip));
- seip->sei_wr_mask |= SG_SEIM_READ_VAL;
- seip->sei_rd_mask |= SG_SEIM_READ_VAL;
- seip->read_value = SG_SEIRV_TRC_MAX_SZ;
- if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
- pr2serr("ioctl(SG_SET_GET_EXTENDED) failed, errno=%d %s\n", errno,
- strerror(errno));
- return 1;
- }
- printf(" %sread_value[SG_SEIRV_TRC_MAX_SZ]= %u\n", cp, seip->read_value);
-
- memset(seip, 0, sizeof(*seip));
- seip->sei_wr_mask |= SG_SEIM_READ_VAL;
- seip->sei_rd_mask |= SG_SEIM_READ_VAL;
seip->read_value = SG_SEIRV_SUBMITTED;
if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
pr2serr("ioctl(SG_SET_GET_EXTENDED) failed, errno=%d %s\n", errno,
@@ -402,7 +383,7 @@ tst_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
return 1;
}
printf(" %sread_value[SG_SEIRV_DEV_SUBMITTED]= %u\n", cp,
- seip->read_value);
+ seip->read_value);
memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_SHARE_FD;
@@ -422,8 +403,6 @@ tst_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
(int)seip->share_fd);
bypass_share:
- // printf("SG_IOSUBMIT value=0x%lx\n", SG_IOSUBMIT);
- // printf("SG_IORECEIVE value=0x%lx\n", SG_IORECEIVE);
if (ioctl(sg_fd, SG_GET_TRANSFORM, NULL) < 0)
pr2serr("ioctl(SG_GET_TRANSFORM) fail expected, errno=%d %s\n",
errno, strerror(errno));
@@ -473,7 +452,7 @@ static int
do_mrqs(int sg_fd, int sg_fd2, int mrqs)
{
bool both = (sg_fd2 >= 0);
- int k, arr_v4_sz, good;
+ int k, j, arr_v4_sz, good;
int res = 0;
struct sg_io_v4 * arr_v4;
struct sg_io_v4 * h4p;
@@ -554,24 +533,42 @@ do_mrqs(int sg_fd, int sg_fd2, int mrqs)
(mrq_iosubmit ? "SUBMIT" : ""), res, strerror(res));
goto fini;
}
+ if ((mrq_h4p->dout_resid > 0) || ((int)mrq_h4p->info < mrqs))
+ pr2serr("ioctl(SG_IO%s, mrq) dout_resid=%d, info=%d\n\n",
+ (mrq_iosubmit ? "SUBMIT" : ""), mrq_h4p->dout_resid,
+ mrq_h4p->info);
+
+ good = 0;
+ j = 0;
if (mrq_immed) {
-mrq_h4p->flags = SGV4_FLAG_MULTIPLE_REQS; // zap SGV4_FLAG_IMMED
+receive_more:
+ if (mrq_half_immed)
+ mrq_h4p->flags = SGV4_FLAG_MULTIPLE_REQS; // zap SGV4_FLAG_IMMED
if (ioctl(sg_fd, SG_IORECEIVE, mrq_h4p) < 0) {
res = errno;
pr2serr("ioctl(SG_IORECEIVE, mrq) failed, errno=%d %s\n",
res, strerror(res));
goto fini;
}
+ if ((mrq_h4p->din_resid > 0) || ((int)mrq_h4p->info < mrqs))
+ pr2serr("ioctl(SG_IORECEIVE, mrq) din_resid=%d, info=%d\n",
+ mrq_h4p->din_resid, mrq_h4p->info);
}
- for (k = 0, good = 0; k < mrqs; ++k) {
+ for (k = 0; k < (int)mrq_h4p->info; ++k, ++j) {
h4p = arr_v4 + k;
if (! (h4p->driver_status || h4p->transport_status ||
h4p->device_status)) {
if (h4p->info & SG_INFO_MRQ_FINI)
++good;
}
+ if ((! (h4p->info & SG_INFO_MRQ_FINI)) && (verbose > 1))
+ pr2serr("%s: k=%d: SG_INFO_MRQ_FINI not set on response\n",
+ __func__, k);
}
+ if (mrq_immed && (j < mrqs))
+ goto receive_more;
+
if (good > 0) {
printf("Final INQUIRY response:\n");
hex2stdout(inqBuff, INQ_REPLY_LEN, 0);
@@ -640,9 +637,12 @@ main(int argc, char * argv[])
}
if ((cp = strchr(argv[k] + 3, ','))) {
mrq_iosubmit = true;
- if (toupper(cp[1]) == 'I')
+ if (cp[1] == 'I')
+ mrq_immed = true;
+ else if (cp[1] == 'i') {
mrq_immed = true;
- else if (toupper(cp[1]) == 'S')
+ mrq_half_immed = true;
+ } else if (toupper(cp[1]) == 'S')
;
else {
printf("-m= option expects 'A' or 'a' as a suffix, "
@@ -669,6 +669,10 @@ main(int argc, char * argv[])
}
} else if (0 == memcmp("-t", argv[k], 2))
q_at_tail = true;
+ else if (0 == memcmp("-vvvvvv", argv[k], 7))
+ verbose += 4;
+ else if (0 == memcmp("-vvvvv", argv[k], 6))
+ verbose += 4;
else if (0 == memcmp("-vvvv", argv[k], 5))
verbose += 4;
else if (0 == memcmp("-vvv", argv[k], 4))
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index c982c868..4a8350a9 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -103,7 +103,7 @@
using namespace std;
-static const char * version_str = "1.25 20190413";
+static const char * version_str = "1.27 20190418";
#ifdef __GNUC__
#ifndef __clang__
@@ -214,6 +214,7 @@ typedef struct global_collection
bool ofile_given;
bool ofile2_given;
bool unit_nanosec; /* default duration unit is millisecond */
+ bool mrq_cmds; /* mrq=<NRQS>,C given */
const char * infp;
const char * outfp;
const char * out2fp;
@@ -226,6 +227,7 @@ typedef struct request_element
bool both_sg;
bool swait; /* interleave READ WRITE async copy segment: READ submit,
* WRITE submit, READ receive, WRITE receive */
+ bool mrq_cmds; /* mrq=<NRQS>,C given */
int id;
int infd;
int nmrqs;
@@ -288,7 +290,7 @@ static int sg_out_open(Gbl_coll *clp, const char *outf, uint8_t **mmpp,
int *mmap_len);
static void sg_in_out_interleave(Gbl_coll *clp, Rq_elem * rep,
mrq_arr_t & def_arr);
-static int sgh_do_def(Rq_elem * rep, mrq_arr_t & def_arr);
+static int sgh_do_def_mrq(Rq_elem * rep, mrq_arr_t & def_arr);
#define STRERR_BUFF_LEN 128
@@ -603,7 +605,7 @@ usage(int pg_num)
pr2serr(" [ae=AEN] [bpt=BPT] [cdbsz=6|10|12|16] [coe=0|1] "
"[deb=VERB]\n"
" [dio=0|1] [elemsz_kb=ESK] [fua=0|1|2|3] "
- "[mrq=NRQS]\n"
+ "[mrq=NRQS[,C]]\n"
" [of2=OFILE2] [ofreg=OFREG] [sync=0|1] [thr=THR] "
"[time=0|1]\n"
" [verbose=VERB] [--dry-run] [--verbose]\n\n"
@@ -664,7 +666,8 @@ page2:
"2->IFILE,\n"
" 3->OFILE+IFILE\n"
" mrq even number of cmds placed in each sg call "
- "(def: 0)\n"
+ "(def: 0);\n"
+ " may have trailing ',C', to send bulk cdb_s\n"
" ofreg OFREG is regular file or pipe to send what is "
"read from\n"
" IFILE in the first half of each shared element\n"
@@ -921,6 +924,7 @@ read_write_thread(void * v_tip)
rep->in_flags = clp->in_flags;
rep->out_flags = clp->out_flags;
rep->nmrqs = clp->nmrqs;
+ rep->mrq_cmds = clp->mrq_cmds;
rep->aen = clp->aen;
rep->rep_count = 0;
@@ -1016,7 +1020,6 @@ read_write_thread(void * v_tip)
/* no more to do, exit loop then thread */
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
-pr2serr_lk("tid=%d: clp->in_stop\n", rep->id);
break;
}
#endif
@@ -1024,6 +1027,13 @@ pr2serr_lk("tid=%d: clp->in_stop\n", rep->id);
if (my_index >= dd_count) {
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
+ if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
+ if (rep->debug > 1)
+ pr2serr_lk("thread=%d: tail-end my_index>=dd_count, "
+ "to_do=%u\n", rep->id,
+ (uint32_t)def_arr.first.size());
+ sgh_do_def_mrq(rep, def_arr);
+ }
break;
} else if ((my_index + clp->bpt) > dd_count)
blocks = dd_count - my_index;
@@ -1079,7 +1089,6 @@ skip_force_out_sequence:
clp->out_stop = true;
status = pthread_mutex_unlock(&clp->out_mutex);
if (0 != status) err_exit(status, "unlock out_mutex");
-pr2serr_lk("tid=%d: clp->out_stop\n", rep->id);
break;
}
if (stop_after_write)
@@ -1133,10 +1142,10 @@ pr2serr_lk("tid=%d: clp->out_stop\n", rep->id);
}
if (0 == rep->num_blks) {
if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
- if (rep->debug)
+ if (rep->debug > 1)
pr2serr_lk("thread=%d: tail-end, to_do=%u\n", rep->id,
(uint32_t)def_arr.first.size());
- sgh_do_def(rep, def_arr);
+ sgh_do_def_mrq(rep, def_arr);
}
clp->out_stop = true;
stop_after_write = true;
@@ -1540,23 +1549,38 @@ fini:
sg_wr_swap_share(rep, rep->outfd, false);
}
-/* Returns 0 on success, 1 if ENOMEM error else -1 for other errors. */
+/* This function sets up a multiple request (mrq) transaction and sends it
+ * to the pass-through. Returns 0 on success, 1 if ENOMEM error else -1 for
+ * other errors. */
static int
-sgh_do_def(Rq_elem * rep, mrq_arr_t & def_arr)
+sgh_do_def_mrq(Rq_elem * rep, mrq_arr_t & def_arr)
{
int n, k, res, fd;
+ const int max_cdb_sz = 16;
struct sg_io_v4 * a_v4p;
struct sg_io_v4 ctl_v4;
+ uint8_t * cmd_ap = NULL;
memset(&ctl_v4, 0, sizeof(ctl_v4));
ctl_v4.guard = 'Q';
a_v4p = def_arr.first.data();
n = def_arr.first.size();
+ if (rep->mrq_cmds) {
+ cmd_ap = (uint8_t *)calloc(n, max_cdb_sz);
+ if (NULL == cmd_ap) {
+ pr2serr_lk("%s: no memory for calloc(%d * 16)\n", __func__, n);
+ return -1;
+ }
+ }
for (k = 0; k < n; ++k) {
struct sg_io_v4 * h4p = a_v4p + k;
uint8_t *cmdp = &def_arr.second[k].front();
- h4p->request = (uint64_t)cmdp;
+ if (rep->mrq_cmds) {
+ memcpy(cmd_ap + (k * max_cdb_sz), cmdp, h4p->request_len);
+ h4p->request = 0;
+ } else
+ h4p->request = (uint64_t)cmdp;
if (rep->debug > 3) {
pr2serr_lk("def_arr[%d]:\n", k);
hex2stderr_lk((const uint8_t *)(a_v4p + k), sizeof(*a_v4p), 1);
@@ -1569,6 +1593,10 @@ sgh_do_def(Rq_elem * rep, mrq_arr_t & def_arr)
else
fd = rep->outfd;
res = 0;
+ if (rep->mrq_cmds) {
+ ctl_v4.request_len = n * max_cdb_sz;
+ ctl_v4.request = (uint64_t)cmd_ap;
+ }
ctl_v4.flags = SGV4_FLAG_MULTIPLE_REQS | SGV4_FLAG_STOP_IF;
ctl_v4.dout_xferp = (uint64_t)a_v4p; /* request array */
ctl_v4.dout_xfer_len = n * sizeof(*a_v4p);
@@ -1606,6 +1634,8 @@ sgh_do_def(Rq_elem * rep, mrq_arr_t & def_arr)
}
def_arr.first.clear();
def_arr.second.clear();
+ if (cmd_ap)
+ free(cmd_ap);
return res;
}
@@ -1730,7 +1760,7 @@ do_v4:
def_arr.second.push_back(cmd_obj);
res = 0;
if ((int)def_arr.first.size() >= rep->nmrqs)
- res = sgh_do_def(rep, def_arr);
+ res = sgh_do_def_mrq(rep, def_arr);
return res;
}
while (((res = ioctl(fd, SG_IOSUBMIT, h4p)) < 0) &&
@@ -2305,6 +2335,7 @@ main(int argc, char * argv[])
int64_t out_num_sect = 0;
int in_sect_sz, out_sect_sz, status, n, flags;
void * vp;
+ const char * cp;
Gbl_coll * clp = &gcoll;
Thread_info thread_arr[MAX_NUM_THREADS];
char ebuff[EBUFF_SZ];
@@ -2428,6 +2459,9 @@ main(int argc, char * argv[])
"zero\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
+ cp = strchr(buf, ',');
+ if (cp && ('C' == toupper(cp[1])))
+ clp->mrq_cmds = true;
} else if (0 == strcmp(key, "obs")) {
obs = sg_get_num(buf);
if (-1 == obs) {
@@ -2596,9 +2630,14 @@ main(int argc, char * argv[])
clp->out_flags.swait = true;
}
clp->unit_nanosec = !!getenv("SG3_UTILS_LINUX_NANO");
- if (clp->debug)
+ if (clp->debug) {
pr2serr("%sif=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%"
- PRId64 "\n", my_name, inf, skip, outf, seek, dd_count);
+ PRId64, my_name, inf, skip, outf, seek, dd_count);
+ if (clp->nmrqs > 0)
+ pr2serr(" mrq=%d%s\n", clp->nmrqs, (clp->mrq_cmds ? ",C" : ""));
+ else
+ pr2serr("\n");
+ }
install_handler(SIGINT, interrupt_handler);
install_handler(SIGQUIT, interrupt_handler);
diff --git a/testing/uapi_sg.h b/testing/uapi_sg.h
index ad41d679..053b0ffc 100644
--- a/testing/uapi_sg.h
+++ b/testing/uapi_sg.h
@@ -14,7 +14,7 @@
* Later extensions (versions 2, 3 and 4) to driver:
* Copyright (C) 1998 - 2018 Douglas Gilbert
*
- * Version 4.0.08 (20190406)
+ * Version 4.0.08 (20190419)
* This version is for Linux 2.6, 3, 4 and 5 series kernels.
*
* Documentation
@@ -206,10 +206,8 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
#define SG_SEIRV_VERS_NUM 0x2 /* get driver version number as int */
#define SG_SEIRV_FL_RQS 0x3 /* number of requests in free list */
#define SG_SEIRV_DEV_FL_RQS 0x4 /* sum(fl rqs) on all dev's fds */
-#define SG_SEIRV_TRC_SZ 0x5 /* current size of trace buffer */
-#define SG_SEIRV_TRC_MAX_SZ 0x6 /* maximum size of trace buffer */
-#define SG_SEIRV_SUBMITTED 0x7 /* number of mrqs submitted+unread */
-#define SG_SEIRV_DEV_SUBMITTED 0x8 /* sum(submiited) on all dev's fds */
+#define SG_SEIRV_SUBMITTED 0x5 /* number of mrqs submitted+unread */
+#define SG_SEIRV_DEV_SUBMITTED 0x6 /* sum(submitted) on all dev's fds */
/*
* A pointer to the following structure is passed as the third argument to