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