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
fab_pci_fabric_to_data(fmd_hdl_t * hdl,nvlist_t * nvl,fab_data_t * data)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
fab_prep_pci_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pci_bdg_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcie_ce_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcie_ue_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcie_sue_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcix_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_send_pcix_ecc_erpt(fmd_hdl_t * hdl,fab_data_t * data)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
fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcix_bdg_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t * hdl,fab_data_t * data)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
fab_prep_pcie_nadv_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcie_rc_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_prep_pcie_fake_rc_erpt(fmd_hdl_t * hdl,fab_data_t * data,nvlist_t * erpt,fab_erpt_tbl_t * tbl)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
fab_xlate_pcie_erpts(fmd_hdl_t * hdl,fab_data_t * data)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
fab_xlate_fabric_erpts(fmd_hdl_t * hdl,nvlist_t * nvl,const char * class)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
fab_set_fake_rp(fmd_hdl_t * hdl)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
fab_setup_master_table()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