summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorGavin Maltby <Gavin.Maltby@Sun.COM>2010-04-22 17:44:11 +1000
committerGavin Maltby <Gavin.Maltby@Sun.COM>2010-04-22 17:44:11 +1000
commit392e836b07e8da771953e4d64233b2abe4393efe (patch)
tree86ab03dfb47574bf1e433d66bb90ee853efd78f3 /usr/src
parent8d7fafffed373567f52062b634e61fd50858b8d9 (diff)
downloadillumos-gate-392e836b07e8da771953e4d64233b2abe4393efe.tar.gz
6935519 raise telemetry for failed scsa-initiated enumeration commands
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/fm/modules/common/eversholt/platform.c2
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/dev.c190
-rw-r--r--usr/src/lib/fm/topo/libtopo/common/topo_hc.h2
-rw-r--r--usr/src/uts/common/io/pciex/pcie_fault.c4
-rw-r--r--usr/src/uts/common/io/scsi/conf/scsi_confsubr.c797
-rw-r--r--usr/src/uts/common/io/scsi/impl/scsi_fm.c39
-rw-r--r--usr/src/uts/common/io/scsi/impl/scsi_hba.c24
-rw-r--r--usr/src/uts/common/io/scsi/targets/sd.c49
-rw-r--r--usr/src/uts/common/os/ddifm.c43
-rw-r--r--usr/src/uts/common/os/devid_cache.c185
-rw-r--r--usr/src/uts/common/os/fm.c52
-rw-r--r--usr/src/uts/common/os/pcifm.c5
-rw-r--r--usr/src/uts/common/sys/fm/protocol.h6
-rw-r--r--usr/src/uts/common/sys/scsi/scsi_fm.h6
-rw-r--r--usr/src/uts/sun4u/io/pci/pci_ecc.c48
-rw-r--r--usr/src/uts/sun4u/io/pci/pcisch.c6
-rw-r--r--usr/src/uts/sun4u/opl/io/mc-opl.c6
17 files changed, 1179 insertions, 285 deletions
diff --git a/usr/src/cmd/fm/modules/common/eversholt/platform.c b/usr/src/cmd/fm/modules/common/eversholt/platform.c
index 2c2fca684a..2c9b40e632 100644
--- a/usr/src/cmd/fm/modules/common/eversholt/platform.c
+++ b/usr/src/cmd/fm/modules/common/eversholt/platform.c
@@ -261,7 +261,7 @@ platform_getpath(nvlist_t *nvl)
if (nvlist_lookup_string(dfmri,
FM_FMRI_DEV_ID, &devid) == 0)
type = DT_DEVID;
- else if (nvlist_lookup_string(nvl,
+ else if (nvlist_lookup_string(dfmri,
TOPO_STORAGE_TARGET_PORT_L0ID, &tp) == 0)
type = DT_TP;
else if (nvlist_lookup_string(dfmri,
diff --git a/usr/src/lib/fm/topo/libtopo/common/dev.c b/usr/src/lib/fm/topo/libtopo/common/dev.c
index b87b287997..f71e124f94 100644
--- a/usr/src/lib/fm/topo/libtopo/common/dev.c
+++ b/usr/src/lib/fm/topo/libtopo/common/dev.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <limits.h>
@@ -128,26 +127,23 @@ dev_release(topo_mod_t *mod, tnode_t *node)
static ssize_t
fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
{
- nvlist_t *anvl = NULL;
- nvpair_t *apair;
- uint8_t version;
- ssize_t size = 0;
- char *devid = NULL;
+ char *devid = NULL, *tpl0id = NULL;
char *devpath = NULL;
- char *aname, *aval;
+ ssize_t size = 0;
+ uint8_t version;
int err;
if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 ||
version > FM_DEV_SCHEME_VERSION)
return (-1);
- /* Get authority, if present */
- err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl);
+ /* Get devid, if present */
+ err = nvlist_lookup_string(nvl, FM_FMRI_DEV_ID, &devid);
if (err != 0 && err != ENOENT)
return (-1);
- /* Get devid, if present */
- err = nvlist_lookup_string(nvl, FM_FMRI_DEV_ID, &devid);
+ /* Get target-port-l0id, if present */
+ err = nvlist_lookup_string(nvl, FM_FMRI_DEV_TGTPTLUN0, &tpl0id);
if (err != 0 && err != ENOENT)
return (-1);
@@ -156,31 +152,40 @@ fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
if (err != 0 || devpath == NULL)
return (-1);
-
- /* dev:// */
+ /*
+ * dev:///
+ *
+ * The dev scheme does not render fmri authority information
+ * in the string form of an fmri. It is meaningless to
+ * transmit a dev scheme fmri outside of the immediate fault
+ * manager.
+ */
topo_fmristr_build(&size,
- buf, buflen, FM_FMRI_SCHEME_DEV, NULL, "://");
-
- /* authority, if any */
- if (anvl != NULL) {
- for (apair = nvlist_next_nvpair(anvl, NULL);
- apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) {
- if (nvpair_type(apair) != DATA_TYPE_STRING ||
- nvpair_value_string(apair, &aval) != 0)
- continue;
- aname = nvpair_name(apair);
- topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL);
- topo_fmristr_build(&size, buf, buflen, "=",
- aname, aval);
- }
- }
+ buf, buflen, FM_FMRI_SCHEME_DEV, NULL, ":///");
/* device-id part, topo_fmristr_build does nothing if devid is NULL */
topo_fmristr_build(&size,
- buf, buflen, devid, "/:" FM_FMRI_DEV_ID "=", NULL);
+ buf, buflen, devid, ":" FM_FMRI_DEV_ID "=", NULL);
+
+ /* target-port-l0id part */
+ topo_fmristr_build(&size,
+ buf, buflen, tpl0id, ":" FM_FMRI_DEV_TGTPTLUN0 "=", NULL);
- /* device-path part */
- topo_fmristr_build(&size, buf, buflen, devpath, "/", NULL);
+ /*
+ * device-path part; the devpath should always start with a /
+ * so you'd think we don't need to add a further / prefix here;
+ * however past implementation has always added the / if
+ * there is a devid component so we continue to do that
+ * so strings match exactly as before. So we can have:
+ *
+ * dev:////pci@0,0/...
+ * dev:///<devid-and-tpl0>//pci@0,0/...
+ *
+ * where <devid-and-tpl0> =
+ * [:devid=<devid>][:target-port-l0id=<tpl0>]
+ */
+ topo_fmristr_build(&size, buf, buflen, devpath,
+ devid || tpl0id ? "/" : NULL, NULL);
return (size);
}
@@ -223,10 +228,11 @@ static int
dev_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version,
nvlist_t *in, nvlist_t **out)
{
+ char *cur, *devid = NULL, *tpl0id = NULL;
+ char *str, *strcp;
nvlist_t *fmri;
char *devpath;
- char *devid = NULL;
- char *str;
+ size_t len;
int err;
if (version > TOPO_METH_STR2NVL_VERSION)
@@ -235,42 +241,124 @@ dev_fmri_str2nvl(topo_mod_t *mod, tnode_t *node, topo_version_t version,
if (nvlist_lookup_string(in, "fmri-string", &str) != 0)
return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
- /* We're expecting a string version of a dev scheme FMRI */
- if (strncmp(str, "dev:///", 7) != 0)
+ len = strlen(str);
+
+ /*
+ * We're expecting a string version of a dev scheme FMRI, and
+ * no fmri authority information.
+ *
+ * The shortest legal string would be "dev:////" (len 8) for a string
+ * with no FMRI auth info, no devid or target-port-l0id and
+ * an empty devpath string.
+ */
+ if (len < 8 || strncmp(str, "dev:///", 7) != 0)
return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
- devpath = str + 7;
- if (strncmp(devpath, ":" FM_FMRI_DEV_ID "=", 7) == 0) {
- char *n;
- int len;
+ strcp = alloca(len + 1);
+ (void) memcpy(strcp, str, len);
+ strcp[len] = '\0';
+ cur = strcp + 7; /* already parsed "dev:///" */
- n = strchr(devpath + 7, '/');
- if (n == NULL)
+ /*
+ * If the first character after the "/" that terminates the (empty)
+ * fmri authority is a colon then we have devid and/or target-port-l0id
+ * info. They could be in either order.
+ *
+ * If not a colon then it must be the / that begins the devpath.
+ */
+ if (*cur == ':') {
+ char *eos, *part[2];
+ int i;
+ /*
+ * Look ahead to the "/" that starts the devpath. If not
+ * found or if straight after the : then we're busted.
+ */
+ eos = devpath = strchr(cur, '/');
+ if (devpath == NULL || devpath == cur + 1)
+ return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
+
+ part[0] = ++cur;
+
+ /*
+ * Replace the initial "/" of the devpath with a NUL
+ * to terminate the string before it. We'll undo this
+ * before rendering devpath.
+ */
+ *eos = '\0';
+
+ /*
+ * We should now have a NUL-terminated string matching
+ * foo=<pat1>[:bar=<pat2>] (we stepped over the initial :)
+ * Look for a second colon; if found there must be space
+ * after it for the additional component, but no more colons.
+ */
+ if ((part[1] = strchr(cur, ':')) != NULL) {
+ if (part[1] + 1 == eos ||
+ strchr(part[1] + 1, ':') != NULL)
+ return (topo_mod_seterrno(mod,
+ EMOD_FMRI_MALFORM));
+ *part[1] = '\0'; /* terminate part[0] */
+ part[1]++;
+ }
+
+ for (i = 0; i < 2; i++) {
+ char *eq;
+
+ if (!part[i])
+ continue;
+
+ if ((eq = strchr(part[i], '=')) == NULL ||
+ *(eq + 1) == '\0')
+ return (topo_mod_seterrno(mod,
+ EMOD_FMRI_MALFORM));
+
+ *eq = '\0';
+ if (strcmp(part[i], FM_FMRI_DEV_ID) == 0)
+ devid = eq + 1;
+ else if (strcmp(part[i], FM_FMRI_DEV_TGTPTLUN0) == 0)
+ tpl0id = eq + 1;
+ else
+ return (topo_mod_seterrno(mod,
+ EMOD_FMRI_MALFORM));
+ }
+
+ if (devid == NULL && tpl0id == NULL)
return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
- len = n - (devpath + 7);
- devid = alloca(len + 1);
- (void) memcpy(devid, devpath + 7, len);
- devid[len] = 0;
- devpath = n + 1;
- }
- /* the device-path should start with a slash */
- if (*devpath != '/')
+ cur = devpath; /* initial slash is NULled */
+ } else if (*cur != '/') {
+ /* the device-path should start with a slash */
return (topo_mod_seterrno(mod, EMOD_FMRI_MALFORM));
+ } else {
+ devpath = cur;
+ }
if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0)
return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
err = nvlist_add_uint8(fmri, FM_VERSION, FM_DEV_SCHEME_VERSION);
err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_DEV);
- err |= nvlist_add_string(fmri, FM_FMRI_DEV_PATH, devpath);
+
if (devid != NULL)
err |= nvlist_add_string(fmri, FM_FMRI_DEV_ID, devid);
+ if (tpl0id != NULL)
+ err |= nvlist_add_string(fmri, FM_FMRI_DEV_TGTPTLUN0, tpl0id);
+
+ if (devid != NULL || tpl0id != NULL)
+ *devpath = '/'; /* we NULed this earlier; put it back */
+
+ /* step over repeated initial / in the devpath */
+ while (*(devpath + 1) == '/')
+ devpath++;
+
+ err |= nvlist_add_string(fmri, FM_FMRI_DEV_PATH, devpath);
+
if (err != 0) {
nvlist_free(fmri);
return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
}
+
*out = fmri;
return (0);
diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h
index 67858ffd3e..5a6d095112 100644
--- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h
@@ -128,8 +128,6 @@ extern "C" {
#define TOPO_STORAGE_MANUFACTURER "manufacturer"
#define TOPO_STORAGE_MODEL "model"
#define TOPO_STORAGE_FIRMWARE_REV "firmware-revision"
-#define TOPO_STORAGE_TARGET_PORT_L0ID "target-port-l0id"
-#define TOPO_STORAGE_TARGET_PORT_L0IDS "target-port-l0ids"
#define TOPO_STORAGE_SAS_PHY_MASK "receptacle-pm"
#define TOPO_STORAGE_SAS_CONNECTOR_TYPE "sas-connector-type"
diff --git a/usr/src/uts/common/io/pciex/pcie_fault.c b/usr/src/uts/common/io/pciex/pcie_fault.c
index c17b4e97d7..a7eebd00c4 100644
--- a/usr/src/uts/common/io/pciex/pcie_fault.c
+++ b/usr/src/uts/common/io/pciex/pcie_fault.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/sysmacros.h>
@@ -2649,7 +2649,7 @@ pf_ereport_setup(dev_info_t *dip, uint64_t ena, nvlist_t **ereport,
}
fm_fmri_dev_set(*detector, FM_DEV_SCHEME_VERSION, NULL,
- device_path, NULL);
+ device_path, NULL, NULL);
if (ena == 0)
ena = fm_ena_generate(0, FM_ENA_FMT1);
diff --git a/usr/src/uts/common/io/scsi/conf/scsi_confsubr.c b/usr/src/uts/common/io/scsi/conf/scsi_confsubr.c
index 3d5c9d4b0a..1b2dc7ab52 100644
--- a/usr/src/uts/common/io/scsi/conf/scsi_confsubr.c
+++ b/usr/src/uts/common/io/scsi/conf/scsi_confsubr.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -34,6 +33,7 @@
#include <sys/scsi/scsi.h>
#include <sys/modctl.h>
#include <sys/bitmap.h>
+#include <sys/fm/protocol.h>
/*
* macro for filling in lun value for scsi-1 support
@@ -57,6 +57,31 @@ static struct modlinkage modlinkage = {
MODREV_1, (void *)&modlmisc, NULL
};
+/*
+ * Contexts from which we call scsi_test
+ */
+enum scsi_test_ctxt {
+ /*
+ * Those in scsi_hba_probe_pi()
+ */
+ STC_PROBE_FIRST_INQ,
+ STC_PROBE_FIRST_INQ_RETRY,
+ STC_PROBE_PARTIAL_SUCCESS,
+ STC_PROBE_RQSENSE1,
+ STC_PROBE_CHK_CLEARED,
+ STC_PROBE_RQSENSE2,
+ STC_PROBE_INQ_FINAL,
+ /*
+ * Those in check_vpd_page_support8083()
+ */
+ STC_VPD_CHECK,
+ /*
+ * Those in scsi_device_identity()
+ */
+ STC_IDENTITY_PG80,
+ STC_IDENTITY_PG83,
+};
+
static void create_inquiry_props(struct scsi_device *);
static int scsi_check_ss2_LUN_limit(struct scsi_device *);
@@ -67,7 +92,8 @@ static int check_vpd_page_support8083(struct scsi_device *sd,
int (*callback)(), int *, int *);
static int send_scsi_INQUIRY(struct scsi_device *sd,
int (*callback)(), uchar_t *bufaddr, size_t buflen,
- uchar_t evpd, uchar_t page_code, size_t *lenp);
+ uchar_t evpd, uchar_t page_code, size_t *lenp,
+ enum scsi_test_ctxt);
/*
* this int-array HBA-node property keeps track of strictly SCSI-2
@@ -138,6 +164,50 @@ int scsi_probe_debug = 0;
int scsi_test_busy_timeout = SCSI_POLL_TIMEOUT; /* in seconds */
int scsi_test_busy_delay = 10000; /* 10msec in usec */
+
+/*
+ * Returns from scsi_test.
+ *
+ * SCSI_TEST_CMPLT_GOOD => TRAN_ACCEPT, CMD_CMPLT, STATUS_GOOD
+ *
+ * SCSI_TEST_CMPLT_BUSY => TRAN_ACCEPT, CMD_CMPLT, STATUS_BUSY
+ *
+ * SCSI_TEST_CMPLT_CHECK => TRAN_ACCEPT, CMD_CMPLT, STATUS_CHECK
+ *
+ * SCSI_TEST_CMPLT_OTHER => TRAN_ACCEPT, CMD_CMPLT, !STATUS_{GOOD,BUSY,CHECK}
+ *
+ * SCSI_TEST_CMD_INCOMPLETE => TRAN_ACCEPT, CMD_INCOMPLETE
+ *
+ * SCSI_TEST_NOTCMPLT => TRAN_ACCEPT, pkt_reason != CMD_{CMPLT,INCOMPLETE}
+ *
+ * SCSI_TEST_TRAN_BUSY => (Repeated) TRAN_BUSY from attempt scsi_transport
+ *
+ * SCSI_TEST_TRAN_REJECT => TRAN_BADPKT or TRAN_FATAL_ERROR
+ *
+ */
+#define SCSI_TEST_CMPLT_GOOD 0x01U
+#define SCSI_TEST_CMPLT_BUSY 0x02U
+#define SCSI_TEST_CMPLT_CHECK 0x04U
+#define SCSI_TEST_CMPLT_OTHER 0x08U
+
+#define SCSI_TEST_CMPLTMASK \
+ (SCSI_TEST_CMPLT_GOOD | SCSI_TEST_CMPLT_BUSY | \
+ SCSI_TEST_CMPLT_CHECK | SCSI_TEST_CMPLT_OTHER)
+
+#define SCSI_TEST_PARTCMPLTMASK \
+ (SCSI_TEST_CMPLTMASK & ~SCSI_TEST_CMPLT_GOOD)
+
+#define SCSI_TEST_CMD_INCOMPLETE 0x10U
+#define SCSI_TEST_NOTCMPLT 0x20U
+#define SCSI_TEST_TRAN_BUSY 0x40U
+#define SCSI_TEST_TRAN_REJECT 0x80U
+
+#define SCSI_TEST_FAILMASK \
+ (SCSI_TEST_CMD_INCOMPLETE | SCSI_TEST_NOTCMPLT | \
+ SCSI_TEST_TRAN_BUSY | SCSI_TEST_TRAN_REJECT)
+
+#define SCSI_TEST_FAILURE(x) (((x) & SCSI_TEST_FAILMASK) != 0)
+
/*
* architecture dependent allocation restrictions. For x86, we'll set
* dma_attr_addr_hi to scsi_max_phys_addr and dma_attr_sgllen to
@@ -386,12 +456,454 @@ scsi_unprobe(struct scsi_device *sd)
}
/*
+ * We log all scsi_test failures (as long as we are SE_HP etc). The
+ * following table controls the "driver-assessment" payload item
+ * in the ereports we raise. If a scsi_test return features in the
+ * retry mask then the calling context will retry; if it features in
+ * the fatal mask then the caller will not retry (although higher-level
+ * software might); if in neither (which shouldn't happen - you either
+ * retry or give up) default to 'retry'.
+ */
+static const struct scsi_test_profile {
+ enum scsi_test_ctxt stp_ctxt; /* Calling context */
+ uint32_t stp_retrymask; /* Returns caller will retry for */
+ uint32_t stp_fatalmask; /* Returns caller considers fatal */
+} scsi_test_profile[] = {
+ /*
+ * This caller will retry on SCSI_TEST_FAILMASK as long as it was
+ * not SCSI_TEST_CMD_INCOMPLETE which is terminal. A return from
+ * SCSI_TEST_PARTCMPLTMASK (command complete but status other than
+ * STATUS_GOOD) is not terminal and we'll move on to the context
+ * of STC_PROBE_PARTIAL_SUCCESS so that's a retry, too.
+ */
+ {
+ STC_PROBE_FIRST_INQ,
+ SCSI_TEST_FAILMASK & ~SCSI_TEST_CMD_INCOMPLETE |
+ SCSI_TEST_PARTCMPLTMASK,
+ SCSI_TEST_CMD_INCOMPLETE
+ },
+
+ /*
+ * If the first inquiry fails outright we always retry just once
+ * (except for SCSI_TEST_CMD_INCOMPLETE as above). A return in
+ * SCSI_TEST_FAILMASK is terminal; for SCSI_TEST_PARTCMPLTMASK
+ * we will retry at STC_PROBE_PARTIAL_SUCCESS.
+ */
+ {
+ STC_PROBE_FIRST_INQ_RETRY,
+ SCSI_TEST_PARTCMPLTMASK,
+ SCSI_TEST_FAILMASK
+ },
+
+ /*
+ * If we've met with partial success we retry at caller context
+ * STC_PROBE_PARTIAL_SUCCESS. Any SCSI_TEST_FAILMASK return
+ * here is terminal, as too is SCSI_TEST_CMPLT_BUSY. A return in
+ * SCSI_TEST_PARTCMPLTMASK and we will continue with further
+ * inquiry attempts.
+ */
+ {
+ STC_PROBE_PARTIAL_SUCCESS,
+ SCSI_TEST_PARTCMPLTMASK & ~SCSI_TEST_CMPLT_BUSY,
+ SCSI_TEST_FAILMASK | SCSI_TEST_CMPLT_BUSY
+ },
+
+ /*
+ * If we get past the above target busy case then we will
+ * perform a sense request if scsi_test indicates STATUS_CHECK
+ * and ARQ was not done. We are not interested in logging telemetry
+ * for transports that do not perform ARQ automatically.
+ */
+ {
+ STC_PROBE_RQSENSE1,
+ 0,
+ 0
+ },
+
+ /*
+ * If "something" responded to the probe but then the next inquiry
+ * sees a change of heart then we fail the probe on any of
+ * SCSI_TEST_FAILMASK or SCSI_TEST_CMPLT_BUSY. For other values
+ * in SCSI_TEST_PARTCMPLTMASK we soldier on.
+ */
+ {
+ STC_PROBE_CHK_CLEARED,
+ SCSI_TEST_PARTCMPLTMASK & ~SCSI_TEST_CMPLT_BUSY,
+ SCSI_TEST_FAILMASK | SCSI_TEST_CMPLT_BUSY
+ },
+
+ /*
+ * If after all that there we still have STATUS_CHECK from the
+ * inquiry status then we resend the sense request but the
+ * result is ignored (just clearing the condition). Do not
+ * log.
+ */
+ {
+ STC_PROBE_RQSENSE2,
+ 0,
+ 0
+ },
+
+ /*
+ * After the above sense request we once again send an inquiry.
+ * If it fails outright or STATUS_CHECK persists we give up.
+ * Any partial result is considered success.
+ */
+ {
+ STC_PROBE_INQ_FINAL,
+ 0,
+ SCSI_TEST_FAILMASK | SCSI_TEST_CMPLT_CHECK
+ },
+
+ /*
+ * check_vpd_page_support8083 called from scsi_device_identity
+ * performs an inquiry with EVPD set (and page necessarily 0)
+ * to see what pages are supported.
+ *
+ * Some devices do not support this command and therefore
+ * check_vpd_page_support8083 only returns an error of kmem_zalloc
+ * fails. If the send_scsi_INQUIRY does not meet with complete
+ * success (SCSI_TEST_CMPLT_GOOD) it returns -1, othewise 0.
+ * So any scsi_test failure here will cause us to assume no page
+ * 80/83 support, and we will proceed without devid support.
+ * So -1 returns from send_scsi_INQUIRY are not terminal.
+ */
+ {
+ STC_VPD_CHECK,
+ 0,
+ 0
+ },
+
+ /*
+ * If the above inquiry claims pg80 support then scsi_device_identity
+ * will perform a send_scsi_INQUIRY to retrieve that page.
+ * Anything other than SCSI_TEST_CMPLT_GOOD is a failure and will
+ * cause scsi_device_identity to return non-zero at which point the
+ * caller goes to SCSIPROBE_FAILURE.
+ */
+ {
+ STC_IDENTITY_PG80,
+ 0,
+ SCSI_TEST_FAILMASK | SCSI_TEST_CMPLTMASK
+ },
+
+ /*
+ * Similarly for pg83
+ */
+ {
+ STC_IDENTITY_PG83,
+ 0,
+ SCSI_TEST_FAILMASK | SCSI_TEST_CMPLTMASK
+ }
+};
+
+int scsi_test_ereport_disable = 0;
+
+extern int e_devid_cache_path_to_devid(char *, char *, char *, ddi_devid_t *);
+
+static void
+scsi_test_ereport_post(struct scsi_pkt *pkt, enum scsi_test_ctxt ctxt,
+ uint32_t stresult)
+{
+ char *nodename = NULL, *devidstr_buf = NULL, *devidstr = NULL;
+ const struct scsi_test_profile *tp = &scsi_test_profile[ctxt];
+ char ua[SCSI_MAXNAMELEN], nodenamebuf[SCSI_MAXNAMELEN];
+ union scsi_cdb *cdbp = (union scsi_cdb *)pkt->pkt_cdbp;
+ struct scsi_address *ap = &pkt->pkt_address;
+ char *tgt_port, *tpl0 = NULL;
+ ddi_devid_t devid = NULL;
+ dev_info_t *probe, *hba;
+ struct scsi_device *sd;
+ scsi_lun64_t lun64;
+ const char *d_ass;
+ const char *class;
+ char *pathbuf;
+ nvlist_t *pl;
+ uint64_t wwn;
+ int err = 0;
+ int dad = 0;
+ size_t len;
+ int lun;
+
+ if (scsi_test_ereport_disable)
+ return;
+
+ ASSERT(tp->stp_ctxt == ctxt);
+
+ if ((sd = scsi_address_device(ap)) == NULL)
+ return; /* Not SCSI_HBA_ADDR_COMPLEX */
+
+ probe = sd->sd_dev;
+ hba = ddi_get_parent(probe);
+
+ /*
+ * We only raise telemetry for SE_HP style enumeration
+ */
+ if (!ndi_dev_is_hotplug_node(hba))
+ return;
+
+ /*
+ * scsi_fm_ereport_post will use the hba for the fm-enabled devinfo
+ */
+ if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(hba)))
+ return;
+
+ /*
+ * Retrieve the unit address we were probing and the target
+ * port component thereof.
+ */
+ if (!scsi_ua_get(sd, ua, sizeof (ua)) ||
+ scsi_device_prop_lookup_string(sd, SCSI_DEVICE_PROP_PATH,
+ SCSI_ADDR_PROP_TARGET_PORT, &tgt_port) != DDI_PROP_SUCCESS)
+ return;
+
+ /*
+ * Determine whether unit address is location based or identity (wwn)
+ * based. If we can't convert the target port address to a wwn then
+ * we're location based.
+ */
+ if (scsi_wwnstr_to_wwn(tgt_port, &wwn) == DDI_FAILURE)
+ return;
+
+ /*
+ * Get lun and lun64
+ */
+ lun = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
+ SCSI_ADDR_PROP_LUN, 0);
+ lun64 = scsi_device_prop_get_int64(sd, SCSI_DEVICE_PROP_PATH,
+ SCSI_ADDR_PROP_LUN64, lun);
+
+ /*
+ * We are guaranteed not to be in interrupt or any other
+ * problematic context. So instead of repeated varargs
+ * style calls to scsi_fm_ereport_post for each flavour of
+ * ereport we have the luxury of being able to allocate
+ * and build an nvlist here.
+ *
+ * The ereports we raise here are all under the category
+ * ereport.io.scsi.cmd.disk category, namely
+ *
+ * ereport.io.scsi.cmd.disk.
+ * {dev.rqs.derr,dev.serr,tran}.
+ *
+ * For all ereports we also add the scsi_test specific payload.
+ * If we have it then we always include the devid in the payload
+ * (but only in the detector for device-as-detector ereports).
+ *
+ * Inherited From Member Name
+ * -------------------- -------------------
+ * .cmd driver-assessment
+ * .cmd op-code
+ * .cmd cdb
+ * .cmd pkt-reason
+ * .cmd pkt-state
+ * .cmd pkt-stats
+ * .cmd.disk stat-code
+ * - scsi-test-return
+ * - scsi-test-context
+ */
+
+ if (nvlist_alloc(&pl, NV_UNIQUE_NAME, 0) != 0)
+ return;
+
+ err |= nvlist_add_uint8(pl, "op-code", cdbp->scc_cmd);
+ err |= nvlist_add_uint8_array(pl, "cdb", pkt->pkt_cdbp,
+ pkt->pkt_cdblen);
+ err |= nvlist_add_uint8(pl, "pkt-reason", pkt->pkt_reason);
+ err |= nvlist_add_uint32(pl, "pkt-state", pkt->pkt_state);
+ err |= nvlist_add_uint32(pl, "pkt-stats", pkt->pkt_statistics);
+ err |= nvlist_add_uint32(pl, "stat-code", *pkt->pkt_scbp);
+ err |= nvlist_add_uint32(pl, "scsi-test-return", stresult);
+ err |= nvlist_add_int32(pl, "scsi-test-context", ctxt);
+
+ switch (stresult) {
+ case SCSI_TEST_CMPLT_BUSY:
+ dad = 1;
+ class = "cmd.disk.dev.serr";
+ break;
+
+ case SCSI_TEST_CMPLT_CHECK:
+ dad = 1;
+
+ if ((pkt->pkt_state & STATE_ARQ_DONE)) {
+ struct scsi_arq_status *arqstat;
+ uint8_t key, asc, ascq;
+ uint8_t *sensep;
+
+ class = "cmd.disk.dev.rqs.derr";
+ arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
+ sensep = (uint8_t *)&arqstat->sts_sensedata;
+ key = scsi_sense_key(sensep);
+ asc = scsi_sense_asc(sensep);
+ ascq = scsi_sense_ascq(sensep);
+
+ /*
+ * Add to payload.
+ */
+ err |= nvlist_add_uint8(pl, "key", key);
+ err |= nvlist_add_uint8(pl, "asc", asc);
+ err |= nvlist_add_uint8(pl, "ascq", ascq);
+ err |= nvlist_add_uint8_array(pl, "sense-data",
+ sensep, sizeof (arqstat->sts_sensedata));
+ } else {
+ class = "cmd.disk.dev.serr";
+ }
+
+ break;
+
+ case SCSI_TEST_CMPLT_OTHER:
+ dad = 1;
+ class = "cmd.disk.dev.serr";
+ break;
+
+ case SCSI_TEST_CMD_INCOMPLETE:
+ case SCSI_TEST_NOTCMPLT:
+ case SCSI_TEST_TRAN_BUSY:
+ case SCSI_TEST_TRAN_REJECT:
+ class = "cmd.disk.tran";
+ break;
+ }
+
+ /*
+ * Determine driver-assessment and add to payload.
+ */
+ if (dad) {
+ /*
+ * While higher level software can retry the enumeration
+ * the belief is that any device-as-detector style error
+ * will be persistent and will survive retries. So we
+ * can make a local determination of driver assessment.
+ * Some day it may be more elegant to raise an ereport from
+ * scsi_tgtmap_scsi_deactivate to confirm retries failed,
+ * and correlate that ereport during diagnosis.
+ */
+ if (stresult & tp->stp_fatalmask)
+ d_ass = (const char *)"fatal";
+ else if (stresult & tp->stp_retrymask)
+ d_ass = (const char *)"retry";
+ else
+ d_ass = (const char *)"retry";
+ } else {
+ /* We do not diagnose transport errors (yet) */
+ d_ass = (const char *)"retry";
+ }
+
+ err |= nvlist_add_string(pl, "driver-assessment", d_ass);
+
+ /*
+ * If we're hoping for a device-as-detector style ereport then
+ * we're going to need a devid for the detector FMRI. We
+ * don't have the devid because the target won't talk to us.
+ * But we do know which hba iport we were probing out of, and
+ * we know the unit address that was being probed (but not
+ * what type of device is or should be there). So we
+ * search the devid cache for any cached devid matching
+ * path <iport-path>/<nodename>@<unit-address> with nodename
+ * wildcarded. If a match is made we are returned not only the
+ * devid but also the nodename for the path that cached that
+ * entry.
+ *
+ * We also attempt to dig up a devid even for transport errors;
+ * we'll include that in the payload but not in the detector FMRI.
+ */
+
+ pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+ (void) ddi_pathname(hba, pathbuf);
+
+ if (e_devid_cache_path_to_devid(pathbuf, ua, nodenamebuf,
+ &devid) == DDI_SUCCESS) {
+ nodename = nodenamebuf;
+ devidstr = devidstr_buf = ddi_devid_str_encode(devid, NULL);
+ kmem_free(devid, ddi_devid_sizeof(devid));
+ err |= nvlist_add_string(pl, "devid", devidstr);
+ }
+
+ /*
+ * If this is lun 0 we will include the target-port-l0id
+ * in the dev scheme detector for device-as-detector.
+ */
+ if (dad && (lun == 0 || lun64 == 0))
+ tpl0 = tgt_port;
+
+ /* Construct the devpath to use in the detector */
+ (void) ddi_pathname(hba, pathbuf);
+ len = strlen(pathbuf);
+ (void) snprintf(pathbuf + len, MAXPATHLEN - len, "/%s@%s",
+ nodename ? nodename : "unknown", ua);
+
+ /*
+ * Let's review.
+ *
+ * Device-as-detector ereports for which the attempted lookup of
+ * devid and nodename succeeded:
+ *
+ * - pathbuf has the full device path including nodename we
+ * dug up from the devid cache
+ *
+ * - class is one of cmd.disk.{dev.rqs.derr,dev.serr}
+ *
+ * - devidstr is non NULL and a valid devid string
+ *
+ * Would-be device-as-detector ereport for which the attempted lookup
+ * of devid failed:
+ *
+ * - pathbuf has a device path with leaf nodename of "unknown"
+ * but still including the unit-address
+ * - class is one of cmd.disk.{dev.rqs.derr,dev.serr}
+ *
+ * Transport errors:
+ *
+ * class is cmd.disk.tran
+ * devidstr is NULL
+ *
+ * - we may have succeeded in looking up a devid and nodename -
+ * the devid we'll have added to the payload but we must not
+ * add to detector FMRI, and if we have have nodename then
+ * we have a full devpath otherwise one with "unknown" for
+ * nodename
+ */
+
+ if (err)
+ (void) nvlist_add_boolean_value(pl, "payload-incomplete",
+ B_TRUE);
+
+ scsi_fm_ereport_post(
+ sd,
+ 0, /* path_instance - always 0 */
+ pathbuf, /* devpath for detector */
+ class, /* ereport class suffix */
+ 0, /* ENA - generate for us */
+ dad ? devidstr : NULL, /* dtcr devid, dev-as-det only */
+ tpl0, /* target-port-l0id */
+ DDI_SLEEP,
+ pl, /* preconstructed payload */
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ NULL);
+
+ nvlist_free(pl);
+ if (devidstr_buf)
+ ddi_devid_str_free(devidstr_buf);
+ kmem_free(pathbuf, MAXPATHLEN);
+}
+
+#ifdef DEBUG
+/*
+ * Testing - fake scsi_test fails
+ */
+char scsi_test_fail_ua[SCSI_MAXNAMELEN]; /* unit address to object to */
+int scsi_test_fail_rc = TRAN_ACCEPT; /* scsi_transport return */
+uchar_t scsi_test_fail_pkt_reason = CMD_CMPLT; /* pkt_reason */
+uchar_t scsi_test_fail_status = STATUS_BUSY; /* status */
+uint_t scsi_test_fail_repeat = (uint_t)-1; /* number of times to fail ua */
+#endif
+
+/*
* This is like scsi_poll, but only does retry for TRAN_BUSY.
*/
-static int
-scsi_test(struct scsi_pkt *pkt)
+static uint32_t
+scsi_test(struct scsi_pkt *pkt, enum scsi_test_ctxt ctxt)
{
- int rval = -1;
+ uint32_t rval;
int wait_usec;
int rc;
extern int do_polled_io;
@@ -427,19 +939,77 @@ scsi_test(struct scsi_pkt *pkt)
}
}
- if (rc != TRAN_ACCEPT) {
- goto exit;
- } else if (pkt->pkt_reason == CMD_INCOMPLETE && pkt->pkt_state == 0) {
- goto exit;
- } else if (pkt->pkt_reason != CMD_CMPLT) {
- goto exit;
- } else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) {
- rval = 0;
- } else {
- rval = 0;
+#ifdef DEBUG
+ if (scsi_test_fail_ua[0] != '\0' && scsi_test_fail_repeat > 0) {
+ struct scsi_address *ap = &pkt->pkt_address;
+ struct scsi_device *sd;
+ dev_info_t *probe;
+ char ua[SCSI_MAXNAMELEN];
+
+ if ((sd = scsi_address_device(ap)) != NULL) {
+ probe = sd->sd_dev;
+
+ if (probe && scsi_ua_get(sd, ua, sizeof (ua)) &&
+ strncmp(ua, scsi_test_fail_ua, sizeof (ua)) == 0) {
+ scsi_test_fail_repeat--;
+ rc = scsi_test_fail_rc;
+ if (rc == TRAN_ACCEPT)
+ pkt->pkt_reason =
+ scsi_test_fail_pkt_reason;
+ *pkt->pkt_scbp = scsi_test_fail_status;
+ if (scsi_test_fail_status == STATUS_CHECK)
+ pkt->pkt_state |= STATE_ARQ_DONE;
+
+ }
+ }
+ }
+#endif
+
+ switch (rc) {
+ case TRAN_ACCEPT:
+ switch (pkt->pkt_reason) {
+ case CMD_CMPLT:
+ switch ((*pkt->pkt_scbp) & STATUS_MASK) {
+ case STATUS_GOOD:
+ rval = SCSI_TEST_CMPLT_GOOD;
+ break;
+
+ case STATUS_BUSY:
+ rval = SCSI_TEST_CMPLT_BUSY;
+ break;
+
+ case STATUS_CHECK:
+ rval = SCSI_TEST_CMPLT_CHECK;
+ break;
+
+ default:
+ rval = SCSI_TEST_CMPLT_OTHER;
+ break;
+ }
+ break;
+
+ case CMD_INCOMPLETE:
+ rval = SCSI_TEST_CMD_INCOMPLETE;
+ break;
+
+ default:
+ rval = SCSI_TEST_NOTCMPLT;
+ break;
+ }
+ break;
+
+ case TRAN_BUSY:
+ rval = SCSI_TEST_TRAN_BUSY;
+ break;
+
+ default:
+ rval = SCSI_TEST_TRAN_REJECT;
+ break;
}
-exit:
+ if (rval != SCSI_TEST_CMPLT_GOOD)
+ scsi_test_ereport_post(pkt, ctxt, rval);
+
return (rval);
}
@@ -510,6 +1080,7 @@ scsi_hba_probe_pi(struct scsi_device *sd, int (*callback)(), int pi)
struct buf *rq_bp = NULL;
int (*cb_flag)();
int pass = 1;
+ uint32_t str;
if (sd->sd_inq == NULL) {
sd->sd_inq = (struct scsi_inquiry *)
@@ -565,35 +1136,41 @@ scsi_hba_probe_pi(struct scsi_device *sd, int (*callback)(), int pi)
bzero((caddr_t)sd->sd_inq, SUN_INQSIZE);
again: FILL_SCSI1_LUN(sd, inq_pkt);
- if (scsi_test(inq_pkt) < 0) {
- if (inq_pkt->pkt_reason == CMD_INCOMPLETE) {
+ str = scsi_test(inq_pkt, STC_PROBE_FIRST_INQ);
+ if (SCSI_TEST_FAILURE(str)) {
+ if (str == SCSI_TEST_CMD_INCOMPLETE) {
rval = SCSIPROBE_NORESP;
goto out;
- } else {
- /*
- * retry one more time
- */
- if (scsi_test(inq_pkt) < 0) {
- rval = SCSIPROBE_FAILURE;
- goto out;
- }
+ }
+
+ /*
+ * Retry one more time for anything other than CMD_INCOMPLETE.
+ */
+ str = scsi_test(inq_pkt, STC_PROBE_FIRST_INQ_RETRY);
+ if (SCSI_TEST_FAILURE(str)) {
+ rval = SCSIPROBE_FAILURE;
+ goto out;
}
}
/*
- * if we are lucky, this inquiry succeeded
+ * Did the inquiry complete and transfer inquiry information,
+ * perhaps after retry?
*/
- if ((inq_pkt->pkt_reason == CMD_CMPLT) &&
- (((*inq_pkt->pkt_scbp) & STATUS_MASK) == 0)) {
+ if (str == SCSI_TEST_CMPLT_GOOD)
goto done;
- }
/*
- * the second inquiry, allows the host adapter to negotiate
+ * We get here for SCSI_TEST_CMPLT_{BUSY,CHECK,OTHER}. We term
+ * this "partial success" in that at least something is talking
+ * to us.
+ *
+ * A second inquiry allows the host adapter to negotiate
* synchronous transfer period and offset
*/
- if (scsi_test(inq_pkt) < 0) {
- if (inq_pkt->pkt_reason == CMD_INCOMPLETE)
+ str = scsi_test(inq_pkt, STC_PROBE_PARTIAL_SUCCESS);
+ if (SCSI_TEST_FAILURE(str)) {
+ if (str == SCSI_TEST_CMD_INCOMPLETE)
rval = SCSIPROBE_NORESP;
else
rval = SCSIPROBE_FAILURE;
@@ -601,72 +1178,73 @@ again: FILL_SCSI1_LUN(sd, inq_pkt);
}
/*
- * if target is still busy, give up now
+ * If target is still busy, give up now.
+ * XXX There's no interval between retries - scsi_test should
+ * probably have a builtin retry on target busy.
*/
- if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_busy) {
+ if (str == SCSI_TEST_CMPLT_BUSY) {
rval = SCSIPROBE_BUSY;
goto out;
}
/*
- * do a rqsense if there was a check condition and ARQ was not done
+ * At this point we are SCSI_TEST_CMPLT_GOOD, SCSI_TEST_CMPLT_CHECK
+ * or SCSI_TEST_CMPLT_OTHER.
+ *
+ * Do a rqsense if there was a check condition and ARQ was not done
*/
- if ((inq_pkt->pkt_state & STATE_ARQ_DONE) == 0) {
- if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) {
-
- /*
- * prepare rqsense packet
- * there is no real need for this because the
- * check condition should have been cleared by now.
- */
- rq_bp = scsi_alloc_consistent_buf(ROUTE,
- (struct buf *)NULL,
- (uint_t)SENSE_LENGTH, B_READ, cb_flag, NULL);
- if (rq_bp == NULL) {
- goto out;
- }
+ if (str == SCSI_TEST_CMPLT_CHECK &&
+ (inq_pkt->pkt_state & STATE_ARQ_DONE) == 0) {
+ /*
+ * prepare rqsense packet
+ * there is no real need for this because the
+ * check condition should have been cleared by now.
+ */
+ rq_bp = scsi_alloc_consistent_buf(ROUTE, (struct buf *)NULL,
+ (uint_t)SENSE_LENGTH, B_READ, cb_flag, NULL);
+ if (rq_bp == NULL) {
+ goto out;
+ }
- rq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
- rq_bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, callback,
- NULL);
+ rq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
+ rq_bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, callback, NULL);
- if (rq_pkt == NULL) {
- if (rq_bp->b_error == 0)
- rval = SCSIPROBE_NOMEM_CB;
- goto out;
- }
- ASSERT(rq_bp->b_error == 0);
+ if (rq_pkt == NULL) {
+ if (rq_bp->b_error == 0)
+ rval = SCSIPROBE_NOMEM_CB;
+ goto out;
+ }
+ ASSERT(rq_bp->b_error == 0);
- (void) scsi_setup_cdb((union scsi_cdb *)rq_pkt->
- pkt_cdbp, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
- FILL_SCSI1_LUN(sd, rq_pkt);
- rq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY;
+ (void) scsi_setup_cdb((union scsi_cdb *)rq_pkt->
+ pkt_cdbp, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
+ FILL_SCSI1_LUN(sd, rq_pkt);
+ rq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY;
- /*
- * set transport path
- */
- if (pi && scsi_pkt_allocated_correctly(rq_pkt)) {
- rq_pkt->pkt_path_instance = pi;
- rq_pkt->pkt_flags |= FLAG_PKT_PATH_INSTANCE;
- }
+ /*
+ * set transport path
+ */
+ if (pi && scsi_pkt_allocated_correctly(rq_pkt)) {
+ rq_pkt->pkt_path_instance = pi;
+ rq_pkt->pkt_flags |= FLAG_PKT_PATH_INSTANCE;
+ }
- /*
- * The FILL_SCSI1_LUN above will find "inq_ansi != 1"
- * on first pass, see "again" comment above.
- *
- * The controller type is as yet unknown, so we
- * have to do a throwaway non-extended request sense,
- * and hope that that clears the check condition for
- * that unit until we can find out what kind of drive
- * it is. A non-extended request sense is specified
- * by stating that the sense block has 0 length,
- * which is taken to mean that it is four bytes in
- * length.
- */
- if (scsi_test(rq_pkt) < 0) {
- rval = SCSIPROBE_FAILURE;
- goto out;
- }
+ /*
+ * The FILL_SCSI1_LUN above will find "inq_ansi != 1"
+ * on first pass, see "again" comment above.
+ *
+ * The controller type is as yet unknown, so we
+ * have to do a throwaway non-extended request sense,
+ * and hope that that clears the check condition for
+ * that unit until we can find out what kind of drive
+ * it is. A non-extended request sense is specified
+ * by stating that the sense block has 0 length,
+ * which is taken to mean that it is four bytes in
+ * length.
+ */
+ if (SCSI_TEST_FAILURE(scsi_test(rq_pkt, STC_PROBE_RQSENSE1))) {
+ rval = SCSIPROBE_FAILURE;
+ goto out;
}
}
@@ -678,12 +1256,13 @@ again: FILL_SCSI1_LUN(sd, inq_pkt);
* lie about a unit being ready, e.g., the Emulex MD21).
*/
- if (scsi_test(inq_pkt) < 0) {
+ str = scsi_test(inq_pkt, STC_PROBE_CHK_CLEARED);
+ if (SCSI_TEST_FAILURE(str)) {
rval = SCSIPROBE_FAILURE;
goto out;
}
- if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_busy) {
+ if (str == SCSI_TEST_CMPLT_BUSY) {
rval = SCSIPROBE_BUSY;
goto out;
}
@@ -697,23 +1276,22 @@ again: FILL_SCSI1_LUN(sd, inq_pkt);
* target/lun).
*/
- if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) {
+ if (str == SCSI_TEST_CMPLT_CHECK) {
/*
* try a request sense if we have a pkt, otherwise
* just retry the inquiry one more time
*/
- if (rq_pkt) {
- (void) scsi_test(rq_pkt);
- }
+ if (rq_pkt)
+ (void) scsi_test(rq_pkt, STC_PROBE_RQSENSE2);
/*
* retry inquiry
*/
- if (scsi_test(inq_pkt) < 0) {
+ str = scsi_test(inq_pkt, STC_PROBE_INQ_FINAL);
+ if (SCSI_TEST_FAILURE(str)) {
rval = SCSIPROBE_FAILURE;
goto out;
- }
- if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) {
+ } else if (str == SCSI_TEST_CMPLT_CHECK) {
rval = SCSIPROBE_FAILURE;
goto out;
}
@@ -997,12 +1575,16 @@ scsi_device_prop_update_inqstring(struct scsi_device *sd,
/*
* Interfaces associated with SCSI_HBA_ADDR_COMPLEX
* per-scsi_device HBA private data support.
+ *
+ * scsi_address_device returns NULL if we're not SCSI_HBA_ADDR_COMPLEX,
+ * thereby allowing use of scsi_address_device as a test for
+ * SCSI_HBA_ADDR_COMPLEX.
*/
struct scsi_device *
scsi_address_device(struct scsi_address *sa)
{
- ASSERT(sa->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX);
- return (sa->a.a_sd);
+ return ((sa->a_hba_tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX) ?
+ sa->a.a_sd : NULL);
}
void
@@ -1431,7 +2013,7 @@ scsi_device_identity(struct scsi_device *sd, int (*callback)())
}
rval = send_scsi_INQUIRY(sd, callback, inq80,
- MAX_INQUIRY_SIZE, 0x01, 0x80, &len);
+ MAX_INQUIRY_SIZE, 0x01, 0x80, &len, STC_IDENTITY_PG80);
if (rval)
goto out; /* should have worked */
@@ -1454,7 +2036,7 @@ scsi_device_identity(struct scsi_device *sd, int (*callback)())
}
rval = send_scsi_INQUIRY(sd, callback, inq83,
- MAX_INQUIRY_SIZE, 0x01, 0x83, &len);
+ MAX_INQUIRY_SIZE, 0x01, 0x83, &len, STC_IDENTITY_PG83);
if (rval)
goto out; /* should have worked */
@@ -1511,7 +2093,7 @@ check_vpd_page_support8083(struct scsi_device *sd, int (*callback)(),
/* issue page 0 (Supported VPD Pages) INQUIRY with evpd set */
rval = send_scsi_INQUIRY(sd, callback,
- page_list, MAX_INQUIRY_SIZE_EVPD, 1, 0, NULL);
+ page_list, MAX_INQUIRY_SIZE_EVPD, 1, 0, NULL, STC_VPD_CHECK);
/*
* Now we must validate that the device accepted the command (some
@@ -1559,7 +2141,8 @@ check_vpd_page_support8083(struct scsi_device *sd, int (*callback)(),
static int
send_scsi_INQUIRY(struct scsi_device *sd, int (*callback)(),
uchar_t *bufaddr, size_t buflen,
- uchar_t evpd, uchar_t page_code, size_t *lenp)
+ uchar_t evpd, uchar_t page_code, size_t *lenp,
+ enum scsi_test_ctxt ctxt)
{
int (*cb_flag)();
struct buf *inq_bp;
@@ -1601,9 +2184,7 @@ send_scsi_INQUIRY(struct scsi_device *sd, int (*callback)(),
* NOPARITY is used. Also seems like we should check pkt_stat for
* STATE_XFERRED_DATA.
*/
- if ((scsi_test(inq_pkt) == 0) &&
- (inq_pkt->pkt_reason == CMD_CMPLT) &&
- (((*inq_pkt->pkt_scbp) & STATUS_MASK) == 0)) {
+ if (scsi_test(inq_pkt, ctxt) == SCSI_TEST_CMPLT_GOOD) {
ASSERT(inq_pkt->pkt_resid >= 0);
ASSERT(inq_pkt->pkt_resid <= buflen);
@@ -1614,6 +2195,10 @@ send_scsi_INQUIRY(struct scsi_device *sd, int (*callback)(),
rval = 0;
}
+ /*
+ * XXX We should retry on target busy
+ */
+
out: if (inq_pkt)
scsi_destroy_pkt(inq_pkt);
if (inq_bp)
diff --git a/usr/src/uts/common/io/scsi/impl/scsi_fm.c b/usr/src/uts/common/io/scsi/impl/scsi_fm.c
index b4dad350f5..1ae635b482 100644
--- a/usr/src/uts/common/io/scsi/impl/scsi_fm.c
+++ b/usr/src/uts/common/io/scsi/impl/scsi_fm.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -36,7 +35,8 @@
/* consolidation private interface to generate dev scheme ereport */
extern void fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
const char *devpath, const char *minor_name, const char *devid,
- const char *error_class, uint64_t ena, int sflag, va_list ap);
+ const char *tpl0, const char *error_class, uint64_t ena, int sflag,
+ nvlist_t *, va_list ap);
extern char *mdi_pi_pathname_by_instance(int);
#define FM_SCSI_CLASS "scsi"
@@ -88,30 +88,45 @@ scsi_fm_fini(struct scsi_device *sd)
/*
*
- * scsi_fm_erepot_post - Post an ereport.
+ * scsi_fm_ereport_post - Post an ereport
*/
void
scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
- const char *error_class, uint64_t ena, char *devid, int sflag, ...)
+ char *devpath, const char *error_class, uint64_t ena,
+ char *devid, char *tpl0, int sflag, nvlist_t *pl, ...)
{
char class[ERPT_CLASS_SZ];
dev_info_t *dip = sd->sd_dev;
- char *devpath, *minor_name;
+ dev_info_t *eqdip = dip;
+ char *minor_name;
va_list ap;
+ /*
+ * If the scsi_device eqdip is not yet ereport capable, send the
+ * report based on parent capabilities. This is needed for
+ * telemetry during enumeration.
+ */
+ if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(eqdip)))
+ eqdip = ddi_get_parent(eqdip);
+
/* Add "scsi." as a prefix to the class */
(void) snprintf(class, ERPT_CLASS_SZ, "%s.%s",
FM_SCSI_CLASS, error_class);
/*
- * Get the path: If pkt_path_instance is non-zero then the packet was
+ * Get the path:
+ *
+ * If path_instance is non-zero then the packet was
* sent to scsi_vhci. We return the pathinfo path_string associated
* with the path_instance path - which refers to the actual hardware.
+ *
+ * If path_instance is zero then use the devpath provided by the
+ * caller; if it was NULL then this will cause fm_dev_ereport_post
+ * to use the devinfo path of the first devi we pass to it, ie
+ * sd->sd_dev.
*/
if (path_instance)
devpath = mdi_pi_pathname_by_instance(path_instance);
- else
- devpath = NULL;
/*
* Set the minor_name to NULL. The block location of a media error
@@ -130,8 +145,8 @@ scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
*/
/* Post the ereport */
- va_start(ap, sflag);
- fm_dev_ereport_postv(dip, dip, devpath, minor_name, devid,
- class, ena, sflag, ap);
+ va_start(ap, pl);
+ fm_dev_ereport_postv(dip, eqdip, devpath, minor_name, devid, tpl0,
+ class, ena, sflag, pl, ap);
va_end(ap);
}
diff --git a/usr/src/uts/common/io/scsi/impl/scsi_hba.c b/usr/src/uts/common/io/scsi/impl/scsi_hba.c
index 7d1725d33e..990603f5a2 100644
--- a/usr/src/uts/common/io/scsi/impl/scsi_hba.c
+++ b/usr/src/uts/common/io/scsi/impl/scsi_hba.c
@@ -43,6 +43,7 @@
#include <sys/damap.h>
#include <sys/time.h>
#include <sys/sunldi.h>
+#include <sys/fm/protocol.h>
extern struct scsi_pkt *scsi_init_cache_pkt(struct scsi_address *,
struct scsi_pkt *, struct buf *, int, int, int, int,
@@ -600,8 +601,9 @@ scsi_hba_log(int level, const char *func, dev_info_t *self, dev_info_t *child,
mutex_exit(&scsi_hba_log_mutex);
}
-static int scsi_enumeration_failed_panic = 0;
-static int scsi_enumeration_failed_hotplug = 1;
+int scsi_enumeration_failed_panic = 0;
+int scsi_enumeration_failed_hotplug = 1;
+
static void
scsi_enumeration_failed(dev_info_t *child, scsi_enum_t se,
char *arg, char *when)
@@ -5094,6 +5096,9 @@ scsi_findchild(dev_info_t *self, char *name, char *addr, int init,
* If no driver binds to the device using driver_alias we establish the driver
* passed in as the node name.
*/
+
+extern int e_devid_cache_pathinfo(mdi_pathinfo_t *, ddi_devid_t);
+
static int
scsi_device_createchild(dev_info_t *self, char *addr, scsi_enum_t se,
struct scsi_device *sdprobe, dev_info_t **dchildp, mdi_pathinfo_t **pchildp)
@@ -5380,6 +5385,21 @@ scsi_device_createchild(dev_info_t *self, char *addr, scsi_enum_t se,
"pathinfo %s created, no devid",
mdi_pi_spathname(pchild)));
}
+
+ /*
+ * The above has registered devid for the device under
+ * the client node. Now register it under the full pHCI
+ * path to the device. We'll get an entry equivalent to
+ * booting with mpxio disabled. This is needed for
+ * telemetry during enumeration.
+ */
+ if (e_devid_cache_pathinfo(pchild, devid) == DDI_SUCCESS) {
+ SCSI_HBA_LOG((_LOG(2), NULL, dchild,
+ "pathinfo @%s created with devid", addr));
+ } else {
+ SCSI_HBA_LOG((_LOG(1), NULL, dchild,
+ "pathinfo @%s devid cache failed", addr));
+ }
}
/* free the node name and compatible information */
diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c
index ab6c1e1d0a..c25241d38e 100644
--- a/usr/src/uts/common/io/scsi/targets/sd.c
+++ b/usr/src/uts/common/io/scsi/targets/sd.c
@@ -31223,6 +31223,9 @@ sd_tg_getinfo(dev_info_t *devi, int cmd, void *arg, void *tg_cookie)
*
* Context: Kernel thread or interrupt context.
*/
+
+#define DEVID_IF_KNOWN(d) "devid", DATA_TYPE_STRING, (d) ? (d) : "unknown"
+
static void
sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
{
@@ -31318,9 +31321,11 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
* driver-assessment will always be "recovered" here.
*/
if (drv_assess == SD_FM_DRV_RECOVERY) {
- scsi_fm_ereport_post(un->un_sd, uscsi_path_instance,
- "cmd.disk.recovered", uscsi_ena, devid, DDI_NOSLEEP,
+ scsi_fm_ereport_post(un->un_sd, uscsi_path_instance, NULL,
+ "cmd.disk.recovered", uscsi_ena, devid, NULL,
+ DDI_NOSLEEP, NULL,
FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment", DATA_TYPE_STRING, assessment,
"op-code", DATA_TYPE_UINT8, op_code,
"cdb", DATA_TYPE_UINT8_ARRAY,
@@ -31344,8 +31349,10 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
if (ssc->ssc_flags & ssc_invalid_flags) {
if (ssc->ssc_flags & SSC_FLAGS_INVALID_SENSE) {
scsi_fm_ereport_post(un->un_sd, uscsi_path_instance,
- "cmd.disk.dev.uderr", uscsi_ena, devid, DDI_NOSLEEP,
+ NULL, "cmd.disk.dev.uderr", uscsi_ena, devid,
+ NULL, DDI_NOSLEEP, NULL,
FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment", DATA_TYPE_STRING,
drv_assess == SD_FM_DRV_FATAL ?
"fail" : assessment,
@@ -31371,8 +31378,11 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
* level payload or inside un-decode-info.
*/
scsi_fm_ereport_post(un->un_sd, uscsi_path_instance,
- "cmd.disk.dev.uderr", uscsi_ena, devid, DDI_NOSLEEP,
+ NULL,
+ "cmd.disk.dev.uderr", uscsi_ena, devid,
+ NULL, DDI_NOSLEEP, NULL,
FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment", DATA_TYPE_STRING,
drv_assess == SD_FM_DRV_FATAL ?
"fail" : assessment,
@@ -31409,9 +31419,10 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
if (ssc->ssc_flags & SSC_FLAGS_TRAN_ABORT)
ssc->ssc_flags &= ~SSC_FLAGS_TRAN_ABORT;
- scsi_fm_ereport_post(un->un_sd, uscsi_path_instance,
- "cmd.disk.tran", uscsi_ena, NULL, DDI_NOSLEEP, FM_VERSION,
- DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ scsi_fm_ereport_post(un->un_sd, uscsi_path_instance, NULL,
+ "cmd.disk.tran", uscsi_ena, NULL, NULL, DDI_NOSLEEP, NULL,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment", DATA_TYPE_STRING,
drv_assess == SD_FM_DRV_FATAL ? "fail" : assessment,
"op-code", DATA_TYPE_UINT8, op_code,
@@ -31445,10 +31456,12 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
* drv_assess is SD_FM_DRV_FATAL.
*/
scsi_fm_ereport_post(un->un_sd,
- uscsi_path_instance,
+ uscsi_path_instance, NULL,
"cmd.disk.dev.rqs.merr",
- uscsi_ena, devid, DDI_NOSLEEP, FM_VERSION,
- DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ uscsi_ena, devid, NULL, DDI_NOSLEEP, NULL,
+ FM_VERSION, DATA_TYPE_UINT8,
+ FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment",
DATA_TYPE_STRING,
drv_assess == SD_FM_DRV_FATAL ?
@@ -31492,11 +31505,13 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
* SD_FM_DRV_FATAL.
*/
scsi_fm_ereport_post(un->un_sd,
- uscsi_path_instance,
+ uscsi_path_instance, NULL,
"cmd.disk.dev.rqs.derr",
- uscsi_ena, devid, DDI_NOSLEEP,
+ uscsi_ena, devid,
+ NULL, DDI_NOSLEEP, NULL,
FM_VERSION,
DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment",
DATA_TYPE_STRING,
drv_assess == SD_FM_DRV_FATAL ?
@@ -31545,10 +31560,12 @@ sd_ssc_ereport_post(sd_ssc_t *ssc, enum sd_driver_assessment drv_assess)
* driver-assessment will be set based on parameter
* drv_assess.
*/
- scsi_fm_ereport_post(un->un_sd,
- uscsi_path_instance, "cmd.disk.dev.serr", uscsi_ena,
- devid, DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8,
- FM_EREPORT_VERS0,
+ scsi_fm_ereport_post(un->un_sd, uscsi_path_instance,
+ NULL,
+ "cmd.disk.dev.serr", uscsi_ena,
+ devid, NULL, DDI_NOSLEEP, NULL,
+ FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
+ DEVID_IF_KNOWN(devid),
"driver-assessment", DATA_TYPE_STRING,
drv_assess == SD_FM_DRV_FATAL ? "fail" : assessment,
"op-code", DATA_TYPE_UINT8, op_code,
diff --git a/usr/src/uts/common/os/ddifm.c b/usr/src/uts/common/os/ddifm.c
index a78d949665..8ad563aad2 100644
--- a/usr/src/uts/common/os/ddifm.c
+++ b/usr/src/uts/common/os/ddifm.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -317,11 +316,29 @@ i_ddi_drv_ereport_post(dev_info_t *dip, const char *error_class,
* non-null devpath, minor_name, and devid arguments depending on
* wether MPXIO is enabled, and wether a transport or non-transport
* error is being posted.
+ *
+ * Additional event payload is specified via the varargs plist and, if
+ * not NULL, the nvlist passed in (such an nvlist will be merged into
+ * the payload; the caller is responsible for freeing this nvlist).
+ * Do not specify any high-level protocol event member names as part of the
+ * payload - eg no payload to be named "class", "version", "detector" etc
+ * or they will replace the members we construct here.
+ *
+ * The 'target-port-l0id' argument is SCSI specific. It is used
+ * by SCSI enumeration code when a devid is unavailable. If non-NULL
+ * the property-value becomes part of the ereport detector. The value
+ * specified might match one of the target-port-l0ids values of a
+ * libtopo disk chassis node. When libtopo finds a disk with a guaranteed
+ * unique wWWN target-port of a single-lun 'real' disk, it can add
+ * the target-port value to the libtopo disk chassis node target-port-l0ids
+ * string array property. Kernel code has no idea if this type of
+ * libtopo chassis node exists, or if matching will in fact occur.
*/
void
fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
const char *devpath, const char *minor_name, const char *devid,
- const char *error_class, uint64_t ena, int sflag, va_list ap)
+ const char *tpl0, const char *error_class, uint64_t ena, int sflag,
+ nvlist_t *pl, va_list ap)
{
nv_alloc_t *nva = NULL;
struct i_ddi_fmhdl *fmhdl = NULL;
@@ -334,6 +351,7 @@ fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
char class[ERPT_CLASS_SZ];
char path[MAXPATHLEN];
+ ASSERT(ap != NULL); /* must supply at least ereport version */
ASSERT(dip && eqdip && error_class);
/*
@@ -376,7 +394,7 @@ fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
/*
* Form parts of an ereport:
* A: version
- * B: error_class
+ * B: error_class
* C: ena
* D: detector (path and optional devid authority)
* E: payload
@@ -414,12 +432,17 @@ fm_dev_ereport_postv(dev_info_t *dip, dev_info_t *eqdip,
(void) strlcat(path, minor_name, sizeof (path));
}
detector = fm_nvlist_create(nva);
- fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, path, devid);
+ fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, path,
+ devid, tpl0);
/* Pull parts of ereport together into ereport. */
fm_ereport_set(ereport, version, class, ena, detector, NULL);
- /* Add the payload to ereport. */
+ /* Merge any preconstructed payload into the event. */
+ if (pl)
+ (void) nvlist_merge(ereport, pl, 0);
+
+ /* Add any remaining (after version) varargs payload to ereport. */
name = va_arg(ap, char *);
(void) i_fm_payload_set(ereport, name, ap);
@@ -466,8 +489,8 @@ ddi_fm_ereport_post(dev_info_t *dip,
ASSERT(dip && error_class);
va_start(ap, sflag);
- fm_dev_ereport_postv(dip, dip, NULL, NULL, NULL,
- error_class, ena, sflag, ap);
+ fm_dev_ereport_postv(dip, dip, NULL, NULL, NULL, NULL,
+ error_class, ena, sflag, NULL, ap);
va_end(ap);
}
@@ -479,8 +502,8 @@ ndi_fm_ereport_post(dev_info_t *dip,
ASSERT(dip && error_class && (sflag == DDI_SLEEP));
va_start(ap, sflag);
- fm_dev_ereport_postv(dip, ddi_get_parent(dip), NULL, NULL, NULL,
- error_class, ena, sflag, ap);
+ fm_dev_ereport_postv(dip, ddi_get_parent(dip), NULL, NULL, NULL, NULL,
+ error_class, ena, sflag, NULL, ap);
va_end(ap);
}
diff --git a/usr/src/uts/common/os/devid_cache.c b/usr/src/uts/common/os/devid_cache.c
index 22d55d535a..dcb3af26d2 100644
--- a/usr/src/uts/common/os/devid_cache.c
+++ b/usr/src/uts/common/os/devid_cache.c
@@ -32,6 +32,7 @@
#include <sys/hwconf.h>
#include <sys/sunddi.h>
#include <sys/sunndi.h>
+#include <sys/sunmdi.h>
#include <sys/ddi_impldefs.h>
#include <sys/ndi_impldefs.h>
#include <sys/kobj.h>
@@ -79,7 +80,7 @@
* Number of times discovery will be attempted prior to mounting root.
* Must be done at least once to recover from corrupted or missing
* devid cache backing store. Probably there's no reason to ever
- * set this to greater than one as a missing device will remain
+ * set this to greater than one as a missing device will remain
* unavailable no matter how often the system searches for it.
*
* devid_discovery_postboot (default 1)
@@ -482,9 +483,14 @@ e_ddi_devid_discovery(ddi_devid_t devid)
* As part of registering a devid for a device,
* update the devid cache with this device/devid pair
* or note that this combination has registered.
+ *
+ * If a devpath is provided it will be used as the path to register the
+ * devid against, otherwise we use ddi_pathname(dip). In both cases
+ * we duplicate the path string so that it can be cached/freed indepdently
+ * of the original owner.
*/
-int
-e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
+static int
+e_devid_cache_register_cmn(dev_info_t *dip, ddi_devid_t devid, char *devpath)
{
nvp_devid_t *np;
nvp_devid_t *new_nvp;
@@ -496,23 +502,29 @@ e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
list_t *listp;
int is_dirty = 0;
- /*
- * We are willing to accept DS_BOUND nodes if we can form a full
- * ddi_pathname (i.e. the node is part way to becomming
- * DS_INITIALIZED and devi_addr/ddi_get_name_addr are non-NULL).
- */
- if (ddi_get_name_addr(dip) == NULL) {
- return (DDI_FAILURE);
- }
ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS);
- fullpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
- (void) ddi_pathname(dip, fullpath);
- pathlen = strlen(fullpath) + 1;
- path = kmem_alloc(pathlen, KM_SLEEP);
- bcopy(fullpath, path, pathlen);
- kmem_free(fullpath, MAXPATHLEN);
+ if (devpath) {
+ pathlen = strlen(devpath) + 1;
+ path = kmem_alloc(pathlen, KM_SLEEP);
+ bcopy(devpath, path, pathlen);
+ } else {
+ /*
+ * We are willing to accept DS_BOUND nodes if we can form a full
+ * ddi_pathname (i.e. the node is part way to becomming
+ * DS_INITIALIZED and devi_addr/ddi_get_name_addr are non-NULL).
+ */
+ if (ddi_get_name_addr(dip) == NULL)
+ return (DDI_FAILURE);
+
+ fullpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+ (void) ddi_pathname(dip, fullpath);
+ pathlen = strlen(fullpath) + 1;
+ path = kmem_alloc(pathlen, KM_SLEEP);
+ bcopy(fullpath, path, pathlen);
+ kmem_free(fullpath, MAXPATHLEN);
+ }
DEVID_LOG_REG(("register", devid, path));
@@ -606,6 +618,12 @@ exit:
return (DDI_SUCCESS);
}
+int
+e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
+{
+ return (e_devid_cache_register_cmn(dip, devid, NULL));
+}
+
/*
* Unregister a device's devid
* Called as an instance detachs
@@ -636,6 +654,15 @@ e_devid_cache_unregister(dev_info_t *dip)
rw_exit(nvf_lock(dcfd_handle));
}
+int
+e_devid_cache_pathinfo(mdi_pathinfo_t *pip, ddi_devid_t devid)
+{
+ char *path = mdi_pi_pathname(pip);
+
+ return (e_devid_cache_register_cmn(mdi_pi_get_client(pip), devid,
+ path));
+}
+
/*
* Purge devid cache of stale devids
*/
@@ -987,6 +1014,130 @@ e_devid_cache_free_devt_list(int ndevts, dev_t *devt_list)
kmem_free(devt_list, ndevts * sizeof (dev_t *));
}
+/*
+ * If given a full path and NULL ua, search for a cache entry
+ * whose path matches the full path. On a cache hit duplicate the
+ * devid of the matched entry into the given devid (caller
+ * must free); nodenamebuf is not touched for this usage.
+ *
+ * Given a path and a non-NULL unit address, search the cache for any entry
+ * matching "<path>/%@<unit-address>" where '%' is a wildcard meaning
+ * any node name. The path should not end a '/'. On a cache hit
+ * duplicate the devid as before (caller must free) and copy into
+ * the caller-provided nodenamebuf (if not NULL) the nodename of the
+ * matched entry.
+ *
+ * We must not make use of nvp_dip since that may be NULL for cached
+ * entries that are not present in the current tree.
+ */
+int
+e_devid_cache_path_to_devid(char *path, char *ua,
+ char *nodenamebuf, ddi_devid_t *devidp)
+{
+ size_t pathlen, ualen;
+ int rv = DDI_FAILURE;
+ nvp_devid_t *np;
+ list_t *listp;
+ char *cand;
+
+ if (path == NULL || *path == '\0' || (ua && *ua == '\0') ||
+ devidp == NULL)
+ return (DDI_FAILURE);
+
+ *devidp = NULL;
+
+ if (ua) {
+ pathlen = strlen(path);
+ ualen = strlen(ua);
+ }
+
+ rw_enter(nvf_lock(dcfd_handle), RW_READER);
+
+ listp = nvf_list(dcfd_handle);
+ for (np = list_head(listp); np; np = list_next(listp, np)) {
+ size_t nodelen, candlen, n;
+ ddi_devid_t devid_dup;
+ char *uasep, *node;
+
+ if (np->nvp_devid == NULL)
+ continue;
+
+ if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
+ DEVIDERR((CE_CONT,
+ "pathsearch: invalid devid %s\n",
+ np->nvp_devpath));
+ continue;
+ }
+
+ cand = np->nvp_devpath; /* candidate path */
+
+ /* If a full pathname was provided the compare is easy */
+ if (ua == NULL) {
+ if (strcmp(cand, path) == 0)
+ goto match;
+ else
+ continue;
+ }
+
+ /*
+ * The compare for initial path plus ua and unknown nodename
+ * is trickier.
+ *
+ * Does the initial path component match 'path'?
+ */
+ if (strncmp(path, cand, pathlen) != 0)
+ continue;
+
+ candlen = strlen(cand);
+
+ /*
+ * The next character must be a '/' and there must be no
+ * further '/' thereafter. Begin by checking that the
+ * candidate is long enough to include at mininum a
+ * "/<nodename>@<ua>" after the initial portion already
+ * matched assuming a nodename length of 1.
+ */
+ if (candlen < pathlen + 1 + 1 + 1 + ualen ||
+ cand[pathlen] != '/' ||
+ strchr(cand + pathlen + 1, '/') != NULL)
+ continue;
+
+ node = cand + pathlen + 1; /* <node>@<ua> string */
+
+ /*
+ * Find the '@' before the unit address. Check for
+ * unit address match.
+ */
+ if ((uasep = strchr(node, '@')) == NULL)
+ continue;
+
+ /*
+ * Check we still have enough length and that ua matches
+ */
+ nodelen = (uintptr_t)uasep - (uintptr_t)node;
+ if (candlen < pathlen + 1 + nodelen + 1 + ualen ||
+ strncmp(ua, uasep + 1, ualen) != 0)
+ continue;
+match:
+ n = ddi_devid_sizeof(np->nvp_devid);
+ devid_dup = kmem_alloc(n, KM_SLEEP); /* caller must free */
+ (void) bcopy(np->nvp_devid, devid_dup, n);
+ *devidp = devid_dup;
+
+ if (ua && nodenamebuf) {
+ (void) strncpy(nodenamebuf, node, nodelen);
+ nodenamebuf[nodelen] = '\0';
+ }
+
+ rv = DDI_SUCCESS;
+ break;
+ }
+
+ rw_exit(nvf_lock(dcfd_handle));
+
+ return (rv);
+}
+
#ifdef DEBUG
static void
devid_log(char *fmt, ddi_devid_t devid, char *path)
diff --git a/usr/src/uts/common/os/fm.c b/usr/src/uts/common/os/fm.c
index 7dec9d8b91..78943eda82 100644
--- a/usr/src/uts/common/os/fm.c
+++ b/usr/src/uts/common/os/fm.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -793,6 +792,14 @@ fm_payload_set(nvlist_t *payload, ...)
* detector nvlist_t <detector>
* ereport-payload nvlist_t <var args>
*
+ * We don't actually add a 'version' member to the payload. Really,
+ * the version quoted to us by our caller is that of the category 1
+ * "ereport" event class (and we require FM_EREPORT_VERS0) but
+ * the payload version of the actual leaf class event under construction
+ * may be something else. Callers should supply a version in the varargs,
+ * or (better) we could take two version arguments - one for the
+ * ereport category 1 classification (expect FM_EREPORT_VERS0) and one
+ * for the leaf class.
*/
void
fm_ereport_set(nvlist_t *ereport, int version, const char *erpt_class,
@@ -925,46 +932,41 @@ fm_fmri_hc_set(nvlist_t *fmri, int version, const nvlist_t *auth,
* version uint8_t 0
* auth nvlist_t <auth>
* devpath string <devpath>
- * devid string <devid>
+ * [devid] string <devid>
+ * [target-port-l0id] string <target-port-lun0-id>
*
* Note that auth and devid are optional members.
*/
void
fm_fmri_dev_set(nvlist_t *fmri_dev, int version, const nvlist_t *auth,
- const char *devpath, const char *devid)
+ const char *devpath, const char *devid, const char *tpl0)
{
- if (version != DEV_SCHEME_VERSION0) {
- atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
- return;
- }
+ int err = 0;
- if (nvlist_add_uint8(fmri_dev, FM_VERSION, version) != 0) {
+ if (version != DEV_SCHEME_VERSION0) {
atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
return;
}
- if (nvlist_add_string(fmri_dev, FM_FMRI_SCHEME,
- FM_FMRI_SCHEME_DEV) != 0) {
- atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
- return;
- }
+ err |= nvlist_add_uint8(fmri_dev, FM_VERSION, version);
+ err |= nvlist_add_string(fmri_dev, FM_FMRI_SCHEME, FM_FMRI_SCHEME_DEV);
if (auth != NULL) {
- if (nvlist_add_nvlist(fmri_dev, FM_FMRI_AUTHORITY,
- (nvlist_t *)auth) != 0) {
- atomic_add_64(
- &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
- }
+ err |= nvlist_add_nvlist(fmri_dev, FM_FMRI_AUTHORITY,
+ (nvlist_t *)auth);
}
- if (nvlist_add_string(fmri_dev, FM_FMRI_DEV_PATH, devpath) != 0) {
- atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
- }
+ err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_PATH, devpath);
if (devid != NULL)
- if (nvlist_add_string(fmri_dev, FM_FMRI_DEV_ID, devid) != 0)
- atomic_add_64(
- &erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+ err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_ID, devid);
+
+ if (tpl0 != NULL)
+ err |= nvlist_add_string(fmri_dev, FM_FMRI_DEV_TGTPTLUN0, tpl0);
+
+ if (err)
+ atomic_add_64(&erpt_kstat_data.fmri_set_failed.value.ui64, 1);
+
}
/*
diff --git a/usr/src/uts/common/os/pcifm.c b/usr/src/uts/common/os/pcifm.c
index 8a1c343b9c..fa6e819a5b 100644
--- a/usr/src/uts/common/os/pcifm.c
+++ b/usr/src/uts/common/os/pcifm.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -1187,7 +1186,7 @@ pci_fm_ereport_post(dev_info_t *dip, const char *error_class, uint64_t ena,
(void) ddi_pathname(dip, device_path);
fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
- device_path, NULL);
+ device_path, NULL, NULL);
(void) snprintf(ddi_error_class, FM_MAX_CLASS, "%s.%s",
DDI_IO_CLASS, error_class);
fm_ereport_set(ereport, version, ddi_error_class, ena, detector, NULL);
diff --git a/usr/src/uts/common/sys/fm/protocol.h b/usr/src/uts/common/sys/fm/protocol.h
index fbf614caa2..c4103c48a4 100644
--- a/usr/src/uts/common/sys/fm/protocol.h
+++ b/usr/src/uts/common/sys/fm/protocol.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_FM_PROTOCOL_H
@@ -247,6 +246,7 @@ extern "C" {
/* dev scheme member names */
#define FM_FMRI_DEV_ID "devid"
+#define FM_FMRI_DEV_TGTPTLUN0 "target-port-l0id"
#define FM_FMRI_DEV_PATH "device-path"
/* pkg scheme member names */
@@ -315,7 +315,7 @@ extern int i_fm_payload_set(nvlist_t *, const char *, va_list);
extern void fm_fmri_hc_set(nvlist_t *, int, const nvlist_t *, nvlist_t *,
int, ...);
extern void fm_fmri_dev_set(nvlist_t *, int, const nvlist_t *, const char *,
- const char *);
+ const char *, const char *);
extern void fm_fmri_de_set(nvlist_t *, int, const nvlist_t *, const char *);
extern void fm_fmri_cpu_set(nvlist_t *, int, const nvlist_t *, uint32_t,
uint8_t *, const char *);
diff --git a/usr/src/uts/common/sys/scsi/scsi_fm.h b/usr/src/uts/common/sys/scsi/scsi_fm.h
index 9001fcb156..e232da04b1 100644
--- a/usr/src/uts/common/sys/scsi/scsi_fm.h
+++ b/usr/src/uts/common/sys/scsi/scsi_fm.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_SCSI_SCSI_FM_H
@@ -40,7 +39,8 @@ void scsi_fm_fini(struct scsi_device *);
/* ereport generation: */
void scsi_fm_ereport_post(struct scsi_device *sd, int path_instance,
- const char *error_class, uint64_t ena, char *devid, int sflag, ...);
+ char *devpath, const char *error_class, uint64_t ena,
+ char *devid, char *tpl0, int sflag, nvlist_t *pl, ...);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/sun4u/io/pci/pci_ecc.c b/usr/src/uts/sun4u/io/pci/pci_ecc.c
index e731b1578c..a4f11d7842 100644
--- a/usr/src/uts/sun4u/io/pci/pci_ecc.c
+++ b/usr/src/uts/sun4u/io/pci/pci_ecc.c
@@ -19,12 +19,9 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* PCI ECC support
*/
@@ -92,9 +89,9 @@ ecc_create(pci_t *pci_p)
DEBUG1(DBG_ATTACH, dip, "ecc_create: csr=%x\n", ecc_p->ecc_csr_pa);
DEBUG2(DBG_ATTACH, dip, "ecc_create: ue_afsr=%x, ue_afar=%x\n",
- ecc_p->ecc_ue.ecc_afsr_pa, ecc_p->ecc_ue.ecc_afar_pa);
+ ecc_p->ecc_ue.ecc_afsr_pa, ecc_p->ecc_ue.ecc_afar_pa);
DEBUG2(DBG_ATTACH, dip, "ecc_create: ce_afsr=%x, ce_afar=%x\n",
- ecc_p->ecc_ce.ecc_afsr_pa, ecc_p->ecc_ce.ecc_afar_pa);
+ ecc_p->ecc_ce.ecc_afsr_pa, ecc_p->ecc_ce.ecc_afar_pa);
ecc_configure(pci_p);
@@ -167,11 +164,11 @@ ecc_configure(pci_t *pci_p)
*/
DEBUG0(DBG_ATTACH, dip, "ecc_configure: clearing UE and CE errors\n");
l = (COMMON_ECC_UE_AFSR_E_MASK << COMMON_ECC_UE_AFSR_PE_SHIFT) |
- (COMMON_ECC_UE_AFSR_E_MASK << COMMON_ECC_UE_AFSR_SE_SHIFT);
+ (COMMON_ECC_UE_AFSR_E_MASK << COMMON_ECC_UE_AFSR_SE_SHIFT);
stdphysio(ecc_p->ecc_ue.ecc_afsr_pa, l);
l = (COMMON_ECC_CE_AFSR_E_MASK << COMMON_ECC_CE_AFSR_PE_SHIFT) |
- (COMMON_ECC_CE_AFSR_E_MASK << COMMON_ECC_CE_AFSR_SE_SHIFT);
+ (COMMON_ECC_CE_AFSR_E_MASK << COMMON_ECC_CE_AFSR_SE_SHIFT);
stdphysio(ecc_p->ecc_ce.ecc_afsr_pa, l);
/*
@@ -339,19 +336,19 @@ ecc_errstate_get(ecc_errstate_t *ecc_err_p)
ecc_err_p->ecc_afar = lddphysio(ecc_err_p->ecc_ii_p.ecc_afar_pa);
ecc_err_p->ecc_offset = ((ecc_err_p->ecc_afsr &
- ecc_err_p->ecc_ii_p.ecc_offset_mask) >>
- ecc_err_p->ecc_ii_p.ecc_offset_shift) <<
- ecc_err_p->ecc_ii_p.ecc_size_log2;
+ ecc_err_p->ecc_ii_p.ecc_offset_mask) >>
+ ecc_err_p->ecc_ii_p.ecc_offset_shift) <<
+ ecc_err_p->ecc_ii_p.ecc_size_log2;
ecc_err_p->ecc_aflt.flt_id = gethrtime();
ecc_err_p->ecc_aflt.flt_stat = ecc_err_p->ecc_afsr;
ecc_err_p->ecc_aflt.flt_addr = P2ALIGN(ecc_err_p->ecc_afar, 64) +
- ecc_err_p->ecc_offset;
+ ecc_err_p->ecc_offset;
ecc_err_p->ecc_aflt.flt_bus_id = bus_id;
ecc_err_p->ecc_aflt.flt_inst = CPU->cpu_id;
ecc_err_p->ecc_aflt.flt_status = ECC_IOBUS;
- ecc_err_p->ecc_aflt.flt_in_memory = (pf_is_memory
- (ecc_err_p->ecc_afar >> MMU_PAGESHIFT))? 1: 0;
+ ecc_err_p->ecc_aflt.flt_in_memory =
+ (pf_is_memory(ecc_err_p->ecc_afar >> MMU_PAGESHIFT))? 1: 0;
ecc_err_p->ecc_aflt.flt_class = BUS_FAULT;
}
@@ -433,21 +430,21 @@ ecc_err_handler(ecc_errstate_t *ecc_err_p)
ecc_errstate_get(ecc_err_p);
pri_err = (ecc_err_p->ecc_afsr >> COMMON_ECC_UE_AFSR_PE_SHIFT) &
- COMMON_ECC_UE_AFSR_E_MASK;
+ COMMON_ECC_UE_AFSR_E_MASK;
sec_err = (ecc_err_p->ecc_afsr >> COMMON_ECC_UE_AFSR_SE_SHIFT) &
- COMMON_ECC_UE_AFSR_E_MASK;
+ COMMON_ECC_UE_AFSR_E_MASK;
switch (ecc_ii_p->ecc_type) {
case CBNINTR_UE:
if (pri_err) {
ecc_err_p->ecc_aflt.flt_synd =
- pci_ecc_get_synd(ecc_err_p->ecc_afsr);
+ pci_ecc_get_synd(ecc_err_p->ecc_afsr);
ecc_err_p->ecc_pri = 1;
pci_ecc_classify(pri_err, ecc_err_p);
errorq_dispatch(pci_ecc_queue, (void *)ecc_err_p,
- sizeof (ecc_errstate_t),
- ecc_err_p->ecc_aflt.flt_panic);
+ sizeof (ecc_errstate_t),
+ ecc_err_p->ecc_aflt.flt_panic);
}
if (sec_err) {
ecc_sec_err = *ecc_err_p;
@@ -474,7 +471,7 @@ ecc_err_handler(ecc_errstate_t *ecc_err_p)
ecc_err_p->ecc_aflt.flt_panic = 1;
if (ecc_err_p->ecc_aflt.flt_panic &&
- ecc_err_p->ecc_aflt.flt_in_memory)
+ ecc_err_p->ecc_aflt.flt_in_memory)
panic_aflt = ecc_err_p->ecc_aflt;
if (ecc_err_p->ecc_aflt.flt_panic) {
@@ -492,10 +489,10 @@ ecc_err_handler(ecc_errstate_t *ecc_err_p)
ecc_err_p->ecc_pri = 1;
pci_ecc_classify(pri_err, ecc_err_p);
ecc_err_p->ecc_aflt.flt_synd =
- pci_ecc_get_synd(ecc_err_p->ecc_afsr);
+ pci_ecc_get_synd(ecc_err_p->ecc_afsr);
ce_scrub(&ecc_err_p->ecc_aflt);
errorq_dispatch(pci_ecc_queue, (void *)ecc_err_p,
- sizeof (ecc_errstate_t), ERRORQ_ASYNC);
+ sizeof (ecc_errstate_t), ERRORQ_ASYNC);
nonfatal++;
}
if (sec_err) {
@@ -587,7 +584,7 @@ ecc_err_drain(void *not_used, ecc_errstate_t *ecc_err, errorq_elem_t *eqep)
}
ecc_cpu_call(ecc, ecc_err->ecc_unum, (ecc_type == CBNINTR_UE) ?
- ECC_IO_UE : ECC_IO_CE);
+ ECC_IO_UE : ECC_IO_CE);
switch (ecc_type) {
case CBNINTR_UE:
@@ -681,7 +678,7 @@ ecc_ereport_post(dev_info_t *dip, ecc_errstate_t *ecc_err)
ecc_err->ecc_bridge_type, ecc_err->ecc_aflt.flt_erpt_class);
ecc_err->ecc_ena = ecc_err->ecc_ena ? ecc_err->ecc_ena :
- fm_ena_generate(0, FM_ENA_FMT1);
+ fm_ena_generate(0, FM_ENA_FMT1);
eqep = errorq_reserve(fmhdl->fh_errorq);
if (eqep == NULL)
@@ -701,7 +698,8 @@ ecc_ereport_post(dev_info_t *dip, ecc_errstate_t *ecc_err)
if (ptr)
*ptr = '\0';
- fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, dev_path, NULL);
+ fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, dev_path,
+ NULL, NULL);
if (ecc_err->ecc_pri) {
if ((ecc_err->ecc_fmri = fm_nvlist_create(nva)) != NULL) {
diff --git a/usr/src/uts/sun4u/io/pci/pcisch.c b/usr/src/uts/sun4u/io/pci/pcisch.c
index 1100f8754a..27916bcc74 100644
--- a/usr/src/uts/sun4u/io/pci/pcisch.c
+++ b/usr/src/uts/sun4u/io/pci/pcisch.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -2839,7 +2838,8 @@ cb_ereport_post(dev_info_t *dip, uint64_t ena, cb_errstate_t *cb_err)
if (ptr)
*ptr = '\0';
- fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, dev_path, NULL);
+ fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, dev_path,
+ NULL, NULL);
DEBUG1(DBG_ERR_INTR, dip, "cb_ereport_post: ereport_set: %s", buf);
diff --git a/usr/src/uts/sun4u/opl/io/mc-opl.c b/usr/src/uts/sun4u/opl/io/mc-opl.c
index e76abf21a3..7d267110da 100644
--- a/usr/src/uts/sun4u/opl/io/mc-opl.c
+++ b/usr/src/uts/sun4u/opl/io/mc-opl.c
@@ -19,14 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
* All Rights Reserved, Copyright (c) FUJITSU LIMITED 2008
*/
-
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/conf.h>
@@ -968,7 +966,7 @@ mc_ereport_post(mc_aflt_t *mc_aflt)
flt_stat = mc_aflt->mflt_stat[0];
(void) ddi_pathname(mc_aflt->mflt_mcp->mc_dip, device_path);
(void) fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
- device_path, NULL);
+ device_path, NULL, NULL);
/*
* Encode all the common data into the ereport.