From owner-svn-src-all@freebsd.org Fri Feb 24 20:51:41 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 561B1CEB27A; Fri, 24 Feb 2017 20:51:41 +0000 (UTC) (envelope-from ken@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1717DE07; Fri, 24 Feb 2017 20:51:41 +0000 (UTC) (envelope-from ken@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1OKpegw051879; Fri, 24 Feb 2017 20:51:40 GMT (envelope-from ken@FreeBSD.org) Received: (from ken@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1OKpdcE051872; Fri, 24 Feb 2017 20:51:39 GMT (envelope-from ken@FreeBSD.org) Message-Id: <201702242051.v1OKpdcE051872@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ken set sender to ken@FreeBSD.org using -f From: "Kenneth D. Merry" Date: Fri, 24 Feb 2017 20:51:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r314221 - stable/10/sbin/camcontrol X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Feb 2017 20:51:41 -0000 Author: ken Date: Fri Feb 24 20:51:39 2017 New Revision: 314221 URL: https://svnweb.freebsd.org/changeset/base/314221 Log: MFC r313893 ------------------------------------------------------------------------ r313893 | ken | 2017-02-17 13:04:22 -0700 (Fri, 17 Feb 2017) | 48 lines Add task attribute support to camcontrol(8). Users can use the new generic argument, -Q task_attr, to specify a task attribute (simple, ordered, head of queue, aca) for the commands issued. The the default is simple, which works with all SCSI devices that support tagged queueing. This will mostly be useful for debugging target behavior in certain situations. You can try it out by compiling CTL with CTL_IO_DELAY turned on (in sys/cam/ctl/ctl_io.h) and then do something like this with one of the CTL LUNs: ctladm delay 0:0 -l done -t 10 camcontrol tur da34 -v And at then before the 10 second timer is up, in another terminal: camcontrol inquiry da34 -Q ordered -v The Inquiry should complete just after the TUR completes. Ordinarily it would complete first because of the delay injection, but because the task attribute is set to ordered in this case, CTL holds it up until the previous command has completed. sbin/camcontrol/camcontrol.c: Add the new generic argument, -Q, which allows the user to specify a SCSI task attribute. The user can specify task attributes by name or numerically. Add a new task_attr arguments to SCSI sub-functions. sbin/camcontrol/attrib.c, sbin/camcontrol/camcontrol.h, sbin/camcontrol/fwdownload.c, sbin/camcontrol/modeedit.c, sbin/camcontrol/persist.c, sbin/camcontrol/timestamp.c, sbin/camcontrol/zone.c: Add the new task_attr argument to SCSI sub-functions. sbin/camcontrol/camcontrol.8: Document the new -Q option, and add an example. Sponsored by: Spectra Logic ------------------------------------------------------------------------ Modified: stable/10/sbin/camcontrol/attrib.c stable/10/sbin/camcontrol/camcontrol.8 stable/10/sbin/camcontrol/camcontrol.c stable/10/sbin/camcontrol/camcontrol.h stable/10/sbin/camcontrol/fwdownload.c stable/10/sbin/camcontrol/modeedit.c stable/10/sbin/camcontrol/persist.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sbin/camcontrol/attrib.c ============================================================================== --- stable/10/sbin/camcontrol/attrib.c Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/attrib.c Fri Feb 24 20:51:39 2017 (r314221) @@ -106,7 +106,8 @@ static struct scsi_nv output_format_map[ int scsiattrib(struct cam_device *device, int argc, char **argv, char *combinedopt, - int retry_count, int timeout, int verbosemode, int err_recover) + int task_attr, int retry_count, int timeout, int verbosemode, + int err_recover) { union ccb *ccb = NULL; int attr_num = -1; @@ -317,7 +318,7 @@ scsiattrib(struct cam_device *device, in scsi_read_attribute(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, /*service_action*/ read_service_action, /*element*/ element_address, /*elem_type*/ element_type, Modified: stable/10/sbin/camcontrol/camcontrol.8 ============================================================================== --- stable/10/sbin/camcontrol/camcontrol.8 Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/camcontrol.8 Fri Feb 24 20:51:39 2017 (r314221) @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 6, 2017 +.Dd February 17, 2017 .Dt CAMCONTROL 8 .Os .Sh NAME @@ -397,6 +397,17 @@ It may take some other actions, dependin the command. .It Fl n Ar dev_name Specify the device type to operate on, e.g.\& "da", "cd". +.It Fl Q Ar task_attr +.Tn SCSI +task attribute for the command, if it is a +.Tn SCSI +command. +This may be ordered, simple, head, or aca. +In most cases this is not needed. +The default is simple, which works with all +.Tn SCSI +devices. +The task attribute may also be specified numerically. .It Fl t Ar timeout SCSI command timeout in seconds. This overrides the default timeout for @@ -2143,7 +2154,7 @@ information if the command fails since t .Fl v switch was not specified. .Bd -literal -offset indent -camcontrol tur da1 -E -C 4 -t 50 -v +camcontrol tur da1 -E -C 4 -t 50 -Q head -v .Ed .Pp Send a test unit ready command to da1. @@ -2156,6 +2167,9 @@ flag) if the command fails. Since error recovery is turned on, the disk will be spun up if it is not currently spinning. The +.Tn SCSI +task attribute for the command will be set to Head of Queue. +The .Nm utility will report whether the disk is ready. .Bd -literal -offset indent Modified: stable/10/sbin/camcontrol/camcontrol.c ============================================================================== --- stable/10/sbin/camcontrol/camcontrol.c Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/camcontrol.c Fri Feb 24 20:51:39 2017 (r314221) @@ -168,6 +168,14 @@ struct ata_set_max_pwd u_int16_t reserved2[239]; }; +static struct scsi_nv task_attrs[] = { + { "simple", MSG_SIMPLE_Q_TAG }, + { "head", MSG_HEAD_OF_Q_TAG }, + { "ordered", MSG_ORDERED_Q_TAG }, + { "iwr", MSG_IGN_WIDE_RESIDUE }, + { "aca", MSG_ACA_TASK } +}; + static const char scsicmd_opts[] = "a:c:dfi:o:r"; static const char readdefect_opts[] = "f:GPqsS:X"; static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; @@ -259,12 +267,14 @@ static int getdevlist(struct cam_device #endif /* MINIMALISTIC */ static int getdevtree(int argc, char **argv, char *combinedopt); #ifndef MINIMALISTIC -static int testunitready(struct cam_device *device, int retry_count, - int timeout, int quiet); +static int testunitready(struct cam_device *device, int task_attr, + int retry_count, int timeout, int quiet); static int scsistart(struct cam_device *device, int startstop, int loadeject, - int retry_count, int timeout); -static int scsiinquiry(struct cam_device *device, int retry_count, int timeout); -static int scsiserial(struct cam_device *device, int retry_count, int timeout); + int task_attr, int retry_count, int timeout); +static int scsiinquiry(struct cam_device *device, int task_attr, + int retry_count, int timeout); +static int scsiserial(struct cam_device *device, int task_attr, + int retry_count, int timeout); #endif /* MINIMALISTIC */ static int parse_btl(char *tstr, path_id_t *bus, target_id_t *target, lun_id_t *lun, cam_argmask *arglst); @@ -274,11 +284,14 @@ static int scanlun_or_reset_dev(path_id_ lun_id_t lun, int scan); #ifndef MINIMALISTIC static int readdefects(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static void modepage(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static int scsicmd(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static int smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout); static int smpreportgeneral(struct cam_device *device, int argc, char **argv, @@ -303,16 +316,21 @@ static int get_cpi(struct cam_device *de static int get_cgd(struct cam_device *device, struct ccb_getdev *cgd); static int get_print_cts(struct cam_device *device, int user_settings, int quiet, struct ccb_trans_settings *cts); -static int ratecontrol(struct cam_device *device, int retry_count, - int timeout, int argc, char **argv, char *combinedopt); +static int ratecontrol(struct cam_device *device, int task_attr, + int retry_count, int timeout, int argc, char **argv, + char *combinedopt); static int scsiformat(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static int scsisanitize(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static int scsireportluns(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static int scsireadcapacity(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); static int atapm(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout); static int atasecurity(struct cam_device *device, int retry_count, int timeout, @@ -325,8 +343,8 @@ static int scsiprintoneopcode(struct cam static int scsiprintopcodes(struct cam_device *device, int td_req, uint8_t *buf, uint32_t valid_len); static int scsiopcodes(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout, - int verbose); + char *combinedopt, int task_attr, int retry_count, + int timeout, int verbose); static int scsireprobe(struct cam_device *device); #endif /* MINIMALISTIC */ @@ -644,8 +662,8 @@ getdevtree(int argc, char **argv, char * #ifndef MINIMALISTIC static int -testunitready(struct cam_device *device, int retry_count, int timeout, - int quiet) +testunitready(struct cam_device *device, int task_attr, int retry_count, + int timeout, int quiet) { int error = 0; union ccb *ccb; @@ -655,7 +673,7 @@ testunitready(struct cam_device *device, scsi_test_unit_ready(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* sense_len */ SSD_FULL_SIZE, /* timeout */ timeout ? timeout : 5000); @@ -699,7 +717,7 @@ testunitready(struct cam_device *device, static int scsistart(struct cam_device *device, int startstop, int loadeject, - int retry_count, int timeout) + int task_attr, int retry_count, int timeout) { union ccb *ccb; int error = 0; @@ -710,13 +728,19 @@ scsistart(struct cam_device *device, int * If we're stopping, send an ordered tag so the drive in question * will finish any previously queued writes before stopping. If * the device isn't capable of tagged queueing, or if tagged - * queueing is turned off, the tag action is a no-op. - */ + * queueing is turned off, the tag action is a no-op. We override + * the default simple tag, although this also has the effect of + * overriding the user's wishes if he wanted to specify a simple + * tag. + */ + if ((startstop == 0) + && (task_attr == MSG_SIMPLE_Q_TAG)) + task_attr = MSG_ORDERED_Q_TAG; + scsi_start_stop(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ startstop ? MSG_SIMPLE_Q_TAG : - MSG_ORDERED_Q_TAG, + /* tag_action */ task_attr, /* start/stop */ startstop, /* load_eject */ loadeject, /* immediate */ 0, @@ -777,7 +801,7 @@ scsistart(struct cam_device *device, int int scsidoinquiry(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout) + char *combinedopt, int task_attr, int retry_count, int timeout) { int c; int error = 0; @@ -806,13 +830,13 @@ scsidoinquiry(struct cam_device *device, arglist |= CAM_ARG_INQ_MASK; if (arglist & CAM_ARG_GET_STDINQ) - error = scsiinquiry(device, retry_count, timeout); + error = scsiinquiry(device, task_attr, retry_count, timeout); if (error != 0) return(error); if (arglist & CAM_ARG_GET_SERIAL) - scsiserial(device, retry_count, timeout); + scsiserial(device, task_attr, retry_count, timeout); if (arglist & CAM_ARG_GET_XFERRATE) error = camxferrate(device); @@ -821,7 +845,8 @@ scsidoinquiry(struct cam_device *device, } static int -scsiinquiry(struct cam_device *device, int retry_count, int timeout) +scsiinquiry(struct cam_device *device, int task_attr, int retry_count, + int timeout) { union ccb *ccb; struct scsi_inquiry_data *inq_buf; @@ -883,7 +908,7 @@ scsiinquiry(struct cam_device *device, i scsi_inquiry(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* inq_buf */ (u_int8_t *)inq_buf, /* inq_len */ SHORT_INQUIRY_LENGTH, /* evpd */ 0, @@ -935,7 +960,8 @@ scsiinquiry(struct cam_device *device, i } static int -scsiserial(struct cam_device *device, int retry_count, int timeout) +scsiserial(struct cam_device *device, int task_attr, int retry_count, + int timeout) { union ccb *ccb; struct scsi_vpd_unit_serial_number *serial_buf; @@ -964,7 +990,7 @@ scsiserial(struct cam_device *device, in scsi_inquiry(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* inq_buf */ (u_int8_t *)serial_buf, /* inq_len */ sizeof(*serial_buf), /* evpd */ 1, @@ -3400,7 +3426,7 @@ static struct scsi_nv defect_list_type_m static int readdefects(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout) + char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb = NULL; struct scsi_read_defect_data_hdr_10 *hdr10 = NULL; @@ -3542,7 +3568,7 @@ next_batch: scsi_read_defects(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, /*list_format*/ list_format, /*addr_desc_index*/ starting_offset, /*data_ptr*/ defect_list, @@ -3980,7 +4006,8 @@ reassignblocks(struct cam_device *device #ifndef MINIMALISTIC void mode_sense(struct cam_device *device, int dbd, int pc, int page, int subpage, - int retry_count, int timeout, u_int8_t *data, int datalen) + int task_attr, int retry_count, int timeout, u_int8_t *data, + int datalen) { union ccb *ccb; int retval; @@ -3995,7 +4022,7 @@ mode_sense(struct cam_device *device, in scsi_mode_sense_subpage(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* dbd */ dbd, /* pc */ pc << 6, /* page */ page, @@ -4030,8 +4057,8 @@ mode_sense(struct cam_device *device, in } void -mode_select(struct cam_device *device, int save_pages, int retry_count, - int timeout, u_int8_t *data, int datalen) +mode_select(struct cam_device *device, int save_pages, int task_attr, + int retry_count, int timeout, u_int8_t *data, int datalen) { union ccb *ccb; int retval; @@ -4046,7 +4073,7 @@ mode_select(struct cam_device *device, i scsi_mode_select(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* scsi_page_fmt */ 1, /* save_pages */ save_pages, /* param_buf */ data, @@ -4081,7 +4108,7 @@ mode_select(struct cam_device *device, i void modepage(struct cam_device *device, int argc, char **argv, char *combinedopt, - int retry_count, int timeout) + int task_attr, int retry_count, int timeout) { char *str_subpage; int c, page = -1, subpage = -1, pc = 0; @@ -4128,16 +4155,17 @@ modepage(struct cam_device *device, int errx(1, "you must specify a mode page!"); if (list != 0) { - mode_list(device, dbd, pc, list > 1, retry_count, timeout); + mode_list(device, dbd, pc, list > 1, task_attr, retry_count, + timeout); } else { mode_edit(device, dbd, pc, page, subpage, edit, binary, - retry_count, timeout); + task_attr, retry_count, timeout); } } static int scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, - int retry_count, int timeout) + int task_attr, int retry_count, int timeout) { union ccb *ccb; u_int32_t flags = CAM_DIR_NONE; @@ -4382,7 +4410,7 @@ scsicmd(struct cam_device *device, int a /*retries*/ retry_count, /*cbfcnp*/ NULL, /*flags*/ flags, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, /*data_ptr*/ data_ptr, /*dxfer_len*/ data_bytes, /*sense_len*/ SSD_FULL_SIZE, @@ -5333,8 +5361,8 @@ get_print_cts_bailout: } static int -ratecontrol(struct cam_device *device, int retry_count, int timeout, - int argc, char **argv, char *combinedopt) +ratecontrol(struct cam_device *device, int task_attr, int retry_count, + int timeout, int argc, char **argv, char *combinedopt) { int c; union ccb *ccb; @@ -5664,7 +5692,7 @@ ratecontrol(struct cam_device *device, i } } if (send_tur) { - retval = testunitready(device, retry_count, timeout, + retval = testunitready(device, task_attr, retry_count, timeout, (arglist & CAM_ARG_VERBOSE) ? 0 : 1); /* * If the TUR didn't succeed, just bail. @@ -5689,7 +5717,7 @@ ratecontrol_bailout: static int scsiformat(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout) + char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb; int c; @@ -5738,7 +5766,7 @@ scsiformat(struct cam_device *device, in "following device:\n"); error = scsidoinquiry(device, argc, argv, combinedopt, - retry_count, timeout); + task_attr, retry_count, timeout); if (error != 0) { warnx("scsiformat: error sending inquiry"); @@ -5810,7 +5838,7 @@ scsiformat(struct cam_device *device, in scsi_format_unit(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* byte2 */ byte2, /* ileave */ 0, /* data_ptr */ data_ptr, @@ -5869,7 +5897,7 @@ doreport: scsi_test_unit_ready(&ccb->csio, /* retries */ 0, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* sense_len */ SSD_FULL_SIZE, /* timeout */ 5000); @@ -5979,7 +6007,7 @@ scsiformat_bailout: static int scsisanitize(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout) + char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb; u_int8_t action = 0; @@ -6144,7 +6172,7 @@ scsisanitize(struct cam_device *device, "following device:\n"); error = scsidoinquiry(device, argc, argv, combinedopt, - retry_count, timeout); + task_attr, retry_count, timeout); if (error != 0) { warnx("scsisanitize: error sending inquiry"); @@ -6202,7 +6230,7 @@ scsisanitize(struct cam_device *device, scsi_sanitize(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* byte2 */ byte2, /* control */ 0, /* data_ptr */ data_ptr, @@ -6277,7 +6305,7 @@ doreport: scsi_test_unit_ready(&ccb->csio, /* retries */ 0, /* cbfcnp */ NULL, - /* tag_action */ MSG_SIMPLE_Q_TAG, + /* tag_action */ task_attr, /* sense_len */ SSD_FULL_SIZE, /* timeout */ 5000); @@ -6389,7 +6417,7 @@ scsisanitize_bailout: static int scsireportluns(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout) + char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb; int c, countonly, lunsonly; @@ -6466,7 +6494,7 @@ retry: scsi_report_luns(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, /*select_report*/ report_type, /*rpl_buf*/ lundata, /*alloc_len*/ alloc_len, @@ -6631,7 +6659,7 @@ bailout: static int scsireadcapacity(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout) + char *combinedopt, int task_attr, int retry_count, int timeout) { union ccb *ccb; int blocksizeonly, humanize, numblocks, quiet, sizeonly, baseten; @@ -6717,7 +6745,7 @@ scsireadcapacity(struct cam_device *devi scsi_read_capacity(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, &rcap, SSD_FULL_SIZE, /*timeout*/ timeout ? timeout : 5000); @@ -6759,7 +6787,7 @@ scsireadcapacity(struct cam_device *devi scsi_read_capacity_16(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, /*lba*/ 0, /*reladdr*/ 0, /*pmi*/ 0, @@ -8200,8 +8228,8 @@ ataaxm(struct cam_device *device, int ar int scsigetopcodes(struct cam_device *device, int opcode_set, int opcode, int show_sa_errors, int sa_set, int service_action, - int timeout_desc, int retry_count, int timeout, int verbosemode, - uint32_t *fill_len, uint8_t **data_ptr) + int timeout_desc, int task_attr, int retry_count, int timeout, + int verbosemode, uint32_t *fill_len, uint8_t **data_ptr) { union ccb *ccb = NULL; uint8_t *buf = NULL; @@ -8268,7 +8296,7 @@ retry_alloc: scsi_report_supported_opcodes(&ccb->csio, /*retries*/ retry_count, /*cbfcnp*/ NULL, - /*tag_action*/ MSG_SIMPLE_Q_TAG, + /*tag_action*/ task_attr, /*options*/ options, /*req_opcode*/ opcode, /*req_service_action*/ service_action, @@ -8568,7 +8596,8 @@ bailout: static int scsiopcodes(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout, int verbosemode) + char *combinedopt, int task_attr, int retry_count, int timeout, + int verbosemode) { int c; uint32_t opcode = 0, service_action = 0; @@ -8632,8 +8661,9 @@ scsiopcodes(struct cam_device *device, i goto bailout; } retval = scsigetopcodes(device, opcode_set, opcode, show_sa_errors, - sa_set, service_action, td_set, retry_count, - timeout, verbosemode, &valid_len, &buf); + sa_set, service_action, td_set, task_attr, + retry_count, timeout, verbosemode, &valid_len, + &buf); if (retval != 0) goto bailout; @@ -8816,6 +8846,7 @@ usage(int printlong) "-u unit specify unit number, e.g. \"0\", \"5\"\n" "-E have the kernel attempt to perform SCSI error recovery\n" "-C count specify the SCSI command retry count (needs -E to work)\n" +"-Q task_attr specify ordered, simple or head tag type for SCSI cmds\n" "modepage arguments:\n" "-l list all available mode pages\n" "-m page specify the mode page to view or edit\n" @@ -8988,10 +9019,11 @@ main(int argc, char **argv) int timeout = 0, retry_count = 1; camcontrol_optret optreturn; char *tstr; - const char *mainopt = "C:En:t:u:v"; + const char *mainopt = "C:En:Q:t:u:v"; const char *subopt = NULL; char combinedopt[256]; int error = 0, optstart = 2; + int task_attr = MSG_SIMPLE_Q_TAG; int devopen = 1; #ifndef MINIMALISTIC path_id_t bus; @@ -9145,6 +9177,40 @@ main(int argc, char **argv) tstr++; device = (char *)strdup(tstr); break; + case 'Q': { + char *endptr; + int table_entry = 0; + + tstr = optarg; + while (isspace(*tstr) && (*tstr != '\0')) + tstr++; + if (isdigit(*tstr)) { + task_attr = strtol(tstr, &endptr, 0); + if (*endptr != '\0') { + errx(1, "Invalid queue option " + "%s", tstr); + } + } else { + size_t table_size; + scsi_nv_status status; + + table_size = sizeof(task_attrs) / + sizeof(task_attrs[0]); + status = scsi_get_nv(task_attrs, + table_size, tstr, &table_entry, + SCSI_NV_FLAG_IG_CASE); + if (status == SCSI_NV_FOUND) + task_attr = task_attrs[ + table_entry].value; + else { + errx(1, "%s option %s", + (status == SCSI_NV_AMBIGUOUS)? + "ambiguous" : "invalid", + tstr); + } + } + break; + } case 't': timeout = strtol(optarg, NULL, 0); if (timeout < 0) @@ -9210,19 +9276,20 @@ main(int argc, char **argv) break; #ifndef MINIMALISTIC case CAM_CMD_TUR: - error = testunitready(cam_dev, retry_count, timeout, 0); + error = testunitready(cam_dev, task_attr, retry_count, + timeout, 0); break; case CAM_CMD_INQUIRY: error = scsidoinquiry(cam_dev, argc, argv, combinedopt, - retry_count, timeout); + task_attr, retry_count, timeout); break; case CAM_CMD_IDENTIFY: error = ataidentify(cam_dev, retry_count, timeout); break; case CAM_CMD_STARTSTOP: error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT, - arglist & CAM_ARG_EJECT, retry_count, - timeout); + arglist & CAM_ARG_EJECT, task_attr, + retry_count, timeout); break; #endif /* MINIMALISTIC */ case CAM_CMD_RESCAN: @@ -9234,15 +9301,15 @@ main(int argc, char **argv) #ifndef MINIMALISTIC case CAM_CMD_READ_DEFECTS: error = readdefects(cam_dev, argc, argv, combinedopt, - retry_count, timeout); + task_attr, retry_count, timeout); break; case CAM_CMD_MODE_PAGE: modepage(cam_dev, argc, argv, combinedopt, - retry_count, timeout); + task_attr, retry_count, timeout); break; case CAM_CMD_SCSI_CMD: error = scsicmd(cam_dev, argc, argv, combinedopt, - retry_count, timeout); + task_attr, retry_count, timeout); break; case CAM_CMD_SMP_CMD: error = smpcmd(cam_dev, argc, argv, combinedopt, @@ -9272,22 +9339,23 @@ main(int argc, char **argv) error = tagcontrol(cam_dev, argc, argv, combinedopt); break; case CAM_CMD_RATE: - error = ratecontrol(cam_dev, retry_count, timeout, - argc, argv, combinedopt); + error = ratecontrol(cam_dev, task_attr, retry_count, + timeout, argc, argv, combinedopt); break; case CAM_CMD_FORMAT: error = scsiformat(cam_dev, argc, argv, - combinedopt, retry_count, timeout); + combinedopt, task_attr, retry_count, + timeout); break; case CAM_CMD_REPORTLUNS: error = scsireportluns(cam_dev, argc, argv, - combinedopt, retry_count, - timeout); + combinedopt, task_attr, + retry_count, timeout); break; case CAM_CMD_READCAP: error = scsireadcapacity(cam_dev, argc, argv, - combinedopt, retry_count, - timeout); + combinedopt, task_attr, + retry_count, timeout); break; case CAM_CMD_IDLE: case CAM_CMD_STANDBY: @@ -9306,25 +9374,30 @@ main(int argc, char **argv) break; case CAM_CMD_DOWNLOAD_FW: error = fwdownload(cam_dev, argc, argv, combinedopt, - arglist & CAM_ARG_VERBOSE, retry_count, timeout); + arglist & CAM_ARG_VERBOSE, task_attr, retry_count, + timeout); break; case CAM_CMD_SANITIZE: error = scsisanitize(cam_dev, argc, argv, - combinedopt, retry_count, timeout); + combinedopt, task_attr, + retry_count, timeout); break; case CAM_CMD_PERSIST: error = scsipersist(cam_dev, argc, argv, combinedopt, - retry_count, timeout, arglist & CAM_ARG_VERBOSE, + task_attr, retry_count, timeout, + arglist & CAM_ARG_VERBOSE, arglist & CAM_ARG_ERR_RECOVER); break; case CAM_CMD_ATTRIB: error = scsiattrib(cam_dev, argc, argv, combinedopt, - retry_count, timeout, arglist & CAM_ARG_VERBOSE, + task_attr, retry_count, timeout, + arglist & CAM_ARG_VERBOSE, arglist & CAM_ARG_ERR_RECOVER); break; case CAM_CMD_OPCODES: error = scsiopcodes(cam_dev, argc, argv, combinedopt, - retry_count, timeout, arglist & CAM_ARG_VERBOSE); + task_attr, retry_count, timeout, + arglist & CAM_ARG_VERBOSE); break; case CAM_CMD_REPROBE: error = scsireprobe(cam_dev); Modified: stable/10/sbin/camcontrol/camcontrol.h ============================================================================== --- stable/10/sbin/camcontrol/camcontrol.h Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/camcontrol.h Fri Feb 24 20:51:39 2017 (r314221) @@ -71,29 +71,32 @@ void build_ata_cmd(union ccb *ccb, uint3 camcontrol_devtype devtype); int camxferrate(struct cam_device *device); int fwdownload(struct cam_device *device, int argc, char **argv, - char *combinedopt, int printerrors, int retry_count, - int timeout); + char *combinedopt, int printerrors, int task_attr, + int retry_count, int timeout); void mode_sense(struct cam_device *device, int dbd, int pc, int page, - int subpage, int retry_count, int timeout, uint8_t *data, - int datalen); -void mode_select(struct cam_device *device, int save_pages, int retry_count, - int timeout, u_int8_t *data, int datalen); -void mode_edit(struct cam_device *device, int dbd, int pc, int page, int subpage, - int edit, int binary, int retry_count, int timeout); -void mode_list(struct cam_device *device, int dbd, int pc, int subpages, + int subpage, int task_attr, int retry_count, int timeout, + uint8_t *data, int datalen); +void mode_select(struct cam_device *device, int save_pages, int task_attr, + int retry_count, int timeout, u_int8_t *data, int datalen); +void mode_edit(struct cam_device *device, int dbd, int pc, int page, + int subpage, int edit, int binary, int task_attr, int retry_count, int timeout); +void mode_list(struct cam_device *device, int dbd, int pc, int subpages, + int task_attr, int retry_count, int timeout); int scsidoinquiry(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout); + char *combinedopt, int task_attr, int retry_count, + int timeout); int scsigetopcodes(struct cam_device *device, int opcode_set, int opcode, int show_sa_errors, int sa_set, int service_action, - int timeout_desc, int retry_count, int timeout, - int verbosemode, uint32_t *fill_len, uint8_t **data_ptr); + int timeout_desc, int task_attr, int retry_count, + int timeout, int verbosemode, uint32_t *fill_len, + uint8_t **data_ptr); int scsipersist(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout, int verbose, - int err_recover); + char *combinedopt, int task_attr, int retry_count, + int timeout, int verbose, int err_recover); int scsiattrib(struct cam_device *device, int argc, char **argv, - char *combinedopt, int retry_count, int timeout, int verbose, - int err_recover); + char *combinedopt, int task_attr, int retry_count, int timeout, + int verbose, int err_recover); char *cget(void *hook, char *name); int iget(void *hook, char *name); void arg_put(void *hook, int letter, void *arg, int count, char *name); Modified: stable/10/sbin/camcontrol/fwdownload.c ============================================================================== --- stable/10/sbin/camcontrol/fwdownload.c Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/fwdownload.c Fri Feb 24 20:51:39 2017 (r314221) @@ -263,7 +263,7 @@ static const struct fw_timeout_desc fw_t static struct fw_vendor *fw_get_vendor(struct cam_device *cam_dev, struct ata_params *ident_buf); static int fw_get_timeout(struct cam_device *cam_dev, struct fw_vendor *vp, - int retry_count, int timeout); + int task_attr, int retry_count, int timeout); static int fw_validate_ibm(struct cam_device *dev, int retry_count, int timeout, int fd, char *buf, const char *fw_img_path, int quiet); @@ -317,7 +317,7 @@ fw_get_vendor(struct cam_device *cam_dev static int fw_get_timeout(struct cam_device *cam_dev, struct fw_vendor *vp, - int retry_count, int timeout) + int task_attr, int retry_count, int timeout) { struct scsi_report_supported_opcodes_one *one; struct scsi_report_supported_opcodes_timeout *td; @@ -349,6 +349,7 @@ fw_get_timeout(struct cam_device *cam_de /*sa_set*/ 0, /*service_action*/ 0, /*timeout_desc*/ 1, + /*task_attr*/ task_attr, /*retry_count*/ retry_count, /*timeout*/ 10000, /*verbose*/ 0, @@ -901,7 +902,8 @@ bailout: int fwdownload(struct cam_device *device, int argc, char **argv, - char *combinedopt, int printerrors, int retry_count, int timeout) + char *combinedopt, int printerrors, int task_attr, int retry_count, + int timeout) { struct fw_vendor *vp; char *fw_img_path = NULL; @@ -976,7 +978,7 @@ fwdownload(struct cam_device *device, in && (devtype == CC_DT_SCSI)) errx(1, "Unsupported device"); - retval = fw_get_timeout(device, vp, retry_count, timeout); + retval = fw_get_timeout(device, vp, task_attr, retry_count, timeout); if (retval != 0) { warnx("Unable to get a firmware download timeout value"); goto bailout; @@ -994,8 +996,8 @@ fwdownload(struct cam_device *device, in " into the following device:\n", fw_img_path); if (devtype == CC_DT_SCSI) { - if (scsidoinquiry(device, argc, argv, combinedopt, 0, - 5000) != 0) { + if (scsidoinquiry(device, argc, argv, combinedopt, + MSG_SIMPLE_Q_TAG, 0, 5000) != 0) { warnx("Error sending inquiry"); retval = 1; goto bailout; Modified: stable/10/sbin/camcontrol/modeedit.c ============================================================================== --- stable/10/sbin/camcontrol/modeedit.c Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/modeedit.c Fri Feb 24 20:51:39 2017 (r314221) @@ -106,10 +106,11 @@ static int editentry_set(char *name, c int editonly); static void editlist_populate(struct cam_device *device, int dbd, int pc, int page, int subpage, - int retries, int timeout); + int task_attr, int retries, + int timeout); static void editlist_save(struct cam_device *device, int dbd, int pc, int page, int subpage, - int retries, int timeout); + int task_attr, int retries, int timeout); static void nameentry_create(int page, int subpage, char *name); static struct pagename *nameentry_lookup(int page, int subpage); static int load_format(const char *pagedb_path, int lpage, @@ -118,8 +119,8 @@ static int modepage_write(FILE *file, static int modepage_read(FILE *file); static void modepage_edit(void); static void modepage_dump(struct cam_device *device, int dbd, - int pc, int page, int subpage, int retries, - int timeout); + int pc, int page, int subpage, int task_attr, + int retries, int timeout); static void cleanup_editfile(void); @@ -550,7 +551,7 @@ load_format(const char *pagedb_path, int static void editlist_populate(struct cam_device *device, int dbd, int pc, int page, - int subpage, int retries, int timeout) + int subpage, int task_attr, int retries, int timeout) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ @@ -562,8 +563,8 @@ editlist_populate(struct cam_device *dev STAILQ_INIT(&editlist); /* Fetch changeable values; use to build initial editlist. */ - mode_sense(device, dbd, 1, page, subpage, retries, timeout, data, - sizeof(data)); + mode_sense(device, dbd, 1, page, subpage, task_attr, retries, timeout, + data, sizeof(data)); mh = (struct scsi_mode_header_6 *)data; mph = MODE_PAGE_HEADER(mh); @@ -581,14 +582,14 @@ editlist_populate(struct cam_device *dev buff_decode_visit(mode_pars, len, format, editentry_create, 0); /* Fetch the current/saved values; use to set editentry values. */ - mode_sense(device, dbd, pc, page, subpage, retries, timeout, + mode_sense(device, dbd, pc, page, subpage, task_attr, retries, timeout, data, sizeof(data)); buff_decode_visit(mode_pars, len, format, editentry_update, 0); } static void editlist_save(struct cam_device *device, int dbd, int pc, int page, - int subpage, int retries, int timeout) + int subpage, int task_attr, int retries, int timeout) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ @@ -602,7 +603,7 @@ editlist_save(struct cam_device *device, return; /* Preload the CDB buffer with the current mode page data. */ - mode_sense(device, dbd, pc, page, subpage, retries, timeout, + mode_sense(device, dbd, pc, page, subpage, task_attr, retries, timeout, data, sizeof(data)); /* Initial headers & offsets. */ @@ -639,7 +640,8 @@ editlist_save(struct cam_device *device, * recorded. */ mode_select(device, (pc << PAGE_CTRL_SHIFT == SMS_PAGE_CTRL_SAVED), - retries, timeout, (u_int8_t *)mh, sizeof(*mh) + hlen + len); + task_attr, retries, timeout, (u_int8_t *)mh, + sizeof(*mh) + hlen + len); } static int @@ -809,7 +811,7 @@ modepage_edit(void) static void modepage_dump(struct cam_device *device, int dbd, int pc, int page, int subpage, - int retries, int timeout) + int task_attr, int retries, int timeout) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ @@ -818,7 +820,7 @@ modepage_dump(struct cam_device *device, struct scsi_mode_page_header_sp *mphsp; size_t indx, len; - mode_sense(device, dbd, pc, page, subpage, retries, timeout, + mode_sense(device, dbd, pc, page, subpage, task_attr, retries, timeout, data, sizeof(data)); mh = (struct scsi_mode_header_6 *)data; @@ -853,7 +855,7 @@ cleanup_editfile(void) void mode_edit(struct cam_device *device, int dbd, int pc, int page, int subpage, - int edit, int binary, int retry_count, int timeout) + int edit, int binary, int task_attr, int retry_count, int timeout) { const char *pagedb_path; /* Path to modepage database. */ @@ -884,8 +886,8 @@ mode_edit(struct cam_device *device, int exit(EX_OSFILE); } - editlist_populate(device, dbd, pc, page, subpage, retry_count, - timeout); + editlist_populate(device, dbd, pc, page, subpage, task_attr, + retry_count, timeout); } if (edit) { @@ -894,10 +896,12 @@ mode_edit(struct cam_device *device, int errx(EX_USAGE, "it only makes sense to edit page 0 " "(current) or page 3 (saved values)"); modepage_edit(); - editlist_save(device, dbd, pc, page, subpage, retry_count, timeout); + editlist_save(device, dbd, pc, page, subpage, task_attr, + retry_count, timeout); } else if (binary || STAILQ_EMPTY(&editlist)) { /* Display without formatting information. */ - modepage_dump(device, dbd, pc, page, subpage, retry_count, timeout); + modepage_dump(device, dbd, pc, page, subpage, task_attr, + retry_count, timeout); } else { /* Display with format. */ modepage_write(stdout, 0); @@ -906,7 +910,7 @@ mode_edit(struct cam_device *device, int void mode_list(struct cam_device *device, int dbd, int pc, int subpages, - int retry_count, int timeout) + int task_attr, int retry_count, int timeout) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ struct scsi_mode_header_6 *mh; /* Location of mode header. */ @@ -927,7 +931,7 @@ mode_list(struct cam_device *device, int /* Build the list of all mode pages by querying the "all pages" page. */ mode_sense(device, dbd, pc, SMS_ALL_PAGES_PAGE, subpages ? SMS_SUBPAGE_ALL : 0, - retry_count, timeout, data, sizeof(data)); + task_attr, retry_count, timeout, data, sizeof(data)); mh = (struct scsi_mode_header_6 *)data; len = sizeof(*mh) + mh->blk_desc_len; /* Skip block descriptors. */ Modified: stable/10/sbin/camcontrol/persist.c ============================================================================== --- stable/10/sbin/camcontrol/persist.c Fri Feb 24 20:47:56 2017 (r314220) +++ stable/10/sbin/camcontrol/persist.c Fri Feb 24 20:51:39 2017 (r314221) @@ -423,7 +423,8 @@ persist_print_full(struct scsi_per_res_i int scsipersist(struct cam_device *device, int argc, char **argv, char *combinedopt, - int retry_count, int timeout, int verbosemode, int err_recover) + int task_attr, int retry_count, int timeout, int verbosemode, + int err_recover) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***