summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/fm/dicts/PCIEX.dict4
-rw-r--r--usr/src/cmd/fm/dicts/PCIEX.po68
-rw-r--r--usr/src/cmd/fm/dicts/SUN4V.dict3
-rw-r--r--usr/src/cmd/fm/dicts/SUN4V.po16
-rw-r--r--usr/src/cmd/fm/eversholt/files/Makefile.com10
-rw-r--r--usr/src/cmd/fm/eversholt/files/common/pciexrc.esc218
-rw-r--r--usr/src/cmd/fm/eversholt/files/i386/Makefile1
-rw-r--r--usr/src/cmd/fm/eversholt/files/sparc/Makefile1
-rw-r--r--usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile4
-rw-r--r--usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc10
-rw-r--r--usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc37
-rw-r--r--usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc37
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/Makefile7
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c1971
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf2
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h173
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c262
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c834
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c396
-rw-r--r--usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c837
-rw-r--r--usr/src/cmd/mdb/common/modules/crypto/impl.c6
21 files changed, 2923 insertions, 1974 deletions
diff --git a/usr/src/cmd/fm/dicts/PCIEX.dict b/usr/src/cmd/fm/dicts/PCIEX.dict
index 5edb88e848..b2934b9de6 100644
--- a/usr/src/cmd/fm/dicts/PCIEX.dict
+++ b/usr/src/cmd/fm/dicts/PCIEX.dict
@@ -50,3 +50,7 @@ fault.io.pciex.device-interr-unaf=20
fault.io.pciex.device-interr-deg=21
fault.io.pciex.fw_corrupt=22
fault.io.pciex.fw_mismatch=23
+fault.io.pciex.rc.generic-ce=24
+fault.io.pciex.rc.generic-ue=25
+fault.io.pciex.rc.generic-sw=26
+fault.io.pciex.rc.generic-fw=27
diff --git a/usr/src/cmd/fm/dicts/PCIEX.po b/usr/src/cmd/fm/dicts/PCIEX.po
index 09bb2c2fc2..a35c83b22a 100644
--- a/usr/src/cmd/fm/dicts/PCIEX.po
+++ b/usr/src/cmd/fm/dicts/PCIEX.po
@@ -390,7 +390,7 @@ msgstr "One or more device instances may be disabled.\n"
msgid "PCIEX-8000-PY.impact"
msgstr "Degraded services provided by the device instances associated with this fault.\n"
msgid "PCIEX-8000-PY.action"
-msgstr "Use fmadm faulty to identify the device and then update the firmware to the latest version or schedule a repair procedure to replace the affected device. Contact Sun support for further information.\n"
+msgstr "Use 'fmadm faulty' to identify the device and then update the firmware to the latest version or schedule a repair procedure to replace the affected device. Contact Sun support for further information.\n"
#
# code: PCIEX-8000-Q3
# keys: fault.io.pciex.fw_mismatch
@@ -406,4 +406,68 @@ msgstr "One or more device instances may be disabled.\n"
msgid "PCIEX-8000-Q3.impact"
msgstr "Degraded services provided by the device instances associated with this fault.\n"
msgid "PCIEX-8000-Q3.action"
-msgstr "Use fmadm faulty to identify the device and then update the firmware to the latest version. Contact Sun support for further information.\n"
+msgstr "Use 'fmadm faulty' to identify the device and then update the firmware to the latest version. Contact Sun support for further information.\n"
+#
+# code: PCIEX-8000-RC
+# keys: fault.io.pciex.rc.generic-ce
+#
+msgid "PCIEX-8000-RC.type"
+msgstr "Fault"
+msgid "PCIEX-8000-RC.severity"
+msgstr "Critical"
+msgid "PCIEX-8000-RC.description"
+msgstr "The number of correctable errors detected in the PCIe Root Complex has crossed the allowed threshold.\n"
+msgid "PCIEX-8000-RC.response"
+msgstr "One or more device instances may be disabled\n"
+msgid "PCIEX-8000-RC.impact"
+msgstr "Loss of services provided by the device\ninstances associated with this fault\n"
+msgid "PCIEX-8000-RC.action"
+msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n"
+#
+# code: PCIEX-8000-SQ
+# keys: fault.io.pciex.rc.generic-ue
+#
+msgid "PCIEX-8000-SQ.type"
+msgstr "Fault"
+msgid "PCIEX-8000-SQ.severity"
+msgstr "Critical"
+msgid "PCIEX-8000-SQ.description"
+msgstr "An uncorrectable error was detected in the PCIe Root Complex.\n Refer to %s for more information."
+msgid "PCIEX-8000-SQ.response"
+msgstr "One or more device instances may be disabled\n"
+msgid "PCIEX-8000-SQ.impact"
+msgstr "Loss of services provided by the device\ninstances associated with this fault\n"
+msgid "PCIEX-8000-SQ.action"
+msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n"
+#
+# code: PCIEX-8000-T4
+# keys: fault.io.pciex.rc.generic-sw
+#
+msgid "PCIEX-8000-T4.type"
+msgstr "Fault"
+msgid "PCIEX-8000-T4.severity"
+msgstr "Critical"
+msgid "PCIEX-8000-T4.description"
+msgstr "A defect in the PCIe Root Complex or Root Port code has been detected.\n Refer to %s for more information."
+msgid "PCIEX-8000-T4.response"
+msgstr "One or more device instances may be disabled\n"
+msgid "PCIEX-8000-T4.impact"
+msgstr "Loss of services provided by the device\ninstances associated with this fault\n"
+msgid "PCIEX-8000-T4.action"
+msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n"
+#
+# code: PCIEX-8000-UR
+# keys: fault.io.pciex.rc.generic-fw
+#
+msgid "PCIEX-8000-UR.type"
+msgstr "Fault"
+msgid "PCIEX-8000-UR.severity"
+msgstr "Critical"
+msgid "PCIEX-8000-UR.description"
+msgstr "A defective firmware associated with the PCIe Root Complex has been detected.\n Refer to %s for more information."
+msgid "PCIEX-8000-UR.response"
+msgstr "One or more device instances may be disabled\n"
+msgid "PCIEX-8000-UR.impact"
+msgstr "Loss of services provided by the device\ninstances associated with this fault\n"
+msgid "PCIEX-8000-UR.action"
+msgstr "Schedule a repair procedure to replace the affected\ndevice if necessary, or contact Sun for support.\n"
diff --git a/usr/src/cmd/fm/dicts/SUN4V.dict b/usr/src/cmd/fm/dicts/SUN4V.dict
index cdf7683b33..ba51084f36 100644
--- a/usr/src/cmd/fm/dicts/SUN4V.dict
+++ b/usr/src/cmd/fm/dicts/SUN4V.dict
@@ -1,5 +1,5 @@
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
@@ -116,3 +116,4 @@ fault.memory.memlink-uc=87
defect.fw.generic-sparc.addr-oob=88
defect.fw.generic-sparc.erpt-gen=89
fault.cpu.generic-sparc.bootbus=90
+fault.sp.failed=91
diff --git a/usr/src/cmd/fm/dicts/SUN4V.po b/usr/src/cmd/fm/dicts/SUN4V.po
index 7066e61dc3..34da106f9c 100644
--- a/usr/src/cmd/fm/dicts/SUN4V.po
+++ b/usr/src/cmd/fm/dicts/SUN4V.po
@@ -1463,3 +1463,19 @@ msgid "SUN4V-8002-T5.impact"
msgstr "The system's integrity is seriously compromised. Processor chip(s)\nmay be unavailable.\n"
msgid "SUN4V-8002-T5.action"
msgstr "Schedule a repair procedure to replace the affected resource, the identity of which can be determined using 'fmadm faulty'.\n"
+#
+# code: SUN4V-8002-US
+# keys: fault.sp.failed
+#
+msgid "SUN4V-8002-US.type"
+msgstr "Fault"
+msgid "SUN4V-8002-US.severity"
+msgstr "Critical"
+msgid "SUN4V-8002-US.description"
+msgstr "The Service Processor failed.\n Refer to %s for more information."
+msgid "SUN4V-8002-US.response"
+msgstr "No automated response.\n"
+msgid "SUN4V-8002-US.impact"
+msgstr "Some services such as Fault Diagnosis may be degraded as a result.\n"
+msgid "SUN4V-8002-US.action"
+msgstr "Schedule a repair procedure for the Service Processor, or contact Sun for support.\n"
diff --git a/usr/src/cmd/fm/eversholt/files/Makefile.com b/usr/src/cmd/fm/eversholt/files/Makefile.com
index 88ed0680f2..c5a22b3a7b 100644
--- a/usr/src/cmd/fm/eversholt/files/Makefile.com
+++ b/usr/src/cmd/fm/eversholt/files/Makefile.com
@@ -19,10 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
.SUFFIXES: .eft .esc
@@ -54,8 +53,11 @@ clean clobber:
$(RM) $(EFT_PLAT_FILES) $(EFT_COMMON_FILES) \
$(USR_PLAT_EFT_FILES) $(ROOT_COMMON_EFT_FILES)
+ESCFLAGS= -D_ESC -I$(ROOT)/usr/include
+pciexrc.eft := ESCFLAGS += -I$(SRC)/uts/sun4v/io/px
+
%.eft: ../common/%.esc
- $(ESC) -I$(ROOT)/usr/include -o $@ $<
+ $(ESC) $(ESCFLAGS) -o $@ $<
%.eft: %.esc
- $(ESC) -o $@ $<
+ $(ESC) $(ESCFLAGS) -o $@ $<
diff --git a/usr/src/cmd/fm/eversholt/files/common/pciexrc.esc b/usr/src/cmd/fm/eversholt/files/common/pciexrc.esc
new file mode 100644
index 0000000000..66a4921b2d
--- /dev/null
+++ b/usr/src/cmd/fm/eversholt/files/common/pciexrc.esc
@@ -0,0 +1,218 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma dictionary "PCIEX"
+
+#include <px_err.h>
+
+/*
+ * generic root complex/root port diagnosis rules
+ */
+
+#define PCIEXFN pciexbus/pciexdev/pciexfn
+#define PCIEXFNHZ pciexbus<>/pciexdev<>/pciexfn<>
+
+#define RC_N 5
+#define RC_T 72h
+
+#define SW_FIT 5000
+#define FW_FIT 5000
+#define HB_FIT 400
+
+#define EPKT_DESC (payloadprop("desc") >> 12)
+#define EPKT_B_BIT (payloadprop("desc") & (1 << 7))
+#define EPKT_C_BIT (payloadprop("desc") & (1 << 5))
+#define EPKT_H_BIT (payloadprop("desc") & (1 << 4))
+
+#define MATCHES_DESC(b, o, p, c, d) \
+ (EPKT_DESC == (b << 16 | o << 12 | p << 8 | c << 4 | d))
+
+#define IS_CE (EPKT_C_BIT != 0 && setserdsuffix(EPKT_DESC))
+#define IS_UE (EPKT_C_BIT == 0)
+#define IS_BLOCKED (EPKT_B_BIT != 0)
+
+#define EPKT(b, o, p, c, d) \
+ ereport.io.pciex.rc.epkt@hostbridge { MATCHES_DESC(b, o, p, c, d) }
+
+/* Ereport Events */
+event ereport.io.pciex.rc.epkt@hostbridge {within(5s)};
+
+/* Internal Events */
+event error.io.pciex.rc.stall@hostbridge;
+event error.io.pciex.rc.poiscomp@hostbridge;
+event error.io.pciex.nr-d@hostbridge/pciexrc/PCIEXFN;
+event error.io.pciex.badreq-u@hostbridge/pciexrc/PCIEXFN;
+event error.io.pciex.poiscomp-d@hostbridge/pciexrc/PCIEXFN;
+event error.io.pciex.noimpact-d@hostbridge/pciexrc/PCIEXFN;
+event error.io.pciex.lost-d@hostbridge/pciexrc/PCIEXFN;
+event error.io.pciex.degraded-d@hostbridge/pciexrc/PCIEXFN;
+
+/* Upset event */
+event upset.io.pciex.rc.discard@hostbridge;
+
+/*
+ * Fault Events
+ * Do no retire and FRUs for SW/FW faults
+ */
+event fault.io.pciex.rc.generic-ue@hostbridge,
+ FITrate=HB_FIT, retire=0, response=0;
+event fault.io.pciex.rc.generic-sw@hostbridge,
+ FITrate=SW_FIT, retire=0, response=0;
+event fault.io.pciex.rc.generic-fw@hostbridge,
+ FITrate=FW_FIT, retire=0, response=0;
+
+/* Serd engine for CE errors */
+engine serd.io.pciex.rc.generic-ce@hostbridge, N=RC_N, T=RC_T;
+event fault.io.pciex.rc.generic-ce@hostbridge, FITrate=HB_FIT,
+ engine=serd.io.pciex.rc.generic-ce@hostbridge;
+
+/* Fire faults */
+event fault.io.fire.pciex.device@PCIEXFN, FITrate=1000;
+event fault.io.fire.pci.device@pcibus/pcidev/pcifn, FITrate=1000;
+
+/* Generic Root Complex Software faults */
+prop fault.io.pciex.rc.generic-sw@hostbridge ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_INTR,OP_FIXED,PH_UNKNOWN,CND_ILL,DIR_INGRESS) ||
+ MATCHES_DESC(BLOCK_INTR,OP_MSI32,PH_UNKNOWN,CND_ILL,DIR_IRR) ||
+ MATCHES_DESC(BLOCK_INTR,OP_PCIEMSG,PH_UNKNOWN,CND_ILL,DIR_INGRESS)
+ };
+
+/* Generic Root Complex Firmware faults */
+prop fault.io.pciex.rc.generic-fw@hostbridge ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_PIO,PH_ADDR,CND_UNMAP,DIR_WRITE)
+ };
+
+/* Generic Root Complex CE faults */
+prop fault.io.pciex.rc.generic-ce@hostbridge { IS_CE } ->
+ ereport.io.pciex.rc.epkt@hostbridge;
+
+/* Generic Root Complex UE faults from propagations */
+event error.io.pciex.rc.generic-ue1@hostbridge;
+event error.io.pciex.rc.generic-ue2@hostbridge;
+
+prop fault.io.pciex.rc.generic-ue@hostbridge ->
+ error.io.pciex.rc.generic-ue1@hostbridge,
+ error.io.pciex.rc.generic-ue2@hostbridge,
+ error.io.pciex.rc.stall@hostbridge,
+ error.io.pciex.rc.poiscomp@hostbridge;
+
+/* Generic Root Complex UE propagations */
+prop error.io.pciex.rc.generic-ue1@hostbridge { IS_UE && !IS_BLOCKED } ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_READ) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_WRITE) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_TO,DIR_READ) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_TO,DIR_WRITE) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_PIO,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_INTR,OP_MSI32,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_INTR,OP_MSIQ,PH_DATA,CND_INT,DIR_UNKNOWN)
+ };
+
+prop error.io.pciex.rc.generic-ue2@hostbridge { IS_UE && !IS_BLOCKED } ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_ADDR,CND_UNKNOWN,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_ADDR,CND_UNMAP,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_DATA,CND_INT,DIR_IRR) ||
+ MATCHES_DESC(BLOCK_MMU,OP_TBW,PH_UNKNOWN,CND_UNKNOWN,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_PORT,OP_DMA,PH_DATA,CND_INT,DIR_READ) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_DATA,CND_INT,DIR_READ) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_PORT,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN) ||
+ MATCHES_DESC(BLOCK_PORT,OP_UNKNOWN,PH_DATA,CND_INT,DIR_UNKNOWN)
+ };
+
+/* Errors that will cause a pipe stall and thus a CTO in the fabric */
+prop error.io.pciex.rc.stall@hostbridge (0) ->
+ error.io.pciex.nr-d@hostbridge/pciexrc<>/PCIEXFNHZ;
+
+prop error.io.pciex.rc.stall@hostbridge { IS_UE && IS_BLOCKED } ->
+ ereport.io.pciex.rc.epkt@hostbridge;
+
+/*
+ * Errors that will send a poisoned data to the fabric
+ * Also the poiscomp-d could represent a fault that a hardened driver
+ * handled and reported a service impact.
+ */
+prop error.io.pciex.rc.poiscomp@hostbridge (0) ->
+ error.io.pciex.poiscomp-d@hostbridge/pciexrc<>/PCIEXFNHZ,
+ error.io.pciex.noimpact-d@hostbridge/pciexrc<>/PCIEXFNHZ,
+ error.io.pciex.lost-d@hostbridge/pciexrc<>/PCIEXFNHZ,
+ error.io.pciex.degraded-d@hostbridge/pciexrc<>/PCIEXFNHZ;
+
+prop error.io.pciex.rc.poiscomp@hostbridge { IS_UE && !IS_BLOCKED } ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_HOSTBUS,OP_DMA,PH_DATA,CND_INT,DIR_READ)
+ };
+
+prop error.io.pciex.badreq-u@hostbridge/pciexrc/PCIEXFN { IS_UE && !IS_BLOCKED } (0) ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_ADDR,CND_UNMAP,DIR_RDWR) ||
+ MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_DATA,CND_INV,DIR_RDWR) ||
+ MATCHES_DESC(BLOCK_MMU,OP_XLAT,PH_DATA,CND_PROT,DIR_RDWR)
+ };
+
+prop upset.io.pciex.rc.discard@hostbridge ->
+ ereport.io.pciex.rc.epkt@hostbridge {
+ MATCHES_DESC(BLOCK_INTR,OP_MSI32,PH_DATA,CND_ILL,DIR_IRR) ||
+ MATCHES_DESC(BLOCK_PORT,OP_LINK,PH_FC,CND_TO,DIR_IRR) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_INV,DIR_RDWR) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_RCA,DIR_WRITE) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_RUR,DIR_WRITE) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_TO,DIR_READ) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_TO,DIR_WRITE) ||
+ MATCHES_DESC(BLOCK_PORT,OP_PIO,PH_IRR,CND_UC,DIR_IRR)
+ };
+
+/* Event queue overflow */
+#define PROP_PLAT_FRU "FRU"
+#define GET_HB_FRU (confprop(asru(hostbridge), PROP_PLAT_FRU))
+#define GET_PCIE_FRU (confprop(asru(pciexbus[b]/pciexdev[d]/pciexfn[0]), PROP_PLAT_FRU))
+#define GET_PCI_FRU (confprop(asru(pcibus[b]/pcidev[d]/pcifn[0]), PROP_PLAT_FRU))
+
+prop fault.io.fire.pciex.device@pciexbus[b]/pciexdev[d]/pciexfn[0]
+ {
+ /*
+ * Indict PCI-E FRU(s) under this root complex excluding the
+ * one that the Fire ASIC resides on.
+ */
+ is_under(hostbridge, pciexbus[b]/pciexdev[d]/pciexfn[0]) &&
+ (GET_HB_FRU != GET_PCIE_FRU)
+ } (0) -> EPKT(BLOCK_INTR,OP_MSIQ,PH_UNKNOWN,CND_OV,DIR_IRR);
+
+prop fault.io.fire.pci.device@pcibus[b]/pcidev[d]/pcifn[0]
+ {
+ /*
+ * Indict PCI FRU(s) under this root complex excluding the
+ * one that the Fire ASIC resides on.
+ */
+ is_under(hostbridge, pcibus[b]/pcidev[d]/pcifn[0]) &&
+ (GET_HB_FRU != GET_PCI_FRU)
+ } (0) -> EPKT(BLOCK_INTR,OP_MSIQ,PH_UNKNOWN,CND_OV,DIR_IRR);
diff --git a/usr/src/cmd/fm/eversholt/files/i386/Makefile b/usr/src/cmd/fm/eversholt/files/i386/Makefile
index 37ad297e4a..80c9314087 100644
--- a/usr/src/cmd/fm/eversholt/files/i386/Makefile
+++ b/usr/src/cmd/fm/eversholt/files/i386/Makefile
@@ -30,6 +30,7 @@ EFT_COMMON_FILES= \
neptune_xfp.eft \
pci.eft \
pciex.eft \
+ pciexrc.eft \
sca500.eft \
sca1000.eft \
sensor.eft
diff --git a/usr/src/cmd/fm/eversholt/files/sparc/Makefile b/usr/src/cmd/fm/eversholt/files/sparc/Makefile
index c0ca8fbb4c..e128505266 100644
--- a/usr/src/cmd/fm/eversholt/files/sparc/Makefile
+++ b/usr/src/cmd/fm/eversholt/files/sparc/Makefile
@@ -30,6 +30,7 @@ EFT_COMMON_FILES= \
neptune_xfp.eft \
pci.eft \
pciex.eft \
+ pciexrc.eft \
sca500.eft \
sca1000.eft \
sensor.eft
diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile
index ea5a28b6e4..f884926bd5 100644
--- a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile
+++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
@@ -28,7 +28,7 @@ include ../sun4/Makefile.sun4
EFT_PLAT= sun4v
SUN4VEFTFILES= n2piu.eft vfncx.eft n2niu_xaui.eft n2niu_xfp.eft zambezi.eft \
-gcpu.eft gmem.eft
+gcpu.eft gmem.eft sp.eft
EFT_PLAT_FILES= $(SUN4VEFTFILES) $(SUN4EFTFILES)
include ../../Makefile.com
diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc
index fbb361ccfc..35af8529df 100644
--- a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc
+++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gcpu.esc
@@ -437,10 +437,11 @@ prop upset.fw.generic-sparc.erpt-gen@chassis
{ !DIAGNOSE_ERPT } (0) ->
ereport.cpu.generic-sparc.inconsistent@chassis;
/*
- * bootbus-to and bootbus-par errors. Fault the detector.
+ * bootbus-prot, bootbus-to and bootbus-par errors. Fault the detector.
*/
event ereport.cpu.generic-sparc.bootbus-to@chip;
event ereport.cpu.generic-sparc.bootbus-par@chip;
+event ereport.cpu.generic-sparc.bootbus-prot@chip;
event upset.cpu.generic-sparc.bootbus@chip;
event fault.cpu.generic-sparc.bootbus@chip, retire=0;
@@ -453,10 +454,15 @@ prop fault.cpu.generic-sparc.bootbus@chip
{ DIAGNOSE_ERPT } (0) ->
ereport.cpu.generic-sparc.bootbus-par@chip;
+prop fault.cpu.generic-sparc.bootbus@chip
+ { DIAGNOSE_ERPT } (0) ->
+ ereport.cpu.generic-sparc.bootbus-prot@chip;
+
prop upset.cpu.generic-sparc.bootbus@chip
{ !DIAGNOSE_ERPT } (0) ->
ereport.cpu.generic-sparc.bootbus-to@chip,
- ereport.cpu.generic-sparc.bootbus-par@chip;
+ ereport.cpu.generic-sparc.bootbus-par@chip,
+ ereport.cpu.generic-sparc.bootbus-prot@chip;
/*
* ignore the pio-read error.
diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc
index 3f36baeda1..a63d0711bb 100644
--- a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc
+++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/gmem.esc
@@ -184,7 +184,7 @@ prop upset.memory.memlink@MEM_CTRL
ereport.cpu.generic-sparc.membuf-crc@MEM_CTRL;
/*
- * membuf-crc-uc will fault the detector FRU and sender FRU
+ * membuf-crc-uc, membuf-other-uc will fault the detector FRU and sender FRU
* if detector is CHIP or MEM_CTRL, the sender is MEM_BUFF.
* if detector is MEM_BUFF, the sender is CHIP or MEM_CTRL
*/
@@ -192,6 +192,10 @@ event ereport.cpu.generic-sparc.membuf-crc-uc@CHIP { within(1s) };
event ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF { within(1s) };
event ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL { within(1s) };
+event ereport.cpu.generic-sparc.membuf-other-uc@CHIP { within(1s) };
+event ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF { within(1s) };
+event ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL { within(1s) };
+
event fault.memory.memlink-uc@CHIP;
event fault.memory.memlink-uc@MEM_BUFF;
event fault.memory.memlink-uc@MEM_CTRL;
@@ -201,55 +205,66 @@ event fault.memory.memlink-uc@MEM_CTRL;
*/
prop fault.memory.memlink-uc@CHIP
{ DIAGNOSE_ERPT } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@CHIP;
+ ereport.cpu.generic-sparc.membuf-crc-uc@CHIP,
+ ereport.cpu.generic-sparc.membuf-other-uc@CHIP;
prop fault.memory.memlink-uc@MEM_BUFF
{ DIAGNOSE_ERPT && CONTAINS_MEMBUFF } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@CHIP<>;
+ ereport.cpu.generic-sparc.membuf-crc-uc@CHIP<>,
+ ereport.cpu.generic-sparc.membuf-other-uc@CHIP<>;
event upset.memory.memlink-uc@CHIP;
prop upset.memory.memlink-uc@CHIP
{ !DIAGNOSE_ERPT } (0)->
- ereport.cpu.generic-sparc.membuf-crc-uc@CHIP;
+ ereport.cpu.generic-sparc.membuf-crc-uc@CHIP,
+ ereport.cpu.generic-sparc.membuf-other-uc@CHIP;
/*
* memory-buffer is detector
*/
prop fault.memory.memlink-uc@MEM_BUFF
{ DIAGNOSE_ERPT } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF;
prop fault.memory.memlink-uc@CHIP
{ DIAGNOSE_ERPT && CONTAINS_CHIP } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF<>;
prop fault.memory.memlink-uc@MEM_CTRL
{ DIAGNOSE_ERPT && CONTAINS_MEMCTRL } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF<>,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF<>;
event upset.memory.memlink-uc@MEM_BUFF;
prop upset.memory.memlink-uc@MEM_BUFF
{ !DIAGNOSE_ERPT } (0)->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_BUFF,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_BUFF;
/*
* memory-controller is detector
*/
prop fault.memory.memlink-uc@MEM_CTRL
{ DIAGNOSE_ERPT } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL;
prop fault.memory.memlink-uc@MEM_BUFF
{ DIAGNOSE_ERPT && CONTAINS_MEMBUFF } (0) ->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL<>;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL<>,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL<>;
event upset.memory.memlink-uc@MEM_CTRL;
prop upset.memory.memlink-uc@MEM_CTRL
{ !DIAGNOSE_ERPT } (0)->
- ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL;
+ ereport.cpu.generic-sparc.membuf-crc-uc@MEM_CTRL,
+ ereport.cpu.generic-sparc.membuf-other-uc@MEM_CTRL;
+
/*
* membuf-crc-failover will fault the detector FRU and sender FRU
* if detector is chip or memory-controller, the sender is memory-buffer.
diff --git a/usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc
new file mode 100644
index 0000000000..c1f272b244
--- /dev/null
+++ b/usr/src/cmd/fm/eversholt/files/sparc/sun4v/sp.esc
@@ -0,0 +1,37 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma dictionary "SUN4V"
+
+/*
+ * Eversholt rule for a faulted Service Processor
+ */
+
+event fault.sp.failed@sp;
+
+event ereport.chassis.sp.unavailable@chassis;
+
+prop fault.sp.failed@sp ->
+ ereport.chassis.sp.unavailable@chassis;
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile b/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile
index 8de8852eda..1609232d57 100644
--- a/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/Makefile
@@ -19,19 +19,18 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
MODULE = fabric-xlate
CLASS = common
-SRCS = fabric-xlate.c
+SRCS = fabric-xlate.c fx_epkt.c fx_fabric.c fx_fire.c fx_subr.c
include ../../Makefile.plugin
CPPFLAGS += -I/usr/include/libxml2 -I$(KMFDIR)/include -I.
+CPPFLAGS += -I$(SRC)/uts/sun4v/io/px
INCDIRS = $(SRC)/uts/common
CFLAGS += -I$(INCDIRS)
LINTFLAGS += -I$(INCDIRS)
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c
index 57df0ce38a..80f37075de 100644
--- a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.c
@@ -23,1500 +23,22 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#include <assert.h>
-#include <stddef.h>
-#include <errno.h>
-#include <strings.h>
-#include <fm/fmd_api.h>
#include <fm/libtopo.h>
#include <sys/fm/util.h>
-#include <sys/fm/protocol.h>
-#include <sys/fm/io/pci.h>
-#include <sys/fm/io/sun4_fire.h>
-#include <sys/pci.h>
-#include <sys/pcie.h>
-#include <sys/nvpair.h>
-#include <sys/nvpair_impl.h>
-#include <libxml/xpath.h>
-#include <libxml/parser.h>
#include <libxml/xpathInternals.h>
-#include <libxml/tree.h>
-/* PCI-E config space data for error handling and fabric ereports */
-typedef struct fab_data {
- /* Original ereport NVL */
- nvlist_t *nvl;
+#include "fabric-xlate.h"
- /* Device Information */
- uint16_t bdf;
- uint16_t device_id;
- uint16_t vendor_id;
- uint8_t rev_id;
- uint16_t dev_type;
- uint16_t pcie_off;
- uint16_t pcix_off;
- uint16_t aer_off;
- uint16_t ecc_ver;
-
- /* Ereport Information */
- uint32_t remainder;
- uint32_t severity;
-
- /* Error Registers */
- uint16_t pci_err_status; /* pci status register */
- uint16_t pci_cfg_comm; /* pci command register */
-
- uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */
- uint16_t pci_bdg_ctrl; /* PCI bridge control reg */
-
- uint16_t pcix_command; /* pcix command register */
- uint32_t pcix_status; /* pcix status register */
-
- uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */
- uint32_t pcix_bdg_stat; /* pcix bridge status reg */
-
- uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */
- uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */
- uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */
- uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */
- uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */
- uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */
- uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */
- uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */
- uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */
- uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */
-
- uint16_t pcie_err_status; /* pcie device status register */
- uint16_t pcie_err_ctl; /* pcie error control register */
- uint32_t pcie_dev_cap; /* pcie device capabilities register */
-
- uint32_t pcie_adv_ctl; /* pcie advanced control reg */
- uint32_t pcie_ue_status; /* pcie ue error status reg */
- uint32_t pcie_ue_mask; /* pcie ue error mask reg */
- uint32_t pcie_ue_sev; /* pcie ue error severity reg */
- uint32_t pcie_ue_hdr[4]; /* pcie ue header log */
- uint32_t pcie_ce_status; /* pcie ce error status reg */
- uint32_t pcie_ce_mask; /* pcie ce error mask reg */
- uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */
- uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */
- pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */
-
- uint32_t pcie_sue_ctl; /* pcie bridge secondary ue control */
- uint32_t pcie_sue_status; /* pcie bridge secondary ue status */
- uint32_t pcie_sue_mask; /* pcie bridge secondary ue mask */
- uint32_t pcie_sue_sev; /* pcie bridge secondary ue severity */
- uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */
- uint32_t pcie_sue_tgt_trans; /* Fault trans type from AER Logs */
- uint64_t pcie_sue_tgt_addr; /* Fault addr from AER Logs */
- pcie_req_id_t pcie_sue_tgt_bdf; /* Fault bdf from SAER Logs */
-
- uint32_t pcie_rp_status; /* root complex status register */
- uint16_t pcie_rp_ctl; /* root complex control register */
- uint32_t pcie_rp_err_status; /* pcie root complex error status reg */
- uint32_t pcie_rp_err_cmd; /* pcie root complex error cmd reg */
- uint16_t pcie_rp_ce_src_id; /* pcie root complex ce sourpe id */
- uint16_t pcie_rp_ue_src_id; /* pcie root complex ue sourpe id */
-} fab_data_t;
-
-/*
- * These values are used for the xxx_tgt_trans value in fab_data_t. They are
- * originally set in pcie_fault.c and originally defined in pcie_impl.h.
- */
-#define PF_ADDR_DMA (1 << 0)
-#define PF_ADDR_PIO (1 << 1)
-#define PF_ADDR_CFG (1 << 2)
-
-typedef struct fab_erpt_tbl {
- const char *err_class; /* Final Ereport Class */
- uint32_t reg_bit; /* Error Bit Mask */
- /* Pointer to function that prepares the ereport body */
- const char *tgt_class; /* Target Ereport Class */
-} fab_erpt_tbl_t;
-
-typedef struct fab_err_tbl {
- fab_erpt_tbl_t *erpt_tbl; /* ereport table */
- uint32_t reg_offset; /* sts reg for ereport table offset */
- uint32_t reg_size; /* size of the status register */
- /* Pointer to function that prepares the ereport body */
- int (*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *,
- fab_erpt_tbl_t *);
-} fab_err_tbl_t;
-
-typedef struct fab_fire_tbl {
- const char *err_class;
- uint32_t fire_bit; /* Fire error bit */
- uint16_t pci_err_sts; /* Equivalent PCI Error Status */
- uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */
-} fab_fire_tbl_t;
-
-/* Static FM Topo XML Format and XML XPath Context */
-static xmlDocPtr fab_doc = NULL;
-static xmlXPathContextPtr fab_xpathCtx = NULL;
-static int fab_valid_topo = 0;
#define XMLTOPOFILE "/tmp/fab-xlate-topo.xml"
-/* Functions that convert ereports to a common C data structure */
-static void fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl,
- fab_data_t *data);
-static void fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data);
-
-/* Common functions for sending translated ereports */
-static int fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
- boolean_t isRC);
-static boolean_t fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath);
-static char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr);
-static char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf);
-static void fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- const char *class, boolean_t isPrimary);
-static void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl);
-
-/*
- * Common functions for converting pci.fabric classes of
- * ereports
- */
-static int fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static void fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data);
-static int fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static void fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data);
-static int fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-static int fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *erpt, fab_erpt_tbl_t *table);
-
-/* Functions for converting fire specific error registers */
-static int fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class);
-static int fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class);
-static int fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class);
-static int fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class);
-
-/* Main functions for converting "fabric" ereports */
-static void fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data);
-static void fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data,
- nvlist_t *nvl, const char *class);
-
-/*
- * Translation tables for converting "fabric" error bits into "pci" ereports.
- * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function>
- */
-
-/* MACRO for table entries with no TGT ereports */
-#define NT(class, bit, prep) class, bit, prep, NULL
-/* Translate Fabric ereports to ereport.io.pci.* */
-static fab_erpt_tbl_t fab_pci_erpt_tbl[] = {
- PCI_DET_PERR, PCI_STAT_PERROR, NULL,
- PCI_MDPE, PCI_STAT_S_PERROR, NULL,
- PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL,
- PCI_MA, PCI_STAT_R_MAST_AB, NULL,
- PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL,
- PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pci.sec-* */
-static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = {
- PCI_DET_PERR, PCI_STAT_PERROR, NULL,
- PCI_MDPE, PCI_STAT_S_PERROR, NULL,
- PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL,
-#ifdef sparc
- PCI_MA, PCI_STAT_R_MAST_AB, NULL,
-#endif
- PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL,
- PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL,
- NULL, NULL, NULL, NULL,
-};
-
-
-/* Translate Fabric ereports to ereport.io.pci.dto */
-static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = {
- PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pciex.* */
-static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = {
- PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL,
- PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL,
- PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL,
- PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL,
- PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL,
- PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pciex.* */
-static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = {
- PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL,
- PCIEX_DLP, PCIE_AER_UCE_DLP, NULL,
- PCIEX_SD, PCIE_AER_UCE_SD, NULL,
- PCIEX_ROF, PCIE_AER_UCE_RO, NULL,
- PCIEX_FCP, PCIE_AER_UCE_FCP, NULL,
- PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL,
- PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA,
- PCIEX_UC, PCIE_AER_UCE_UC, NULL,
- PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL,
- PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA,
-#ifdef sparc
- PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA,
-#endif
- PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pciex.* */
-static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = {
- PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA,
- PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA,
- PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA,
-#ifdef sparc
- PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA,
-#endif
- PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL,
- PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA,
- PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE,
- PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE,
- PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE,
- PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL,
- PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE,
- PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL,
- PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pcix.* */
-static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = {
- PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL,
- PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL,
- PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL,
- NULL, NULL, NULL
-};
-static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl;
-
-/* Translate Fabric ereports to ereport.io.pcix.sec-* */
-static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = {
- PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL,
- PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL,
- PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL,
- PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pciex.* */
-static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = {
-#ifdef sparc
- PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL,
-#endif
- PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL,
- PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL,
- PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL,
- NULL, NULL, NULL
-};
-
-/* Translate Fabric ereports to ereport.io.pciex.* */
-static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = {
- PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL,
- PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL,
- PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL,
- PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL,
- PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL,
- NULL, NULL, NULL
-};
-
-/*
- * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages.
- * If the RP is not a PCIe compliant RP or does not support AER, rely on the
- * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC.
- */
-static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = {
- PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL,
- PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL,
- PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL,
- NULL, NULL, NULL,
-};
-
-static fab_err_tbl_t *fab_master_err_tbl;
-
-/*
- * Translation tables for converting fire error bits into "pci" ereports.
- * <Fire Bit>
- * <pci ereport Class>
- * <pci error status reg>
- * <pci bridge status reg>
- * <pci target class>
- */
-#define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb
-#define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb
-#define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb
-#define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb
-
-#define FAB_FIRE_UE(fb, bit, sts, bdg) \
- FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
-#define FAB_OB_UE(fb, bit, sts, bdg) \
- FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
-static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = {
- FAB_FIRE_UE(UR, UR, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(UC, UC, PCI_STAT_S_SYSERR, 0),
- FAB_OB_UE(ECRC, ECRC, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(CTO, TO, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(ROF, RO, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(MFP, MTLP, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(PP, PTLP, PCI_STAT_S_PERROR,
- (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)),
- FAB_FIRE_UE(FCP, FCP, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(DLP, DLP, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(TE, TRAINING, PCI_STAT_S_SYSERR, 0),
- FAB_FIRE_UE(CA, CA, PCI_STAT_S_TARG_AB,
- PCI_STAT_S_TARG_AB),
- NULL, NULL, NULL,
-};
-
-#define FAB_FIRE_CE(fb, bit) \
- FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0
-static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = {
- FAB_FIRE_CE(RTO, REPLAY_TO),
- FAB_FIRE_CE(RNR, REPLAY_ROLLOVER),
- FAB_FIRE_CE(BDP, BAD_DLLP),
- FAB_FIRE_CE(BTP, BAD_TLP),
- FAB_FIRE_CE(RE, RECEIVER_ERR),
- NULL, NULL, NULL,
-};
-
-/*
- * WUC/RUC will need to be special cased for the target ereports, because you
- * need to decode the tlp log.
- */
-#define FAB_FIRE_WUCRUC(fb) \
- FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR)
-#define FAB_FIRE_OE(fb, bit) \
- FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
-#define FAB_OB_OE(fb, bit) \
- FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
-static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = {
- FAB_FIRE_WUCRUC(WUC),
- FAB_FIRE_WUCRUC(RUC),
- FAB_FIRE_OE(ERU, DLP),
- FAB_FIRE_OE(ERO, DLP),
- FAB_FIRE_OE(EMP, DLP),
- FAB_FIRE_OE(EPE, DLP),
- NULL, NULL, NULL,
-};
-
-#define FAB_FIRE_DMC(fb) \
- FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
-#define FAB_N2_DMU(fb) \
- FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
-static fab_fire_tbl_t fab_fire_dmc_tbl[] = {
- FAB_FIRE_DMC(BYP_ERR),
- FAB_FIRE_DMC(BYP_OOR),
- FAB_FIRE_DMC(TRN_OOR),
- FAB_FIRE_DMC(TTE_INV),
- FAB_FIRE_DMC(TTE_PRT),
- FAB_N2_DMU("iotsbdesc_inv"),
- FAB_N2_DMU("sun4v_adj_va_uf"),
- FAB_N2_DMU("sun4v_inv_pg_sz"),
- FAB_N2_DMU("sun4v_key_err"),
- FAB_N2_DMU("sun4v_va_oor"),
- NULL, NULL, NULL
-};
-
-static fmd_xprt_t *fab_fmd_xprt = NULL; /* FMD transport layer handle */
-static char fab_buf[FM_MAX_CLASS];
-static boolean_t fab_xlate_fake_rp = B_TRUE;
-
-#define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name)
-#define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name))
-#define FREE_PROP(prop) xmlFree((xmlChar *)prop)
-#define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0)
-
-#define FAB_LOOKUP(sz, name, field) \
- (void) nvlist_lookup_uint ## sz(nvl, name, field)
-/* ARGSUSED */
-static void
-fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) {
- data->nvl = nvl;
-
- /* Generic PCI device information */
- FAB_LOOKUP(16, "bdf", &data->bdf);
- FAB_LOOKUP(16, "device_id", &data->device_id);
- FAB_LOOKUP(16, "vendor_id", &data->vendor_id);
- FAB_LOOKUP(8, "rev_id", &data->rev_id);
- FAB_LOOKUP(16, "dev_type", &data->dev_type);
- FAB_LOOKUP(16, "pcie_off", &data->pcie_off);
- FAB_LOOKUP(16, "pcix_off", &data->pcix_off);
- FAB_LOOKUP(16, "aer_off", &data->aer_off);
- FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver);
-
- /* Misc ereport information */
- FAB_LOOKUP(32, "remainder", &data->remainder);
- FAB_LOOKUP(32, "severity", &data->severity);
-
- /* PCI registers */
- FAB_LOOKUP(16, "pci_status", &data->pci_err_status);
- FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm);
-
- /* PCI bridge registers */
- FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat);
- FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl);
-
- /* PCIx registers */
- FAB_LOOKUP(32, "pcix_status", &data->pcix_status);
- FAB_LOOKUP(16, "pcix_command", &data->pcix_command);
-
- /* PCIx ECC Registers */
- FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0);
- FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0);
- FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0);
- FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0);
- FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0);
-
- /* PCIx ECC Bridge Registers */
- FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1);
- FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1);
- FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1);
- FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1);
- FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1);
-
- /* PCIx Bridge */
- FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat);
- FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat);
-
- /* PCIe registers */
- FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status);
- FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl);
- FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap);
-
- /* PCIe AER registers */
- FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl);
- FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status);
- FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask);
- FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev);
- FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]);
- FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]);
- FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]);
- FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]);
- FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status);
- FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask);
- FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans);
- FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr);
- FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf);
-
- /* PCIe BDG AER registers */
- FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl);
- FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status);
- FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask);
- FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev);
- FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]);
- FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]);
- FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]);
- FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]);
- FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans);
- FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr);
- FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf);
-
- /* PCIe RP registers */
- FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status);
- FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl);
-
- /* PCIe RP AER registers */
- FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status);
- FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd);
- FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id);
- FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id);
-
- /*
- * If the system has a PCIe complaint RP with AER, turn off translating
- * fake RP ereports.
- */
- if (fab_xlate_fake_rp &&
- (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) &&
- data->aer_off)
- fab_xlate_fake_rp = B_FALSE;
-}
-
-/* ARGSUSED */
-static void
-fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) {
- data->nvl = nvl;
-
- /* Always Root Complex */
- data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT;
-
- data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD |
- PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP);
-}
-
-/* ARGSUSED */
-static int
-fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
- boolean_t isRC) {
- uint64_t *now;
- uint64_t ena;
- uint_t nelem;
- nvlist_t *detector, *new_detector;
- char rcpath[255];
- int err = 0;
-
- /* Grab the tod, ena and detector(FMRI) */
- err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
- err |= nvlist_lookup_uint64(nvl, "ena", &ena);
- err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector);
- if (err)
- return (err);
-
- /* Make a copy of the detector */
- err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME);
- if (err)
- return (err);
-
- /* Copy the tod and ena to erpt */
- (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
- (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
-
- /*
- * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used
- * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl
- * comments for more information.
- */
- if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) {
- /* Create the correct PCIe RC new_detector aka FMRI */
- (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH,
- DATA_TYPE_STRING);
- (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH,
- rcpath);
- }
-
- /* Copy the FMRI to erpt */
- (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector);
-
- nvlist_free(new_detector);
- return (err);
-}
-
-static void
-fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class,
- boolean_t isPrimary)
-{
- nvlist_t *nvl = data->nvl;
- nvlist_t *erpt;
- char *fmri = NULL;
- uint32_t tgt_trans;
- uint64_t tgt_addr;
- uint16_t tgt_bdf;
-
- if (isPrimary) {
- tgt_trans = data->pcie_ue_tgt_trans;
- tgt_addr = data->pcie_ue_tgt_addr;
- tgt_bdf = data->pcie_ue_tgt_bdf;
- } else {
- tgt_trans = data->pcie_sue_tgt_trans;
- tgt_addr = data->pcie_sue_tgt_addr;
- tgt_bdf = data->pcie_sue_tgt_bdf;
- }
-
- fmd_hdl_debug(hdl, "Sending Target Ereport: "
- "type 0x%x addr 0x%llx fltbdf 0x%x\n",
- tgt_trans, tgt_addr, tgt_bdf);
-
- if (!tgt_trans)
- return;
-
- if ((tgt_trans == PF_ADDR_PIO) && tgt_addr)
- fmri = fab_find_addr(hdl, nvl, tgt_addr);
- else if ((tgt_trans == PF_ADDR_CFG) && tgt_bdf)
- fmri = fab_find_bdf(hdl, nvl, tgt_bdf);
-
- if (fmri) {
- uint64_t *now;
- uint64_t ena;
- uint_t nelem;
- nvlist_t *detector;
- int err = 0;
-
- /* Allocate space for new erpt */
- if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
- goto done;
-
- /* Generate the target ereport class */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCI_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- /* Grab the tod, ena and detector(FMRI) */
- err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
- err |= nvlist_lookup_uint64(nvl, "ena", &ena);
-
- /* Copy the tod and ena to erpt */
- (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
- (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
-
- /* Create the correct FMRI */
- if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
- nvlist_free(erpt);
- goto done;
- }
- (void) nvlist_add_uint8(detector, FM_VERSION,
- FM_DEV_SCHEME_VERSION);
- (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
- FM_FMRI_SCHEME_DEV);
- (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri);
- (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector);
- nvlist_free(detector);
-
- /* Add the address payload */
- (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr);
-
- fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n",
- fab_buf, tgt_addr);
- fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
- if (fmd_xprt_error(hdl, fab_fmd_xprt))
- goto done;
- xmlFree(fmri);
- } else {
- fmd_hdl_debug(hdl, "Cannot find Target FMRI addr:0x%llx",
- tgt_addr);
- }
-
- return;
-done:
- if (fmri)
- xmlFree(fmri);
- fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n");
-}
-
-static void
-fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl)
-{
- fab_erpt_tbl_t *erpt_tbl, *entry;
- nvlist_t *erpt;
- uint32_t reg;
-
- erpt_tbl = tbl->erpt_tbl;
- if (tbl->reg_size == 16) {
- reg = (uint32_t)*((uint16_t *)
- ((uint32_t)data + tbl->reg_offset));
- } else {
- reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset));
- }
-
- for (entry = erpt_tbl; entry->err_class; entry++) {
- if (!(reg & entry->reg_bit))
- continue;
-
- if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
- goto done;
- if (tbl->fab_prep(hdl, data, erpt, entry) != 0) {
- fmd_hdl_debug(hdl, "Prepping ereport failed\n");
- nvlist_free(erpt);
- continue;
- }
-
- fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg);
- fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
- if (fmd_xprt_error(hdl, fab_fmd_xprt)) {
- fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
- return;
- }
- }
-
- return;
-done:
- fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
-}
-
-static int
-fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCI_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status);
- (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm);
-
- return (err);
-}
-
-static int
-fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s",
- PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
- data->pci_bdg_sec_stat);
- (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
-
- return (err);
-}
-
-static int
-fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCI_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
- data->pci_bdg_sec_stat);
- (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
-
- return (err);
-}
-
-
-static int
-fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIEX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
- (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG,
- data->pcie_ce_status);
-
- return (err);
-}
-
-static int
-fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- uint32_t first_err = 1 << (data->pcie_adv_ctl &
- PCIE_AER_CTL_FST_ERR_PTR_MASK);
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIEX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
- (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG,
- data->pcie_ue_status);
- (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev);
- (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl);
-
- fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
-
- if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
- data->pcie_ue_tgt_bdf);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
- } else {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
- }
-
- if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_trans) {
- if (tbl->tgt_class)
- fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE);
- }
-
- return (err);
-}
-
-static int
-fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- uint32_t first_err = 1 << (data->pcie_sue_ctl &
- PCIE_AER_SCTL_FST_ERR_PTR_MASK);
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIEX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS,
- data->pcie_sue_status);
-
- fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
-
- if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
- data->pcie_sue_tgt_bdf);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
- } else {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
- }
-
- if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_trans) {
- if (tbl->tgt_class)
- fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE);
- }
-
- return (err);
-}
-
-static int
-fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = 0;
-
- /* Only send if this is not a bridge */
- if (!data->pcix_status || data->pcix_bdg_sec_stat)
- return (1);
-
- err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command);
- (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
-
- return (err);
-}
-
-static void
-fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
-{
- nvlist_t *erpt;
- int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4;
- int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR;
- int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE;
- int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE;
- uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) |
- data->pcix_ecc_status_0;
-
- switch (ecc_phase) {
- case PCI_PCIX_ECC_PHASE_NOERR:
- break;
- case PCI_PCIX_ECC_PHASE_FADDR:
- case PCI_PCIX_ECC_PHASE_SADDR:
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s", PCIX_ERROR_SUBCLASS,
- ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
- break;
- case PCI_PCIX_ECC_PHASE_ATTR:
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s", PCIX_ERROR_SUBCLASS,
- ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
- break;
- case PCI_PCIX_ECC_PHASE_DATA32:
- case PCI_PCIX_ECC_PHASE_DATA64:
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s", PCIX_ERROR_SUBCLASS,
- ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
- break;
- }
-
- if (ecc_phase) {
- if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
- goto done;
- (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
- (void) nvlist_add_uint16(erpt, PCIX_COMMAND,
- data->pcix_command);
- (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
- data->pcix_ecc_attr_0);
- fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
- fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
- if (fmd_xprt_error(hdl, fab_fmd_xprt))
- fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
- }
-
- if (sec_ce || sec_ue) {
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s", PCIX_ERROR_SUBCLASS,
- sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
- if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
- goto done;
- (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
- (void) nvlist_add_uint16(erpt, PCIX_COMMAND,
- data->pcix_command);
- (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
- data->pcix_ecc_attr_0);
- fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
- fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
- if (fmd_xprt_error(hdl, fab_fmd_xprt))
- fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
- }
-
- return;
-done:
- fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
-}
-
-static int
-fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s",
- PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
- data->pcix_bdg_sec_stat);
- (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
-
- return (err);
-}
-
-static int
-fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
- data->pcix_bdg_sec_stat);
- (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
-
- return (err);
-}
-
-static void
-fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
-{
- nvlist_t *erpt;
- int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4;
- int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR;
- int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE;
- int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE;
- uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) |
- data->pcix_ecc_status_1;
-
- switch (ecc_phase) {
- case PCI_PCIX_ECC_PHASE_NOERR:
- break;
- case PCI_PCIX_ECC_PHASE_FADDR:
- case PCI_PCIX_ECC_PHASE_SADDR:
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
- ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
- break;
- case PCI_PCIX_ECC_PHASE_ATTR:
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
- ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
- break;
- case PCI_PCIX_ECC_PHASE_DATA32:
- case PCI_PCIX_ECC_PHASE_DATA64:
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
- ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
- break;
- }
- if (ecc_phase) {
- if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
- goto done;
- (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
- (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
- data->pcix_bdg_sec_stat);
- (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
- data->pcix_bdg_stat);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
- data->pcix_ecc_attr_1);
- fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
- fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
- if (fmd_xprt_error(hdl, fab_fmd_xprt))
- fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
- }
-
- if (sec_ce || sec_ue) {
- (void) snprintf(fab_buf, FM_MAX_CLASS,
- "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
- sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
- if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
- goto done;
- (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
- (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
- data->pcix_bdg_sec_stat);
- (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
- data->pcix_bdg_stat);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
- (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
- data->pcix_ecc_attr_1);
- fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
- fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
- if (fmd_xprt_error(hdl, fab_fmd_xprt))
- fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
- }
- return;
-done:
- fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
-}
-
-static int
-fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- int err = 0;
-
- /* Don't send this for PCI device, Root Ports, or PCIe with AER */
- if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
- (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
- data->aer_off)
- return (1);
-
- err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIEX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
-
- return (err);
-}
-
-static int
-fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- uint32_t status = data->pcie_rp_err_status;
- int err = 0;
- int isFE = 0, isNFE = 0;
-
- fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class);
-
- if (!data->aer_off)
- return (-1);
-
- /* Only send a FE Msg if the 1st UE error is FE */
- if (STRCMP(class, PCIEX_RC_FE_MSG))
- if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL))
- return (-1);
- else
- isFE = 1;
-
- /* Only send a NFE Msg is the 1st UE error is NFE */
- if (STRCMP(class, PCIEX_RC_NFE_MSG))
- if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL)
- return (-1);
- else
- isNFE = 1;
-
- fmd_hdl_debug(hdl, "XLATE RP Error");
-
- err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIEX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status);
- if ((isFE || isNFE) && data->pcie_rp_ue_src_id) {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
- data->pcie_rp_ue_src_id);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
- }
- if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
- data->pcie_rp_ce_src_id);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
- }
-
- return (err);
-}
-
-static int
-fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- fab_erpt_tbl_t *tbl)
-{
- const char *class = tbl->err_class;
- uint32_t rc_err_sts = 0;
- int err = 0;
-
- /*
- * Don't send this for PCI device or Root Ports. Only send it on
- * systems with non-compliant RPs.
- */
- if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
- (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
- (!fab_xlate_fake_rp))
- return (-1);
-
- err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE);
-
- /* Generate an ereport for this error bit. */
- (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
- PCIEX_ERROR_SUBCLASS, class);
- (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
-
- /* Send PCIe RC Ereports */
- if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) {
- rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD;
- }
-
- /* NFE/FE src id takes precedence over CE src id */
- if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) {
- rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD;
- rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
- }
- if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) {
- rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD;
- rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
- }
- if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) &&
- (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) {
- rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL;
- rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD;
- }
-
- (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts);
-
- if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) {
- (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf);
- (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
- }
-
- return (err);
-}
-
-static int
-fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class)
-{
- fab_fire_tbl_t *entry;
- uint64_t reg;
-
- for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) {
- if (STRCMP(class, entry->err_class))
- goto send;
- }
-
- return (0);
-
-send:
- fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class);
-
- /* Fill in the device status register */
- data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED;
-
- /* Fill in the AER CE register */
- if (nvlist_lookup_uint64(erpt, "tlu-cess", &reg) == 0) {
- data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32);
- }
-
- return (1);
-}
-
-static int
-fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class)
-{
- fab_fire_tbl_t *entry;
- uint64_t reg;
- uint32_t temp;
- pcie_tlp_hdr_t *hdr;
-
- for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) {
- if (STRCMP(class, entry->err_class))
- goto send;
- }
-
- return (0);
-
-send:
- fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class);
+fmd_xprt_t *fab_fmd_xprt; /* FMD transport layer handle */
+char fab_buf[FM_MAX_CLASS];
- /* Fill in PCI Status Register */
- data->pci_err_status = entry->pci_err_sts;
- data->pci_bdg_sec_stat = entry->pci_bdg_sts;
-
- /* Fill in the device status register */
- if (entry->fire_bit & data->pcie_ue_sev)
- data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
- else
- data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
-
- if (entry->fire_bit == PCIE_AER_UCE_UR)
- data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED;
-
- /* Fill in the AER UE register */
- if (nvlist_lookup_uint64(erpt, "tlu-uess", &reg) == 0) {
- data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32);
- }
-
- /* Fill in the AER Control register */
- if ((reg & (uint64_t)entry->fire_bit) &&
- nvlist_lookup_boolean(erpt, "primary")) {
- temp = entry->fire_bit;
- for (data->pcie_adv_ctl = (uint32_t)-1; temp;
- data->pcie_adv_ctl++)
- temp = temp >> 1;
- }
-
- /* If CTO create target information */
- if (entry->fire_bit == PCIE_AER_UCE_TO &&
- nvlist_lookup_boolean(erpt, "primary")) {
- if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", &reg) == 0) {
- data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
- data->pcie_ue_hdr[1] = (uint32_t)(reg);
- }
- if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", &reg) == 0) {
- data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
- data->pcie_ue_hdr[3] = (uint32_t)(reg);
- }
-
- hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]);
- switch (hdr->type) {
- case PCIE_TLP_TYPE_IO:
- case PCIE_TLP_TYPE_MEM:
- case PCIE_TLP_TYPE_MEMLK:
- data->pcie_ue_tgt_trans = PF_ADDR_PIO;
- if (hdr->fmt & 0x1) {
- data->pcie_ue_tgt_addr = reg;
- } else {
- data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2];
- }
- break;
- case PCIE_TLP_TYPE_CFG0:
- case PCIE_TLP_TYPE_CFG1:
- data->pcie_ue_tgt_trans = PF_ADDR_CFG;
- data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16;
- break;
- }
- }
-
- /* Fill in the AER Header registers */
- if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", &reg) == 0) {
- data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
- data->pcie_ue_hdr[1] = (uint32_t)(reg);
- }
- if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", &reg) == 0) {
- data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
- data->pcie_ue_hdr[3] = (uint32_t)(reg);
- }
-
- return (1);
-}
-
-static int
-fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class)
-{
- fab_fire_tbl_t *entry;
- uint64_t reg;
-
- for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) {
- if (STRCMP(class, entry->err_class))
- goto send;
- }
-
- return (0);
-
-send:
- fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class);
-
- /* Fill in PCI Status Register */
- if (entry->fire_bit) {
- data->pci_err_status = entry->pci_err_sts;
- data->pci_bdg_sec_stat = entry->pci_bdg_sts;
- } else {
- if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", &reg) == 0) {
- data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
- data->pcie_ue_hdr[1] = (uint32_t)(reg);
- }
- if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", &reg) == 0) {
- data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
- data->pcie_ue_hdr[3] = (uint32_t)(reg);
- }
-
- if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type ==
- PCIE_TLP_TYPE_CPL) {
- pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1];
- switch (cpl->status) {
- case PCIE_CPL_STS_UR:
- data->pci_err_status = 0;
- data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB |
- PCI_STAT_S_SYSERR;
- break;
- case PCIE_CPL_STS_CA:
- data->pci_err_status = 0;
- data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB |
- PCI_STAT_S_SYSERR;
- break;
- }
- }
- }
-
- /* Fill in the device status register */
- if (entry->fire_bit & data->pcie_ue_sev)
- data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
- else
- data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
-
- /* Fill in the AER UE register */
- data->pcie_ue_status = entry->fire_bit;
-
- return (1);
-}
-
-static int
-fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
- const char *class)
-{
- fab_fire_tbl_t *entry;
- uint64_t reg;
- uint32_t temp;
-
- for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) {
- fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class);
- if (STRCMP(class, entry->err_class) &&
- nvlist_lookup_boolean(erpt, "primary"))
- goto send;
- }
-
- return (0);
-
-send:
- fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class);
-
- /* Fill in PCI Status Register */
- data->pci_err_status = entry->pci_err_sts;
- data->pci_bdg_sec_stat = entry->pci_bdg_sts;
-
- /* Fill in the device status register */
- data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
-
- /* Fill in the AER UE register */
- data->pcie_ue_status = entry->fire_bit;
-
- /* Fill in the AER Control register */
- temp = entry->fire_bit;
- for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++)
- temp = temp >> 1;
-
- /* Fill in the AER Header registers */
- if (nvlist_lookup_uint64(erpt, "mmu-tfsr", &reg) == 0) {
- fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg);
- /* Get the trans type */
- temp = (reg & 0x3F0000) >> 16;
- data->pcie_ue_hdr[0] = (uint32_t)(temp << 24);
- data->pcie_ue_tgt_trans = PF_ADDR_DMA;
- /* Get the req id */
- temp = (reg & 0xFFFF);
- data->pcie_ue_hdr[1] = (uint32_t)(temp << 16);
- data->pcie_ue_tgt_bdf = temp;
- }
-
- if (nvlist_lookup_uint64(erpt, "mmu-tfar", &reg) == 0) {
- fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg);
- /* Get the address */
- data->pcie_ue_hdr[2] = reg;
- data->pcie_ue_hdr[3] = 0;
- data->pcie_ue_tgt_addr = reg;
- }
-
- fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]);
- fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]);
- fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]);
- fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]);
-
- return (1);
-}
-
-static void
-fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data)
-{
- fab_err_tbl_t *tbl;
-
- fmd_hdl_debug(hdl, "Sending Ereports Now");
-
- /* Go through the error logs and send the relavant reports */
- for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) {
- fab_send_erpt(hdl, data, tbl);
- }
-
- /* Send PCI-X ECC Ereports */
- fab_send_pcix_ecc_erpt(hdl, data);
- fab_send_pcix_bdg_ecc_erpt(hdl, data);
-}
-
-static void
-fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *nvl,
- const char *class)
-{
- if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) {
- if (fab_xlate_fire_ce(hdl, data, nvl, class))
- return;
-
- if (fab_xlate_fire_ue(hdl, data, nvl, class))
- return;
-
- if (fab_xlate_fire_oe(hdl, data, nvl, class))
- return;
- } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") ||
- fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) {
- if (fab_xlate_fire_dmc(hdl, data, nvl, class))
- return;
- }
-}
+/* Static FM Topo XML Format and XML XPath Context */
+static xmlDocPtr fab_doc = NULL;
+xmlXPathContextPtr fab_xpathCtx = NULL;
+static int fab_valid_topo = 0;
static void
fab_update_topo(fmd_hdl_t *hdl)
@@ -1553,452 +75,33 @@ fab_update_topo(fmd_hdl_t *hdl)
fab_valid_topo = 1;
}
-#define FAB_HC2DEV_QUERY_SIZE_MIN 160
-#define FAB_HC2DEV_QUERY_SIZE(sz) \
- ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char))
-
-static boolean_t
-fab_hc2dev(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path,
- uint_t *dev_path_size) {
- xmlXPathObjectPtr xpathObj;
- xmlNodeSetPtr nodes;
- char *query, *query_end, *temp;
- uint_t i, size;
- size_t query_size = 0;
- nvlist_t **hcl;
-
- if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl,
- &size) != 0)
- goto fail;
-
- for (i = 0; i < size; i++) {
- if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp) != 0)
- goto fail;
- query_size += strlen(temp);
- if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp) != 0)
- goto fail;
- query_size += strlen(temp);
- /* Adjust for '=' and '/' later */
- query_size += 2;
- }
-
- query = fmd_hdl_alloc(hdl, FAB_HC2DEV_QUERY_SIZE(query_size),
- FMD_SLEEP);
- (void) sprintf(query, "//propval[@name='resource' and "
- "contains(substring(@value, string-length(@value) - %d), '",
- query_size);
-
- query_end = query;
- query_end += strlen(query);
-
- for (i = 0; i < size; i++) {
- (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &temp);
- (void) snprintf(query_end, query_size, "%s=", temp);
- query_end += strlen(temp) + 1;
- (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &temp);
- (void) snprintf(query_end, query_size, "%s", temp);
- query_end += strlen(temp);
- if (i != (size - 1)) {
- (void) sprintf(query_end++, "/");
- }
- }
-
- (void) sprintf(query_end, "')]/parent::*/following-sibling::*/"
- "propval[@name='dev']/@value");
-
- fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
-
- xpathObj = xmlXPathEvalExpression((const xmlChar *)query,
- fab_xpathCtx);
- fmd_hdl_free(hdl, query, FAB_HC2DEV_QUERY_SIZE(query_size));
-
- if (xpathObj == NULL)
- goto fail;
-
- fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj,
- xpathObj->type);
- nodes = xpathObj->nodesetval;
-
- if (nodes) {
- temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]);
- fmd_hdl_debug(hdl, "HC Dev Path: %s\n", temp);
- *dev_path_size = strlen(temp) + 1;
- *dev_path = fmd_hdl_alloc(hdl, *dev_path_size, FMD_SLEEP);
- (void) strlcpy(*dev_path, (char *)temp, *dev_path_size);
- xmlFree(temp);
- xmlXPathFreeObject(xpathObj);
- return (B_TRUE);
- }
- xmlXPathFreeObject(xpathObj);
-fail:
- return (B_FALSE);
-}
-
-/* ARGSUSED */
-static boolean_t
-fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) {
- nvlist_t *detector;
- char *path, *scheme;
- uint_t size;
-
- if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0)
- goto fail;
- if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0)
- goto fail;
-
- if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) {
- if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH,
- &path) != 0)
- goto fail;
- (void) strncpy(rcpath, path, FM_MAX_CLASS);
- } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) {
- /*
- * This should only occur for ereports that come from the RC
- * itself. In this case convert HC scheme to dev path.
- */
- if (fab_hc2dev(hdl, detector, &path, &size)) {
- (void) strncpy(rcpath, path, FM_MAX_CLASS);
- fmd_hdl_free(hdl, path, size);
- } else {
- goto fail;
- }
- } else {
- return (B_FALSE);
- }
-
- /*
- * Extract the RC path by taking the first device in the dev path
- *
- * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0
- * - to -
- * /pci@0,0
- */
- path = strchr(rcpath + 1, '/');
- if (path)
- path[0] = '\0';
-
- return (B_TRUE);
-fail:
- return (B_FALSE);
-}
-
-static char *
-fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) {
- xmlXPathObjectPtr xpathObj;
- xmlNodeSetPtr nodes;
- xmlChar *retval;
- char query[500];
- int bus, dev, fn;
- char rcpath[255];
-
- if (bdf != (uint16_t)-1) {
- bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
- dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
- fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
- }
-
- if (!fab_get_rcpath(hdl, nvl, rcpath))
- goto fail;
-
- /*
- * Explanation of the XSL XPATH Query
- * Line 1: Look at all nodes with the node name "propval"
- * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
- * Line 4-5: See if the "value" of the node ends with correct PCI BDF
- * Line 6: Go up one level to the parent of the current node
- * Line 7: See if child node contains "ASRU" with the same PCIe Root
- * Line 8: Traverse up the parent and the other siblings and look for
- * the io "propgroup" and get the value of the dev "propval"
- */
- (void) snprintf(query, sizeof (query), "//propval["
- "contains(substring(@value, string-length(@value) - 34), "
- "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
- "contains(substring(@value, string-length(@value) - 28), "
- "'pcibus=%d/pcidev=%d/pcifn=%d')"
- "]/parent::"
- "*/propval[@name='ASRU' and contains(@value, '%s')]"
- "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/"
- "@value", bus, dev, fn, bus, dev, fn, rcpath);
-
- fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
-
- xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
-
- if (xpathObj == NULL)
- goto fail;
-
- fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
-
- nodes = xpathObj->nodesetval;
- if (nodes) {
- retval = xmlNodeGetContent(nodes->nodeTab[0]);
- fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval);
- xmlXPathFreeObject(xpathObj);
- return ((char *)retval);
- }
-fail:
- return (NULL);
-}
-
-static char *
-fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) {
- xmlXPathObjectPtr xpathObj;
- xmlNodeSetPtr nodes;
- xmlNodePtr devNode;
- char *retval;
- char query[500];
- int size, i, j;
- uint32_t prop[50];
- char *token;
- pci_regspec_t *assign_p;
- uint64_t low, hi;
- char rcpath[255];
-
- if (!fab_get_rcpath(hdl, nvl, rcpath))
- goto fail;
-
- (void) snprintf(query, sizeof (query), "//propval["
- "@name='ASRU' and contains(@value, '%s')]/"
- "parent::*/following-sibling::*[@name='pci']/"
- "propval[@name='assigned-addresses']", rcpath);
-
- fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
-
- xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
-
- if (xpathObj == NULL)
- goto fail;
-
- fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
-
- nodes = xpathObj->nodesetval;
- size = (nodes) ? nodes->nodeNr : 0;
-
- /* Decode the list of assigned addresses xml nodes for each device */
- for (i = 0; i < size; i++) {
- char *tprop;
-
- devNode = nodes->nodeTab[i];
- if (!HAS_PROP(devNode, "value"))
- continue;
-
- /* Convert "string" assigned-addresses to pci_regspec_t */
- j = 0;
- tprop = GET_PROP(devNode, "value");
- for (token = strtok(tprop, " "); token;
- token = strtok(NULL, " ")) {
- prop[j++] = strtoul(token, (char **)NULL, 16);
- }
- prop[j] = (uint32_t)-1;
- FREE_PROP(tprop);
-
- /* Check if address belongs to this device */
- for (assign_p = (pci_regspec_t *)prop;
- assign_p->pci_phys_hi != (uint_t)-1; assign_p++) {
- low = assign_p->pci_phys_low;
- hi = low + assign_p->pci_size_low;
- if ((addr < hi) && (addr >= low)) {
- fmd_hdl_debug(hdl, "Found Address\n");
- goto found;
- }
- }
- }
- goto fail;
-
-found:
- /* Traverse up the xml tree and back down to find the right propgroup */
- for (devNode = devNode->parent->parent->children;
- devNode; devNode = devNode->next) {
- char *tprop;
-
- tprop = GET_PROP(devNode, "name");
- if (STRCMP(devNode->name, "propgroup") &&
- STRCMP(tprop, "io")) {
- FREE_PROP(tprop);
- goto propgroup;
- }
- FREE_PROP(tprop);
- }
- goto fail;
-
-propgroup:
- /* Retrive the "dev" propval and return */
- for (devNode = devNode->children; devNode; devNode = devNode->next) {
- char *tprop;
-
- tprop = GET_PROP(devNode, "name");
- if (STRCMP(devNode->name, "propval") &&
- STRCMP(tprop, "dev")) {
- FREE_PROP(tprop);
- retval = GET_PROP(devNode, "value");
- fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval);
- xmlXPathFreeObject(xpathObj);
- return (retval);
- }
- FREE_PROP(tprop);
- }
-fail:
- if (xpathObj != NULL)
- xmlXPathFreeObject(xpathObj);
- return (NULL);
-}
-
-static void
-fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) {
- nvpair_t *nvp;
-
- for (nvp = nvlist_next_nvpair(nvl, NULL);
- nvp != NULL;
- nvp = nvlist_next_nvpair(nvl, nvp)) {
-
- data_type_t type = nvpair_type(nvp);
- const char *name = nvpair_name(nvp);
-
- boolean_t b;
- uint8_t i8;
- uint16_t i16;
- uint32_t i32;
- uint64_t i64;
- char *str;
- nvlist_t *cnv;
-
- nvlist_t **nvlarr;
- uint_t arrsize;
- int arri;
-
-
- if (STRCMP(name, FM_CLASS))
- continue; /* already printed by caller */
-
- fmd_hdl_debug(hdl, " %s=", name);
-
- switch (type) {
- case DATA_TYPE_BOOLEAN:
- fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1");
- break;
-
- case DATA_TYPE_BOOLEAN_VALUE:
- (void) nvpair_value_boolean_value(nvp, &b);
- fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d",
- b ? "1" : "0");
- break;
-
- case DATA_TYPE_BYTE:
- (void) nvpair_value_byte(nvp, &i8);
- fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8);
- break;
-
- case DATA_TYPE_INT8:
- (void) nvpair_value_int8(nvp, (void *)&i8);
- fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8);
- break;
-
- case DATA_TYPE_UINT8:
- (void) nvpair_value_uint8(nvp, &i8);
- fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8);
- break;
-
- case DATA_TYPE_INT16:
- (void) nvpair_value_int16(nvp, (void *)&i16);
- fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16);
- break;
-
- case DATA_TYPE_UINT16:
- (void) nvpair_value_uint16(nvp, &i16);
- fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16);
- break;
-
- case DATA_TYPE_INT32:
- (void) nvpair_value_int32(nvp, (void *)&i32);
- fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32);
- break;
-
- case DATA_TYPE_UINT32:
- (void) nvpair_value_uint32(nvp, &i32);
- fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32);
- break;
-
- case DATA_TYPE_INT64:
- (void) nvpair_value_int64(nvp, (void *)&i64);
- fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx",
- (u_longlong_t)i64);
- break;
-
- case DATA_TYPE_UINT64:
- (void) nvpair_value_uint64(nvp, &i64);
- fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx",
- (u_longlong_t)i64);
- break;
-
- case DATA_TYPE_HRTIME:
- (void) nvpair_value_hrtime(nvp, (void *)&i64);
- fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx",
- (u_longlong_t)i64);
- break;
-
- case DATA_TYPE_STRING:
- (void) nvpair_value_string(nvp, &str);
- fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"",
- str ? str : "<NULL>");
- break;
-
- case DATA_TYPE_NVLIST:
- fmd_hdl_debug(hdl, "[");
- (void) nvpair_value_nvlist(nvp, &cnv);
- fab_pr(hdl, NULL, cnv);
- fmd_hdl_debug(hdl, " ]");
- break;
-
- case DATA_TYPE_BOOLEAN_ARRAY:
- case DATA_TYPE_BYTE_ARRAY:
- case DATA_TYPE_INT8_ARRAY:
- case DATA_TYPE_UINT8_ARRAY:
- case DATA_TYPE_INT16_ARRAY:
- case DATA_TYPE_UINT16_ARRAY:
- case DATA_TYPE_INT32_ARRAY:
- case DATA_TYPE_UINT32_ARRAY:
- case DATA_TYPE_INT64_ARRAY:
- case DATA_TYPE_UINT64_ARRAY:
- case DATA_TYPE_STRING_ARRAY:
- fmd_hdl_debug(hdl, "[...]");
- break;
- case DATA_TYPE_NVLIST_ARRAY:
- arrsize = 0;
- (void) nvpair_value_nvlist_array(nvp, &nvlarr,
- &arrsize);
-
- for (arri = 0; arri < arrsize; arri++) {
- fab_pr(hdl, ep, nvlarr[arri]);
- }
-
- break;
- case DATA_TYPE_UNKNOWN:
- fmd_hdl_debug(hdl, "<unknown>");
- break;
- }
- }
-}
-
/*ARGSUSED*/
static void
fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
{
- fab_data_t fab_data = {0};
+ nvlist_t *new_nvl;
if (!fab_valid_topo)
fab_update_topo(hdl);
- if (fmd_nvl_class_match(hdl, nvl, "ereport.io.pci.fabric")) {
- fmd_hdl_debug(hdl, "PCI ereport received: %s\n", class);
- fab_pci_fabric_to_data(hdl, nvl, &fab_data);
- fab_xlate_pcie_erpts(hdl, &fab_data);
+ if (nvlist_dup(nvl, &new_nvl, NV_UNIQUE_NAME) != 0) {
+ fmd_hdl_error(hdl, "failed to duplicate event");
+ return;
+ }
+
+ if (fmd_nvl_class_match(hdl, new_nvl, "ereport.io.pci.fabric")) {
+ fab_xlate_fabric_erpts(hdl, new_nvl, class);
} else {
- fab_pr(hdl, ep, nvl);
- fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class);
- fab_fire_to_data(hdl, nvl, &fab_data);
- fab_xlate_fire_erpts(hdl, &fab_data, nvl, class);
- fab_xlate_pcie_erpts(hdl, &fab_data);
+ fab_pr(hdl, ep, new_nvl);
+ if (fmd_nvl_class_match(hdl, new_nvl,
+ "ereport.io.pciex.rc.epkt")) {
+ fab_xlate_epkt_erpts(hdl, new_nvl, class);
+ } else {
+ fab_xlate_fire_erpts(hdl, new_nvl, class);
+ }
}
+
+ nvlist_free(new_nvl);
}
/* ARGSUSED */
@@ -2022,18 +125,9 @@ static const fmd_hdl_info_t fmd_info = {
"Fabric Ereport Translater", "1.0", &fmd_ops, NULL
};
-#define REG_OFF(reg) ((uint32_t)(uint32_t)&fab_data.reg - (uint32_t)&fab_data)
-#define SET_TBL(n, err, reg, sz) \
- fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \
- fab_master_err_tbl[n].reg_offset = REG_OFF(reg); \
- fab_master_err_tbl[n].reg_size = sz; \
- fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt;
-
void
_fmd_init(fmd_hdl_t *hdl)
{
- fab_data_t fab_data;
-
if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0)
return;
@@ -2043,22 +137,7 @@ _fmd_init(fmd_hdl_t *hdl)
fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL);
fmd_hdl_debug(hdl, "Fabric Translater Started\n");
- /* Setup the master error table */
- fab_master_err_tbl = (fab_err_tbl_t *)calloc(13,
- sizeof (fab_err_tbl_t));
-
- SET_TBL(0, pci, pci_err_status, 16);
- SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16);
- SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16);
- SET_TBL(3, pcie_ce, pcie_ce_status, 32);
- SET_TBL(4, pcie_ue, pcie_ue_status, 32);
- SET_TBL(5, pcie_sue, pcie_sue_status, 32);
- SET_TBL(6, pcix, pcix_status, 32);
- SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16);
- SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32);
- SET_TBL(9, pcie_nadv, pcie_err_status, 16);
- SET_TBL(10, pcie_rc, pcie_rp_err_status, 32);
- SET_TBL(11, pcie_fake_rc, pcie_err_status, 16);
+ fab_setup_master_table();
}
void
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf
index 17c65ca987..53d6d17bdd 100644
--- a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.conf
@@ -37,4 +37,4 @@ subscribe ereport.io.n2.dmu.sun4v_adj_va_uf
subscribe ereport.io.n2.dmu.sun4v_inv_pg_sz
subscribe ereport.io.n2.dmu.sun4v_key_err
subscribe ereport.io.n2.dmu.sun4v_va_oor
-
+subscribe ereport.io.pciex.rc.epkt
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h
new file mode 100644
index 0000000000..e03f310bfa
--- /dev/null
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fabric-xlate.h
@@ -0,0 +1,173 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _FABRIC_XLATE_H
+#define _FABRIC_XLATE_H
+
+#include <fm/fmd_api.h>
+#include <sys/fm/protocol.h>
+#include <sys/nvpair.h>
+#include <sys/types.h>
+#include <sys/pcie.h>
+#include <sys/fm/io/pci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0)
+/*
+ * These values are used for the xxx_tgt_trans value in fab_data_t. They are
+ * originally set in pcie_fault.c and originally defined in pcie_impl.h.
+ */
+#define PF_ADDR_DMA (1 << 0)
+#define PF_ADDR_PIO (1 << 1)
+#define PF_ADDR_CFG (1 << 2)
+
+extern fmd_xprt_t *fab_fmd_xprt; /* FMD transport layer handle */
+extern char fab_buf[];
+
+/* PCI-E config space data for error handling and fabric ereports */
+typedef struct fab_data {
+ /* Original ereport NVL */
+ nvlist_t *nvl;
+
+ /* Device Information */
+ uint16_t bdf;
+ uint16_t device_id;
+ uint16_t vendor_id;
+ uint8_t rev_id;
+ uint16_t dev_type;
+ uint16_t pcie_off;
+ uint16_t pcix_off;
+ uint16_t aer_off;
+ uint16_t ecc_ver;
+
+ /* Ereport Information */
+ uint32_t remainder;
+ uint32_t severity;
+
+ /* Error Registers */
+ uint16_t pci_err_status; /* pci status register */
+ uint16_t pci_cfg_comm; /* pci command register */
+
+ uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */
+ uint16_t pci_bdg_ctrl; /* PCI bridge control reg */
+
+ uint16_t pcix_command; /* pcix command register */
+ uint32_t pcix_status; /* pcix status register */
+
+ uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */
+ uint32_t pcix_bdg_stat; /* pcix bridge status reg */
+
+ uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */
+ uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */
+ uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */
+ uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */
+ uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */
+ uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */
+ uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */
+ uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */
+ uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */
+ uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */
+
+ uint16_t pcie_err_status; /* pcie device status register */
+ uint16_t pcie_err_ctl; /* pcie error control register */
+ uint32_t pcie_dev_cap; /* pcie device capabilities register */
+
+ uint32_t pcie_adv_ctl; /* pcie advanced control reg */
+ uint32_t pcie_ue_status; /* pcie ue error status reg */
+ uint32_t pcie_ue_mask; /* pcie ue error mask reg */
+ uint32_t pcie_ue_sev; /* pcie ue error severity reg */
+ uint32_t pcie_ue_hdr[4]; /* pcie ue header log */
+ uint32_t pcie_ce_status; /* pcie ce error status reg */
+ uint32_t pcie_ce_mask; /* pcie ce error mask reg */
+ uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */
+ uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */
+ pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */
+ boolean_t pcie_ue_no_tgt_erpt; /* Don't send target ereports */
+
+ uint32_t pcie_sue_ctl; /* pcie bridge secondary ue control */
+ uint32_t pcie_sue_status; /* pcie bridge secondary ue status */
+ uint32_t pcie_sue_mask; /* pcie bridge secondary ue mask */
+ uint32_t pcie_sue_sev; /* pcie bridge secondary ue severity */
+ uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */
+ uint32_t pcie_sue_tgt_trans; /* Fault trans type from AER Logs */
+ uint64_t pcie_sue_tgt_addr; /* Fault addr from AER Logs */
+ pcie_req_id_t pcie_sue_tgt_bdf; /* Fault bdf from SAER Logs */
+
+ uint32_t pcie_rp_status; /* root complex status register */
+ uint16_t pcie_rp_ctl; /* root complex control register */
+ uint32_t pcie_rp_err_status; /* pcie root complex error status reg */
+ uint32_t pcie_rp_err_cmd; /* pcie root complex error cmd reg */
+ uint16_t pcie_rp_ce_src_id; /* pcie root complex ce sourpe id */
+ uint16_t pcie_rp_ue_src_id; /* pcie root complex ue sourpe id */
+} fab_data_t;
+
+typedef struct fab_erpt_tbl {
+ const char *err_class; /* Final Ereport Class */
+ uint32_t reg_bit; /* Error Bit Mask */
+ /* Pointer to function that prepares the ereport body */
+ const char *tgt_class; /* Target Ereport Class */
+} fab_erpt_tbl_t;
+
+typedef struct fab_err_tbl {
+ fab_erpt_tbl_t *erpt_tbl; /* ereport table */
+ uint32_t reg_offset; /* sts reg for ereport table offset */
+ uint32_t reg_size; /* size of the status register */
+ /* Pointer to function that prepares the ereport body */
+ int (*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *,
+ fab_erpt_tbl_t *);
+} fab_err_tbl_t;
+
+extern void fab_setup_master_table();
+
+/* Main functions for converting "fabric" ereports */
+extern void fab_xlate_pcie_erpts(fmd_hdl_t *, fab_data_t *);
+extern void fab_xlate_fabric_erpts(fmd_hdl_t *, nvlist_t *, const char *);
+extern void fab_xlate_fire_erpts(fmd_hdl_t *, nvlist_t *, const char *);
+extern void fab_xlate_epkt_erpts(fmd_hdl_t *, nvlist_t *, const char *);
+
+/* Common functions for sending translated ereports */
+extern int fab_prep_basic_erpt(fmd_hdl_t *, nvlist_t *, nvlist_t *, boolean_t);
+extern void fab_send_tgt_erpt(fmd_hdl_t *, fab_data_t *, const char *,
+ boolean_t);
+extern void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl);
+
+/* Misc Functions */
+extern void fab_pr(fmd_hdl_t *, fmd_event_t *, nvlist_t *);
+extern boolean_t fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath);
+extern char *fab_find_rppath_by_df(fmd_hdl_t *, nvlist_t *, uint8_t);
+extern char *fab_find_rppath_by_devbdf(fmd_hdl_t *, nvlist_t *, pcie_req_id_t);
+extern char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr);
+extern char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf);
+extern boolean_t fab_hc2dev(fmd_hdl_t *, const char *, char **);
+extern boolean_t fab_hc2dev_nvl(fmd_hdl_t *, nvlist_t *, char **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FABRIC_XLATE_H */
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c
new file mode 100644
index 0000000000..ccace31212
--- /dev/null
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_epkt.c
@@ -0,0 +1,262 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/types.h>
+#include <px_err.h>
+
+#include "fabric-xlate.h"
+
+#define EPKT_DESC(b, o, p, c, d) (BLOCK_##b << 16 | OP_##o << 12 | \
+ PH_##p << 8 | CND_##c << 4 | DIR_##d)
+
+/* EPKT Table used only for RC/RP errors */
+typedef struct fab_epkt_tbl {
+ uint32_t epkt_desc;
+ uint32_t pcie_ue_sts; /* Equivalent PCIe UE Status */
+ uint16_t pci_err_sts; /* Equivalent PCI Error Status */
+ uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */
+ const char *tgt_class; /* Target Ereport Class */
+} fab_epkt_tbl_t;
+
+static fab_epkt_tbl_t fab_epkt_tbl[] = {
+ EPKT_DESC(MMU, XLAT, DATA, INV, RDWR),
+ PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0,
+ EPKT_DESC(MMU, XLAT, ADDR, UNMAP, RDWR),
+ PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0,
+ EPKT_DESC(MMU, XLAT, DATA, PROT, RDWR),
+ PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB, 0,
+
+ EPKT_DESC(INTR, MSI32, DATA, ILL, IRR),
+ PCIE_AER_UCE_MTLP, PCI_STAT_S_SYSERR, 0, 0,
+
+ EPKT_DESC(PORT, PIO, IRR, RCA, WRITE),
+ PCIE_AER_UCE_CA, PCI_STAT_S_SYSERR, PCI_STAT_S_TARG_AB, 0,
+
+ EPKT_DESC(PORT, PIO, IRR, RUR, WRITE),
+ PCIE_AER_UCE_UR, PCI_STAT_S_SYSERR, 0, 0,
+
+ EPKT_DESC(PORT, PIO, IRR, INV, RDWR),
+ PCIE_AER_UCE_MTLP, PCI_STAT_S_SYSERR, 0, 0,
+
+ EPKT_DESC(PORT, PIO, IRR, TO, READ),
+ PCIE_AER_UCE_TO, PCI_STAT_S_SYSERR, 0, PCI_TARG_MA,
+ EPKT_DESC(PORT, PIO, IRR, TO, WRITE),
+ PCIE_AER_UCE_TO, PCI_STAT_S_SYSERR, 0, PCI_TARG_MA,
+
+ EPKT_DESC(PORT, PIO, IRR, UC, IRR),
+ PCIE_AER_UCE_UC, PCI_STAT_S_SYSERR, 0, 0,
+
+ EPKT_DESC(PORT, LINK, FC, TO, IRR),
+ PCIE_AER_UCE_FCP, PCI_STAT_S_SYSERR, 0, 0,
+
+ 0, 0, 0, 0, 0
+};
+
+/* ARGSUSED */
+void
+fab_epkt_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data)
+{
+ data->nvl = nvl;
+
+ /* Always Root Complex */
+ data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT;
+
+ data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD |
+ PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP);
+}
+
+static int
+fab_xlate_epkt(fmd_hdl_t *hdl, fab_data_t *data, px_rc_err_t *epktp)
+{
+ fab_epkt_tbl_t *entry;
+ uint32_t temp;
+
+ for (entry = fab_epkt_tbl; entry->epkt_desc != 0; entry++) {
+ temp = *(uint32_t *)&epktp->rc_descr >> 12;
+ if (entry->epkt_desc == temp)
+ goto send;
+ }
+
+ return (0);
+
+send:
+ fmd_hdl_debug(hdl, "Translate epkt DESC = %#x\n", temp);
+
+ /* Fill in PCI Status Register */
+ data->pci_err_status = entry->pci_err_sts;
+ data->pci_bdg_sec_stat = entry->pci_bdg_sts;
+
+ /* Fill in the device status register */
+ if (epktp->rc_descr.STOP)
+ data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
+ else if (epktp->rc_descr.C)
+ data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED;
+ else
+ data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
+
+ /* Fill in the AER UE register */
+ data->pcie_ue_status = entry->pcie_ue_sts;
+
+ /* Fill in the AER Control register */
+ temp = entry->pcie_ue_sts;
+ for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++)
+ temp = temp >> 1;
+
+ /* Send target ereports */
+ data->pcie_ue_no_tgt_erpt = B_TRUE;
+ if (entry->tgt_class && !epktp->rc_descr.STOP) {
+ if (epktp->rc_descr.D) {
+ data->pcie_ue_tgt_trans = PF_ADDR_DMA;
+ data->pcie_ue_tgt_addr = epktp->addr;
+ } else if (epktp->rc_descr.M) {
+ data->pcie_ue_tgt_trans = PF_ADDR_PIO;
+ data->pcie_ue_tgt_addr = epktp->addr;
+ }
+
+ if (data->pcie_ue_tgt_trans)
+ fab_send_tgt_erpt(hdl, data, entry->tgt_class,
+ B_TRUE);
+ }
+ return (1);
+}
+
+void
+fab_xlate_epkt_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class)
+{
+ fab_data_t data = {0};
+ px_rc_err_t epkt = {0};
+ pcie_tlp_hdr_t *tlp_hdr;
+ void *ptr;
+ uint8_t ver;
+ int err;
+ char *rppath = NULL;
+ nvlist_t *detector;
+
+ fmd_hdl_debug(hdl, "epkt ereport received: %s\n", class);
+ fab_epkt_to_data(hdl, nvl, &data);
+
+ err = nvlist_lookup_uint8(nvl, "epkt_ver", &ver);
+ err |= nvlist_lookup_uint32(nvl, "desc", (uint32_t *)&epkt.rc_descr);
+ err |= nvlist_lookup_uint32(nvl, "size", &epkt.size);
+ err |= nvlist_lookup_uint64(nvl, "addr", &epkt.addr);
+ err |= nvlist_lookup_uint64(nvl, "hdr1", &epkt.hdr[0]);
+ err |= nvlist_lookup_uint64(nvl, "hdr2", &epkt.hdr[1]);
+ err |= nvlist_lookup_uint64(nvl, "reserved", &epkt.reserved);
+
+ if (err != 0) {
+ fmd_hdl_debug(hdl, "Failed to retrieve all epkt payloads");
+ return;
+ }
+
+ fmd_hdl_debug(hdl, "epkt flags: %c%c%c%c%c%c%c%c%c %s",
+ epkt.rc_descr.S ? 'S' : '-', epkt.rc_descr.M ? 'M' : '-',
+ epkt.rc_descr.S ? 'Q' : '-', epkt.rc_descr.D ? 'D' : '-',
+ epkt.rc_descr.R ? 'R' : '-', epkt.rc_descr.H ? 'H' : '-',
+ epkt.rc_descr.C ? 'C' : '-', epkt.rc_descr.I ? 'I' : '-',
+ epkt.rc_descr.B ? 'B' : '-', epkt.rc_descr.STOP ? "STOP" : "");
+
+ /*
+ * If the least byte of the 'reserved' is non zero, it is device
+ * and function of the port
+ */
+ if (epkt.reserved && 0xff)
+ rppath = fab_find_rppath_by_df(hdl, nvl, epkt.reserved & 0xff);
+
+ if (epkt.rc_descr.H) {
+ data.pcie_ue_hdr[0] = (uint32_t)(epkt.hdr[0] >> 32);
+ data.pcie_ue_hdr[1] = (uint32_t)epkt.hdr[0];
+ data.pcie_ue_hdr[2] = (uint32_t)(epkt.hdr[1] >> 32);
+ data.pcie_ue_hdr[3] = (uint32_t)(epkt.hdr[1]);
+
+ tlp_hdr = (pcie_tlp_hdr_t *)&data.pcie_ue_hdr[0];
+ ptr = &data.pcie_ue_hdr[1];
+ switch (tlp_hdr->type) {
+ case PCIE_TLP_TYPE_IO:
+ case PCIE_TLP_TYPE_MEM:
+ case PCIE_TLP_TYPE_MEMLK:
+ {
+ pcie_mem64_t *pmp = ptr;
+ data.pcie_ue_tgt_trans = PF_ADDR_PIO;
+ data.pcie_ue_tgt_bdf = pmp->rid;
+ if (tlp_hdr->fmt & 0x1)
+ data.pcie_ue_tgt_addr =
+ ((uint64_t)pmp->addr1 << 32) | pmp->addr0;
+ else
+ data.pcie_ue_tgt_addr =
+ ((pcie_memio32_t *)ptr)->addr0;
+
+ break;
+ }
+
+ case PCIE_TLP_TYPE_CFG0:
+ case PCIE_TLP_TYPE_CFG1:
+ {
+ pcie_cfg_t *pcp = ptr;
+
+ data.pcie_ue_tgt_trans = PF_ADDR_CFG;
+ data.pcie_ue_tgt_bdf =
+ (pcp->bus << 8) | (pcp->dev << 3) | pcp->func;
+ break;
+ }
+
+ case PCIE_TLP_TYPE_CPL:
+ case PCIE_TLP_TYPE_CPLLK:
+ data.pcie_ue_tgt_bdf = ((pcie_cpl_t *)ptr)->rid;
+ break;
+ }
+
+ fmd_hdl_debug(hdl, "HEADER 0 0x%x", data.pcie_ue_hdr[0]);
+ fmd_hdl_debug(hdl, "HEADER 1 0x%x", data.pcie_ue_hdr[1]);
+ fmd_hdl_debug(hdl, "HEADER 2 0x%x", data.pcie_ue_hdr[2]);
+ fmd_hdl_debug(hdl, "HEADER 3 0x%x", data.pcie_ue_hdr[3]);
+ fmd_hdl_debug(hdl, "In header bdf = %#hx addr = %#llx",
+ data.pcie_ue_tgt_bdf,
+ (uint64_t)data.pcie_ue_tgt_addr);
+
+ /* find the root port to which this error is related */
+ if (data.pcie_ue_tgt_bdf)
+ rppath = fab_find_rppath_by_devbdf(hdl, nvl,
+ data.pcie_ue_tgt_bdf);
+ }
+
+ /*
+ * reset the detector in the original ereport to the root port
+ */
+ if (rppath && nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) == 0) {
+ (void) nvlist_add_string(detector, FM_VERSION,
+ FM_DEV_SCHEME_VERSION);
+ (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
+ FM_FMRI_SCHEME_DEV);
+ (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, rppath);
+ (void) nvlist_remove_all(nvl, FM_EREPORT_DETECTOR);
+ (void) nvlist_add_nvlist(nvl, FM_EREPORT_DETECTOR, detector);
+ nvlist_free(detector);
+ }
+
+ fmd_hdl_strfree(hdl, rppath);
+
+ (void) fab_xlate_epkt(hdl, &data, &epkt);
+ fab_xlate_pcie_erpts(hdl, &data);
+}
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c
new file mode 100644
index 0000000000..3a9b1e4f77
--- /dev/null
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c
@@ -0,0 +1,834 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <stddef.h>
+#include <strings.h>
+#include <sys/fm/util.h>
+
+#include "fabric-xlate.h"
+
+#define FAB_LOOKUP(sz, name, field) \
+ (void) nvlist_lookup_uint ## sz(nvl, name, field)
+
+static boolean_t fab_xlate_fake_rp = B_TRUE;
+static fab_err_tbl_t *fab_master_err_tbl;
+
+/*
+ * Translation tables for converting "fabric" error bits into "pci" ereports.
+ * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function>
+ */
+
+/* MACRO for table entries with no TGT ereports */
+#define NT(class, bit, prep) class, bit, prep, NULL
+/* Translate Fabric ereports to ereport.io.pci.* */
+fab_erpt_tbl_t fab_pci_erpt_tbl[] = {
+ PCI_DET_PERR, PCI_STAT_PERROR, NULL,
+ PCI_MDPE, PCI_STAT_S_PERROR, NULL,
+ PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL,
+ PCI_MA, PCI_STAT_R_MAST_AB, NULL,
+ PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL,
+ PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL,
+ NULL, NULL, NULL
+};
+
+/* Translate Fabric ereports to ereport.io.pci.sec-* */
+static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = {
+ PCI_DET_PERR, PCI_STAT_PERROR, NULL,
+ PCI_MDPE, PCI_STAT_S_PERROR, NULL,
+ PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL,
+#ifdef sparc
+ PCI_MA, PCI_STAT_R_MAST_AB, NULL,
+#endif
+ PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL,
+ PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL,
+ NULL, NULL, NULL, NULL,
+};
+
+
+/* Translate Fabric ereports to ereport.io.pci.dto */
+static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = {
+ PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL,
+ NULL, NULL, NULL
+};
+
+/* Translate Fabric ereports to ereport.io.pciex.* */
+static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = {
+ PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL,
+ PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL,
+ PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL,
+ PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL,
+ PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL,
+ PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL,
+ NULL, NULL, NULL
+};
+
+/*
+ * Translate Fabric ereports to ereport.io.pciex.*
+ * The Target Ereports for this section is only used on leaf devices, with the
+ * exception of TO
+ */
+static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = {
+ PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL,
+ PCIEX_DLP, PCIE_AER_UCE_DLP, NULL,
+ PCIEX_SD, PCIE_AER_UCE_SD, NULL,
+ PCIEX_ROF, PCIE_AER_UCE_RO, NULL,
+ PCIEX_FCP, PCIE_AER_UCE_FCP, NULL,
+ PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL,
+ PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA,
+ PCIEX_UC, PCIE_AER_UCE_UC, NULL,
+ PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL,
+ PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA,
+#ifdef sparc
+ PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA,
+#endif
+ PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE,
+ NULL, NULL, NULL
+};
+
+/* Translate Fabric ereports to ereport.io.pciex.* */
+static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = {
+ PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA,
+ PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA,
+ PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA,
+#ifdef sparc
+ PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA,
+#endif
+ PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL,
+ PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA,
+ PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE,
+ PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE,
+ PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE,
+ PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL,
+ PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE,
+ PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL,
+ PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL,
+ NULL, NULL, NULL
+};
+
+/* Translate Fabric ereports to ereport.io.pcix.* */
+static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = {
+ PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL,
+ PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL,
+ PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL,
+ NULL, NULL, NULL
+};
+static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl;
+
+/* Translate Fabric ereports to ereport.io.pcix.sec-* */
+static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = {
+ PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL,
+ PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL,
+ PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL,
+ PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL,
+ NULL, NULL, NULL
+};
+
+/* Translate Fabric ereports to ereport.io.pciex.* */
+static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = {
+#ifdef sparc
+ PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL,
+#endif
+ PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL,
+ PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL,
+ PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL,
+ NULL, NULL, NULL
+};
+
+/* Translate Fabric ereports to ereport.io.pciex.* */
+static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = {
+ PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL,
+ PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL,
+ PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL,
+ PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL,
+ PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL,
+ NULL, NULL, NULL
+};
+
+/*
+ * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages.
+ * If the RP is not a PCIe compliant RP or does not support AER, rely on the
+ * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC.
+ */
+static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = {
+ PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL,
+ PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL,
+ PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL,
+ NULL, NULL, NULL,
+};
+
+/* ARGSUSED */
+void
+fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data)
+{
+ data->nvl = nvl;
+
+ /* Generic PCI device information */
+ FAB_LOOKUP(16, "bdf", &data->bdf);
+ FAB_LOOKUP(16, "device_id", &data->device_id);
+ FAB_LOOKUP(16, "vendor_id", &data->vendor_id);
+ FAB_LOOKUP(8, "rev_id", &data->rev_id);
+ FAB_LOOKUP(16, "dev_type", &data->dev_type);
+ FAB_LOOKUP(16, "pcie_off", &data->pcie_off);
+ FAB_LOOKUP(16, "pcix_off", &data->pcix_off);
+ FAB_LOOKUP(16, "aer_off", &data->aer_off);
+ FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver);
+
+ /* Misc ereport information */
+ FAB_LOOKUP(32, "remainder", &data->remainder);
+ FAB_LOOKUP(32, "severity", &data->severity);
+
+ /* PCI registers */
+ FAB_LOOKUP(16, "pci_status", &data->pci_err_status);
+ FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm);
+
+ /* PCI bridge registers */
+ FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat);
+ FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl);
+
+ /* PCIx registers */
+ FAB_LOOKUP(32, "pcix_status", &data->pcix_status);
+ FAB_LOOKUP(16, "pcix_command", &data->pcix_command);
+
+ /* PCIx ECC Registers */
+ FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0);
+ FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0);
+ FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0);
+ FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0);
+ FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0);
+
+ /* PCIx ECC Bridge Registers */
+ FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1);
+ FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1);
+ FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1);
+ FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1);
+ FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1);
+
+ /* PCIx Bridge */
+ FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat);
+ FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat);
+
+ /* PCIe registers */
+ FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status);
+ FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl);
+ FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap);
+
+ /* PCIe AER registers */
+ FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl);
+ FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status);
+ FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask);
+ FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev);
+ FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]);
+ FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]);
+ FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]);
+ FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]);
+ FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status);
+ FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask);
+ FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans);
+ FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr);
+ FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf);
+
+ /* PCIe BDG AER registers */
+ FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl);
+ FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status);
+ FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask);
+ FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev);
+ FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]);
+ FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]);
+ FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]);
+ FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]);
+ FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans);
+ FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr);
+ FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf);
+
+ /* PCIe RP registers */
+ FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status);
+ FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl);
+
+ /* PCIe RP AER registers */
+ FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status);
+ FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd);
+ FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id);
+ FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id);
+
+ /*
+ * If the system has a PCIe complaint RP with AER, turn off translating
+ * fake RP ereports.
+ */
+ if (fab_xlate_fake_rp &&
+ (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) &&
+ data->aer_off)
+ fab_xlate_fake_rp = B_FALSE;
+}
+
+static int
+fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCI_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status);
+ (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm);
+
+ return (err);
+}
+
+static int
+fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s",
+ PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
+ data->pci_bdg_sec_stat);
+ (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
+
+ return (err);
+}
+
+static int
+fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCI_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
+ data->pci_bdg_sec_stat);
+ (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
+
+ return (err);
+}
+
+
+static int
+fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIEX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
+ (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG,
+ data->pcie_ce_status);
+
+ return (err);
+}
+
+static int
+fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ uint32_t first_err = 1 << (data->pcie_adv_ctl &
+ PCIE_AER_CTL_FST_ERR_PTR_MASK);
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIEX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
+ (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG,
+ data->pcie_ue_status);
+ (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev);
+ (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl);
+
+ fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
+
+ if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
+ data->pcie_ue_tgt_bdf);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
+ } else {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
+ }
+
+ if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt &&
+ data->pcie_ue_tgt_trans) {
+ if (tbl->tgt_class)
+ fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE);
+ }
+
+ return (err);
+}
+
+static int
+fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ uint32_t first_err = 1 << (data->pcie_sue_ctl &
+ PCIE_AER_SCTL_FST_ERR_PTR_MASK);
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIEX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS,
+ data->pcie_sue_status);
+
+ fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
+
+ if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
+ data->pcie_sue_tgt_bdf);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
+ } else {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
+ }
+
+ if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt &&
+ data->pcie_sue_tgt_trans) {
+ if (tbl->tgt_class)
+ fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE);
+ }
+
+ return (err);
+}
+
+static int
+fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = 0;
+
+ /* Only send if this is not a bridge */
+ if (!data->pcix_status || data->pcix_bdg_sec_stat)
+ return (1);
+
+ err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command);
+ (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
+
+ return (err);
+}
+
+static void
+fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
+{
+ nvlist_t *erpt;
+ int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4;
+ int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR;
+ int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE;
+ int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE;
+ uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) |
+ data->pcix_ecc_status_0;
+
+ switch (ecc_phase) {
+ case PCI_PCIX_ECC_PHASE_NOERR:
+ break;
+ case PCI_PCIX_ECC_PHASE_FADDR:
+ case PCI_PCIX_ECC_PHASE_SADDR:
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s", PCIX_ERROR_SUBCLASS,
+ ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
+ break;
+ case PCI_PCIX_ECC_PHASE_ATTR:
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s", PCIX_ERROR_SUBCLASS,
+ ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
+ break;
+ case PCI_PCIX_ECC_PHASE_DATA32:
+ case PCI_PCIX_ECC_PHASE_DATA64:
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s", PCIX_ERROR_SUBCLASS,
+ ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
+ break;
+ }
+
+ if (ecc_phase) {
+ if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
+ goto done;
+ (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+ (void) nvlist_add_uint16(erpt, PCIX_COMMAND,
+ data->pcix_command);
+ (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
+ data->pcix_ecc_attr_0);
+ fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
+ fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
+ if (fmd_xprt_error(hdl, fab_fmd_xprt))
+ fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
+ }
+
+ if (sec_ce || sec_ue) {
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s", PCIX_ERROR_SUBCLASS,
+ sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
+ if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
+ goto done;
+ (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+ (void) nvlist_add_uint16(erpt, PCIX_COMMAND,
+ data->pcix_command);
+ (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
+ data->pcix_ecc_attr_0);
+ fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
+ fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
+ if (fmd_xprt_error(hdl, fab_fmd_xprt))
+ fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
+ }
+
+ return;
+done:
+ fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
+}
+
+static int
+fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s",
+ PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
+ data->pcix_bdg_sec_stat);
+ (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
+
+ return (err);
+}
+
+static int
+fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
+ data->pcix_bdg_sec_stat);
+ (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
+
+ return (err);
+}
+
+static void
+fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
+{
+ nvlist_t *erpt;
+ int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4;
+ int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR;
+ int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE;
+ int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE;
+ uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) |
+ data->pcix_ecc_status_1;
+
+ switch (ecc_phase) {
+ case PCI_PCIX_ECC_PHASE_NOERR:
+ break;
+ case PCI_PCIX_ECC_PHASE_FADDR:
+ case PCI_PCIX_ECC_PHASE_SADDR:
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
+ ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
+ break;
+ case PCI_PCIX_ECC_PHASE_ATTR:
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
+ ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
+ break;
+ case PCI_PCIX_ECC_PHASE_DATA32:
+ case PCI_PCIX_ECC_PHASE_DATA64:
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
+ ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
+ break;
+ }
+ if (ecc_phase) {
+ if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
+ goto done;
+ (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+ (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
+ data->pcix_bdg_sec_stat);
+ (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
+ data->pcix_bdg_stat);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
+ data->pcix_ecc_attr_1);
+ fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
+ fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
+ if (fmd_xprt_error(hdl, fab_fmd_xprt))
+ fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
+ }
+
+ if (sec_ce || sec_ue) {
+ (void) snprintf(fab_buf, FM_MAX_CLASS,
+ "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
+ sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
+ if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
+ goto done;
+ (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+ (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
+ data->pcix_bdg_sec_stat);
+ (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
+ data->pcix_bdg_stat);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
+ (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
+ data->pcix_ecc_attr_1);
+ fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
+ fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
+ if (fmd_xprt_error(hdl, fab_fmd_xprt))
+ fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
+ }
+ return;
+done:
+ fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
+}
+
+static int
+fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ int err = 0;
+
+ /* Don't send this for PCI device, Root Ports, or PCIe with AER */
+ if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
+ (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
+ data->aer_off)
+ return (1);
+
+ err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIEX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
+
+ return (err);
+}
+
+static int
+fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ uint32_t status = data->pcie_rp_err_status;
+ int err = 0;
+ int isFE = 0, isNFE = 0;
+
+ fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class);
+
+ if (!data->aer_off)
+ return (-1);
+
+ /* Only send a FE Msg if the 1st UE error is FE */
+ if (STRCMP(class, PCIEX_RC_FE_MSG))
+ if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL))
+ return (-1);
+ else
+ isFE = 1;
+
+ /* Only send a NFE Msg is the 1st UE error is NFE */
+ if (STRCMP(class, PCIEX_RC_NFE_MSG))
+ if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL)
+ return (-1);
+ else
+ isNFE = 1;
+
+ fmd_hdl_debug(hdl, "XLATE RP Error");
+
+ err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIEX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status);
+ if ((isFE || isNFE) && data->pcie_rp_ue_src_id) {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
+ data->pcie_rp_ue_src_id);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
+ }
+ if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
+ data->pcie_rp_ce_src_id);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
+ }
+
+ return (err);
+}
+
+static int
+fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ fab_erpt_tbl_t *tbl)
+{
+ const char *class = tbl->err_class;
+ uint32_t rc_err_sts = 0;
+ int err = 0;
+
+ /*
+ * Don't send this for PCI device or Root Ports. Only send it on
+ * systems with non-compliant RPs.
+ */
+ if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
+ (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
+ (!fab_xlate_fake_rp))
+ return (-1);
+
+ err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE);
+
+ /* Generate an ereport for this error bit. */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCIEX_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ /* Send PCIe RC Ereports */
+ if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) {
+ rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD;
+ }
+
+ /* NFE/FE src id takes precedence over CE src id */
+ if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) {
+ rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD;
+ rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
+ }
+ if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) {
+ rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD;
+ rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
+ }
+ if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) &&
+ (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) {
+ rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL;
+ rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD;
+ }
+
+ (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts);
+
+ if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) {
+ (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf);
+ (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
+ }
+
+ return (err);
+}
+
+void
+fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data)
+{
+ fab_err_tbl_t *tbl;
+
+ fmd_hdl_debug(hdl, "Sending Ereports Now");
+
+ /* Go through the error logs and send the relavant reports */
+ for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) {
+ fab_send_erpt(hdl, data, tbl);
+ }
+
+ /* Send PCI-X ECC Ereports */
+ fab_send_pcix_ecc_erpt(hdl, data);
+ fab_send_pcix_bdg_ecc_erpt(hdl, data);
+}
+
+void
+fab_xlate_fabric_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class)
+{
+ fab_data_t data = {0};
+
+ fmd_hdl_debug(hdl, "fabric ereport received: %s\n", class);
+
+ fab_pci_fabric_to_data(hdl, nvl, &data);
+ fab_xlate_pcie_erpts(hdl, &data);
+}
+
+#define SET_TBL(n, err, reg, sz) \
+ fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \
+ fab_master_err_tbl[n].reg_offset = offsetof(fab_data_t, reg); \
+ fab_master_err_tbl[n].reg_size = sz; \
+ fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt;
+
+void
+fab_setup_master_table()
+{
+ /* Setup the master error table */
+ fab_master_err_tbl = (fab_err_tbl_t *)calloc(13,
+ sizeof (fab_err_tbl_t));
+
+ SET_TBL(0, pci, pci_err_status, 16);
+ SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16);
+ SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16);
+ SET_TBL(3, pcie_ce, pcie_ce_status, 32);
+ SET_TBL(4, pcie_ue, pcie_ue_status, 32);
+ SET_TBL(5, pcie_sue, pcie_sue_status, 32);
+ SET_TBL(6, pcix, pcix_status, 32);
+ SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16);
+ SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32);
+ SET_TBL(9, pcie_nadv, pcie_err_status, 16);
+ SET_TBL(10, pcie_rc, pcie_rp_err_status, 32);
+ SET_TBL(11, pcie_fake_rc, pcie_err_status, 16);
+}
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c
new file mode 100644
index 0000000000..f508f24569
--- /dev/null
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fire.c
@@ -0,0 +1,396 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <strings.h>
+#include <sys/fm/io/sun4_fire.h>
+
+#include "fabric-xlate.h"
+
+typedef struct fab_fire_tbl {
+ const char *err_class;
+ uint32_t fire_bit; /* Fire error bit */
+ uint16_t pci_err_sts; /* Equivalent PCI Error Status */
+ uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */
+} fab_fire_tbl_t;
+
+/*
+ * Translation tables for converting fire error bits into "pci" ereports.
+ * <Fire Bit>
+ * <pci ereport Class>
+ * <pci error status reg>
+ * <pci bridge status reg>
+ * <pci target class>
+ */
+#define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb
+#define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb
+#define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb
+#define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb
+
+#define FAB_FIRE_UE(fb, bit, sts, bdg) \
+ FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
+#define FAB_OB_UE(fb, bit, sts, bdg) \
+ FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
+static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = {
+ FAB_FIRE_UE(UR, UR, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(UC, UC, PCI_STAT_S_SYSERR, 0),
+ FAB_OB_UE(ECRC, ECRC, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(CTO, TO, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(ROF, RO, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(MFP, MTLP, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(PP, PTLP, PCI_STAT_S_PERROR,
+ (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)),
+ FAB_FIRE_UE(FCP, FCP, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(DLP, DLP, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(TE, TRAINING, PCI_STAT_S_SYSERR, 0),
+ FAB_FIRE_UE(CA, CA, PCI_STAT_S_TARG_AB,
+ PCI_STAT_S_TARG_AB),
+ NULL, NULL, NULL,
+};
+
+#define FAB_FIRE_CE(fb, bit) \
+ FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0
+static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = {
+ FAB_FIRE_CE(RTO, REPLAY_TO),
+ FAB_FIRE_CE(RNR, REPLAY_ROLLOVER),
+ FAB_FIRE_CE(BDP, BAD_DLLP),
+ FAB_FIRE_CE(BTP, BAD_TLP),
+ FAB_FIRE_CE(RE, RECEIVER_ERR),
+ NULL, NULL, NULL,
+};
+
+/*
+ * WUC/RUC will need to be special cased for the target ereports, because you
+ * need to decode the tlp log.
+ */
+#define FAB_FIRE_WUCRUC(fb) \
+ FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR)
+#define FAB_FIRE_OE(fb, bit) \
+ FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
+#define FAB_OB_OE(fb, bit) \
+ FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
+static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = {
+ FAB_FIRE_WUCRUC(WUC),
+ FAB_FIRE_WUCRUC(RUC),
+ FAB_FIRE_OE(ERU, DLP),
+ FAB_FIRE_OE(ERO, DLP),
+ FAB_FIRE_OE(EMP, DLP),
+ FAB_FIRE_OE(EPE, DLP),
+ NULL, NULL, NULL,
+};
+
+#define FAB_FIRE_DMC(fb) \
+ FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
+#define FAB_N2_DMU(fb) \
+ FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
+static fab_fire_tbl_t fab_fire_dmc_tbl[] = {
+ FAB_FIRE_DMC(BYP_ERR),
+ FAB_FIRE_DMC(BYP_OOR),
+ FAB_FIRE_DMC(TRN_OOR),
+ FAB_FIRE_DMC(TTE_INV),
+ FAB_FIRE_DMC(TTE_PRT),
+ FAB_N2_DMU("iotsbdesc_inv"),
+ FAB_N2_DMU("sun4v_adj_va_uf"),
+ FAB_N2_DMU("sun4v_inv_pg_sz"),
+ FAB_N2_DMU("sun4v_key_err"),
+ FAB_N2_DMU("sun4v_va_oor"),
+ NULL, NULL, NULL
+};
+
+/* ARGSUSED */
+static void
+fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data)
+{
+ data->nvl = nvl;
+
+ /* Always Root Complex */
+ data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT;
+
+ data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD |
+ PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP);
+}
+
+static int
+fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ const char *class)
+{
+ fab_fire_tbl_t *entry;
+ uint64_t reg;
+
+ for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) {
+ if (STRCMP(class, entry->err_class))
+ goto send;
+ }
+
+ return (0);
+
+send:
+ fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class);
+
+ /* Fill in the device status register */
+ data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED;
+
+ /* Fill in the AER CE register */
+ if (nvlist_lookup_uint64(erpt, "tlu-cess", &reg) == 0) {
+ data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32);
+ }
+
+ return (1);
+}
+
+static int
+fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ const char *class)
+{
+ fab_fire_tbl_t *entry;
+ uint64_t reg;
+ uint32_t temp;
+ pcie_tlp_hdr_t *hdr;
+
+ for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) {
+ if (STRCMP(class, entry->err_class))
+ goto send;
+ }
+
+ return (0);
+
+send:
+ fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class);
+
+ /* Fill in PCI Status Register */
+ data->pci_err_status = entry->pci_err_sts;
+ data->pci_bdg_sec_stat = entry->pci_bdg_sts;
+
+ /* Fill in the device status register */
+ if (entry->fire_bit & data->pcie_ue_sev)
+ data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
+ else
+ data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
+
+ if (entry->fire_bit == PCIE_AER_UCE_UR)
+ data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED;
+
+ /* Fill in the AER UE register */
+ if (nvlist_lookup_uint64(erpt, "tlu-uess", &reg) == 0) {
+ data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32);
+ }
+
+ /* Fill in the AER Control register */
+ if ((reg & (uint64_t)entry->fire_bit) &&
+ nvlist_lookup_boolean(erpt, "primary")) {
+ temp = entry->fire_bit;
+ for (data->pcie_adv_ctl = (uint32_t)-1; temp;
+ data->pcie_adv_ctl++)
+ temp = temp >> 1;
+ }
+
+ /* If CTO create target information */
+ if (entry->fire_bit == PCIE_AER_UCE_TO &&
+ nvlist_lookup_boolean(erpt, "primary")) {
+ if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", &reg) == 0) {
+ data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
+ data->pcie_ue_hdr[1] = (uint32_t)(reg);
+ }
+ if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", &reg) == 0) {
+ data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
+ data->pcie_ue_hdr[3] = (uint32_t)(reg);
+ }
+
+ hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]);
+ switch (hdr->type) {
+ case PCIE_TLP_TYPE_IO:
+ case PCIE_TLP_TYPE_MEM:
+ case PCIE_TLP_TYPE_MEMLK:
+ data->pcie_ue_tgt_trans = PF_ADDR_PIO;
+ if (hdr->fmt & 0x1) {
+ data->pcie_ue_tgt_addr = reg;
+ } else {
+ data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2];
+ }
+ break;
+ case PCIE_TLP_TYPE_CFG0:
+ case PCIE_TLP_TYPE_CFG1:
+ data->pcie_ue_tgt_trans = PF_ADDR_CFG;
+ data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16;
+ break;
+ }
+ }
+
+ /* Fill in the AER Header registers */
+ if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", &reg) == 0) {
+ data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
+ data->pcie_ue_hdr[1] = (uint32_t)(reg);
+ }
+ if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", &reg) == 0) {
+ data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
+ data->pcie_ue_hdr[3] = (uint32_t)(reg);
+ }
+
+ return (1);
+}
+
+static int
+fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ const char *class)
+{
+ fab_fire_tbl_t *entry;
+ uint64_t reg;
+
+ for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) {
+ if (STRCMP(class, entry->err_class))
+ goto send;
+ }
+
+ return (0);
+
+send:
+ fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class);
+
+ /* Fill in PCI Status Register */
+ if (entry->fire_bit) {
+ data->pci_err_status = entry->pci_err_sts;
+ data->pci_bdg_sec_stat = entry->pci_bdg_sts;
+ } else {
+ if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", &reg) == 0) {
+ data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32);
+ data->pcie_ue_hdr[1] = (uint32_t)(reg);
+ }
+ if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", &reg) == 0) {
+ data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32);
+ data->pcie_ue_hdr[3] = (uint32_t)(reg);
+ }
+
+ if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type ==
+ PCIE_TLP_TYPE_CPL) {
+ pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1];
+ switch (cpl->status) {
+ case PCIE_CPL_STS_UR:
+ data->pci_err_status = 0;
+ data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB |
+ PCI_STAT_S_SYSERR;
+ break;
+ case PCIE_CPL_STS_CA:
+ data->pci_err_status = 0;
+ data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB |
+ PCI_STAT_S_SYSERR;
+ break;
+ }
+ }
+ }
+
+ /* Fill in the device status register */
+ if (entry->fire_bit & data->pcie_ue_sev)
+ data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED;
+ else
+ data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
+
+ /* Fill in the AER UE register */
+ data->pcie_ue_status = entry->fire_bit;
+
+ return (1);
+}
+
+static int
+fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
+ const char *class)
+{
+ fab_fire_tbl_t *entry;
+ uint64_t reg;
+ uint32_t temp;
+
+ for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) {
+ fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class);
+ if (STRCMP(class, entry->err_class) &&
+ nvlist_lookup_boolean(erpt, "primary"))
+ goto send;
+ }
+
+ return (0);
+
+send:
+ fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class);
+
+ /* Fill in PCI Status Register */
+ data->pci_err_status = entry->pci_err_sts;
+ data->pci_bdg_sec_stat = entry->pci_bdg_sts;
+
+ /* Fill in the device status register */
+ data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED;
+
+ /* Fill in the AER UE register */
+ data->pcie_ue_status = entry->fire_bit;
+
+ /* Fill in the AER Control register */
+ temp = entry->fire_bit;
+ for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++)
+ temp = temp >> 1;
+
+ /* Fill in the AER Header registers */
+ if (nvlist_lookup_uint64(erpt, "mmu-tfsr", &reg) == 0) {
+ fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg);
+ /* Get the trans type */
+ temp = (reg & 0x3F0000) >> 16;
+ data->pcie_ue_hdr[0] = (uint32_t)(temp << 24);
+ data->pcie_ue_tgt_trans = PF_ADDR_DMA;
+ /* Get the req id */
+ temp = (reg & 0xFFFF);
+ data->pcie_ue_hdr[1] = (uint32_t)(temp << 16);
+ data->pcie_ue_tgt_bdf = temp;
+ }
+
+ if (nvlist_lookup_uint64(erpt, "mmu-tfar", &reg) == 0) {
+ fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg);
+ /* Get the address */
+ data->pcie_ue_hdr[2] = reg;
+ data->pcie_ue_hdr[3] = 0;
+ data->pcie_ue_tgt_addr = reg;
+ }
+
+ fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]);
+ fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]);
+ fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]);
+ fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]);
+
+ return (1);
+}
+
+void
+fab_xlate_fire_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class)
+{
+ fab_data_t data = {0};
+
+ fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class);
+
+ fab_fire_to_data(hdl, nvl, &data);
+
+ if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) {
+ if (! fab_xlate_fire_ce(hdl, &data, nvl, class) &&
+ ! fab_xlate_fire_ue(hdl, &data, nvl, class))
+ (void) fab_xlate_fire_oe(hdl, &data, nvl, class);
+ } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") ||
+ fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*"))
+ (void) fab_xlate_fire_dmc(hdl, &data, nvl, class);
+
+ fab_xlate_pcie_erpts(hdl, &data);
+}
diff --git a/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c
new file mode 100644
index 0000000000..c88afe982f
--- /dev/null
+++ b/usr/src/cmd/fm/modules/common/fabric-xlate/fx_subr.c
@@ -0,0 +1,837 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <strings.h>
+#include <fm/topo_hc.h>
+#include <sys/fm/util.h>
+#include <libxml/xpath.h>
+#include <libxml/parser.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/tree.h>
+
+#include "fabric-xlate.h"
+
+#define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name)
+#define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name))
+#define FREE_PROP(prop) xmlFree((xmlChar *)prop)
+
+extern xmlXPathContextPtr fab_xpathCtx;
+
+/* ARGSUSED */
+int
+fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt,
+ boolean_t isRC)
+{
+ uint64_t *now;
+ uint64_t ena;
+ uint_t nelem;
+ nvlist_t *detector, *new_detector;
+ char rcpath[255];
+ int err = 0;
+
+ /* Grab the tod, ena and detector(FMRI) */
+ err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
+ err |= nvlist_lookup_uint64(nvl, "ena", &ena);
+ err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector);
+ if (err)
+ return (err);
+
+ /* Make a copy of the detector */
+ err = nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME);
+ if (err)
+ return (err);
+
+ /* Copy the tod and ena to erpt */
+ (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
+ (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
+
+ /*
+ * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used
+ * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl
+ * comments for more information.
+ */
+ if (isRC && fab_get_rcpath(hdl, nvl, rcpath)) {
+ /* Create the correct PCIe RC new_detector aka FMRI */
+ (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH,
+ DATA_TYPE_STRING);
+ (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH,
+ rcpath);
+ }
+
+ /* Copy the FMRI to erpt */
+ (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector);
+
+ nvlist_free(new_detector);
+ return (err);
+}
+
+void
+fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class,
+ boolean_t isPrimary)
+{
+ nvlist_t *nvl = data->nvl;
+ nvlist_t *erpt;
+ char *fmri = NULL;
+ uint32_t tgt_trans;
+ uint64_t tgt_addr;
+ uint16_t tgt_bdf;
+
+ if (isPrimary) {
+ tgt_trans = data->pcie_ue_tgt_trans;
+ tgt_addr = data->pcie_ue_tgt_addr;
+ tgt_bdf = data->pcie_ue_tgt_bdf;
+ } else {
+ tgt_trans = data->pcie_sue_tgt_trans;
+ tgt_addr = data->pcie_sue_tgt_addr;
+ tgt_bdf = data->pcie_sue_tgt_bdf;
+ }
+
+ fmd_hdl_debug(hdl, "Sending Target Ereport: "
+ "type 0x%x addr 0x%llx fltbdf 0x%x\n",
+ tgt_trans, tgt_addr, tgt_bdf);
+
+ if (!tgt_trans)
+ return;
+
+ if ((tgt_trans == PF_ADDR_PIO) && tgt_addr)
+ fmri = fab_find_addr(hdl, nvl, tgt_addr);
+ else if ((tgt_trans == PF_ADDR_CFG || (tgt_trans == PF_ADDR_DMA)) &&
+ tgt_bdf)
+ fmri = fab_find_bdf(hdl, nvl, tgt_bdf);
+
+ if (fmri) {
+ uint64_t *now;
+ uint64_t ena;
+ uint_t nelem;
+ nvlist_t *detector;
+ int err = 0;
+
+ /* Allocate space for new erpt */
+ if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
+ goto done;
+
+ /* Generate the target ereport class */
+ (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
+ PCI_ERROR_SUBCLASS, class);
+ (void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
+
+ /* Grab the tod, ena and detector(FMRI) */
+ err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem);
+ err |= nvlist_lookup_uint64(nvl, "ena", &ena);
+
+ /* Copy the tod and ena to erpt */
+ (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena);
+ (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem);
+
+ /* Create the correct FMRI */
+ if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0) {
+ nvlist_free(erpt);
+ goto done;
+ }
+ (void) nvlist_add_uint8(detector, FM_VERSION,
+ FM_DEV_SCHEME_VERSION);
+ (void) nvlist_add_string(detector, FM_FMRI_SCHEME,
+ FM_FMRI_SCHEME_DEV);
+ (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri);
+ (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector);
+ nvlist_free(detector);
+
+ /* Add the address payload */
+ (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr);
+
+ fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n",
+ fab_buf, tgt_addr);
+ fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
+ if (fmd_xprt_error(hdl, fab_fmd_xprt))
+ goto done;
+ fmd_hdl_strfree(hdl, fmri);
+ } else {
+ fmd_hdl_debug(hdl,
+ "Cannot find Target FMRI addr:0x%llx bdf 0x%x\n",
+ tgt_addr, tgt_bdf);
+ }
+
+ return;
+done:
+ if (fmri)
+ xmlFree(fmri);
+ fmd_hdl_debug(hdl, "Failed to send Target PCI ereport\n");
+}
+
+void
+fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl)
+{
+ fab_erpt_tbl_t *erpt_tbl, *entry;
+ nvlist_t *erpt;
+ uint32_t reg;
+
+ erpt_tbl = tbl->erpt_tbl;
+ if (tbl->reg_size == 16) {
+ reg = (uint32_t)*((uint16_t *)
+ ((uint32_t)data + tbl->reg_offset));
+ } else {
+ reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset));
+ }
+
+ for (entry = erpt_tbl; entry->err_class; entry++) {
+ if (!(reg & entry->reg_bit))
+ continue;
+
+ if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
+ goto done;
+ if (tbl->fab_prep(hdl, data, erpt, entry) != 0) {
+ fmd_hdl_debug(hdl, "Prepping ereport failed: "
+ "class = %s\n", entry->err_class);
+ nvlist_free(erpt);
+ continue;
+ }
+
+ fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg);
+ fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
+ if (fmd_xprt_error(hdl, fab_fmd_xprt)) {
+ fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
+ return;
+ }
+ }
+
+ return;
+done:
+ fmd_hdl_debug(hdl, "Failed to send PCI ereport\n");
+}
+
+char *
+fab_xpath_query(fmd_hdl_t *hdl, const char *query)
+{
+ xmlXPathObjectPtr xpathObj;
+ xmlNodeSetPtr nodes;
+ char *temp, *res;
+
+ fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
+
+ xpathObj = xmlXPathEvalExpression((const xmlChar *)query,
+ fab_xpathCtx);
+
+ if (xpathObj == NULL)
+ return (NULL);
+
+ fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj,
+ xpathObj->type);
+ nodes = xpathObj->nodesetval;
+
+ if (nodes) {
+ temp = (char *)xmlNodeGetContent(nodes->nodeTab[0]);
+ fmd_hdl_debug(hdl, "query result: %s\n", temp);
+ res = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
+ xmlFree(temp);
+ xmlXPathFreeObject(xpathObj);
+ return (res);
+ }
+ xmlXPathFreeObject(xpathObj);
+ return (NULL);
+}
+
+#define FAB_HC2DEV_QUERY_SIZE_MIN 160
+#define FAB_HC2DEV_QUERY_SIZE(sz) \
+ ((sz + FAB_HC2DEV_QUERY_SIZE_MIN) * sizeof (char))
+
+/*
+ * hc_path is in form of "/motherboard=0/hostbridge=0/pciexrc=0"
+ */
+boolean_t
+fab_hc2dev(fmd_hdl_t *hdl, const char *hc_path, char **dev_path)
+{
+ char *query;
+ uint_t len = FAB_HC2DEV_QUERY_SIZE_MIN + strlen(hc_path);
+
+ query = fmd_hdl_alloc(hdl, len, FMD_SLEEP);
+ (void) snprintf(query, len, "//propval[@name='resource' and contains("
+ "substring(@value, string-length(@value) - %d + 1), '%s')]"
+ "/parent::*/following-sibling::*/propval[@name='dev']/@value",
+ strlen(hc_path) + 1, hc_path);
+
+ *dev_path = fab_xpath_query(hdl, query);
+
+ fmd_hdl_free(hdl, query, len);
+
+ return (*dev_path != NULL);
+}
+
+static boolean_t
+fab_hc_path(fmd_hdl_t *hdl, nvlist_t *detector, char **hcpath, size_t *lenp)
+{
+ char c, *name, *id, *buf;
+ uint_t i, size;
+ nvlist_t **hcl;
+ size_t len = 0, buf_size = 0;
+
+ if (nvlist_lookup_nvlist_array(detector, FM_FMRI_HC_LIST, &hcl,
+ &size) != 0)
+ return (B_FALSE);
+
+ for (i = 0; i < size; i++) {
+ if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0)
+ return (B_FALSE);
+ if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id) != 0)
+ return (B_FALSE);
+ buf_size += snprintf(&c, 1, "/%s=%s", name, id);
+ }
+
+ buf_size++;
+ buf = fmd_hdl_alloc(hdl, buf_size, FMD_SLEEP);
+
+ for (i = 0; i < size; i++) {
+ (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name);
+ (void) nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &id);
+ len += snprintf(buf + len, buf_size - len, "/%s=%s", name, id);
+ }
+
+ *hcpath = buf;
+ *lenp = buf_size;
+
+ return (B_TRUE);
+}
+
+boolean_t
+fab_hc2dev_nvl(fmd_hdl_t *hdl, nvlist_t *detector, char **dev_path)
+{
+ char *hcl;
+ size_t len;
+
+ if (! fab_hc_path(hdl, detector, &hcl, &len))
+ return (B_FALSE);
+
+ (void) fab_hc2dev(hdl, hcl, dev_path);
+
+ fmd_hdl_free(hdl, hcl, len);
+
+ return (*dev_path != NULL);
+}
+
+boolean_t
+fab_get_hcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char **hcpath, size_t *len)
+{
+ nvlist_t *detector;
+ char *scheme;
+
+ if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0 ||
+ nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0 ||
+ ! STRCMP(scheme, FM_FMRI_SCHEME_HC))
+ return (B_FALSE);
+
+ return (fab_hc_path(hdl, detector, hcpath, len));
+}
+
+char *
+fab_find_rppath_by_df(fmd_hdl_t *hdl, nvlist_t *nvl, uint8_t df)
+{
+ char query[500];
+ char str[10];
+ char *hcpath;
+ size_t len;
+
+ (void) snprintf(str, sizeof (str), "%0hhx", df);
+
+ /*
+ * get the string form of the hc detector, eg
+ * /chassis=0/motherboard=0/hostbridge=0
+ */
+ if (!fab_get_hcpath(hdl, nvl, &hcpath, &len))
+ return (NULL);
+
+ /*
+ * Explanation of the XSL XPATH Query
+ * Line 1: Look at all nodes with the node name "propval"
+ * Line 2: See if the "BDF" of the node matches DF
+ * Line 3-4: See if the the node is pciexrc
+ * Line 5-6: See if the "ASRU" contains root complex
+ * Line 7-8: Go up one level and get prop value of io/dev
+ */
+ (void) snprintf(query, sizeof (query), "//propval["
+ "@name='BDF' and contains(substring(@value, "
+ "string-length(@value) - 1), '%s')]"
+ "/parent::*/parent::*/propgroup[@name='pci']/propval"
+ "[@name='extended-capabilities' and @value='%s']"
+ "/parent::*/parent::*/propgroup[@name='protocol']"
+ "/propval[@name='resource' and contains(@value, '%s')]"
+ "/parent::*/parent::*/propgroup[@name='io']"
+ "/propval[@name='dev']/@value", str, PCIEX_ROOT, hcpath);
+
+ fmd_hdl_free(hdl, hcpath, len);
+
+ return (fab_xpath_query(hdl, query));
+}
+
+char *
+fab_find_rppath_by_devbdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf)
+{
+ xmlXPathObjectPtr xpathObj;
+ xmlNodeSetPtr nodes;
+ xmlNodePtr devNode;
+ char *retval, *temp;
+ char query[500];
+ int i, size, bus, dev, fn;
+ char *hcpath;
+ size_t len;
+
+ if (bdf != (uint16_t)-1) {
+ bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
+ dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
+ fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
+ }
+
+ /*
+ * get the string form of the hc detector, eg
+ * /chassis=0/motherboard=0/hostbridge=0
+ */
+ if (!fab_get_hcpath(hdl, nvl, &hcpath, &len))
+ goto fail;
+
+ /*
+ * Explanation of the XSL XPATH Query
+ * Line 1: Look at all nodes with the node name "propval"
+ * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
+ * Line 4-5: See if the "value" of the node ends with correct PCI BDF
+ * Line 6: Go up one level to the parent of the current node
+ * Line 7: See if child node contains "ASRU" with the same PCIe Root
+ * Line 8: Go up see all the ancestors
+ */
+ (void) snprintf(query, sizeof (query), "//propval["
+ "contains(substring(@value, string-length(@value) - 34), "
+ "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
+ "contains(substring(@value, string-length(@value) - 28), "
+ "'pcibus=%d/pcidev=%d/pcifn=%d')"
+ "]/parent::"
+ "*/propval[@name='resource' and contains(@value, '%s')]"
+ "/ancestor::*",
+ bus, dev, fn, bus, dev, fn, hcpath);
+
+ fmd_hdl_free(hdl, hcpath, len);
+
+ fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
+
+ xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
+
+ if (xpathObj == NULL)
+ goto fail;
+
+ nodes = xpathObj->nodesetval;
+ size = (nodes) ? nodes->nodeNr : 0;
+
+ fmd_hdl_debug(hdl, "xpathObj 0x%p type %d size %d\n",
+ xpathObj, xpathObj->type, size);
+
+ for (i = 0; i < size; i++) {
+ devNode = nodes->nodeTab[i];
+ if (STRCMP(devNode->name, "range") &&
+ HAS_PROP(devNode, "name")) {
+ char *tprop = GET_PROP(devNode, "name");
+
+ /* find "range name='pciexrc'" in ancestors */
+ if (STRCMP(tprop, PCIEX_ROOT)) {
+ /* go down to the pciexrc instance node */
+ FREE_PROP(tprop);
+ devNode = nodes->nodeTab[i+1];
+ goto found;
+ }
+ FREE_PROP(tprop);
+ }
+ }
+ goto fail;
+
+found:
+ /* Traverse down the xml tree to find the right propgroup */
+ for (devNode = devNode->children; devNode; devNode = devNode->next) {
+ if (STRCMP(devNode->name, "propgroup")) {
+ char *tprop = GET_PROP(devNode, "name");
+
+ if (STRCMP(tprop, "io")) {
+ FREE_PROP(tprop);
+ goto propgroup;
+ }
+ FREE_PROP(tprop);
+ }
+ }
+ goto fail;
+
+propgroup:
+ /* Retrive the "dev" propval and return */
+ for (devNode = devNode->children; devNode; devNode = devNode->next) {
+ if (STRCMP(devNode->name, "propval")) {
+ char *tprop = GET_PROP(devNode, "name");
+
+ if (STRCMP(tprop, "dev")) {
+ temp = GET_PROP(devNode, "value");
+ retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
+ fmd_hdl_debug(hdl, "RP Path: %s\n", retval);
+ xmlFree(temp);
+ xmlXPathFreeObject(xpathObj);
+ }
+ FREE_PROP(tprop);
+
+ return (retval);
+ }
+ }
+fail:
+ if (xpathObj != NULL)
+ xmlXPathFreeObject(xpathObj);
+ return (NULL);
+}
+
+/* ARGSUSED */
+boolean_t
+fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath)
+{
+ nvlist_t *detector;
+ char *path, *scheme;
+
+ if (nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector) != 0)
+ goto fail;
+ if (nvlist_lookup_string(detector, FM_FMRI_SCHEME, &scheme) != 0)
+ goto fail;
+
+ if (STRCMP(scheme, FM_FMRI_SCHEME_DEV)) {
+ if (nvlist_lookup_string(detector, FM_FMRI_DEV_PATH,
+ &path) != 0)
+ goto fail;
+ (void) strncpy(rcpath, path, FM_MAX_CLASS);
+ } else if (STRCMP(scheme, FM_FMRI_SCHEME_HC)) {
+ /*
+ * This should only occur for ereports that come from the RC
+ * itself. In this case convert HC scheme to dev path.
+ */
+ if (fab_hc2dev_nvl(hdl, detector, &path)) {
+ (void) strncpy(rcpath, path, FM_MAX_CLASS);
+ fmd_hdl_strfree(hdl, path);
+ } else {
+ goto fail;
+ }
+ } else {
+ return (B_FALSE);
+ }
+
+ /*
+ * Extract the RC path by taking the first device in the dev path
+ *
+ * /pci@0,0/pci8086,3605@2/pci8086,3500@0/pci8086,3514@1/pci8086,105e@0
+ * - to -
+ * /pci@0,0
+ */
+ path = strchr(rcpath + 1, '/');
+ if (path)
+ path[0] = '\0';
+
+ return (B_TRUE);
+fail:
+ return (B_FALSE);
+}
+
+char *
+fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf)
+{
+ char *retval;
+ char query[500];
+ int bus, dev, fn;
+ char rcpath[255];
+
+ if (bdf != (uint16_t)-1) {
+ bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT;
+ dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT;
+ fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT;
+ }
+
+ if (!fab_get_rcpath(hdl, nvl, rcpath))
+ goto fail;
+
+ /*
+ * Explanation of the XSL XPATH Query
+ * Line 1: Look at all nodes with the node name "propval"
+ * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF
+ * Line 4-5: See if the "value" of the node ends with correct PCI BDF
+ * Line 6: Go up one level to the parent of the current node
+ * Line 7: See if child node contains "ASRU" with the same PCIe Root
+ * Line 8: Traverse up the parent and the other siblings and look for
+ * the io "propgroup" and get the value of the dev "propval"
+ */
+ (void) snprintf(query, sizeof (query), "//propval["
+ "contains(substring(@value, string-length(@value) - 34), "
+ "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or "
+ "contains(substring(@value, string-length(@value) - 28), "
+ "'pcibus=%d/pcidev=%d/pcifn=%d')"
+ "]/parent::"
+ "*/propval[@name='ASRU' and contains(@value, '%s')]"
+ "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/"
+ "@value", bus, dev, fn, bus, dev, fn, rcpath);
+
+ retval = fab_xpath_query(hdl, query);
+ if (retval) {
+ fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", retval);
+ return (retval);
+ }
+fail:
+ return (NULL);
+}
+
+char *
+fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr)
+{
+ xmlXPathObjectPtr xpathObj;
+ xmlNodeSetPtr nodes;
+ xmlNodePtr devNode;
+ char *retval, *temp;
+ char query[500];
+ int size, i, j;
+ uint32_t prop[50];
+ char *token;
+ pci_regspec_t *assign_p;
+ uint64_t low, hi;
+ char rcpath[255];
+
+ if (!fab_get_rcpath(hdl, nvl, rcpath))
+ goto fail;
+
+ (void) snprintf(query, sizeof (query), "//propval["
+ "@name='ASRU' and contains(@value, '%s')]/"
+ "parent::*/following-sibling::*[@name='pci']/"
+ "propval[@name='assigned-addresses']", rcpath);
+
+ fmd_hdl_debug(hdl, "xpathObj query %s\n", query);
+
+ xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx);
+
+ if (xpathObj == NULL)
+ goto fail;
+
+ fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type);
+
+ nodes = xpathObj->nodesetval;
+ size = (nodes) ? nodes->nodeNr : 0;
+
+ /* Decode the list of assigned addresses xml nodes for each device */
+ for (i = 0; i < size; i++) {
+ char *tprop;
+
+ devNode = nodes->nodeTab[i];
+ if (!HAS_PROP(devNode, "value"))
+ continue;
+
+ /* Convert "string" assigned-addresses to pci_regspec_t */
+ j = 0;
+ tprop = GET_PROP(devNode, "value");
+ for (token = strtok(tprop, " "); token;
+ token = strtok(NULL, " ")) {
+ prop[j++] = strtoul(token, (char **)NULL, 16);
+ }
+ prop[j] = (uint32_t)-1;
+ FREE_PROP(tprop);
+
+ /* Check if address belongs to this device */
+ for (assign_p = (pci_regspec_t *)prop;
+ assign_p->pci_phys_hi != (uint_t)-1; assign_p++) {
+ low = assign_p->pci_phys_low;
+ hi = low + assign_p->pci_size_low;
+ if ((addr < hi) && (addr >= low)) {
+ fmd_hdl_debug(hdl, "Found Address\n");
+ goto found;
+ }
+ }
+ }
+ goto fail;
+
+found:
+ /* Traverse up the xml tree and back down to find the right propgroup */
+ for (devNode = devNode->parent->parent->children;
+ devNode; devNode = devNode->next) {
+ char *tprop;
+
+ tprop = GET_PROP(devNode, "name");
+ if (STRCMP(devNode->name, "propgroup") &&
+ STRCMP(tprop, "io")) {
+ FREE_PROP(tprop);
+ goto propgroup;
+ }
+ FREE_PROP(tprop);
+ }
+ goto fail;
+
+propgroup:
+ /* Retrive the "dev" propval and return */
+ for (devNode = devNode->children; devNode; devNode = devNode->next) {
+ char *tprop;
+
+ tprop = GET_PROP(devNode, "name");
+ if (STRCMP(devNode->name, "propval") &&
+ STRCMP(tprop, "dev")) {
+ FREE_PROP(tprop);
+ temp = GET_PROP(devNode, "value");
+ retval = fmd_hdl_strdup(hdl, temp, FMD_SLEEP);
+ fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", retval);
+ xmlFree(temp);
+ xmlXPathFreeObject(xpathObj);
+ return (retval);
+ }
+ FREE_PROP(tprop);
+ }
+fail:
+ if (xpathObj != NULL)
+ xmlXPathFreeObject(xpathObj);
+ return (NULL);
+}
+
+void
+fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl)
+{
+ nvpair_t *nvp;
+
+ for (nvp = nvlist_next_nvpair(nvl, NULL);
+ nvp != NULL;
+ nvp = nvlist_next_nvpair(nvl, nvp)) {
+
+ data_type_t type = nvpair_type(nvp);
+ const char *name = nvpair_name(nvp);
+
+ boolean_t b;
+ uint8_t i8;
+ uint16_t i16;
+ uint32_t i32;
+ uint64_t i64;
+ char *str;
+ nvlist_t *cnv;
+
+ nvlist_t **nvlarr;
+ uint_t arrsize;
+ int arri;
+
+
+ if (STRCMP(name, FM_CLASS))
+ continue; /* already printed by caller */
+
+ fmd_hdl_debug(hdl, " %s=", name);
+
+ switch (type) {
+ case DATA_TYPE_BOOLEAN:
+ fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1");
+ break;
+
+ case DATA_TYPE_BOOLEAN_VALUE:
+ (void) nvpair_value_boolean_value(nvp, &b);
+ fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d",
+ b ? "1" : "0");
+ break;
+
+ case DATA_TYPE_BYTE:
+ (void) nvpair_value_byte(nvp, &i8);
+ fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8);
+ break;
+
+ case DATA_TYPE_INT8:
+ (void) nvpair_value_int8(nvp, (void *)&i8);
+ fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8);
+ break;
+
+ case DATA_TYPE_UINT8:
+ (void) nvpair_value_uint8(nvp, &i8);
+ fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8);
+ break;
+
+ case DATA_TYPE_INT16:
+ (void) nvpair_value_int16(nvp, (void *)&i16);
+ fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16);
+ break;
+
+ case DATA_TYPE_UINT16:
+ (void) nvpair_value_uint16(nvp, &i16);
+ fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16);
+ break;
+
+ case DATA_TYPE_INT32:
+ (void) nvpair_value_int32(nvp, (void *)&i32);
+ fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32);
+ break;
+
+ case DATA_TYPE_UINT32:
+ (void) nvpair_value_uint32(nvp, &i32);
+ fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32);
+ break;
+
+ case DATA_TYPE_INT64:
+ (void) nvpair_value_int64(nvp, (void *)&i64);
+ fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx",
+ (u_longlong_t)i64);
+ break;
+
+ case DATA_TYPE_UINT64:
+ (void) nvpair_value_uint64(nvp, &i64);
+ fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx",
+ (u_longlong_t)i64);
+ break;
+
+ case DATA_TYPE_HRTIME:
+ (void) nvpair_value_hrtime(nvp, (void *)&i64);
+ fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx",
+ (u_longlong_t)i64);
+ break;
+
+ case DATA_TYPE_STRING:
+ (void) nvpair_value_string(nvp, &str);
+ fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"",
+ str ? str : "<NULL>");
+ break;
+
+ case DATA_TYPE_NVLIST:
+ fmd_hdl_debug(hdl, "[");
+ (void) nvpair_value_nvlist(nvp, &cnv);
+ fab_pr(hdl, NULL, cnv);
+ fmd_hdl_debug(hdl, " ]");
+ break;
+
+ case DATA_TYPE_BOOLEAN_ARRAY:
+ case DATA_TYPE_BYTE_ARRAY:
+ case DATA_TYPE_INT8_ARRAY:
+ case DATA_TYPE_UINT8_ARRAY:
+ case DATA_TYPE_INT16_ARRAY:
+ case DATA_TYPE_UINT16_ARRAY:
+ case DATA_TYPE_INT32_ARRAY:
+ case DATA_TYPE_UINT32_ARRAY:
+ case DATA_TYPE_INT64_ARRAY:
+ case DATA_TYPE_UINT64_ARRAY:
+ case DATA_TYPE_STRING_ARRAY:
+ fmd_hdl_debug(hdl, "[...]");
+ break;
+ case DATA_TYPE_NVLIST_ARRAY:
+ arrsize = 0;
+ (void) nvpair_value_nvlist_array(nvp, &nvlarr,
+ &arrsize);
+
+ for (arri = 0; arri < arrsize; arri++) {
+ fab_pr(hdl, ep, nvlarr[arri]);
+ }
+
+ break;
+ case DATA_TYPE_UNKNOWN:
+ fmd_hdl_debug(hdl, "<unknown>");
+ break;
+ }
+ }
+}
diff --git a/usr/src/cmd/mdb/common/modules/crypto/impl.c b/usr/src/cmd/mdb/common/modules/crypto/impl.c
index 52d20d2509..69afb4ecc1 100644
--- a/usr/src/cmd/mdb/common/modules/crypto/impl.c
+++ b/usr/src/cmd/mdb/common/modules/crypto/impl.c
@@ -175,11 +175,13 @@ kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list);
mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque);
- mdb_printf("pd_flags:\t\t%s %s %s %s %s\n",
+ mdb_printf("pd_flags:\t\t%s %s %s %s %s %s\n",
(desc.pd_flags & CRYPTO_HIDE_PROVIDER) ?
"CRYPTO_HIDE_PROVIDER" : " ",
(desc.pd_flags & CRYPTO_HASH_NO_UPDATE) ?
"CRYPTO_HASH_NO_UPDATE" : " ",
+ (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE) ?
+ "CRYPTO_HMAC_NO_UPDATE" : " ",
(desc.pd_flags & CRYPTO_SYNCHRONOUS) ?
"CRYPTO_SYNCHRONOUS" : " ",
(desc.pd_flags & KCF_LPROV_MEMBER) ?
@@ -188,6 +190,8 @@ kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
"KCF_PROV_RESTRICTED" : " ");
if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE)
mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit);
+ if (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE)
+ mdb_printf("pd_hmac_limit:\t\t%u\n", desc.pd_hmac_limit);
mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat);