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
35static boolean_t fab_xlate_fake_rp = B_TRUE;
36static 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.* */
46fab_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, NULL, NULL
54};
55
56/* Translate Fabric ereports to ereport.io.pci.sec-* */
57static 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, NULL, NULL, NULL,
67};
68
69
70/* Translate Fabric ereports to ereport.io.pci.dto */
71static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = {
72	PCI_DTO,	PCI_BCNF_BCNTRL_DTO_STAT,	NULL,
73	NULL, NULL, NULL
74};
75
76/* Translate Fabric ereports to ereport.io.pciex.* */
77static 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, NULL, 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 */
92static 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, NULL, NULL
108};
109
110/* Translate Fabric ereports to ereport.io.pciex.* */
111static 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, NULL, NULL
128};
129
130/* Translate Fabric ereports to ereport.io.pcix.* */
131static 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, NULL, NULL
136};
137static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl;
138
139/* Translate Fabric ereports to ereport.io.pcix.sec-* */
140static 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, NULL, NULL
146};
147
148/* Translate Fabric ereports to ereport.io.pciex.* */
149static 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, NULL, NULL
157};
158
159/* Translate Fabric ereports to ereport.io.pciex.* */
160static 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, NULL, 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 */
174static 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, NULL, NULL,
179};
180
181/* ARGSUSED */
182void
183fab_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
276static int
277fab_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
294static int
295fab_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
313static int
314fab_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
333static int
334fab_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
352static int
353fab_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
392static int
393fab_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
429static int
430fab_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
453static void
454fab_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;
524done:
525	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
526}
527
528static int
529fab_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
547static int
548fab_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
566static void
567fab_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;
637done:
638	fmd_hdl_debug(hdl, "Failed to send ECC ereport\n");
639}
640
641static int
642fab_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
666static int
667fab_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
718static int
719fab_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
772void
773fab_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
789void
790fab_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
800void
801fab_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
839void
840fab_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