Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev Add reading of supported opcodes and their timeouts
details: https://anonhg.NetBSD.org/src/rev/5332fd86b0be
branches: trunk
changeset: 449902:5332fd86b0be
user: kardel <kardel%NetBSD.org@localhost>
date: Thu Mar 28 10:44:29 2019 +0000
description:
Add reading of supported opcodes and their timeouts
at attachment time. Though this information is optional,
it allows to override our fixed timeouts with device
provided timeouts. These timeouts will override the
hardcoded values if the device provided timeouts
exceed the hardcoded values and are less than a day.
Using the device provided timeouts avoids premature
device resets and unreliable operation due to
inadequate timeouts.
Due to the limited implementations of USB
umass devices this feature is disabled for all
umass attached devices.
diffstat:
sys/dev/scsipi/scsi_spc.h | 66 +++++++++++++-
sys/dev/scsipi/scsiconf.c | 19 ++-
sys/dev/scsipi/scsipi_base.c | 206 +++++++++++++++++++++++++++++++++++++++++-
sys/dev/scsipi/scsipiconf.c | 6 +-
sys/dev/scsipi/scsipiconf.h | 33 ++++++-
sys/dev/usb/umass_scsipi.c | 7 +-
6 files changed, 317 insertions(+), 20 deletions(-)
diffs (truncated from 513 to 300 lines):
diff -r d8ef641a63cf -r 5332fd86b0be sys/dev/scsipi/scsi_spc.h
--- a/sys/dev/scsipi/scsi_spc.h Thu Mar 28 08:56:55 2019 +0000
+++ b/sys/dev/scsipi/scsi_spc.h Thu Mar 28 10:44:29 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: scsi_spc.h,v 1.5 2010/02/06 23:13:59 cegger Exp $ */
+/* $NetBSD: scsi_spc.h,v 1.6 2019/03/28 10:44:29 kardel Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -406,6 +406,70 @@
*/
/*
+ * MAINTENANCE_IN[REPORT SUPPORTED OPERATION CODES]
+ */
+#define SCSI_MAINTENANCE_IN 0xA3
+
+struct scsi_repsuppopcode {
+ u_int8_t opcode;
+ u_int8_t svcaction;
+#define RSOC_REPORT_SUPPORTED_OPCODES 0x0C
+
+ u_int8_t repoption;
+#define RSOC_ALL 0x00 /* report all */
+#define RSOC_ONE 0x01 /* report one */
+#define RSOC_ONESACD 0x02 /* report one or CHECK CONDITION */
+#define RSOC_ONESA 0x03 /* report one mark presense in data */
+#define RSOC_RCTD 0x80 /* report timeouts */
+
+ u_int8_t reqopcode;
+ u_int8_t reqsvcaction[2];
+ u_int8_t alloclen[4];
+ u_int8_t _res0;
+ u_int8_t control;
+};
+
+struct scsi_repsupopcode_all_commands_descriptor {
+ u_int8_t opcode;
+ u_int8_t _res0;
+ u_int8_t serviceaction[2];
+ u_int8_t _res1;
+ u_int8_t flags;
+#define RSOC_ACD_CTDP 0x02 /* timeouts present */
+#define RSOC_ACD_SERVACTV 0x01 /* service action valid */
+ u_int8_t cdblen[2];
+};
+
+struct scsi_repsupopcode_one_command_descriptor {
+ u_int8_t _res0;
+ u_int8_t support;
+#define RSOC_OCD_CTDP 0x80 /* timeouts present */
+#define RSOC_OCD_SUP_NOT_AVAIL 0x00 /* not available */
+#define RSOC_OCD_SUP_NOT_SUPP 0x01 /* not supported */
+#define RSOC_OCD_SUP_SUPP_STD 0x03 /* supported - standard */
+#define RSOC_OCD_SUP_SUPP_VENDOR 0x05 /* supported - vendor */
+#define RSOC_OCD_SUP 0x07 /* mask for support field */
+
+ u_int8_t cdblen[2];
+ /*
+ * u_int8_t usage[0...]- cdblen bytes
+ * usage data
+ */
+ /*
+ * scsi_repsupopcode_timeouts_descriptor
+ * if RSOC_OCD_CTDP is set
+ */
+};
+
+struct scsi_repsupopcode_timeouts_descriptor {
+ u_int8_t descriptor_length[2];
+ u_int8_t _res0;
+ u_int8_t cmd_specific;
+ u_int8_t nom_process_timeout[4];
+ u_int8_t cmd_process_timeout[4];
+};
+
+/*
* REQUEST SENSE
*/
diff -r d8ef641a63cf -r 5332fd86b0be sys/dev/scsipi/scsiconf.c
--- a/sys/dev/scsipi/scsiconf.c Thu Mar 28 08:56:55 2019 +0000
+++ b/sys/dev/scsipi/scsiconf.c Thu Mar 28 10:44:29 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: scsiconf.c,v 1.283 2019/01/12 13:59:53 tsutsui Exp $ */
+/* $NetBSD: scsiconf.c,v 1.284 2019/03/28 10:44:29 kardel Exp $ */
/*-
* Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.283 2019/01/12 13:59:53 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.284 2019/03/28 10:44:29 kardel Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -500,9 +500,11 @@
strnvisx(revision, sizeof(revision), inqbuf->revision, 4,
VIS_TRIM|VIS_SAFE|VIS_OCTAL);
- aprint_normal(" target %d lun %d: <%s, %s, %s> %s %s",
- target, lun, vendor, product, revision, dtype,
- inqbuf->removable ? "removable" : "fixed");
+ aprint_normal(" target %d lun %d: <%s, %s, %s> %s %s%s",
+ target, lun, vendor, product, revision, dtype,
+ inqbuf->removable ? "removable" : "fixed",
+ (sa->sa_periph->periph_opcs != NULL)
+ ? " timeout-info" : "");
return (UNCONF);
}
@@ -1018,6 +1020,13 @@
if ((cf = config_search_loc(config_stdsubmatch, sc->sc_dev,
"scsibus", locs, &sa)) != NULL) {
scsipi_insert_periph(chan, periph);
+
+ /*
+ * determine supported opcodes and
+ * timeouts if available
+ */
+ scsipi_get_opcodeinfo(periph);
+
/*
* XXX Can't assign periph_dev here, because we'll
* XXX need it before config_attach() returns. Must
diff -r d8ef641a63cf -r 5332fd86b0be sys/dev/scsipi/scsipi_base.c
--- a/sys/dev/scsipi/scsipi_base.c Thu Mar 28 08:56:55 2019 +0000
+++ b/sys/dev/scsipi/scsipi_base.c Thu Mar 28 10:44:29 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: scsipi_base.c,v 1.181 2019/02/05 11:11:32 mrg Exp $ */
+/* $NetBSD: scsipi_base.c,v 1.182 2019/03/28 10:44:29 kardel Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.181 2019/02/05 11:11:32 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.182 2019/03/28 10:44:29 kardel Exp $");
#ifdef _KERNEL_OPT
#include "opt_scsi.h"
@@ -84,6 +84,8 @@
static void scsipi_adapter_lock(struct scsipi_adapter *adapt);
static void scsipi_adapter_unlock(struct scsipi_adapter *adapt);
+static void scsipi_update_timeouts(struct scsipi_xfer *xs);
+
static struct pool scsipi_xfer_pool;
int scsipi_xs_count = 0;
@@ -860,7 +862,7 @@
sense = &xs->sense.scsi_sense;
#ifdef SCSIPI_DEBUG
if (periph->periph_flags & SCSIPI_DB1) {
- int count;
+ int count, len;
scsipi_printaddr(periph);
printf(" sense debug information:\n");
printf("\tcode 0x%x valid %d\n",
@@ -879,8 +881,9 @@
sense->info[2],
sense->info[3],
sense->extra_len);
- printf("\textra: ");
- for (count = 0; count < SSD_ADD_BYTES_LIM(sense); count++)
+ len = SSD_ADD_BYTES_LIM(sense);
+ printf("\textra (up to %d bytes): ", len);
+ for (count = 0; count < len; count++)
printf("0x%x ", sense->csi[count]);
printf("\n");
}
@@ -1354,6 +1357,197 @@
}
/*
+ * scsipi_get_opcodeinfo:
+ *
+ * query the device for supported commends and their timeout
+ * building a timeout lookup table if timeout information is available.
+ */
+void
+scsipi_get_opcodeinfo(struct scsipi_periph *periph)
+{
+ u_int8_t *data;
+ int len = 16*1024;
+ int rc;
+ struct scsi_repsuppopcode cmd;
+
+ /* refrain from asking for supported opcodes */
+ if (periph->periph_quirks & PQUIRK_NOREPSUPPOPC ||
+ periph->periph_type == T_PROCESSOR || /* spec. */
+ periph->periph_type == T_CDROM) /* spec. */
+ return;
+
+ scsipi_free_opcodeinfo(periph);
+
+ /*
+ * query REPORT SUPPORTED OPERATION CODES
+ * if OK
+ * enumerate all codes
+ * if timeout exists insert maximum into opcode table
+ */
+
+ data = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (data == NULL) {
+ SC_DEBUG(periph, SCSIPI_DB3,
+ ("unable to allocate data buffer "
+ "for REPORT SUPPORTED OPERATION CODES\n"));
+ return;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ cmd.opcode = SCSI_MAINTENANCE_IN;
+ cmd.svcaction = RSOC_REPORT_SUPPORTED_OPCODES;
+ cmd.repoption = RSOC_RCTD|RSOC_ALL;
+ _lto4b(len, cmd.alloclen);
+
+ rc = scsipi_command(periph, (void *)&cmd, sizeof(cmd),
+ (void *)data, len, 0, 1000, NULL,
+ XS_CTL_DATA_IN|XS_CTL_SILENT);
+
+ if (rc == 0) {
+ int count;
+ int dlen = _4btol(data);
+ u_int8_t *c = data + 4;
+
+ SC_DEBUG(periph, SCSIPI_DB3,
+ ("supported opcode timeout-values loaded\n"));
+ SC_DEBUG(periph, SCSIPI_DB3,
+ ("CMD LEN SA spec nom. time cmd timeout\n"));
+
+ struct scsipi_opcodes *tot =
+ (struct scsipi_opcodes *)malloc(sizeof(struct scsipi_opcodes),
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ count = 0;
+ while (tot != NULL &&
+ dlen >= (int)sizeof(struct scsi_repsupopcode_all_commands_descriptor)) {
+ struct scsi_repsupopcode_all_commands_descriptor *acd
+ = (struct scsi_repsupopcode_all_commands_descriptor *)c;
+#ifdef SCSIPI_DEBUG
+ int cdblen = _2btol((const u_int8_t *)&acd->cdblen);
+#endif
+ dlen -= sizeof(struct scsi_repsupopcode_all_commands_descriptor);
+ c += sizeof(struct scsi_repsupopcode_all_commands_descriptor);
+ SC_DEBUG(periph, SCSIPI_DB3,
+ ("0x%02x(%2d) ", acd->opcode, cdblen));
+
+ tot->opcode_info[acd->opcode].ti_flags = SCSIPI_TI_VALID;
+
+ if (acd->flags & RSOC_ACD_SERVACTV) {
+ SC_DEBUGN(periph, SCSIPI_DB3,
+ ("0x%02x%02x ",
+ acd->serviceaction[0],
+ acd->serviceaction[1]));
+ } else {
+ SC_DEBUGN(periph, SCSIPI_DB3, (" "));
+ }
+
+ if (acd->flags & RSOC_ACD_CTDP
+ && dlen >= (int)sizeof(struct scsi_repsupopcode_timeouts_descriptor)) {
+ struct scsi_repsupopcode_timeouts_descriptor *td
+ = (struct scsi_repsupopcode_timeouts_descriptor *)c;
+ long nomto = _4btol(td->nom_process_timeout);
+ long cmdto = _4btol(td->cmd_process_timeout);
+ long t = (cmdto > nomto) ? cmdto : nomto;
+
+ dlen -= sizeof(struct scsi_repsupopcode_timeouts_descriptor);
+ c += sizeof(struct scsi_repsupopcode_timeouts_descriptor);
+
+ SC_DEBUGN(periph, SCSIPI_DB3,
+ ("0x%02x %10ld %10ld",
+ td->cmd_specific,
+ nomto, cmdto));
+
+ if (t > tot->opcode_info[acd->opcode].ti_timeout) {
+ tot->opcode_info[acd->opcode].ti_timeout = t;
+ ++count;
+ }
+ }
+ SC_DEBUGN(periph, SCSIPI_DB3,("\n"));
+ }
+
+ if (count > 0) {
+ periph->periph_opcs = tot;
+ } else {
+ free(tot, M_DEVBUF);
+ SC_DEBUG(periph, SCSIPI_DB3,
+ ("no usable timeout values available\n"));
+ }
+ } else {
+ SC_DEBUG(periph, SCSIPI_DB3,
+ ("SCSI_MAINTENANCE_IN"
+ "[RSOC_REPORT_SUPPORTED_OPCODES] failed error=%d"
+ " - no device provided timeout "
Home |
Main Index |
Thread Index |
Old Index