xref: /illumos-gate/usr/src/cmd/fm/modules/common/fabric-xlate/fx_fabric.c (revision 0245b61fd282e95735b173b8d95be0d6688163b4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright 2019 Joyent, Inc.
27  */
28 #include <stddef.h>
29 #include <strings.h>
30 #include <sys/fm/util.h>
31 #include <sys/pcie.h>
32 
33 #include "fabric-xlate.h"
34 
35 #define	FAB_LOOKUP(sz, name, field) \
36 	(void) nvlist_lookup_uint ## sz(nvl, name, field)
37 
38 static boolean_t fab_xlate_fake_rp = B_TRUE;
39 static fab_err_tbl_t *fab_master_err_tbl;
40 
41 /*
42  * Translation tables for converting "fabric" error bits into "pci" ereports.
43  * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function>
44  */
45 
46 /* MACRO for table entries with no TGT ereports */
47 #define	NT(class, bit, prep) class, bit, prep, NULL
48 /* Translate Fabric ereports to ereport.io.pci.* */
49 fab_erpt_tbl_t fab_pci_erpt_tbl[] = {
50 	PCI_DET_PERR,		PCI_STAT_PERROR,	NULL,
51 	PCI_MDPE,		PCI_STAT_S_PERROR,	NULL,
52 	PCI_SIG_SERR,		PCI_STAT_S_SYSERR,	NULL,
53 	PCI_MA,			PCI_STAT_R_MAST_AB,	NULL,
54 	PCI_REC_TA,		PCI_STAT_R_TARG_AB,	NULL,
55 	PCI_SIG_TA,		PCI_STAT_S_TARG_AB,	NULL,
56 	NULL, 0, NULL
57 };
58 
59 /* Translate Fabric ereports to ereport.io.pci.sec-* */
60 static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = {
61 	PCI_DET_PERR,		PCI_STAT_PERROR,	NULL,
62 	PCI_MDPE,		PCI_STAT_S_PERROR,	NULL,
63 	PCI_REC_SERR,		PCI_STAT_S_SYSERR,	NULL,
64 #ifdef sparc
65 	PCI_MA,			PCI_STAT_R_MAST_AB,	NULL,
66 #endif
67 	PCI_REC_TA,		PCI_STAT_R_TARG_AB,	NULL,
68 	PCI_SIG_TA,		PCI_STAT_S_TARG_AB,	NULL,
69 	NULL, 0, NULL,
70 };
71 
72 
73 /* Translate Fabric ereports to ereport.io.pci.dto */
74 static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = {
75 	PCI_DTO,	PCI_BCNF_BCNTRL_DTO_STAT,	NULL,
76 	NULL, 0, NULL
77 };
78 
79 /* Translate Fabric ereports to ereport.io.pciex.* */
80 static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = {
81 	PCIEX_RE,	PCIE_AER_CE_RECEIVER_ERR,	NULL,
82 	PCIEX_RNR,	PCIE_AER_CE_REPLAY_ROLLOVER,	NULL,
83 	PCIEX_RTO,	PCIE_AER_CE_REPLAY_TO,		NULL,
84 	PCIEX_BDP,	PCIE_AER_CE_BAD_DLLP,		NULL,
85 	PCIEX_BTP,	PCIE_AER_CE_BAD_TLP,		NULL,
86 	PCIEX_ANFE,	PCIE_AER_CE_AD_NFE,		NULL,
87 	NULL, 0, NULL
88 };
89 
90 /*
91  * Translate Fabric ereports to ereport.io.pciex.*
92  * The Target Ereports for this section is only used on leaf devices, with the
93  * exception of TO
94  */
95 static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = {
96 	PCIEX_TE,	PCIE_AER_UCE_TRAINING,		NULL,
97 	PCIEX_DLP,	PCIE_AER_UCE_DLP,		NULL,
98 	PCIEX_SD,	PCIE_AER_UCE_SD,		NULL,
99 	PCIEX_ROF,	PCIE_AER_UCE_RO,		NULL,
100 	PCIEX_FCP,	PCIE_AER_UCE_FCP,		NULL,
101 	PCIEX_MFP,	PCIE_AER_UCE_MTLP,		NULL,
102 	PCIEX_CTO,	PCIE_AER_UCE_TO,		PCI_TARG_MA,
103 	PCIEX_UC,	PCIE_AER_UCE_UC,		NULL,
104 	PCIEX_ECRC,	PCIE_AER_UCE_ECRC,		NULL,
105 	PCIEX_CA,	PCIE_AER_UCE_CA,		PCI_TARG_REC_TA,
106 #ifdef sparc
107 	PCIEX_UR,	PCIE_AER_UCE_UR,		PCI_TARG_MA,
108 #endif
109 	PCIEX_POIS,	PCIE_AER_UCE_PTLP,		PCI_TARG_MDPE,
110 	NULL, 0, NULL
111 };
112 
113 /* Translate Fabric ereports to ereport.io.pciex.* */
114 static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = {
115 	PCIEX_S_TA_SC,	PCIE_AER_SUCE_TA_ON_SC,		PCI_TARG_REC_TA,
116 	PCIEX_S_MA_SC,	PCIE_AER_SUCE_MA_ON_SC,		PCI_TARG_MA,
117 	PCIEX_S_RTA,	PCIE_AER_SUCE_RCVD_TA,		PCI_TARG_REC_TA,
118 #ifdef sparc
119 	PCIEX_S_RMA,	PCIE_AER_SUCE_RCVD_MA,		PCI_TARG_MA,
120 #endif
121 	PCIEX_S_USC,	PCIE_AER_SUCE_USC_ERR,		NULL,
122 	PCIEX_S_USCMD,	PCIE_AER_SUCE_USC_MSG_DATA_ERR,	PCI_TARG_REC_TA,
123 	PCIEX_S_UDE,	PCIE_AER_SUCE_UC_DATA_ERR,	PCI_TARG_MDPE,
124 	PCIEX_S_UAT,	PCIE_AER_SUCE_UC_ATTR_ERR,	PCI_TARG_MDPE,
125 	PCIEX_S_UADR,	PCIE_AER_SUCE_UC_ADDR_ERR,	PCI_TARG_MDPE,
126 	PCIEX_S_TEX,	PCIE_AER_SUCE_TIMER_EXPIRED,	NULL,
127 	PCIEX_S_PERR,	PCIE_AER_SUCE_PERR_ASSERT,	PCI_TARG_MDPE,
128 	PCIEX_S_SERR,	PCIE_AER_SUCE_SERR_ASSERT,	NULL,
129 	PCIEX_INTERR,	PCIE_AER_SUCE_INTERNAL_ERR,	NULL,
130 	NULL, 0, NULL
131 };
132 
133 /* Translate Fabric ereports to ereport.io.pcix.* */
134 static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = {
135 	PCIX_SPL_DIS,		PCI_PCIX_SPL_DSCD,	NULL,
136 	PCIX_UNEX_SPL,		PCI_PCIX_UNEX_SPL,	NULL,
137 	PCIX_RX_SPL_MSG,	PCI_PCIX_RX_SPL_MSG,	NULL,
138 	NULL, 0, NULL
139 };
140 static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl;
141 
142 /* Translate Fabric ereports to ereport.io.pcix.sec-* */
143 static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = {
144 	PCIX_SPL_DIS,		PCI_PCIX_BSS_SPL_DSCD,	NULL,
145 	PCIX_UNEX_SPL,		PCI_PCIX_BSS_UNEX_SPL,	NULL,
146 	PCIX_BSS_SPL_OR,	PCI_PCIX_BSS_SPL_OR,	NULL,
147 	PCIX_BSS_SPL_DLY,	PCI_PCIX_BSS_SPL_DLY,	NULL,
148 	NULL, 0, NULL
149 };
150 
151 /* Translate Fabric ereports to ereport.io.pciex.* */
152 static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = {
153 #ifdef sparc
154 	PCIEX_UR,		PCIE_DEVSTS_UR_DETECTED,	NULL,
155 #endif
156 	PCIEX_FAT,		PCIE_DEVSTS_FE_DETECTED,	NULL,
157 	PCIEX_NONFAT,		PCIE_DEVSTS_NFE_DETECTED,	NULL,
158 	PCIEX_CORR,		PCIE_DEVSTS_CE_DETECTED,	NULL,
159 	NULL, 0, NULL
160 };
161 
162 /* Translate Fabric ereports to ereport.io.pciex.* */
163 static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = {
164 	PCIEX_RC_FE_MSG,	PCIE_AER_RE_STS_FE_MSGS_RCVD,	NULL,
165 	PCIEX_RC_NFE_MSG,	PCIE_AER_RE_STS_NFE_MSGS_RCVD,	NULL,
166 	PCIEX_RC_CE_MSG,	PCIE_AER_RE_STS_CE_RCVD,	NULL,
167 	PCIEX_RC_MCE_MSG,	PCIE_AER_RE_STS_MUL_CE_RCVD,	NULL,
168 	PCIEX_RC_MUE_MSG,	PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL,
169 	NULL, 0, NULL
170 };
171 
172 /*
173  * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages.
174  * If the RP is not a PCIe compliant RP or does not support AER, rely on the
175  * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC.
176  */
177 static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = {
178 	PCIEX_RC_FE_MSG,	PCIE_DEVSTS_FE_DETECTED,	NULL,
179 	PCIEX_RC_NFE_MSG,	PCIE_DEVSTS_NFE_DETECTED,	NULL,
180 	PCIEX_RC_CE_MSG,	PCIE_DEVSTS_CE_DETECTED,	NULL,
181 	NULL, 0, NULL,
182 };
183 
184 /* ARGSUSED */
185 void
186 fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data)
187 {
188 	data->nvl = nvl;
189 
190 	/* Generic PCI device information */
191 	FAB_LOOKUP(16,	"bdf",			&data->bdf);
192 	FAB_LOOKUP(16,	"device_id",		&data->device_id);
193 	FAB_LOOKUP(16,	"vendor_id",		&data->vendor_id);
194 	FAB_LOOKUP(8,	"rev_id",		&data->rev_id);
195 	FAB_LOOKUP(16,	"dev_type",		&data->dev_type);
196 	FAB_LOOKUP(16,	"pcie_off",		&data->pcie_off);
197 	FAB_LOOKUP(16,	"pcix_off",		&data->pcix_off);
198 	FAB_LOOKUP(16,	"aer_off",		&data->aer_off);
199 	FAB_LOOKUP(16,	"ecc_ver",		&data->ecc_ver);
200 
201 	/* Misc ereport information */
202 	FAB_LOOKUP(32,	"remainder",		&data->remainder);
203 	FAB_LOOKUP(32,	"severity",		&data->severity);
204 
205 	/* PCI registers */
206 	FAB_LOOKUP(16,	"pci_status",		&data->pci_err_status);
207 	FAB_LOOKUP(16,	"pci_command",		&data->pci_cfg_comm);
208 
209 	/* PCI bridge registers */
210 	FAB_LOOKUP(16,	"pci_bdg_sec_status",	&data->pci_bdg_sec_stat);
211 	FAB_LOOKUP(16,	"pci_bdg_ctrl",		&data->pci_bdg_ctrl);
212 
213 	/* PCIx registers */
214 	FAB_LOOKUP(32,	"pcix_status",		&data->pcix_status);
215 	FAB_LOOKUP(16,	"pcix_command",		&data->pcix_command);
216 
217 	/* PCIx ECC Registers */
218 	FAB_LOOKUP(16,	"pcix_ecc_control_0",	&data->pcix_ecc_control_0);
219 	FAB_LOOKUP(16,	"pcix_ecc_status_0",	&data->pcix_ecc_status_0);
220 	FAB_LOOKUP(32,	"pcix_ecc_fst_addr_0",	&data->pcix_ecc_fst_addr_0);
221 	FAB_LOOKUP(32,	"pcix_ecc_sec_addr_0",	&data->pcix_ecc_sec_addr_0);
222 	FAB_LOOKUP(32,	"pcix_ecc_attr_0",	&data->pcix_ecc_attr_0);
223 
224 	/* PCIx ECC Bridge Registers */
225 	FAB_LOOKUP(16,	"pcix_ecc_control_1",	&data->pcix_ecc_control_1);
226 	FAB_LOOKUP(16,	"pcix_ecc_status_1",	&data->pcix_ecc_status_1);
227 	FAB_LOOKUP(32,	"pcix_ecc_fst_addr_1",	&data->pcix_ecc_fst_addr_1);
228 	FAB_LOOKUP(32,	"pcix_ecc_sec_addr_1",	&data->pcix_ecc_sec_addr_1);
229 	FAB_LOOKUP(32,	"pcix_ecc_attr_1",	&data->pcix_ecc_attr_1);
230 
231 	/* PCIx Bridge */
232 	FAB_LOOKUP(32,	"pcix_bdg_status",	&data->pcix_bdg_stat);
233 	FAB_LOOKUP(16,	"pcix_bdg_sec_status",	&data->pcix_bdg_sec_stat);
234 
235 	/* PCIe registers */
236 	FAB_LOOKUP(16,	"pcie_status",		&data->pcie_err_status);
237 	FAB_LOOKUP(16,	"pcie_command",		&data->pcie_err_ctl);
238 	FAB_LOOKUP(32,	"pcie_dev_cap",		&data->pcie_dev_cap);
239 
240 	/* PCIe AER registers */
241 	FAB_LOOKUP(32,	"pcie_adv_ctl",		&data->pcie_adv_ctl);
242 	FAB_LOOKUP(32,	"pcie_ue_status",	&data->pcie_ue_status);
243 	FAB_LOOKUP(32,	"pcie_ue_mask",		&data->pcie_ue_mask);
244 	FAB_LOOKUP(32,	"pcie_ue_sev",		&data->pcie_ue_sev);
245 	FAB_LOOKUP(32,	"pcie_ue_hdr0",		&data->pcie_ue_hdr[0]);
246 	FAB_LOOKUP(32,	"pcie_ue_hdr1",		&data->pcie_ue_hdr[1]);
247 	FAB_LOOKUP(32,	"pcie_ue_hdr2",		&data->pcie_ue_hdr[2]);
248 	FAB_LOOKUP(32,	"pcie_ue_hdr3",		&data->pcie_ue_hdr[3]);
249 	FAB_LOOKUP(32,	"pcie_ce_status",	&data->pcie_ce_status);
250 	FAB_LOOKUP(32,	"pcie_ce_mask",		&data->pcie_ce_mask);
251 	FAB_LOOKUP(32,	"pcie_ue_tgt_trans",	&data->pcie_ue_tgt_trans);
252 	FAB_LOOKUP(64,	"pcie_ue_tgt_addr",	&data->pcie_ue_tgt_addr);
253 	FAB_LOOKUP(16,	"pcie_ue_tgt_bdf",	&data->pcie_ue_tgt_bdf);
254 
255 	/* PCIe BDG AER registers */
256 	FAB_LOOKUP(32,	"pcie_sue_adv_ctl",	&data->pcie_sue_ctl);
257 	FAB_LOOKUP(32,	"pcie_sue_status",	&data->pcie_sue_status);
258 	FAB_LOOKUP(32,	"pcie_sue_mask",	&data->pcie_sue_mask);
259 	FAB_LOOKUP(32,	"pcie_sue_sev",		&data->pcie_sue_sev);
260 	FAB_LOOKUP(32,	"pcie_sue_hdr0",	&data->pcie_sue_hdr[0]);
261 	FAB_LOOKUP(32,	"pcie_sue_hdr1",	&data->pcie_sue_hdr[1]);
262 	FAB_LOOKUP(32,	"pcie_sue_hdr2",	&data->pcie_sue_hdr[2]);
263 	FAB_LOOKUP(32,	"pcie_sue_hdr3",	&data->pcie_sue_hdr[3]);
264 	FAB_LOOKUP(32,	"pcie_sue_tgt_trans",	&data->pcie_sue_tgt_trans);
265 	FAB_LOOKUP(64,	"pcie_sue_tgt_addr",	&data->pcie_sue_tgt_addr);
266 	FAB_LOOKUP(16,	"pcie_sue_tgt_bdf",	&data->pcie_sue_tgt_bdf);
267 
268 	/* PCIe RP registers */
269 	FAB_LOOKUP(32,	"pcie_rp_status",	&data->pcie_rp_status);
270 	FAB_LOOKUP(16,	"pcie_rp_control",	&data->pcie_rp_ctl);
271 
272 	/* PCIe RP AER registers */
273 	FAB_LOOKUP(32,	"pcie_adv_rp_status",	&data->pcie_rp_err_status);
274 	FAB_LOOKUP(32,	"pcie_adv_rp_command",	&data->pcie_rp_err_cmd);
275 	FAB_LOOKUP(16,	"pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id);
276 	FAB_LOOKUP(16,	"pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id);
277 
278 	/*
279 	 * PCIe Parent Slot Registers
280 	 *
281 	 * These are only passed in the ereport if the parent PCIe component
282 	 * supports the registers and the registers have valid data. As such, we
283 	 * look up one slot register value first: If that value is present in
284 	 * the input ereport data, then we know the others should be there as
285 	 * well. We also set the pcie_slot_data_valid flag to ensure we know
286 	 * the slot register data is safe to use in the module.
287 	 */
288 	data->pcie_slot_data_valid = B_FALSE;
289 	if (nvlist_lookup_uint32(nvl, "pcie_slot_cap", &data->pcie_slot_cap) ==
290 	    0) {
291 		FAB_LOOKUP(16,	"pcie_slot_control", &data->pcie_slot_control);
292 		FAB_LOOKUP(16,	"pcie_slot_status", &data->pcie_slot_status);
293 		data->pcie_slot_data_valid = B_TRUE;
294 	}
295 }
296 
297 static int
298 fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
299     fab_erpt_tbl_t *tbl)
300 {
301 	const char *class = tbl->err_class;
302 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
303 
304 	/* Generate an ereport for this error bit. */
305 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
306 	    PCI_ERROR_SUBCLASS, class);
307 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
308 
309 	(void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status);
310 	(void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm);
311 
312 	return (err);
313 }
314 
315 static int
316 fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
317     fab_erpt_tbl_t *tbl)
318 {
319 	const char *class = tbl->err_class;
320 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
321 
322 	/* Generate an ereport for this error bit. */
323 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s",
324 	    PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class);
325 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
326 
327 	(void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
328 	    data->pci_bdg_sec_stat);
329 	(void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
330 
331 	return (err);
332 }
333 
334 static int
335 fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
336     fab_erpt_tbl_t *tbl)
337 {
338 	const char *class = tbl->err_class;
339 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
340 
341 	/* Generate an ereport for this error bit. */
342 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
343 	    PCI_ERROR_SUBCLASS, class);
344 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
345 
346 	(void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS,
347 	    data->pci_bdg_sec_stat);
348 	(void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl);
349 
350 	return (err);
351 }
352 
353 
354 static int
355 fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
356     fab_erpt_tbl_t *tbl)
357 {
358 	const char *class = tbl->err_class;
359 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
360 
361 	/* Generate an ereport for this error bit. */
362 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
363 	    PCIEX_ERROR_SUBCLASS, class);
364 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
365 
366 	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
367 	(void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG,
368 	    data->pcie_ce_status);
369 
370 	return (err);
371 }
372 
373 static int
374 fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
375     fab_erpt_tbl_t *tbl)
376 {
377 	const char *class = tbl->err_class;
378 	uint32_t first_err = 1 << (data->pcie_adv_ctl &
379 	    PCIE_AER_CTL_FST_ERR_PTR_MASK);
380 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
381 
382 	if (data->pcie_slot_data_valid) {
383 		(void) nvlist_add_uint32(erpt, "pcie_slot_cap",
384 		    data->pcie_slot_cap);
385 		(void) nvlist_add_uint16(erpt, "pcie_slot_control",
386 		    data->pcie_slot_control);
387 		(void) nvlist_add_uint16(erpt, "pcie_slot_status",
388 		    data->pcie_slot_status);
389 
390 		/*
391 		 * It is possible to see uncorrectable errors for a slot that
392 		 * are related to the slot's child device being physically
393 		 * removed from the slot. As such, in the case that the slot
394 		 * reports that it is empty, we do not want to generate an
395 		 * ereport for all errors. Generating an ereport here will cause
396 		 * the eft module to fault the device and io-retire to
397 		 * subsequently retire the device. Retiring the device makes
398 		 * little sense given that the device is physically gone; more
399 		 * confusingly, if plugged back into the slot, it would be
400 		 * marked retired already.
401 		 *
402 		 * The only error ignored for this case is Completion Timeout.
403 		 * It is possible more errors should be ignored, and if they
404 		 * are seen in the field it might be worth broadening the set
405 		 * of ignored errors.
406 		 */
407 		if (tbl->reg_bit == PCIE_AER_UCE_TO &&
408 		    ((data->pcie_slot_status &
409 		    PCIE_SLOTSTS_PRESENCE_DETECTED) == 0x0)) {
410 			return (PF_EREPORT_IGNORE);
411 		}
412 	}
413 
414 	/* Generate an ereport for this error bit. */
415 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
416 	    PCIEX_ERROR_SUBCLASS, class);
417 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
418 
419 	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
420 	(void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG,
421 	    data->pcie_ue_status);
422 	(void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev);
423 	(void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl);
424 
425 	fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
426 
427 	if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) {
428 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
429 		    data->pcie_ue_tgt_bdf);
430 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
431 	} else {
432 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
433 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
434 	}
435 
436 	if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt &&
437 	    data->pcie_ue_tgt_trans) {
438 		if (tbl->tgt_class)
439 			fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE);
440 	}
441 
442 	return (err);
443 }
444 
445 static int
446 fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
447     fab_erpt_tbl_t *tbl)
448 {
449 	const char *class = tbl->err_class;
450 	uint32_t first_err = 1 << (data->pcie_sue_ctl &
451 	    PCIE_AER_SCTL_FST_ERR_PTR_MASK);
452 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
453 
454 	/* Generate an ereport for this error bit. */
455 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
456 	    PCIEX_ERROR_SUBCLASS, class);
457 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
458 
459 	(void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS,
460 	    data->pcie_sue_status);
461 
462 	fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err);
463 
464 	if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) {
465 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
466 		    data->pcie_sue_tgt_bdf);
467 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
468 	} else {
469 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0);
470 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE);
471 	}
472 
473 	if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt &&
474 	    data->pcie_sue_tgt_trans) {
475 		if (tbl->tgt_class)
476 			fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE);
477 	}
478 
479 	return (err);
480 }
481 
482 static int
483 fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
484     fab_erpt_tbl_t *tbl)
485 {
486 	const char *class = tbl->err_class;
487 	int err = 0;
488 
489 	/* Only send if this is not a bridge */
490 	if (!data->pcix_status || data->pcix_bdg_sec_stat)
491 		return (1);
492 
493 	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
494 
495 	/* Generate an ereport for this error bit. */
496 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
497 	    PCIX_ERROR_SUBCLASS, class);
498 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
499 
500 	(void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command);
501 	(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
502 
503 	return (err);
504 }
505 
506 static void
507 fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
508 {
509 	nvlist_t *erpt;
510 	int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4;
511 	int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR;
512 	int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE;
513 	int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE;
514 	uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) |
515 	    data->pcix_ecc_status_0;
516 
517 	switch (ecc_phase) {
518 	case PCI_PCIX_ECC_PHASE_NOERR:
519 		break;
520 	case PCI_PCIX_ECC_PHASE_FADDR:
521 	case PCI_PCIX_ECC_PHASE_SADDR:
522 		(void) snprintf(fab_buf, FM_MAX_CLASS,
523 		    "%s.%s", PCIX_ERROR_SUBCLASS,
524 		    ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
525 		break;
526 	case PCI_PCIX_ECC_PHASE_ATTR:
527 		(void) snprintf(fab_buf, FM_MAX_CLASS,
528 		    "%s.%s", PCIX_ERROR_SUBCLASS,
529 		    ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
530 		break;
531 	case PCI_PCIX_ECC_PHASE_DATA32:
532 	case PCI_PCIX_ECC_PHASE_DATA64:
533 		(void) snprintf(fab_buf, FM_MAX_CLASS,
534 		    "%s.%s", PCIX_ERROR_SUBCLASS,
535 		    ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
536 		break;
537 	}
538 
539 	if (ecc_phase) {
540 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
541 			goto done;
542 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
543 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
544 		(void) nvlist_add_uint16(erpt, PCIX_COMMAND,
545 		    data->pcix_command);
546 		(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
547 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
548 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
549 		    data->pcix_ecc_attr_0);
550 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
551 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
552 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
553 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
554 	}
555 
556 	if (sec_ce || sec_ue) {
557 		(void) snprintf(fab_buf, FM_MAX_CLASS,
558 		    "%s.%s", PCIX_ERROR_SUBCLASS,
559 		    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
560 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
561 			goto done;
562 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
563 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
564 		(void) nvlist_add_uint16(erpt, PCIX_COMMAND,
565 		    data->pcix_command);
566 		(void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status);
567 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
568 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
569 		    data->pcix_ecc_attr_0);
570 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
571 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
572 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
573 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
574 	}
575 
576 	return;
577 done:
578 	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
579 }
580 
581 static int
582 fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
583     fab_erpt_tbl_t *tbl)
584 {
585 	const char *class = tbl->err_class;
586 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
587 
588 	/* Generate an ereport for this error bit. */
589 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s",
590 	    PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class);
591 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
592 
593 	(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
594 	    data->pcix_bdg_sec_stat);
595 	(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
596 
597 	return (err);
598 }
599 
600 static int
601 fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
602     fab_erpt_tbl_t *tbl)
603 {
604 	const char *class = tbl->err_class;
605 	int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
606 
607 	/* Generate an ereport for this error bit. */
608 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
609 	    PCIX_ERROR_SUBCLASS, class);
610 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
611 
612 	(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
613 	    data->pcix_bdg_sec_stat);
614 	(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat);
615 
616 	return (err);
617 }
618 
619 static void
620 fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data)
621 {
622 	nvlist_t *erpt;
623 	int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4;
624 	int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR;
625 	int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE;
626 	int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE;
627 	uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) |
628 	    data->pcix_ecc_status_1;
629 
630 	switch (ecc_phase) {
631 	case PCI_PCIX_ECC_PHASE_NOERR:
632 		break;
633 	case PCI_PCIX_ECC_PHASE_FADDR:
634 	case PCI_PCIX_ECC_PHASE_SADDR:
635 		(void) snprintf(fab_buf, FM_MAX_CLASS,
636 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
637 		    ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR);
638 		break;
639 	case PCI_PCIX_ECC_PHASE_ATTR:
640 		(void) snprintf(fab_buf, FM_MAX_CLASS,
641 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
642 		    ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR);
643 		break;
644 	case PCI_PCIX_ECC_PHASE_DATA32:
645 	case PCI_PCIX_ECC_PHASE_DATA64:
646 		(void) snprintf(fab_buf, FM_MAX_CLASS,
647 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
648 		    ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA);
649 		break;
650 	}
651 	if (ecc_phase) {
652 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
653 			goto done;
654 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
655 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
656 		(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
657 		    data->pcix_bdg_sec_stat);
658 		(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
659 		    data->pcix_bdg_stat);
660 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
661 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
662 		    data->pcix_ecc_attr_1);
663 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
664 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
665 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
666 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
667 	}
668 
669 	if (sec_ce || sec_ue) {
670 		(void) snprintf(fab_buf, FM_MAX_CLASS,
671 		    "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS,
672 		    sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE);
673 		if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0)
674 			goto done;
675 		(void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
676 		(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
677 		(void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS,
678 		    data->pcix_bdg_sec_stat);
679 		(void) nvlist_add_uint32(erpt, PCIX_BDG_STAT,
680 		    data->pcix_bdg_stat);
681 		(void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat);
682 		(void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR,
683 		    data->pcix_ecc_attr_1);
684 		fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf);
685 		fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0);
686 		if (fmd_xprt_error(hdl, fab_fmd_xprt))
687 			fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
688 	}
689 	return;
690 done:
691 	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
692 }
693 
694 static int
695 fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
696     fab_erpt_tbl_t *tbl)
697 {
698 	const char *class = tbl->err_class;
699 	int err = 0;
700 
701 	/* Don't send this for PCI device, Root Ports, or PCIe with AER */
702 	if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
703 	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
704 	    data->aer_off)
705 		return (1);
706 
707 	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
708 
709 	/* Generate an ereport for this error bit. */
710 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
711 	    PCIEX_ERROR_SUBCLASS, class);
712 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
713 
714 	(void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status);
715 
716 	return (err);
717 }
718 
719 static int
720 fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
721     fab_erpt_tbl_t *tbl)
722 {
723 	const char *class = tbl->err_class;
724 	uint32_t status = data->pcie_rp_err_status;
725 	int err = 0;
726 	int isFE = 0, isNFE = 0;
727 
728 	fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class);
729 
730 	if (!data->aer_off)
731 		return (-1);
732 
733 	/* Only send a FE Msg if the 1st UE error is FE */
734 	if (STRCMP(class, PCIEX_RC_FE_MSG))
735 		if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL))
736 			return (-1);
737 		else
738 			isFE = 1;
739 
740 	/* Only send a NFE Msg is the 1st UE error is NFE */
741 	if (STRCMP(class, PCIEX_RC_NFE_MSG))
742 		if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL)
743 			return (-1);
744 		else
745 			isNFE = 1;
746 
747 	fmd_hdl_debug(hdl, "XLATE RP Error");
748 
749 	err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE);
750 
751 	/* Generate an ereport for this error bit. */
752 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
753 	    PCIEX_ERROR_SUBCLASS, class);
754 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
755 
756 	(void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status);
757 	if ((isFE || isNFE) && data->pcie_rp_ue_src_id) {
758 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
759 		    data->pcie_rp_ue_src_id);
760 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
761 	}
762 	if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) {
763 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID,
764 		    data->pcie_rp_ce_src_id);
765 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
766 	}
767 
768 	return (err);
769 }
770 
771 static int
772 fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt,
773     fab_erpt_tbl_t *tbl)
774 {
775 	const char *class = tbl->err_class;
776 	uint32_t rc_err_sts = 0;
777 	int err = 0;
778 
779 	/*
780 	 * Don't send this for PCI device or Root Ports.  Only send it on
781 	 * systems with non-compliant RPs.
782 	 */
783 	if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) ||
784 	    (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) ||
785 	    (!fab_xlate_fake_rp))
786 		return (-1);
787 
788 	err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE);
789 
790 	/* Generate an ereport for this error bit. */
791 	(void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s",
792 	    PCIEX_ERROR_SUBCLASS, class);
793 	(void) nvlist_add_string(erpt, FM_CLASS, fab_buf);
794 
795 	/* Send PCIe RC Ereports */
796 	if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) {
797 		rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD;
798 	}
799 
800 	/* NFE/FE src id takes precedence over CE src id */
801 	if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) {
802 		rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD;
803 		rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
804 	}
805 	if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) {
806 		rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD;
807 		rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD;
808 	}
809 	if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) &&
810 	    (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) {
811 		rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL;
812 		rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD;
813 	}
814 
815 	(void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts);
816 
817 	if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) {
818 		(void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf);
819 		(void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE);
820 	}
821 
822 	return (err);
823 }
824 
825 void
826 fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data)
827 {
828 	fab_err_tbl_t *tbl;
829 
830 	fmd_hdl_debug(hdl, "Sending Ereports Now");
831 
832 	/* Go through the error logs and send the relevant reports */
833 	for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) {
834 		fab_send_erpt(hdl, data, tbl);
835 	}
836 
837 	/* Send PCI-X ECC Ereports */
838 	fab_send_pcix_ecc_erpt(hdl, data);
839 	fab_send_pcix_bdg_ecc_erpt(hdl, data);
840 }
841 
842 void
843 fab_xlate_fabric_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class)
844 {
845 	fab_data_t data = {0};
846 
847 	fmd_hdl_debug(hdl, "fabric ereport received: %s\n", class);
848 
849 	fab_pci_fabric_to_data(hdl, nvl, &data);
850 	fab_xlate_pcie_erpts(hdl, &data);
851 }
852 
853 void
854 fab_set_fake_rp(fmd_hdl_t *hdl)
855 {
856 	char *rppath = fab_get_rpdev(hdl), *str = NULL;
857 	int count = 0;
858 
859 	if (!rppath) {
860 		fmd_hdl_debug(hdl, "Can't find root port dev path");
861 		return;
862 	}
863 
864 	/*
865 	 * For the path '/pci@xxx' is fake root port,
866 	 * and  '/pci@xxx/pci@y' is real root port.
867 	 */
868 	str = rppath;
869 	while (*str) {
870 		if (*str == '/')
871 			count++;
872 		str++;
873 	}
874 
875 	if (count == 1)
876 		fab_xlate_fake_rp = B_TRUE;
877 	else
878 		/*
879 		 * If count is 0, then it should still be B_FALSE
880 		 */
881 		fab_xlate_fake_rp = B_FALSE;
882 
883 	fmd_hdl_strfree(hdl, rppath);
884 }
885 
886 #define	SET_TBL(n, err, reg, sz) \
887 	fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \
888 	fab_master_err_tbl[n].reg_offset = offsetof(fab_data_t, reg); \
889 	fab_master_err_tbl[n].reg_size = sz; \
890 	fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt;
891 
892 void
893 fab_setup_master_table()
894 {
895 	/* Setup the master error table */
896 	fab_master_err_tbl = (fab_err_tbl_t *)calloc(13,
897 	    sizeof (fab_err_tbl_t));
898 
899 	SET_TBL(0, pci,			pci_err_status,	    16);
900 	SET_TBL(1, pci_bdg,		pci_bdg_sec_stat,   16);
901 	SET_TBL(2, pci_bdg_ctl,		pci_bdg_ctrl,	    16);
902 	SET_TBL(3, pcie_ce,		pcie_ce_status,	    32);
903 	SET_TBL(4, pcie_ue,		pcie_ue_status,	    32);
904 	SET_TBL(5, pcie_sue,		pcie_sue_status,    32);
905 	SET_TBL(6, pcix,		pcix_status,	    32);
906 	SET_TBL(7, pcix_bdg_sec,	pcix_bdg_sec_stat,  16);
907 	SET_TBL(8, pcix_bdg,		pcix_bdg_stat,	    32);
908 	SET_TBL(9, pcie_nadv,		pcie_err_status,    16);
909 	SET_TBL(10, pcie_rc,		pcie_rp_err_status, 32);
910 	SET_TBL(11, pcie_fake_rc,	pcie_err_status,    16);
911 }
912