xref: /onnv-gate/usr/src/uts/sun4u/io/px/px_err.c (revision 1772:78cca3d2cc4b)
127Sjchu /*
227Sjchu  * CDDL HEADER START
327Sjchu  *
427Sjchu  * The contents of this file are subject to the terms of the
51648Sjchu  * Common Development and Distribution License (the "License").
61648Sjchu  * You may not use this file except in compliance with the License.
727Sjchu  *
827Sjchu  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
927Sjchu  * or http://www.opensolaris.org/os/licensing.
1027Sjchu  * See the License for the specific language governing permissions
1127Sjchu  * and limitations under the License.
1227Sjchu  *
1327Sjchu  * When distributing Covered Code, include this CDDL HEADER in each
1427Sjchu  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1527Sjchu  * If applicable, add the following below this CDDL HEADER, with the
1627Sjchu  * fields enclosed by brackets "[]" replaced with your own identifying
1727Sjchu  * information: Portions Copyright [yyyy] [name of copyright owner]
1827Sjchu  *
1927Sjchu  * CDDL HEADER END
2027Sjchu  */
2127Sjchu /*
221648Sjchu  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2327Sjchu  * Use is subject to license terms.
2427Sjchu  */
2527Sjchu 
2627Sjchu #pragma ident	"%Z%%M%	%I%	%E% SMI"
2727Sjchu 
2827Sjchu /*
2927Sjchu  * sun4u Fire Error Handling
3027Sjchu  */
3127Sjchu 
3227Sjchu #include <sys/types.h>
3327Sjchu #include <sys/ddi.h>
3427Sjchu #include <sys/sunddi.h>
3527Sjchu #include <sys/fm/protocol.h>
3627Sjchu #include <sys/fm/util.h>
3727Sjchu #include <sys/pcie.h>
3827Sjchu #include <sys/pcie_impl.h>
3927Sjchu #include "px_obj.h"
4027Sjchu #include <px_regs.h>
4127Sjchu #include <px_csr.h>
4227Sjchu #include <sys/membar.h>
43*1772Sjl139090 #include <sys/machcpuvar.h>
44*1772Sjl139090 #include <sys/platform_module.h>
45118Sjchu #include "pcie_pwr.h"
4627Sjchu #include "px_lib4u.h"
4727Sjchu #include "px_err.h"
4827Sjchu #include "px_err_impl.h"
49*1772Sjl139090 #include "oberon_regs.h"
50*1772Sjl139090 
51*1772Sjl139090 uint64_t px_tlu_ue_intr_mask	= PX_ERR_EN_ALL;
52*1772Sjl139090 uint64_t px_tlu_ue_log_mask	= PX_ERR_EN_ALL;
53*1772Sjl139090 uint64_t px_tlu_ue_count_mask	= PX_ERR_EN_ALL;
54*1772Sjl139090 
55*1772Sjl139090 uint64_t px_tlu_ce_intr_mask	= PX_ERR_MASK_NONE;
56*1772Sjl139090 uint64_t px_tlu_ce_log_mask	= PX_ERR_MASK_NONE;
57*1772Sjl139090 uint64_t px_tlu_ce_count_mask	= PX_ERR_MASK_NONE;
58*1772Sjl139090 
59*1772Sjl139090 /*
60*1772Sjl139090  * Do not enable Link Interrupts
61*1772Sjl139090  */
62*1772Sjl139090 uint64_t px_tlu_oe_intr_mask	= PX_ERR_EN_ALL & ~0x80000000800;
63*1772Sjl139090 uint64_t px_tlu_oe_log_mask	= PX_ERR_EN_ALL & ~0x80000000800;
64*1772Sjl139090 uint64_t px_tlu_oe_count_mask	= PX_ERR_EN_ALL;
65*1772Sjl139090 
66*1772Sjl139090 uint64_t px_mmu_intr_mask	= PX_ERR_EN_ALL;
67*1772Sjl139090 uint64_t px_mmu_log_mask	= PX_ERR_EN_ALL;
68*1772Sjl139090 uint64_t px_mmu_count_mask	= PX_ERR_EN_ALL;
69*1772Sjl139090 
70*1772Sjl139090 uint64_t px_imu_intr_mask	= PX_ERR_EN_ALL;
71*1772Sjl139090 uint64_t px_imu_log_mask	= PX_ERR_EN_ALL;
72*1772Sjl139090 uint64_t px_imu_count_mask	= PX_ERR_EN_ALL;
73*1772Sjl139090 
74*1772Sjl139090 /*
75*1772Sjl139090  * (1ull << ILU_INTERRUPT_ENABLE_IHB_PE_S) |
76*1772Sjl139090  * (1ull << ILU_INTERRUPT_ENABLE_IHB_PE_P);
77*1772Sjl139090  */
78*1772Sjl139090 uint64_t px_ilu_intr_mask	= (((uint64_t)0x10 << 32) | 0x10);
79*1772Sjl139090 uint64_t px_ilu_log_mask	= (((uint64_t)0x10 << 32) | 0x10);
80*1772Sjl139090 uint64_t px_ilu_count_mask	= PX_ERR_EN_ALL;
81*1772Sjl139090 
82*1772Sjl139090 uint64_t px_ubc_intr_mask	= PX_ERR_EN_ALL;
83*1772Sjl139090 uint64_t px_ubc_log_mask		= PX_ERR_EN_ALL;
84*1772Sjl139090 uint64_t px_ubc_count_mask	= PX_ERR_EN_ALL;
85*1772Sjl139090 
86*1772Sjl139090 uint64_t px_jbc_intr_mask	= PX_ERR_EN_ALL;
87*1772Sjl139090 uint64_t px_jbc_log_mask		= PX_ERR_EN_ALL;
88*1772Sjl139090 uint64_t px_jbc_count_mask	= PX_ERR_EN_ALL;
89*1772Sjl139090 
90*1772Sjl139090 /*
91*1772Sjl139090  * LPU Intr Registers are reverse encoding from the registers above.
92*1772Sjl139090  * 1 = disable
93*1772Sjl139090  * 0 = enable
94*1772Sjl139090  *
95*1772Sjl139090  * Log and Count are however still the same.
96*1772Sjl139090  */
97*1772Sjl139090 uint64_t px_lpul_intr_mask	= LPU_INTR_DISABLE;
98*1772Sjl139090 uint64_t px_lpul_log_mask	= PX_ERR_EN_ALL;
99*1772Sjl139090 uint64_t px_lpul_count_mask	= PX_ERR_EN_ALL;
100*1772Sjl139090 
101*1772Sjl139090 uint64_t px_lpup_intr_mask	= LPU_INTR_DISABLE;
102*1772Sjl139090 uint64_t px_lpup_log_mask	= PX_ERR_EN_ALL;
103*1772Sjl139090 uint64_t px_lpup_count_mask	= PX_ERR_EN_ALL;
104*1772Sjl139090 
105*1772Sjl139090 uint64_t px_lpur_intr_mask	= LPU_INTR_DISABLE;
106*1772Sjl139090 uint64_t px_lpur_log_mask	= PX_ERR_EN_ALL;
107*1772Sjl139090 uint64_t px_lpur_count_mask	= PX_ERR_EN_ALL;
108*1772Sjl139090 
109*1772Sjl139090 uint64_t px_lpux_intr_mask	= LPU_INTR_DISABLE;
110*1772Sjl139090 uint64_t px_lpux_log_mask	= PX_ERR_EN_ALL;
111*1772Sjl139090 uint64_t px_lpux_count_mask	= PX_ERR_EN_ALL;
112*1772Sjl139090 
113*1772Sjl139090 uint64_t px_lpus_intr_mask	= LPU_INTR_DISABLE;
114*1772Sjl139090 uint64_t px_lpus_log_mask	= PX_ERR_EN_ALL;
115*1772Sjl139090 uint64_t px_lpus_count_mask	= PX_ERR_EN_ALL;
116*1772Sjl139090 
117*1772Sjl139090 uint64_t px_lpug_intr_mask	= LPU_INTR_DISABLE;
118*1772Sjl139090 uint64_t px_lpug_log_mask	= PX_ERR_EN_ALL;
119*1772Sjl139090 uint64_t px_lpug_count_mask	= PX_ERR_EN_ALL;
12027Sjchu 
12127Sjchu /*
12227Sjchu  * JBC error bit table
12327Sjchu  */
12427Sjchu #define	JBC_BIT_DESC(bit, hdl, erpt) \
12527Sjchu 	JBC_INTERRUPT_STATUS_ ## bit ## _P, \
12627Sjchu 	0, \
12727Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
12827Sjchu 	PX_ERPT_SEND(erpt), \
129739Sjchu 	PX_ERR_JBC_CLASS(bit) }, \
130739Sjchu 	{ JBC_INTERRUPT_STATUS_ ## bit ## _S, \
131739Sjchu 	0, \
132739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
133739Sjchu 	PX_ERPT_SEND(erpt), \
13427Sjchu 	PX_ERR_JBC_CLASS(bit)
135*1772Sjl139090 px_err_bit_desc_t px_err_jbc_tbl[] = {
13627Sjchu 	/* JBC FATAL - see io erpt doc, section 1.1 */
13727Sjchu 	{ JBC_BIT_DESC(MB_PEA,	fatal_hw,	jbc_fatal) },
13827Sjchu 	{ JBC_BIT_DESC(CPE,	fatal_hw,	jbc_fatal) },
13927Sjchu 	{ JBC_BIT_DESC(APE,	fatal_hw,	jbc_fatal) },
14027Sjchu 	{ JBC_BIT_DESC(PIO_CPE,	fatal_hw,	jbc_fatal) },
14127Sjchu 	{ JBC_BIT_DESC(JTCEEW,	fatal_hw,	jbc_fatal) },
14227Sjchu 	{ JBC_BIT_DESC(JTCEEI,	fatal_hw,	jbc_fatal) },
14327Sjchu 	{ JBC_BIT_DESC(JTCEER,	fatal_hw,	jbc_fatal) },
14427Sjchu 
14527Sjchu 	/* JBC MERGE - see io erpt doc, section 1.2 */
14627Sjchu 	{ JBC_BIT_DESC(MB_PER,	jbc_merge,	jbc_merge) },
14727Sjchu 	{ JBC_BIT_DESC(MB_PEW,	jbc_merge,	jbc_merge) },
14827Sjchu 
14927Sjchu 	/* JBC Jbusint IN - see io erpt doc, section 1.3 */
15027Sjchu 	{ JBC_BIT_DESC(UE_ASYN,	fatal_gos,	jbc_in) },
1511648Sjchu 	{ JBC_BIT_DESC(CE_ASYN,	non_fatal,	jbc_in) },
15227Sjchu 	{ JBC_BIT_DESC(JTE,	fatal_gos,	jbc_in) },
15327Sjchu 	{ JBC_BIT_DESC(JBE,	jbc_jbusint_in,	jbc_in) },
15427Sjchu 	{ JBC_BIT_DESC(JUE,	jbc_jbusint_in,	jbc_in) },
15527Sjchu 	{ JBC_BIT_DESC(ICISE,	fatal_gos,	jbc_in) },
15627Sjchu 	{ JBC_BIT_DESC(WR_DPE,	jbc_jbusint_in,	jbc_in) },
15727Sjchu 	{ JBC_BIT_DESC(RD_DPE,	jbc_jbusint_in,	jbc_in) },
15827Sjchu 	{ JBC_BIT_DESC(ILL_BMW,	jbc_jbusint_in,	jbc_in) },
15927Sjchu 	{ JBC_BIT_DESC(ILL_BMR,	jbc_jbusint_in,	jbc_in) },
16027Sjchu 	{ JBC_BIT_DESC(BJC,	jbc_jbusint_in,	jbc_in) },
16127Sjchu 
16227Sjchu 	/* JBC Jbusint Out - see io erpt doc, section 1.4 */
16327Sjchu 	{ JBC_BIT_DESC(IJP,	fatal_gos,	jbc_out) },
16427Sjchu 
16527Sjchu 	/* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
16627Sjchu 	{ JBC_BIT_DESC(PIO_UNMAP_RD,	jbc_dmcint_odcd,	jbc_odcd) },
16727Sjchu 	{ JBC_BIT_DESC(ILL_ACC_RD,	jbc_dmcint_odcd,	jbc_odcd) },
16827Sjchu 	{ JBC_BIT_DESC(PIO_UNMAP,	jbc_dmcint_odcd,	jbc_odcd) },
16927Sjchu 	{ JBC_BIT_DESC(PIO_DPE,		jbc_dmcint_odcd,	jbc_odcd) },
17027Sjchu 	{ JBC_BIT_DESC(PIO_CPE,		non_fatal,		jbc_odcd) },
17127Sjchu 	{ JBC_BIT_DESC(ILL_ACC,		jbc_dmcint_odcd,	jbc_odcd) },
17227Sjchu 
17327Sjchu 	/* JBC Dmcint IDC - see io erpt doc, section 1.6 */
17427Sjchu 	{ JBC_BIT_DESC(UNSOL_RD,	non_fatal,	jbc_idc) },
17527Sjchu 	{ JBC_BIT_DESC(UNSOL_INTR,	non_fatal,	jbc_idc) },
17627Sjchu 
17727Sjchu 	/* JBC CSR - see io erpt doc, section 1.7 */
17827Sjchu 	{ JBC_BIT_DESC(EBUS_TO,	jbc_csr,	jbc_csr) }
17927Sjchu };
18027Sjchu 
181*1772Sjl139090 #define	px_err_jbc_keys \
182*1772Sjl139090 	(sizeof (px_err_jbc_tbl)) / (sizeof (px_err_bit_desc_t))
183*1772Sjl139090 
184*1772Sjl139090 /*
185*1772Sjl139090  * UBC error bit table
186*1772Sjl139090  */
187*1772Sjl139090 #define	UBC_BIT_DESC(bit, hdl, erpt) \
188*1772Sjl139090 	UBC_INTERRUPT_STATUS_ ## bit ## _P, \
189*1772Sjl139090 	0, \
190*1772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
191*1772Sjl139090 	PX_ERPT_SEND(erpt), \
192*1772Sjl139090 	PX_ERR_UBC_CLASS(bit) }, \
193*1772Sjl139090 	{ UBC_INTERRUPT_STATUS_ ## bit ## _S, \
194*1772Sjl139090 	0, \
195*1772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
196*1772Sjl139090 	PX_ERPT_SEND(erpt), \
197*1772Sjl139090 	PX_ERR_UBC_CLASS(bit)
198*1772Sjl139090 px_err_bit_desc_t px_err_ubc_tbl[] = {
199*1772Sjl139090 	/* UBC FATAL  */
200*1772Sjl139090 	{ UBC_BIT_DESC(DMARDUEA,	non_fatal,	ubc_fatal) },
201*1772Sjl139090 	{ UBC_BIT_DESC(DMAWTUEA,	fatal_sw,	ubc_fatal) },
202*1772Sjl139090 	{ UBC_BIT_DESC(MEMRDAXA,	fatal_sw,	ubc_fatal) },
203*1772Sjl139090 	{ UBC_BIT_DESC(MEMWTAXA,	fatal_sw,	ubc_fatal) },
204*1772Sjl139090 	{ UBC_BIT_DESC(DMARDUEB,	non_fatal,	ubc_fatal) },
205*1772Sjl139090 	{ UBC_BIT_DESC(DMAWTUEB,	fatal_sw,	ubc_fatal) },
206*1772Sjl139090 	{ UBC_BIT_DESC(MEMRDAXB,	fatal_sw,	ubc_fatal) },
207*1772Sjl139090 	{ UBC_BIT_DESC(MEMWTAXB,	fatal_sw,	ubc_fatal) },
208*1772Sjl139090 	{ UBC_BIT_DESC(PIOWTUE,		fatal_sw,	ubc_fatal) },
209*1772Sjl139090 	{ UBC_BIT_DESC(PIOWBEUE,	fatal_sw,	ubc_fatal) },
210*1772Sjl139090 	{ UBC_BIT_DESC(PIORBEUE,	fatal_sw,	ubc_fatal) }
211*1772Sjl139090 };
212*1772Sjl139090 
213*1772Sjl139090 #define	px_err_ubc_keys \
214*1772Sjl139090 	(sizeof (px_err_ubc_tbl)) / (sizeof (px_err_bit_desc_t))
215*1772Sjl139090 
216*1772Sjl139090 
217*1772Sjl139090 char *ubc_class_eid_qualifier[] = {
218*1772Sjl139090 	"-mem",
219*1772Sjl139090 	"-channel",
220*1772Sjl139090 	"-cpu",
221*1772Sjl139090 	"-path"
222*1772Sjl139090 };
223*1772Sjl139090 
22427Sjchu 
22527Sjchu /*
22627Sjchu  * DMC error bit tables
22727Sjchu  */
22827Sjchu #define	IMU_BIT_DESC(bit, hdl, erpt) \
22927Sjchu 	IMU_INTERRUPT_STATUS_ ## bit ## _P, \
23027Sjchu 	0, \
23127Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
23227Sjchu 	PX_ERPT_SEND(erpt), \
233739Sjchu 	PX_ERR_DMC_CLASS(bit) }, \
234739Sjchu 	{ IMU_INTERRUPT_STATUS_ ## bit ## _S, \
235739Sjchu 	0, \
236739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
237739Sjchu 	PX_ERPT_SEND(erpt), \
23827Sjchu 	PX_ERR_DMC_CLASS(bit)
23927Sjchu px_err_bit_desc_t px_err_imu_tbl[] = {
24027Sjchu 	/* DMC IMU RDS - see io erpt doc, section 2.1 */
24127Sjchu 	{ IMU_BIT_DESC(MSI_MAL_ERR,		non_fatal,	imu_rds) },
24227Sjchu 	{ IMU_BIT_DESC(MSI_PAR_ERR,		fatal_stuck,	imu_rds) },
24327Sjchu 	{ IMU_BIT_DESC(PMEACK_MES_NOT_EN,	imu_rbne,	imu_rds) },
244118Sjchu 	{ IMU_BIT_DESC(PMPME_MES_NOT_EN,	imu_pme,	imu_rds) },
24527Sjchu 	{ IMU_BIT_DESC(FATAL_MES_NOT_EN,	imu_rbne,	imu_rds) },
24627Sjchu 	{ IMU_BIT_DESC(NONFATAL_MES_NOT_EN,	imu_rbne,	imu_rds) },
24727Sjchu 	{ IMU_BIT_DESC(COR_MES_NOT_EN,		imu_rbne,	imu_rds) },
24827Sjchu 	{ IMU_BIT_DESC(MSI_NOT_EN,		imu_rbne,	imu_rds) },
24927Sjchu 
25027Sjchu 	/* DMC IMU SCS - see io erpt doc, section 2.2 */
25127Sjchu 	{ IMU_BIT_DESC(EQ_NOT_EN,		imu_rbne,	imu_rds) },
25227Sjchu 
25327Sjchu 	/* DMC IMU - see io erpt doc, section 2.3 */
25427Sjchu 	{ IMU_BIT_DESC(EQ_OVER,			imu_eq_ovfl,	imu) }
25527Sjchu };
25627Sjchu 
25727Sjchu #define	px_err_imu_keys (sizeof (px_err_imu_tbl)) / (sizeof (px_err_bit_desc_t))
25827Sjchu 
25927Sjchu /* mmu errors */
26027Sjchu #define	MMU_BIT_DESC(bit, hdl, erpt) \
26127Sjchu 	MMU_INTERRUPT_STATUS_ ## bit ## _P, \
26227Sjchu 	0, \
26327Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
26427Sjchu 	PX_ERPT_SEND(erpt), \
265739Sjchu 	PX_ERR_DMC_CLASS(bit) }, \
266739Sjchu 	{ MMU_INTERRUPT_STATUS_ ## bit ## _S, \
267739Sjchu 	0, \
268739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
269739Sjchu 	PX_ERPT_SEND(erpt), \
27027Sjchu 	PX_ERR_DMC_CLASS(bit)
27127Sjchu px_err_bit_desc_t px_err_mmu_tbl[] = {
27227Sjchu 	/* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
27327Sjchu 	{ MMU_BIT_DESC(BYP_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
27427Sjchu 	{ MMU_BIT_DESC(BYP_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
27527Sjchu 	{ MMU_BIT_DESC(TRN_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
27627Sjchu 	{ MMU_BIT_DESC(TRN_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
27727Sjchu 	{ MMU_BIT_DESC(TTE_INV,		mmu_tfa,	mmu_tfar_tfsr) },
27827Sjchu 	{ MMU_BIT_DESC(TTE_PRT,		mmu_tfa,	mmu_tfar_tfsr) },
27927Sjchu 	{ MMU_BIT_DESC(TTC_DPE,		mmu_tfa,	mmu_tfar_tfsr) },
28027Sjchu 	{ MMU_BIT_DESC(TBW_DME,		mmu_tblwlk,	mmu_tfar_tfsr) },
28127Sjchu 	{ MMU_BIT_DESC(TBW_UDE,		mmu_tblwlk,	mmu_tfar_tfsr) },
28227Sjchu 	{ MMU_BIT_DESC(TBW_ERR,		mmu_tblwlk,	mmu_tfar_tfsr) },
28327Sjchu 	{ MMU_BIT_DESC(TBW_DPE,		mmu_tblwlk,	mmu_tfar_tfsr) },
28427Sjchu 
28527Sjchu 	/* DMC MMU - see io erpt doc, section 2.5 */
28627Sjchu 	{ MMU_BIT_DESC(TTC_CAE,		non_fatal,	mmu) }
28727Sjchu };
28827Sjchu #define	px_err_mmu_keys (sizeof (px_err_mmu_tbl)) / (sizeof (px_err_bit_desc_t))
28927Sjchu 
290*1772Sjl139090 
29127Sjchu /*
29227Sjchu  * PEC error bit tables
29327Sjchu  */
29427Sjchu #define	ILU_BIT_DESC(bit, hdl, erpt) \
29527Sjchu 	ILU_INTERRUPT_STATUS_ ## bit ## _P, \
29627Sjchu 	0, \
29727Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
29827Sjchu 	PX_ERPT_SEND(erpt), \
299739Sjchu 	PX_ERR_PEC_CLASS(bit) }, \
300739Sjchu 	{ ILU_INTERRUPT_STATUS_ ## bit ## _S, \
301739Sjchu 	0, \
302739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
303739Sjchu 	PX_ERPT_SEND(erpt), \
30427Sjchu 	PX_ERR_PEC_CLASS(bit)
30527Sjchu px_err_bit_desc_t px_err_ilu_tbl[] = {
30627Sjchu 	/* PEC ILU none - see io erpt doc, section 3.1 */
30727Sjchu 	{ ILU_BIT_DESC(IHB_PE,		fatal_gos,	pec_ilu) }
30827Sjchu };
30927Sjchu #define	px_err_ilu_keys \
31027Sjchu 	(sizeof (px_err_ilu_tbl)) / (sizeof (px_err_bit_desc_t))
31127Sjchu 
31227Sjchu /*
31327Sjchu  * PEC UE errors implementation is incomplete pending PCIE generic
314383Set142600  * fabric rules.  Must handle both PRIMARY and SECONDARY errors.
31527Sjchu  */
31627Sjchu /* pec ue errors */
31727Sjchu #define	TLU_UC_BIT_DESC(bit, hdl, erpt) \
31827Sjchu 	TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
31927Sjchu 	0, \
320383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
321383Set142600 	PX_ERPT_SEND(erpt), \
322383Set142600 	PX_ERR_PEC_CLASS(bit) }, \
323383Set142600 	{ TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _S, \
324383Set142600 	0, \
325383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
326383Set142600 	PX_ERPT_SEND(erpt), \
327383Set142600 	PX_ERR_PEC_CLASS(bit)
328*1772Sjl139090 #define	TLU_UC_OB_BIT_DESC(bit, hdl, erpt) \
329*1772Sjl139090 	TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
330*1772Sjl139090 	0, \
331*1772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
332*1772Sjl139090 	PX_ERPT_SEND(erpt), \
333*1772Sjl139090 	PX_ERR_PEC_OB_CLASS(bit) }, \
334*1772Sjl139090 	{ TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _S, \
335*1772Sjl139090 	0, \
336*1772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
337*1772Sjl139090 	PX_ERPT_SEND(erpt), \
338*1772Sjl139090 	PX_ERR_PEC_CLASS(bit)
33927Sjchu px_err_bit_desc_t px_err_tlu_ue_tbl[] = {
34027Sjchu 	/* PCI-E Receive Uncorrectable Errors - see io erpt doc, section 3.2 */
341383Set142600 	{ TLU_UC_BIT_DESC(UR,		pciex_ue,	pciex_rx_ue) },
342383Set142600 	{ TLU_UC_BIT_DESC(UC,		pciex_ue,	pciex_rx_ue) },
34327Sjchu 
34427Sjchu 	/* PCI-E Transmit Uncorrectable Errors - see io erpt doc, section 3.3 */
345*1772Sjl139090 	{ TLU_UC_OB_BIT_DESC(ECRC,	pciex_ue,	pciex_rx_ue) },
346383Set142600 	{ TLU_UC_BIT_DESC(CTO,		pciex_ue,	pciex_tx_ue) },
347383Set142600 	{ TLU_UC_BIT_DESC(ROF,		pciex_ue,	pciex_tx_ue) },
34827Sjchu 
34927Sjchu 	/* PCI-E Rx/Tx Uncorrectable Errors - see io erpt doc, section 3.4 */
350383Set142600 	{ TLU_UC_BIT_DESC(MFP,		pciex_ue,	pciex_rx_tx_ue) },
351383Set142600 	{ TLU_UC_BIT_DESC(PP,		pciex_ue,	pciex_rx_tx_ue) },
35227Sjchu 
35327Sjchu 	/* Other PCI-E Uncorrectable Errors - see io erpt doc, section 3.5 */
354383Set142600 	{ TLU_UC_BIT_DESC(FCP,		pciex_ue,	pciex_ue) },
355383Set142600 	{ TLU_UC_BIT_DESC(DLP,		pciex_ue,	pciex_ue) },
356383Set142600 	{ TLU_UC_BIT_DESC(TE,		pciex_ue,	pciex_ue) },
357383Set142600 
358383Set142600 	/* Not used */
359383Set142600 	{ TLU_UC_BIT_DESC(CA,		pciex_ue,	do_not) }
36027Sjchu };
36127Sjchu #define	px_err_tlu_ue_keys \
36227Sjchu 	(sizeof (px_err_tlu_ue_tbl)) / (sizeof (px_err_bit_desc_t))
36327Sjchu 
364*1772Sjl139090 
36527Sjchu /*
36627Sjchu  * PEC CE errors implementation is incomplete pending PCIE generic
36727Sjchu  * fabric rules.
36827Sjchu  */
36927Sjchu /* pec ce errors */
37027Sjchu #define	TLU_CE_BIT_DESC(bit, hdl, erpt) \
37127Sjchu 	TLU_CORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
37227Sjchu 	0, \
373383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
374383Set142600 	PX_ERPT_SEND(erpt), \
375383Set142600 	PX_ERR_PEC_CLASS(bit) }, \
376383Set142600 	{ TLU_CORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _S, \
377383Set142600 	0, \
378383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
379383Set142600 	PX_ERPT_SEND(erpt), \
380383Set142600 	PX_ERR_PEC_CLASS(bit)
38127Sjchu px_err_bit_desc_t px_err_tlu_ce_tbl[] = {
38227Sjchu 	/* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
383383Set142600 	{ TLU_CE_BIT_DESC(RTO,		pciex_ce,	pciex_ce) },
384383Set142600 	{ TLU_CE_BIT_DESC(RNR,		pciex_ce,	pciex_ce) },
385383Set142600 	{ TLU_CE_BIT_DESC(BDP,		pciex_ce,	pciex_ce) },
386383Set142600 	{ TLU_CE_BIT_DESC(BTP,		pciex_ce,	pciex_ce) },
387383Set142600 	{ TLU_CE_BIT_DESC(RE,		pciex_ce,	pciex_ce) }
38827Sjchu };
38927Sjchu #define	px_err_tlu_ce_keys \
39027Sjchu 	(sizeof (px_err_tlu_ce_tbl)) / (sizeof (px_err_bit_desc_t))
39127Sjchu 
392*1772Sjl139090 
39327Sjchu /* pec oe errors */
39427Sjchu #define	TLU_OE_BIT_DESC(bit, hdl, erpt) \
39527Sjchu 	TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _P, \
39627Sjchu 	0, \
39727Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
39827Sjchu 	PX_ERPT_SEND(erpt), \
399739Sjchu 	PX_ERR_PEC_CLASS(bit) }, \
400739Sjchu 	{ TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _S, \
401739Sjchu 	0, \
402739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
403739Sjchu 	PX_ERPT_SEND(erpt), \
40427Sjchu 	PX_ERR_PEC_CLASS(bit)
405*1772Sjl139090 #define	TLU_OE_OB_BIT_DESC(bit, hdl, erpt) \
406*1772Sjl139090 	TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _P, \
407*1772Sjl139090 	0, \
408*1772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
409*1772Sjl139090 	PX_ERPT_SEND(erpt), \
410*1772Sjl139090 	PX_ERR_PEC_OB_CLASS(bit) }, \
411*1772Sjl139090 	{ TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _S, \
412*1772Sjl139090 	0, \
413*1772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
414*1772Sjl139090 	PX_ERPT_SEND(erpt), \
415*1772Sjl139090 	PX_ERR_PEC_OB_CLASS(bit)
41627Sjchu px_err_bit_desc_t px_err_tlu_oe_tbl[] = {
41727Sjchu 	/*
41827Sjchu 	 * TLU Other Event Status (receive only) - see io erpt doc, section 3.7
41927Sjchu 	 */
42027Sjchu 	{ TLU_OE_BIT_DESC(MRC,		fatal_hw,	pciex_rx_oe) },
42127Sjchu 
42227Sjchu 	/* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
423383Set142600 	{ TLU_OE_BIT_DESC(WUC,		non_fatal,	pciex_rx_tx_oe) },
424383Set142600 	{ TLU_OE_BIT_DESC(RUC,		non_fatal,	pciex_rx_tx_oe) },
42527Sjchu 	{ TLU_OE_BIT_DESC(CRS,		non_fatal,	pciex_rx_tx_oe) },
42627Sjchu 
42727Sjchu 	/* TLU Other Event - see io erpt doc, section 3.9 */
42827Sjchu 	{ TLU_OE_BIT_DESC(IIP,		fatal_gos,	pciex_oe) },
42927Sjchu 	{ TLU_OE_BIT_DESC(EDP,		fatal_gos,	pciex_oe) },
43027Sjchu 	{ TLU_OE_BIT_DESC(EHP,		fatal_gos,	pciex_oe) },
431*1772Sjl139090 	{ TLU_OE_OB_BIT_DESC(TLUEITMO,	fatal_gos,	pciex_oe) },
43227Sjchu 	{ TLU_OE_BIT_DESC(LIN,		non_fatal,	pciex_oe) },
43327Sjchu 	{ TLU_OE_BIT_DESC(LRS,		non_fatal,	pciex_oe) },
4341147Sjchu 	{ TLU_OE_BIT_DESC(LDN,		tlu_ldn,	pciex_oe) },
4351147Sjchu 	{ TLU_OE_BIT_DESC(LUP,		tlu_lup,	pciex_oe) },
43627Sjchu 	{ TLU_OE_BIT_DESC(ERU,		fatal_gos,	pciex_oe) },
43727Sjchu 	{ TLU_OE_BIT_DESC(ERO,		fatal_gos,	pciex_oe) },
43827Sjchu 	{ TLU_OE_BIT_DESC(EMP,		fatal_gos,	pciex_oe) },
43927Sjchu 	{ TLU_OE_BIT_DESC(EPE,		fatal_gos,	pciex_oe) },
44027Sjchu 	{ TLU_OE_BIT_DESC(ERP,		fatal_gos,	pciex_oe) },
44127Sjchu 	{ TLU_OE_BIT_DESC(EIP,		fatal_gos,	pciex_oe) }
44227Sjchu };
44327Sjchu 
44427Sjchu #define	px_err_tlu_oe_keys \
44527Sjchu 	(sizeof (px_err_tlu_oe_tbl)) / (sizeof (px_err_bit_desc_t))
44627Sjchu 
447*1772Sjl139090 
44827Sjchu /*
44927Sjchu  * All the following tables below are for LPU Interrupts.  These interrupts
45027Sjchu  * are *NOT* error interrupts, but event status interrupts.
45127Sjchu  *
45227Sjchu  * These events are probably of most interest to:
45327Sjchu  * o Hotplug
45427Sjchu  * o Power Management
45527Sjchu  * o etc...
45627Sjchu  *
45727Sjchu  * There are also a few events that would be interresting for FMA.
45827Sjchu  * Again none of the regiseters below state that an error has occured
45927Sjchu  * or that data has been lost.  If anything, they give status that an
46027Sjchu  * error is *about* to occur.  examples
46127Sjchu  * o INT_SKP_ERR - indicates clock between fire and child is too far
46227Sjchu  *		   off and is most unlikely able to compensate
46327Sjchu  * o INT_TX_PAR_ERR - A parity error occured in ONE lane.  This is
46427Sjchu  *		      HW recoverable, but will like end up as a future
46527Sjchu  *		      fabric error as well.
46627Sjchu  *
46727Sjchu  * For now, we don't care about any of these errors and should be ignore,
46827Sjchu  * but cleared.
46927Sjchu  */
47027Sjchu 
47127Sjchu /* LPU Link Interrupt Table */
47227Sjchu #define	LPUL_BIT_DESC(bit, hdl, erpt) \
47327Sjchu 	LPU_LINK_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
47427Sjchu 	0, \
47527Sjchu 	NULL, \
47627Sjchu 	NULL, \
47727Sjchu 	""
47827Sjchu px_err_bit_desc_t px_err_lpul_tbl[] = {
47927Sjchu 	{ LPUL_BIT_DESC(LINK_ERR_ACT,	NULL,		NULL) }
48027Sjchu };
48127Sjchu #define	px_err_lpul_keys \
48227Sjchu 	(sizeof (px_err_lpul_tbl)) / (sizeof (px_err_bit_desc_t))
48327Sjchu 
48427Sjchu /* LPU Physical Interrupt Table */
48527Sjchu #define	LPUP_BIT_DESC(bit, hdl, erpt) \
48627Sjchu 	LPU_PHY_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
48727Sjchu 	0, \
48827Sjchu 	NULL, \
48927Sjchu 	NULL, \
49027Sjchu 	""
49127Sjchu px_err_bit_desc_t px_err_lpup_tbl[] = {
49227Sjchu 	{ LPUP_BIT_DESC(PHY_LAYER_ERR,	NULL,		NULL) }
49327Sjchu };
49427Sjchu #define	px_err_lpup_keys \
49527Sjchu 	(sizeof (px_err_lpup_tbl)) / (sizeof (px_err_bit_desc_t))
49627Sjchu 
49727Sjchu /* LPU Receive Interrupt Table */
49827Sjchu #define	LPUR_BIT_DESC(bit, hdl, erpt) \
49927Sjchu 	LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
50027Sjchu 	0, \
50127Sjchu 	NULL, \
50227Sjchu 	NULL, \
50327Sjchu 	""
50427Sjchu px_err_bit_desc_t px_err_lpur_tbl[] = {
50527Sjchu 	{ LPUR_BIT_DESC(RCV_PHY,	NULL,		NULL) }
50627Sjchu };
50727Sjchu #define	px_err_lpur_keys \
50827Sjchu 	(sizeof (px_err_lpur_tbl)) / (sizeof (px_err_bit_desc_t))
50927Sjchu 
51027Sjchu /* LPU Transmit Interrupt Table */
51127Sjchu #define	LPUX_BIT_DESC(bit, hdl, erpt) \
51227Sjchu 	LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
51327Sjchu 	0, \
51427Sjchu 	NULL, \
51527Sjchu 	NULL, \
51627Sjchu 	""
51727Sjchu px_err_bit_desc_t px_err_lpux_tbl[] = {
51827Sjchu 	{ LPUX_BIT_DESC(UNMSK,		NULL,		NULL) }
51927Sjchu };
52027Sjchu #define	px_err_lpux_keys \
52127Sjchu 	(sizeof (px_err_lpux_tbl)) / (sizeof (px_err_bit_desc_t))
52227Sjchu 
52327Sjchu /* LPU LTSSM Interrupt Table */
52427Sjchu #define	LPUS_BIT_DESC(bit, hdl, erpt) \
52527Sjchu 	LPU_LTSSM_INTERRUPT_AND_STATUS_INT_ ## bit, \
52627Sjchu 	0, \
52727Sjchu 	NULL, \
52827Sjchu 	NULL, \
52927Sjchu 	""
53027Sjchu px_err_bit_desc_t px_err_lpus_tbl[] = {
53127Sjchu 	{ LPUS_BIT_DESC(ANY,		NULL,		NULL) }
53227Sjchu };
53327Sjchu #define	px_err_lpus_keys \
53427Sjchu 	(sizeof (px_err_lpus_tbl)) / (sizeof (px_err_bit_desc_t))
53527Sjchu 
53627Sjchu /* LPU Gigablaze Glue Interrupt Table */
53727Sjchu #define	LPUG_BIT_DESC(bit, hdl, erpt) \
53827Sjchu 	LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_INT_ ## bit, \
53927Sjchu 	0, \
54027Sjchu 	NULL, \
54127Sjchu 	NULL, \
54227Sjchu 	""
54327Sjchu px_err_bit_desc_t px_err_lpug_tbl[] = {
54427Sjchu 	{ LPUG_BIT_DESC(GLOBL_UNMSK,	NULL,		NULL) }
54527Sjchu };
54627Sjchu #define	px_err_lpug_keys \
54727Sjchu 	(sizeof (px_err_lpug_tbl)) / (sizeof (px_err_bit_desc_t))
54827Sjchu 
54927Sjchu 
55027Sjchu /* Mask and Tables */
55127Sjchu #define	MnT6(pre) \
55227Sjchu 	B_FALSE, \
55327Sjchu 	&px_ ## pre ## _intr_mask, \
55427Sjchu 	&px_ ## pre ## _log_mask, \
55527Sjchu 	&px_ ## pre ## _count_mask, \
55627Sjchu 	px_err_ ## pre ## _tbl, \
55727Sjchu 	px_err_ ## pre ## _keys, \
55827Sjchu 	0
55927Sjchu 
560*1772Sjl139090 #define	MnT6_ob(pre) \
561*1772Sjl139090 	B_FALSE, \
562*1772Sjl139090 	&px_ ## pre ## _intr_mask, \
563*1772Sjl139090 	&px_ ## pre ## _log_mask, \
564*1772Sjl139090 	&px_ ## pre ## _count_mask, \
565*1772Sjl139090 	px_err_ ## pre ## _ob_tbl, \
566*1772Sjl139090 	px_err_ ## pre ## _ob_keys, \
567*1772Sjl139090 	0
568*1772Sjl139090 
56927Sjchu /* LPU Registers Addresses */
57027Sjchu #define	LR4(pre) \
57127Sjchu 	NULL, \
57227Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
57327Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS, \
57427Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS
57527Sjchu 
57627Sjchu /* LPU Registers Addresses with Irregularities */
57727Sjchu #define	LR4_FIXME(pre) \
57827Sjchu 	NULL, \
57927Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
58027Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS, \
58127Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS
58227Sjchu 
58327Sjchu /* TLU Registers Addresses */
58427Sjchu #define	TR4(pre) \
58527Sjchu 	TLU_ ## pre ## _LOG_ENABLE, \
58627Sjchu 	TLU_ ## pre ## _INTERRUPT_ENABLE, \
58727Sjchu 	TLU_ ## pre ## _INTERRUPT_STATUS, \
58827Sjchu 	TLU_ ## pre ## _STATUS_CLEAR
58927Sjchu 
590*1772Sjl139090 /* Registers Addresses for JBC, UBC, MMU, IMU and ILU */
59127Sjchu #define	R4(pre) \
59227Sjchu 	pre ## _ERROR_LOG_ENABLE, \
59327Sjchu 	pre ## _INTERRUPT_ENABLE, \
59427Sjchu 	pre ## _INTERRUPT_STATUS, \
59527Sjchu 	pre ## _ERROR_STATUS_CLEAR
59627Sjchu 
59727Sjchu /*
59827Sjchu  * Register error handling tables.
59927Sjchu  * The ID Field (first field) is identified by an enum px_err_id_t.
60027Sjchu  * It is located in px_err.h
60127Sjchu  */
60227Sjchu px_err_reg_desc_t px_err_reg_tbl[] = {
603*1772Sjl139090 	{ MnT6(jbc),	R4(JBC),		  "JBC Error"},
604*1772Sjl139090 	{ MnT6(ubc),	R4(UBC),		  "UBC Error"},
605435Sjchu 	{ MnT6(mmu),	R4(MMU),		  "MMU Error"},
606435Sjchu 	{ MnT6(imu),	R4(IMU),		  "IMU Error"},
60727Sjchu 	{ MnT6(tlu_ue),	TR4(UNCORRECTABLE_ERROR), "TLU UE"},
60827Sjchu 	{ MnT6(tlu_ce), TR4(CORRECTABLE_ERROR),	  "TLU CE"},
60927Sjchu 	{ MnT6(tlu_oe), TR4(OTHER_EVENT),	  "TLU OE"},
610435Sjchu 	{ MnT6(ilu),	R4(ILU),		  "ILU Error"},
61127Sjchu 	{ MnT6(lpul),	LR4(LINK_LAYER),	  "LPU Link Layer"},
61227Sjchu 	{ MnT6(lpup),	LR4_FIXME(PHY),		  "LPU Phy Layer"},
61327Sjchu 	{ MnT6(lpur),	LR4(RECEIVE_PHY),	  "LPU RX Phy Layer"},
61427Sjchu 	{ MnT6(lpux),	LR4(TRANSMIT_PHY),	  "LPU TX Phy Layer"},
61527Sjchu 	{ MnT6(lpus),	LR4(LTSSM),		  "LPU LTSSM"},
616*1772Sjl139090 	{ MnT6(lpug),	LR4(GIGABLAZE_GLUE),	  "LPU GigaBlaze Glue"},
61727Sjchu };
61827Sjchu #define	PX_ERR_REG_KEYS (sizeof (px_err_reg_tbl)) / (sizeof (px_err_reg_tbl[0]))
61927Sjchu 
62027Sjchu typedef struct px_err_ss {
62127Sjchu 	uint64_t err_status[PX_ERR_REG_KEYS];
62227Sjchu } px_err_ss_t;
62327Sjchu 
624*1772Sjl139090 static void px_err_snapshot(px_t *px_p, px_err_ss_t *ss, boolean_t chk_cb);
62527Sjchu static int  px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr,
62627Sjchu     px_err_ss_t *ss);
62727Sjchu static int  px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr,
62827Sjchu     int err, int caller);
62927Sjchu 
63027Sjchu /*
63127Sjchu  * px_err_cb_intr:
632*1772Sjl139090  * Interrupt handler for the JBC/UBC block.
63327Sjchu  * o lock
63427Sjchu  * o create derr
635*1772Sjl139090  * o px_err_handle(leaf1, with cb)
636*1772Sjl139090  * o px_err_handle(leaf2, without cb)
63727Sjchu  * o dispatch (leaf1)
63827Sjchu  * o dispatch (leaf2)
63927Sjchu  * o unlock
64027Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
64127Sjchu  */
64227Sjchu uint_t
64327Sjchu px_err_cb_intr(caddr_t arg)
64427Sjchu {
64527Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
64627Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
64727Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
648118Sjchu 	int		err = PX_OK;
649118Sjchu 	int		ret = DDI_FM_OK;
65027Sjchu 	int		fatal = 0;
65127Sjchu 	ddi_fm_error_t	derr;
65227Sjchu 
65327Sjchu 	/* Create the derr */
65427Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
65527Sjchu 	derr.fme_version = DDI_FME_VERSION;
65627Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
65727Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
65827Sjchu 
6591648Sjchu 	mutex_enter(&px_p->px_fm_mutex);
66027Sjchu 
6611648Sjchu 	err |= px_err_handle(px_p, &derr, PX_INTR_CALL, B_TRUE);
66227Sjchu 
6631648Sjchu 	ret = ndi_fm_handler_dispatch(rpdip, NULL, &derr);
6641648Sjchu 	switch (ret) {
6651648Sjchu 	case DDI_FM_FATAL:
6661648Sjchu 		fatal++;
6671648Sjchu 		break;
6681648Sjchu 	case DDI_FM_NONFATAL:
6691648Sjchu 	case DDI_FM_UNKNOWN:
6701648Sjchu 	default:
6711648Sjchu 		break;
67227Sjchu 	}
67327Sjchu 
67427Sjchu 	/* Set the intr state to idle for the leaf that received the mondo */
6751648Sjchu 
67627Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
67727Sjchu 	    INTR_IDLE_STATE);
67827Sjchu 
6791648Sjchu 	mutex_exit(&px_p->px_fm_mutex);
68027Sjchu 
68127Sjchu 	/*
68227Sjchu 	 * PX_FATAL_HW error is diagnosed after system recovered from
68327Sjchu 	 * HW initiated reset, therefore no furthur handling is required.
68427Sjchu 	 */
68527Sjchu 	if (fatal || err & (PX_FATAL_GOS | PX_FATAL_SW))
686677Sjchu 		PX_FM_PANIC("Fatal System Bus Error has occurred\n");
68727Sjchu 
68827Sjchu 	return (DDI_INTR_CLAIMED);
68927Sjchu }
69027Sjchu 
69127Sjchu /*
69227Sjchu  * px_err_dmc_pec_intr:
69327Sjchu  * Interrupt handler for the DMC/PEC block.
69427Sjchu  * o lock
69527Sjchu  * o create derr
696*1772Sjl139090  * o px_err_handle(leaf, with cb)
69727Sjchu  * o dispatch (leaf)
69827Sjchu  * o unlock
69927Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
70027Sjchu  */
70127Sjchu uint_t
70227Sjchu px_err_dmc_pec_intr(caddr_t arg)
70327Sjchu {
70427Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
70527Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
70627Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
707118Sjchu 	int		err = PX_OK;
708118Sjchu 	int		ret = DDI_FM_OK;
70927Sjchu 	ddi_fm_error_t	derr;
71027Sjchu 
71127Sjchu 	/* Create the derr */
71227Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
71327Sjchu 	derr.fme_version = DDI_FME_VERSION;
71427Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
71527Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
71627Sjchu 
7171648Sjchu 	mutex_enter(&px_p->px_fm_mutex);
71827Sjchu 
71927Sjchu 	/* send ereport/handle/clear fire registers */
72027Sjchu 	err |= px_err_handle(px_p, &derr, PX_INTR_CALL, B_TRUE);
72127Sjchu 
72227Sjchu 	/* Check all child devices for errors */
72327Sjchu 	ret = ndi_fm_handler_dispatch(rpdip, NULL, &derr);
72427Sjchu 
72527Sjchu 	/* Set the interrupt state to idle */
72627Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
72727Sjchu 	    INTR_IDLE_STATE);
72827Sjchu 
7291648Sjchu 	mutex_exit(&px_p->px_fm_mutex);
73027Sjchu 
73127Sjchu 	/*
73227Sjchu 	 * PX_FATAL_HW indicates a condition recovered from Fatal-Reset,
73327Sjchu 	 * therefore it does not cause panic.
73427Sjchu 	 */
73527Sjchu 	if ((err & (PX_FATAL_GOS | PX_FATAL_SW)) || (ret == DDI_FM_FATAL))
736677Sjchu 		PX_FM_PANIC("Fatal System Port Error has occurred\n");
73727Sjchu 
73827Sjchu 	return (DDI_INTR_CLAIMED);
73927Sjchu }
74027Sjchu 
74127Sjchu /*
74227Sjchu  * Error register are being handled by px_hlib xxx_init functions.
74327Sjchu  * They are also called again by px_err_add_intr for mondo62 and 63
74427Sjchu  * from px_cb_attach and px_attach
74527Sjchu  */
74627Sjchu void
74727Sjchu px_err_reg_enable(px_t *px_p, px_err_id_t id)
74827Sjchu {
74927Sjchu 	px_err_reg_desc_t	*reg_desc = &px_err_reg_tbl[id];
75027Sjchu 	uint64_t 		intr_mask = *reg_desc->intr_mask_p;
75127Sjchu 	uint64_t 		log_mask = *reg_desc->log_mask_p;
75227Sjchu 	caddr_t			csr_base;
75327Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
75427Sjchu 
755*1772Sjl139090 	/* Get the correct CSR BASE */
756*1772Sjl139090 	if (PX_ERR_XBC(id))
75727Sjchu 		csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
75827Sjchu 	else
75927Sjchu 		csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
76027Sjchu 
76127Sjchu 	reg_desc->enabled = B_TRUE;
76227Sjchu 
76327Sjchu 	/* Enable logs if it exists */
76427Sjchu 	if (reg_desc->log_addr != NULL)
76527Sjchu 		CSR_XS(csr_base, reg_desc->log_addr, log_mask);
76627Sjchu 
76727Sjchu 	/*
76827Sjchu 	 * For readability you in code you set 1 to enable an interrupt.
76927Sjchu 	 * But in Fire it's backwards.  You set 1 to *disable* an intr.
77027Sjchu 	 * Reverse the user tunable intr mask field.
77127Sjchu 	 *
77227Sjchu 	 * Disable All Errors
77327Sjchu 	 * Clear All Errors
77427Sjchu 	 * Enable Errors
77527Sjchu 	 */
77627Sjchu 	CSR_XS(csr_base, reg_desc->enable_addr, 0);
77727Sjchu 	CSR_XS(csr_base, reg_desc->clear_addr, -1);
77827Sjchu 	CSR_XS(csr_base, reg_desc->enable_addr, intr_mask);
77927Sjchu 	DBG(DBG_ATTACH, NULL, "%s Mask: 0x%llx\n",
78027Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->enable_addr));
78127Sjchu 	DBG(DBG_ATTACH, NULL, "%s Status: 0x%llx\n",
78227Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->status_addr));
78327Sjchu 	DBG(DBG_ATTACH, NULL, "%s Clear: 0x%llx\n",
78427Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->clear_addr));
78527Sjchu 	if (reg_desc->log_addr != NULL) {
78627Sjchu 		DBG(DBG_ATTACH, NULL, "%s Log: 0x%llx\n",
78727Sjchu 		    reg_desc->msg, CSR_XR(csr_base, reg_desc->log_addr));
78827Sjchu 	}
78927Sjchu }
79027Sjchu 
79127Sjchu void
79227Sjchu px_err_reg_disable(px_t *px_p, px_err_id_t id)
79327Sjchu {
79427Sjchu 	px_err_reg_desc_t	*reg_desc = &px_err_reg_tbl[id];
79527Sjchu 	caddr_t			csr_base;
796693Sgovinda 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
79727Sjchu 
798*1772Sjl139090 	/* Get the correct CSR BASE */
799*1772Sjl139090 	if (PX_ERR_XBC(id))
800693Sgovinda 		csr_base = (caddr_t)(uintptr_t)pxu_p->px_address[PX_REG_XBC];
80127Sjchu 	else
802693Sgovinda 		csr_base = (caddr_t)(uintptr_t)pxu_p->px_address[PX_REG_CSR];
80327Sjchu 
80427Sjchu 	reg_desc->enabled = B_FALSE;
80527Sjchu 
80627Sjchu 	switch (id) {
80727Sjchu 	case PX_ERR_JBC:
808*1772Sjl139090 	case PX_ERR_UBC:
80927Sjchu 	case PX_ERR_MMU:
81027Sjchu 	case PX_ERR_IMU:
81127Sjchu 	case PX_ERR_TLU_UE:
81227Sjchu 	case PX_ERR_TLU_CE:
81327Sjchu 	case PX_ERR_TLU_OE:
81427Sjchu 	case PX_ERR_ILU:
81527Sjchu 		if (reg_desc->log_addr != NULL) {
81627Sjchu 			CSR_XS(csr_base, reg_desc->log_addr, 0);
81727Sjchu 		}
81827Sjchu 		CSR_XS(csr_base, reg_desc->enable_addr, 0);
81927Sjchu 		break;
82027Sjchu 	case PX_ERR_LPU_LINK:
82127Sjchu 	case PX_ERR_LPU_PHY:
82227Sjchu 	case PX_ERR_LPU_RX:
82327Sjchu 	case PX_ERR_LPU_TX:
82427Sjchu 	case PX_ERR_LPU_LTSSM:
82527Sjchu 	case PX_ERR_LPU_GIGABLZ:
82627Sjchu 		if (reg_desc->log_addr != NULL) {
82727Sjchu 			CSR_XS(csr_base, reg_desc->log_addr, -1);
82827Sjchu 		}
82927Sjchu 		CSR_XS(csr_base, reg_desc->enable_addr, -1);
83027Sjchu 		break;
83127Sjchu 	}
83227Sjchu }
83327Sjchu 
83427Sjchu /*
83527Sjchu  * px_err_handle:
83627Sjchu  * Common function called by trap, mondo and fabric intr.
83727Sjchu  * o Snap shot current fire registers
83827Sjchu  * o check for safe access
83927Sjchu  * o send ereport and clear snap shot registers
84027Sjchu  * o check severity of snap shot registers
84127Sjchu  *
84227Sjchu  * @param px_p		leaf in which to check access
84327Sjchu  * @param derr		fm err data structure to be updated
84427Sjchu  * @param caller	PX_TRAP_CALL | PX_INTR_CALL
845*1772Sjl139090  * @param chk_cb	whether to handle cb registers
84627Sjchu  * @return err		PX_OK | PX_NONFATAL |
84727Sjchu  *                      PX_FATAL_GOS | PX_FATAL_HW | PX_STUCK_FATAL
84827Sjchu  */
84927Sjchu int
85027Sjchu px_err_handle(px_t *px_p, ddi_fm_error_t *derr, int caller,
851*1772Sjl139090     boolean_t chk_cb)
85227Sjchu {
85327Sjchu 	px_err_ss_t		ss;
854118Sjchu 	int			err = PX_OK;
85527Sjchu 
8561648Sjchu 	ASSERT(MUTEX_HELD(&px_p->px_fm_mutex));
85727Sjchu 
85827Sjchu 	/* snap shot the current fire registers */
859*1772Sjl139090 	px_err_snapshot(px_p, &ss, chk_cb);
86027Sjchu 
86127Sjchu 	/* check for safe access */
86227Sjchu 	px_err_safeacc_check(px_p, derr);
86327Sjchu 
86427Sjchu 	/* send ereports/handle/clear registers */
86527Sjchu 	err = px_err_erpt_and_clr(px_p, derr, &ss);
86627Sjchu 
86727Sjchu 	/* check for error severity */
86827Sjchu 	err = px_err_check_severity(px_p, derr, err, caller);
86927Sjchu 
87027Sjchu 	/* Mark the On Trap Handle if an error occured */
87127Sjchu 	if (err != PX_OK) {
87227Sjchu 		px_pec_t	*pec_p = px_p->px_pec_p;
87327Sjchu 		on_trap_data_t	*otd = pec_p->pec_ontrap_data;
87427Sjchu 
875118Sjchu 		if ((otd != NULL) && (otd->ot_prot & OT_DATA_ACCESS))
87627Sjchu 			otd->ot_trap |= OT_DATA_ACCESS;
87727Sjchu 	}
87827Sjchu 
87927Sjchu 	return (err);
88027Sjchu }
88127Sjchu 
88227Sjchu /*
88327Sjchu  * Static function
88427Sjchu  */
88527Sjchu 
88627Sjchu /*
88727Sjchu  * px_err_snapshot:
88827Sjchu  * Take a current snap shot of all the fire error registers.  This includes
889*1772Sjl139090  * JBC/UBC, DMC, and PEC, unless chk_cb == false;
89027Sjchu  *
89127Sjchu  * @param px_p		leaf in which to take the snap shot.
89227Sjchu  * @param ss		pre-allocated memory to store the snap shot.
893*1772Sjl139090  * @param chk_cb	boolean on whether to store jbc/ubc register.
89427Sjchu  */
89527Sjchu static void
896*1772Sjl139090 px_err_snapshot(px_t *px_p, px_err_ss_t *ss, boolean_t chk_cb)
89727Sjchu {
89827Sjchu 	pxu_t	*pxu_p = (pxu_t *)px_p->px_plat_p;
89927Sjchu 	caddr_t	xbc_csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
90027Sjchu 	caddr_t	pec_csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
90127Sjchu 	px_err_reg_desc_t *reg_desc;
90227Sjchu 	int reg_id;
90327Sjchu 
904*1772Sjl139090 	switch (PX_CHIP_TYPE(pxu_p)) {
905*1772Sjl139090 	case PX_CHIP_OBERON:
906*1772Sjl139090 		reg_id = PX_ERR_UBC;
907*1772Sjl139090 		break;
908*1772Sjl139090 	case PX_CHIP_FIRE:
909*1772Sjl139090 		reg_id = PX_ERR_JBC;
910*1772Sjl139090 		break;
911*1772Sjl139090 	default:
912*1772Sjl139090 		DBG(DBG_ERR_INTR, NULL, "px_err_snapshot - "
913*1772Sjl139090 		    "unknown chip type: 0x%x\n", PX_CHIP_TYPE(pxu_p));
914*1772Sjl139090 		reg_id = 0;
915*1772Sjl139090 		break;
916*1772Sjl139090 	}
917*1772Sjl139090 
918*1772Sjl139090 	/* snapshot CB interrupt status */
919*1772Sjl139090 	if (chk_cb == B_TRUE) {
92027Sjchu 		reg_desc = &px_err_reg_tbl[reg_id];
921*1772Sjl139090 		/* Only look at enabled groups. */
922*1772Sjl139090 		if (reg_desc->enabled == B_TRUE)	{
923*1772Sjl139090 			ss->err_status[reg_id] = CSR_XR(xbc_csr_base,
924*1772Sjl139090 			    reg_desc->status_addr);
925*1772Sjl139090 		}
92627Sjchu 	} else {
92727Sjchu 		ss->err_status[reg_id] = 0;
92827Sjchu 	}
92927Sjchu 
93027Sjchu 	/* snapshot DMC/PEC interrupt status */
931*1772Sjl139090 	for (reg_id = 2; reg_id < PX_ERR_REG_KEYS; reg_id += 1) {
93227Sjchu 		reg_desc = &px_err_reg_tbl[reg_id];
933*1772Sjl139090 		/* Only look at enabled groups. */
934*1772Sjl139090 		if (reg_desc->enabled == B_TRUE)	{
935*1772Sjl139090 			ss->err_status[reg_id] = CSR_XR(pec_csr_base,
936*1772Sjl139090 			    reg_desc->status_addr);
937*1772Sjl139090 		}
93827Sjchu 	}
93927Sjchu }
94027Sjchu 
94127Sjchu /*
94227Sjchu  * px_err_erpt_and_clr:
94327Sjchu  * This function does the following thing to all the fire registers based
94427Sjchu  * on an earlier snap shot.
94527Sjchu  * o Send ereport
94627Sjchu  * o Handle the error
94727Sjchu  * o Clear the error
94827Sjchu  *
94927Sjchu  * @param px_p		leaf in which to take the snap shot.
95027Sjchu  * @param derr		fm err in which the ereport is to be based on
95127Sjchu  * @param ss		pre-allocated memory to store the snap shot.
95227Sjchu  */
95327Sjchu static int
95427Sjchu px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr, px_err_ss_t *ss)
95527Sjchu {
95627Sjchu 	dev_info_t		*rpdip = px_p->px_dip;
95727Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
95827Sjchu 	caddr_t			csr_base;
95927Sjchu 	px_err_reg_desc_t	*err_reg_tbl;
96027Sjchu 	px_err_bit_desc_t	*err_bit_tbl;
96127Sjchu 	px_err_bit_desc_t	*err_bit_desc;
96227Sjchu 
96327Sjchu 	uint64_t		*log_mask, *count_mask;
96427Sjchu 	uint64_t		status_addr, clear_addr;
96527Sjchu 	uint64_t		ss_reg;
96627Sjchu 
96727Sjchu 	int			(*err_handler)();
96827Sjchu 	int			(*erpt_handler)();
96927Sjchu 	int			reg_id, key;
97027Sjchu 	int			err = PX_OK;
9711147Sjchu 	int			biterr;
97227Sjchu 
9731648Sjchu 	ASSERT(MUTEX_HELD(&px_p->px_fm_mutex));
97427Sjchu 
97527Sjchu 	/* send erport/handle/clear JBC errors */
97627Sjchu 	for (reg_id = 0; reg_id < PX_ERR_REG_KEYS; reg_id += 1) {
97727Sjchu 		/* Get the correct register description table */
97827Sjchu 		err_reg_tbl = &px_err_reg_tbl[reg_id];
97927Sjchu 
980*1772Sjl139090 		/* Only look at enabled groups. */
981*1772Sjl139090 		if (err_reg_tbl->enabled != B_TRUE)
982*1772Sjl139090 			continue;
983*1772Sjl139090 
98427Sjchu 		/* Get the correct CSR BASE */
985*1772Sjl139090 		if (PX_ERR_XBC(reg_id))
98627Sjchu 			csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
987*1772Sjl139090 		else
98827Sjchu 			csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
98927Sjchu 
99027Sjchu 		/* Get pointers to masks and register addresses */
99127Sjchu 		log_mask = err_reg_tbl->log_mask_p;
99227Sjchu 		count_mask = err_reg_tbl->count_mask_p;
99327Sjchu 		status_addr = err_reg_tbl->status_addr;
99427Sjchu 		clear_addr = err_reg_tbl->clear_addr;
99527Sjchu 		ss_reg = ss->err_status[reg_id];
99627Sjchu 
99727Sjchu 		/* Get the register BIT description table */
99827Sjchu 		err_bit_tbl = err_reg_tbl->err_bit_tbl;
99927Sjchu 
100027Sjchu 		/* For each known bit in the register send erpt and handle */
100127Sjchu 		for (key = 0; key < err_reg_tbl->err_bit_keys; key += 1) {
100227Sjchu 			/* Get the bit description table for this register */
100327Sjchu 			err_bit_desc = &err_bit_tbl[key];
100427Sjchu 
100527Sjchu 			/*
100627Sjchu 			 * If the ss_reg is set for this bit,
100727Sjchu 			 * send ereport and handle
100827Sjchu 			 */
100927Sjchu 			if (BIT_TST(ss_reg, err_bit_desc->bit)) {
101027Sjchu 				/* Increment the counter if necessary */
101127Sjchu 				if (BIT_TST(*count_mask, err_bit_desc->bit)) {
101227Sjchu 					err_bit_desc->counter++;
101327Sjchu 				}
101427Sjchu 
101527Sjchu 				/* Error Handle for this bit */
101627Sjchu 				err_handler = err_bit_desc->err_handler;
10171147Sjchu 				if (err_handler) {
10181147Sjchu 					biterr = err_handler(rpdip,
101927Sjchu 					    csr_base,
102027Sjchu 					    derr,
102127Sjchu 					    err_reg_tbl,
102227Sjchu 					    err_bit_desc);
10231147Sjchu 					err |= biterr;
10241147Sjchu 				}
102527Sjchu 
1026383Set142600 				/* Send the ereport if it's an UNEXPECTED err */
102727Sjchu 				erpt_handler = err_bit_desc->erpt_handler;
10281147Sjchu 				if ((derr->fme_flag == DDI_FM_ERR_UNEXPECTED) &&
10291147Sjchu 				    (biterr != PX_OK)) {
1030383Set142600 					if (erpt_handler)
1031383Set142600 						(void) erpt_handler(rpdip,
1032383Set142600 						    csr_base,
1033383Set142600 						    ss_reg,
1034383Set142600 						    derr,
1035739Sjchu 						    err_bit_desc->bit,
1036383Set142600 						    err_bit_desc->class_name);
1037383Set142600 				}
103827Sjchu 			}
103927Sjchu 		}
1040332Sjchu 		/* Print register status */
1041332Sjchu 		if (ss_reg & *log_mask)
1042332Sjchu 			DBG(DBG_ERR_INTR, rpdip, "<%x>=%16llx %s\n",
104327Sjchu 			    status_addr, ss_reg, err_reg_tbl->msg);
104427Sjchu 
104527Sjchu 		/* Clear the register and error */
104627Sjchu 		CSR_XS(csr_base, clear_addr, ss_reg);
104727Sjchu 	}
104827Sjchu 
104927Sjchu 	return (err);
105027Sjchu }
105127Sjchu 
105227Sjchu /*
105327Sjchu  * px_err_check_severity:
105427Sjchu  * Check the severity of the fire error based on an earlier snapshot
105527Sjchu  *
105627Sjchu  * @param px_p		leaf in which to take the snap shot.
105727Sjchu  * @param derr		fm err in which the ereport is to be based on
105827Sjchu  * @param ss		pre-allocated memory to store the snap shot.
105927Sjchu  */
106027Sjchu static int
106127Sjchu px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr, int err, int caller)
106227Sjchu {
106327Sjchu 	px_pec_t 	*pec_p = px_p->px_pec_p;
106427Sjchu 	boolean_t	is_safeacc = B_FALSE;
1065118Sjchu 
1066118Sjchu 	/* nothing to do if called with no error */
1067118Sjchu 	if (err == PX_OK)
1068118Sjchu 		return (err);
106927Sjchu 
107027Sjchu 	/* Cautious access error handling  */
107127Sjchu 	switch (derr->fme_flag) {
107227Sjchu 	case DDI_FM_ERR_EXPECTED:
107327Sjchu 		if (caller == PX_TRAP_CALL) {
107427Sjchu 			/*
107527Sjchu 			 * for ddi_caut_get treat all events as nonfatal
107627Sjchu 			 * The trampoline will set err_ena = 0,
107727Sjchu 			 * err_status = NONFATAL.
107827Sjchu 			 */
107927Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
108027Sjchu 			is_safeacc = B_TRUE;
108127Sjchu 		} else {
108227Sjchu 			/*
108327Sjchu 			 * For ddi_caut_put treat all events as nonfatal. Here
108427Sjchu 			 * we have the handle and can call ndi_fm_acc_err_set().
108527Sjchu 			 */
108627Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
108727Sjchu 			ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr);
108827Sjchu 			is_safeacc = B_TRUE;
108927Sjchu 		}
109027Sjchu 		break;
109127Sjchu 	case DDI_FM_ERR_PEEK:
109227Sjchu 	case DDI_FM_ERR_POKE:
109327Sjchu 		/*
109427Sjchu 		 * For ddi_peek/poke treat all events as nonfatal.
109527Sjchu 		 */
109627Sjchu 		is_safeacc = B_TRUE;
109727Sjchu 		break;
109827Sjchu 	default:
109927Sjchu 		is_safeacc = B_FALSE;
110027Sjchu 	}
110127Sjchu 
110227Sjchu 	/*
110327Sjchu 	 * The third argument "err" is passed in as error status from checking
110427Sjchu 	 * Fire register, re-adjust error status from safe access.
110527Sjchu 	 */
110627Sjchu 	if (is_safeacc && !(err & PX_FATAL_GOS))
1107118Sjchu 		return (PX_NONFATAL);
110827Sjchu 
1109118Sjchu 	return (err);
111027Sjchu }
111127Sjchu 
111227Sjchu /* predefined convenience functions */
111327Sjchu /* ARGSUSED */
111427Sjchu int
111527Sjchu px_err_fatal_hw_handle(dev_info_t *rpdip, caddr_t csr_base,
111627Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
111727Sjchu 	px_err_bit_desc_t *err_bit_descr)
111827Sjchu {
111927Sjchu 	return (PX_FATAL_HW);
112027Sjchu }
112127Sjchu 
112227Sjchu /* ARGSUSED */
112327Sjchu int
112427Sjchu px_err_fatal_gos_handle(dev_info_t *rpdip, caddr_t csr_base,
112527Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
112627Sjchu 	px_err_bit_desc_t *err_bit_descr)
112727Sjchu {
112827Sjchu 	return (PX_FATAL_GOS);
112927Sjchu }
113027Sjchu 
113127Sjchu /* ARGSUSED */
113227Sjchu int
113327Sjchu px_err_fatal_stuck_handle(dev_info_t *rpdip, caddr_t csr_base,
113427Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
113527Sjchu 	px_err_bit_desc_t *err_bit_descr)
113627Sjchu {
113727Sjchu 	return (PX_STUCK_FATAL);
113827Sjchu }
113927Sjchu 
114027Sjchu /* ARGSUSED */
114127Sjchu int
114227Sjchu px_err_fatal_sw_handle(dev_info_t *rpdip, caddr_t csr_base,
114327Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
114427Sjchu 	px_err_bit_desc_t *err_bit_descr)
114527Sjchu {
114627Sjchu 	return (PX_FATAL_SW);
114727Sjchu }
114827Sjchu 
114927Sjchu /* ARGSUSED */
115027Sjchu int
115127Sjchu px_err_non_fatal_handle(dev_info_t *rpdip, caddr_t csr_base,
115227Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
115327Sjchu 	px_err_bit_desc_t *err_bit_descr)
115427Sjchu {
115527Sjchu 	return (PX_NONFATAL);
115627Sjchu }
115727Sjchu 
115827Sjchu /* ARGSUSED */
115927Sjchu int
116027Sjchu px_err_ok_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
116127Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
116227Sjchu {
116327Sjchu 	return (PX_OK);
116427Sjchu }
116527Sjchu 
116627Sjchu /* ARGSUSED */
116727Sjchu int
116827Sjchu px_err_unknown_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
116927Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
117027Sjchu {
117127Sjchu 	return (PX_ERR_UNKNOWN);
117227Sjchu }
117327Sjchu 
1174383Set142600 /* ARGSUSED */
1175383Set142600 PX_ERPT_SEND_DEC(do_not)
1176383Set142600 {
1177383Set142600 	return (PX_OK);
1178383Set142600 }
1179383Set142600 
1180*1772Sjl139090 /* UBC FATAL - see io erpt doc, section 1.1 */
1181*1772Sjl139090 /* ARGSUSED */
1182*1772Sjl139090 PX_ERPT_SEND_DEC(ubc_fatal)
1183*1772Sjl139090 {
1184*1772Sjl139090 	char		buf[FM_MAX_CLASS];
1185*1772Sjl139090 	uint64_t	memory_ue_log, marked;
1186*1772Sjl139090 	char		unum[FM_MAX_CLASS];
1187*1772Sjl139090 	int		unum_length;
1188*1772Sjl139090 	uint64_t	device_id = 0;
1189*1772Sjl139090 	uint8_t		cpu_version = 0;
1190*1772Sjl139090 	nvlist_t	*resource = NULL;
1191*1772Sjl139090 
1192*1772Sjl139090 	unum[0] = '\0';
1193*1772Sjl139090 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1194*1772Sjl139090 
1195*1772Sjl139090 	memory_ue_log = CSR_XR(csr_base, UBC_MEMORY_UE_LOG);
1196*1772Sjl139090 	marked = (memory_ue_log >> UBC_MEMORY_UE_LOG_MARKED) &
1197*1772Sjl139090 	    UBC_MEMORY_UE_LOG_MARKED_MASK;
1198*1772Sjl139090 
1199*1772Sjl139090 	if ((strstr(class_name, "ubc.piowtue") != NULL) ||
1200*1772Sjl139090 	    (strstr(class_name, "ubc.piowbeue") != NULL) ||
1201*1772Sjl139090 	    (strstr(class_name, "ubc.piorbeue") != NULL) ||
1202*1772Sjl139090 	    (strstr(class_name, "ubc.dmarduea") != NULL) ||
1203*1772Sjl139090 	    (strstr(class_name, "ubc.dmardueb") != NULL)) {
1204*1772Sjl139090 		int eid = (memory_ue_log >> UBC_MEMORY_UE_LOG_EID) &
1205*1772Sjl139090 		    UBC_MEMORY_UE_LOG_EID_MASK;
1206*1772Sjl139090 		(void) strncat(buf, ubc_class_eid_qualifier[eid],
1207*1772Sjl139090 		    FM_MAX_CLASS);
1208*1772Sjl139090 
1209*1772Sjl139090 		if (eid == UBC_EID_MEM) {
1210*1772Sjl139090 			uint64_t phys_addr = memory_ue_log &
1211*1772Sjl139090 			    MMU_OBERON_PADDR_MASK;
1212*1772Sjl139090 			uint64_t offset = (uint64_t)-1;
1213*1772Sjl139090 
1214*1772Sjl139090 			resource = fm_nvlist_create(NULL);
1215*1772Sjl139090 			if (&plat_get_mem_unum) {
1216*1772Sjl139090 				if ((plat_get_mem_unum(0,
1217*1772Sjl139090 				    phys_addr, 0, B_TRUE, 0, unum,
1218*1772Sjl139090 				    FM_MAX_CLASS, &unum_length)) != 0)
1219*1772Sjl139090 					unum[0] = '\0';
1220*1772Sjl139090 			}
1221*1772Sjl139090 			fm_fmri_mem_set(resource, FM_MEM_SCHEME_VERSION,
1222*1772Sjl139090 					NULL, unum, NULL, offset);
1223*1772Sjl139090 
1224*1772Sjl139090 		} else if (eid == UBC_EID_CPU) {
1225*1772Sjl139090 			int cpuid = (marked & UBC_MARKED_MAX_CPUID_MASK);
1226*1772Sjl139090 			char sbuf[21]; /* sizeof (UINT64_MAX) + '\0' */
1227*1772Sjl139090 
1228*1772Sjl139090 			resource = fm_nvlist_create(NULL);
1229*1772Sjl139090 			cpu_version = cpunodes[cpuid].version;
1230*1772Sjl139090 			device_id = cpunodes[cpuid].device_id;
1231*1772Sjl139090 			(void) snprintf(sbuf, sizeof (sbuf), "%lX",
1232*1772Sjl139090 			    device_id);
1233*1772Sjl139090 			(void) fm_fmri_cpu_set(resource,
1234*1772Sjl139090 			    FM_CPU_SCHEME_VERSION, NULL, cpuid,
1235*1772Sjl139090 			    &cpu_version, sbuf);
1236*1772Sjl139090 		}
1237*1772Sjl139090 	}
1238*1772Sjl139090 
1239*1772Sjl139090 	if (resource) {
1240*1772Sjl139090 		ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1241*1772Sjl139090 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1242*1772Sjl139090 		    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1243*1772Sjl139090 		    OBERON_UBC_ELE, DATA_TYPE_UINT64,
1244*1772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_LOG_ENABLE),
1245*1772Sjl139090 		    OBERON_UBC_IE, DATA_TYPE_UINT64,
1246*1772Sjl139090 		    CSR_XR(csr_base, UBC_INTERRUPT_ENABLE),
1247*1772Sjl139090 		    OBERON_UBC_IS, DATA_TYPE_UINT64,
1248*1772Sjl139090 		    CSR_XR(csr_base, UBC_INTERRUPT_STATUS),
1249*1772Sjl139090 		    OBERON_UBC_ESS, DATA_TYPE_UINT64,
1250*1772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_STATUS_SET),
1251*1772Sjl139090 		    OBERON_UBC_MUE, DATA_TYPE_UINT64, memory_ue_log,
1252*1772Sjl139090 		    OBERON_UBC_UNUM, DATA_TYPE_STRING, unum,
1253*1772Sjl139090 		    OBERON_UBC_DID, DATA_TYPE_UINT64, device_id,
1254*1772Sjl139090 		    OBERON_UBC_CPUV, DATA_TYPE_UINT32, cpu_version,
1255*1772Sjl139090 		    OBERON_UBC_RESOURCE, DATA_TYPE_NVLIST, resource,
1256*1772Sjl139090 		    NULL);
1257*1772Sjl139090 		fm_nvlist_destroy(resource, FM_NVA_FREE);
1258*1772Sjl139090 	} else {
1259*1772Sjl139090 		ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1260*1772Sjl139090 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1261*1772Sjl139090 		    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
1262*1772Sjl139090 		    OBERON_UBC_ELE, DATA_TYPE_UINT64,
1263*1772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_LOG_ENABLE),
1264*1772Sjl139090 		    OBERON_UBC_IE, DATA_TYPE_UINT64,
1265*1772Sjl139090 		    CSR_XR(csr_base, UBC_INTERRUPT_ENABLE),
1266*1772Sjl139090 		    OBERON_UBC_IS, DATA_TYPE_UINT64,
1267*1772Sjl139090 		    CSR_XR(csr_base, UBC_INTERRUPT_STATUS),
1268*1772Sjl139090 		    OBERON_UBC_ESS, DATA_TYPE_UINT64,
1269*1772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_STATUS_SET),
1270*1772Sjl139090 		    OBERON_UBC_MUE, DATA_TYPE_UINT64, memory_ue_log,
1271*1772Sjl139090 		    OBERON_UBC_UNUM, DATA_TYPE_STRING, unum,
1272*1772Sjl139090 		    OBERON_UBC_DID, DATA_TYPE_UINT64, device_id,
1273*1772Sjl139090 		    OBERON_UBC_CPUV, DATA_TYPE_UINT32, cpu_version,
1274*1772Sjl139090 		    NULL);
1275*1772Sjl139090 	}
1276*1772Sjl139090 
1277*1772Sjl139090 	return (PX_OK);
1278*1772Sjl139090 }
1279383Set142600 
128027Sjchu /* JBC FATAL - see io erpt doc, section 1.1 */
128127Sjchu PX_ERPT_SEND_DEC(jbc_fatal)
128227Sjchu {
128327Sjchu 	char		buf[FM_MAX_CLASS];
1284739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
128527Sjchu 
128627Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
128727Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
128827Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1289739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
129027Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
129127Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
129227Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
129327Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
129427Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
129527Sjchu 	    ss_reg,
129627Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
129727Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
129827Sjchu 	    FIRE_JBC_FEL1, DATA_TYPE_UINT64,
129927Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_1),
130027Sjchu 	    FIRE_JBC_FEL2, DATA_TYPE_UINT64,
130127Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_2),
130227Sjchu 	    NULL);
130327Sjchu 
130427Sjchu 	return (PX_OK);
130527Sjchu }
130627Sjchu 
130727Sjchu /* JBC MERGE - see io erpt doc, section 1.2 */
130827Sjchu PX_ERPT_SEND_DEC(jbc_merge)
130927Sjchu {
131027Sjchu 	char		buf[FM_MAX_CLASS];
1311739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
131227Sjchu 
131327Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
131427Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
131527Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1316739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
131727Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
131827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
131927Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
132027Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
132127Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
132227Sjchu 	    ss_reg,
132327Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
132427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
132527Sjchu 	    FIRE_JBC_MTEL, DATA_TYPE_UINT64,
132627Sjchu 	    CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG),
132727Sjchu 	    NULL);
132827Sjchu 
132927Sjchu 	return (PX_OK);
133027Sjchu }
133127Sjchu 
133227Sjchu /*
133327Sjchu  * JBC Merge buffer nonfatal errors:
133427Sjchu  *    Merge buffer parity error (rd_buf): dma:read:M:nonfatal
133527Sjchu  *    Merge buffer parity error (wr_buf): dma:write:M:nonfatal
133627Sjchu  */
133727Sjchu /* ARGSUSED */
133827Sjchu int
133927Sjchu px_err_jbc_merge_handle(dev_info_t *rpdip, caddr_t csr_base,
134027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
134127Sjchu 	px_err_bit_desc_t *err_bit_descr)
134227Sjchu {
1343739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
134427Sjchu 	uint64_t	paddr;
134527Sjchu 	int		ret;
134627Sjchu 
1347739Sjchu 	if (!pri)
1348739Sjchu 		return (PX_FATAL_GOS);
1349739Sjchu 
135027Sjchu 	paddr = CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG);
135127Sjchu 	paddr &= MERGE_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
135227Sjchu 
135327Sjchu 	ret = px_handle_lookup(
135427Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
135527Sjchu 
135627Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
135727Sjchu }
135827Sjchu 
135927Sjchu /* JBC Jbusint IN - see io erpt doc, section 1.3 */
136027Sjchu PX_ERPT_SEND_DEC(jbc_in)
136127Sjchu {
136227Sjchu 	char		buf[FM_MAX_CLASS];
1363739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
136427Sjchu 
136527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
136627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
136727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1368739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
136927Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
137027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
137127Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
137227Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
137327Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
137427Sjchu 	    ss_reg,
137527Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
137627Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
137727Sjchu 	    FIRE_JBC_JITEL1, DATA_TYPE_UINT64,
137827Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG),
137927Sjchu 	    FIRE_JBC_JITEL2, DATA_TYPE_UINT64,
138027Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG_2),
138127Sjchu 	    NULL);
138227Sjchu 
138327Sjchu 	return (PX_OK);
138427Sjchu }
138527Sjchu 
138627Sjchu /*
138727Sjchu  * JBC Jbusint IN nonfatal errors: PA logged in Jbusint In Transaction Error
138827Sjchu  * Log Reg[42:0].
138927Sjchu  *     CE async fault error: nonfatal
139027Sjchu  *     Jbus bus error: dma::nonfatal
139127Sjchu  *     Jbus unmapped error: pio|dma:rdwr:M:nonfatal
139227Sjchu  *     Write data parity error: pio/write:M:nonfatal
139327Sjchu  *     Read data parity error: pio/read:M:nonfatal
139427Sjchu  *     Illegal NCWR bytemask: pio:write:M:nonfatal
139527Sjchu  *     Illegal NCRD bytemask: pio:write:M:nonfatal
139627Sjchu  *     Invalid jbus transaction: nonfatal
139727Sjchu  */
139827Sjchu /* ARGSUSED */
139927Sjchu int
140027Sjchu px_err_jbc_jbusint_in_handle(dev_info_t *rpdip, caddr_t csr_base,
140127Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
140227Sjchu 	px_err_bit_desc_t *err_bit_descr)
140327Sjchu {
1404739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
140527Sjchu 	uint64_t	paddr;
140627Sjchu 	int		ret;
140727Sjchu 
1408739Sjchu 	if (!pri)
1409739Sjchu 		return (PX_FATAL_GOS);
1410739Sjchu 
141127Sjchu 	paddr = CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG);
141227Sjchu 	paddr &= JBCINT_IN_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
141327Sjchu 
141427Sjchu 	ret = px_handle_lookup(
141527Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
141627Sjchu 
141727Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
141827Sjchu }
141927Sjchu 
142027Sjchu 
142127Sjchu /* JBC Jbusint Out - see io erpt doc, section 1.4 */
142227Sjchu PX_ERPT_SEND_DEC(jbc_out)
142327Sjchu {
142427Sjchu 	char		buf[FM_MAX_CLASS];
1425739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
142627Sjchu 
142727Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
142827Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
142927Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1430739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
143127Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
143227Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
143327Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
143427Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
143527Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
143627Sjchu 	    ss_reg,
143727Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
143827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
143927Sjchu 	    FIRE_JBC_JOTEL1, DATA_TYPE_UINT64,
144027Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG),
144127Sjchu 	    FIRE_JBC_JOTEL2, DATA_TYPE_UINT64,
144227Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG_2),
144327Sjchu 	    NULL);
144427Sjchu 
144527Sjchu 	return (PX_OK);
144627Sjchu }
144727Sjchu 
144827Sjchu /* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
144927Sjchu PX_ERPT_SEND_DEC(jbc_odcd)
145027Sjchu {
145127Sjchu 	char		buf[FM_MAX_CLASS];
1452739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
145327Sjchu 
145427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
145527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
145627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1457739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
145827Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
145927Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
146027Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
146127Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
146227Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
146327Sjchu 	    ss_reg,
146427Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
146527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
146627Sjchu 	    FIRE_JBC_DMC_ODCD, DATA_TYPE_UINT64,
146727Sjchu 	    CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG),
146827Sjchu 	    NULL);
146927Sjchu 
147027Sjchu 	return (PX_OK);
147127Sjchu }
147227Sjchu 
147327Sjchu /*
147427Sjchu  * JBC Dmcint ODCO nonfatal errer handling -
147527Sjchu  *    Unmapped PIO read error: pio:read:M:nonfatal
147627Sjchu  *    Unmapped PIO write error: pio:write:M:nonfatal
147727Sjchu  *    PIO data parity error: pio:write:M:nonfatal
147827Sjchu  *    Invalid PIO write to PCIe cfg/io, csr, ebus or i2c bus: pio:write:nonfatal
147927Sjchu  *    Invalid PIO read to PCIe cfg/io, csr, ebus or i2c bus: pio:read:nonfatal
148027Sjchu  */
148127Sjchu /* ARGSUSED */
148227Sjchu int
148327Sjchu px_err_jbc_dmcint_odcd_handle(dev_info_t *rpdip, caddr_t csr_base,
148427Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
148527Sjchu 	px_err_bit_desc_t *err_bit_descr)
148627Sjchu {
1487739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
148827Sjchu 	uint64_t	paddr;
148927Sjchu 	int		ret;
149027Sjchu 
1491739Sjchu 	if (!pri)
1492739Sjchu 		return (PX_FATAL_GOS);
1493739Sjchu 
149427Sjchu 	paddr = CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG);
149527Sjchu 	paddr &= DMCINT_ODCD_ERROR_LOG_ADDRESS_MASK;
149627Sjchu 
149727Sjchu 	ret = px_handle_lookup(
149827Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
149927Sjchu 
150027Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
150127Sjchu }
150227Sjchu 
150327Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
150427Sjchu PX_ERPT_SEND_DEC(jbc_idc)
150527Sjchu {
150627Sjchu 	char		buf[FM_MAX_CLASS];
1507739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
150827Sjchu 
150927Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
151027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
151127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1512739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
151327Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
151427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
151527Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
151627Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
151727Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
151827Sjchu 	    ss_reg,
151927Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
152027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
152127Sjchu 	    FIRE_JBC_DMC_IDC, DATA_TYPE_UINT64,
152227Sjchu 	    CSR_XR(csr_base, DMCINT_IDC_ERROR_LOG),
152327Sjchu 	    NULL);
152427Sjchu 
152527Sjchu 	return (PX_OK);
152627Sjchu }
152727Sjchu 
152827Sjchu /* JBC CSR - see io erpt doc, section 1.7 */
152927Sjchu PX_ERPT_SEND_DEC(jbc_csr)
153027Sjchu {
153127Sjchu 	char		buf[FM_MAX_CLASS];
1532739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
153327Sjchu 
153427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
153527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
153627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1537739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
153827Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
153927Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
154027Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
154127Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
154227Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
154327Sjchu 	    ss_reg,
154427Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
154527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
154627Sjchu 	    "jbc-error-reg", DATA_TYPE_UINT64,
154727Sjchu 	    CSR_XR(csr_base, CSR_ERROR_LOG),
154827Sjchu 	    NULL);
154927Sjchu 
155027Sjchu 	return (PX_OK);
155127Sjchu }
155227Sjchu 
155327Sjchu /*
155427Sjchu  * JBC CSR errer handling -
155527Sjchu  * Ebus ready timeout error: pio:rdwr:M:nonfatal
155627Sjchu  */
155727Sjchu /* ARGSUSED */
155827Sjchu int
155927Sjchu px_err_jbc_csr_handle(dev_info_t *rpdip, caddr_t csr_base,
156027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
156127Sjchu 	px_err_bit_desc_t *err_bit_descr)
156227Sjchu {
1563739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
156427Sjchu 	uint64_t	paddr;
156527Sjchu 	int		ret;
156627Sjchu 
1567739Sjchu 	if (!pri)
1568739Sjchu 		return (PX_FATAL_GOS);
1569739Sjchu 
157027Sjchu 	paddr = CSR_XR(csr_base, CSR_ERROR_LOG);
157127Sjchu 	paddr &= CSR_ERROR_LOG_ADDRESS_MASK;
157227Sjchu 
157327Sjchu 	ret = px_handle_lookup(
157427Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
157527Sjchu 
157627Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
157727Sjchu }
157827Sjchu 
157927Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
158027Sjchu 
158127Sjchu /* DMC IMU RDS - see io erpt doc, section 2.1 */
158227Sjchu PX_ERPT_SEND_DEC(imu_rds)
158327Sjchu {
158427Sjchu 	char		buf[FM_MAX_CLASS];
1585739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
158627Sjchu 
158727Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
158827Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
158927Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1590739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
159127Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
159227Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
159327Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
159427Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
159527Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
159627Sjchu 	    ss_reg,
159727Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
159827Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
159927Sjchu 	    FIRE_IMU_RDS, DATA_TYPE_UINT64,
160027Sjchu 	    CSR_XR(csr_base, IMU_RDS_ERROR_LOG),
160127Sjchu 	    NULL);
160227Sjchu 
160327Sjchu 	return (PX_OK);
160427Sjchu }
160527Sjchu 
160627Sjchu /* imu function to handle all Received but Not Enabled errors */
160727Sjchu /* ARGSUSED */
160827Sjchu int
160927Sjchu px_err_imu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
161027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
161127Sjchu 	px_err_bit_desc_t *err_bit_descr)
161227Sjchu {
161327Sjchu 	uint64_t	imu_log_enable, imu_intr_enable;
161427Sjchu 	int		mask = BITMASK(err_bit_descr->bit);
161527Sjchu 	int		err = PX_NONFATAL;
161627Sjchu 
161727Sjchu 	imu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
161827Sjchu 	imu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
161927Sjchu 
1620435Sjchu 	/*
1621435Sjchu 	 * If matching bit is not set, meaning corresponding rbne not
1622435Sjchu 	 * enabled, then receiving it indicates some sort of malfunction
1623435Sjchu 	 * possibly in hardware.
1624435Sjchu 	 *
1625435Sjchu 	 * Other wise, software may have intentionally disabled certain
1626435Sjchu 	 * errors for a period of time within which the occuring of the
1627435Sjchu 	 * disabled errors become rbne, that is non fatal.
1628435Sjchu 	 */
1629*1772Sjl139090 
1630435Sjchu 	if (!(imu_log_enable & imu_intr_enable & mask))
163127Sjchu 		err = PX_FATAL_SW;
163227Sjchu 
163327Sjchu 	return (err);
163427Sjchu }
163527Sjchu 
1636118Sjchu /*
1637118Sjchu  * No platforms uses PME. Any PME received is simply logged
1638118Sjchu  * for analysis.
1639118Sjchu  */
1640118Sjchu /* ARGSUSED */
1641118Sjchu int
1642118Sjchu px_err_imu_pme_handle(dev_info_t *rpdip, caddr_t csr_base,
1643118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1644118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1645118Sjchu {
1646118Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
1647118Sjchu 
1648118Sjchu 	px_p->px_pme_ignored++;
1649118Sjchu 	return (PX_NONFATAL);
1650118Sjchu }
1651118Sjchu 
165227Sjchu /* handle EQ overflow */
165327Sjchu /* ARGSUSED */
165427Sjchu int
165527Sjchu px_err_imu_eq_ovfl_handle(dev_info_t *rpdip, caddr_t csr_base,
165627Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
165727Sjchu 	px_err_bit_desc_t *err_bit_descr)
165827Sjchu {
165927Sjchu 	px_t			*px_p = DIP_TO_STATE(rpdip);
166027Sjchu 	px_msiq_state_t 	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
166127Sjchu 	msiqid_t		eqno;
166227Sjchu 	pci_msiq_state_t	msiq_state;
166327Sjchu 	int			err = PX_NONFATAL;
166427Sjchu 	int			i;
166527Sjchu 
166627Sjchu 	eqno = msiq_state_p->msiq_1st_msiq_id;
166727Sjchu 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
166827Sjchu 		if (px_lib_msiq_getstate(rpdip, eqno, &msiq_state) ==
166927Sjchu 			DDI_SUCCESS) {
167027Sjchu 			if (msiq_state == PCI_MSIQ_STATE_ERROR) {
167127Sjchu 				err = PX_FATAL_SW;
167227Sjchu 			}
167327Sjchu 		}
167427Sjchu 	}
167527Sjchu 
167627Sjchu 	return (err);
167727Sjchu }
167827Sjchu 
167927Sjchu /* DMC IMU SCS - see io erpt doc, section 2.2 */
168027Sjchu PX_ERPT_SEND_DEC(imu_scs)
168127Sjchu {
168227Sjchu 	char		buf[FM_MAX_CLASS];
1683739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
168427Sjchu 
168527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
168627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
168727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1688739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
168927Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
169027Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
169127Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
169227Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
169327Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
169427Sjchu 	    ss_reg,
169527Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
169627Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
169727Sjchu 	    FIRE_IMU_SCS, DATA_TYPE_UINT64,
169827Sjchu 	    CSR_XR(csr_base, IMU_SCS_ERROR_LOG),
169927Sjchu 	    NULL);
170027Sjchu 
170127Sjchu 	return (PX_OK);
170227Sjchu }
170327Sjchu 
170427Sjchu /* DMC IMU - see io erpt doc, section 2.3 */
170527Sjchu PX_ERPT_SEND_DEC(imu)
170627Sjchu {
170727Sjchu 	char		buf[FM_MAX_CLASS];
1708739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
170927Sjchu 
171027Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
171127Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
171227Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1713739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
171427Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
171527Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
171627Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
171727Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
171827Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
171927Sjchu 	    ss_reg,
172027Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
172127Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
172227Sjchu 	    NULL);
172327Sjchu 
172427Sjchu 	return (PX_OK);
172527Sjchu }
172627Sjchu 
172727Sjchu /* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
172827Sjchu PX_ERPT_SEND_DEC(mmu_tfar_tfsr)
172927Sjchu {
173027Sjchu 	char		buf[FM_MAX_CLASS];
1731739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
173227Sjchu 
173327Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1734*1772Sjl139090 
173527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
173627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1737739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
173827Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
173927Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
174027Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
174127Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
174227Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
174327Sjchu 	    ss_reg,
174427Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
174527Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
174627Sjchu 	    FIRE_MMU_TFAR, DATA_TYPE_UINT64,
174727Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS),
174827Sjchu 	    FIRE_MMU_TFSR, DATA_TYPE_UINT64,
174927Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_STATUS),
175027Sjchu 	    NULL);
175127Sjchu 
175227Sjchu 	return (PX_OK);
175327Sjchu }
175427Sjchu 
175527Sjchu /* DMC MMU - see io erpt doc, section 2.5 */
175627Sjchu PX_ERPT_SEND_DEC(mmu)
175727Sjchu {
175827Sjchu 	char		buf[FM_MAX_CLASS];
1759739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
176027Sjchu 
176127Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
176227Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
176327Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1764739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
176527Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
176627Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
176727Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
176827Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
176927Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
177027Sjchu 	    ss_reg,
177127Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
177227Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
177327Sjchu 	    NULL);
177427Sjchu 
177527Sjchu 	return (PX_OK);
177627Sjchu }
177727Sjchu 
177827Sjchu /* imu function to handle all Received but Not Enabled errors */
177927Sjchu int
178027Sjchu px_err_mmu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
178127Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
178227Sjchu 	px_err_bit_desc_t *err_bit_descr)
178327Sjchu {
1784739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
1785260Set142600 	uint64_t	mmu_log_enable, mmu_intr_enable;
178627Sjchu 	uint64_t	mask = BITMASK(err_bit_descr->bit);
1787260Set142600 	uint64_t	mmu_tfa, mmu_ctrl;
1788260Set142600 	uint64_t	mmu_enable_bit = 0;
178927Sjchu 	int		err = PX_NONFATAL;
179027Sjchu 	int		ret;
179127Sjchu 
179227Sjchu 	mmu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
179327Sjchu 	mmu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
179427Sjchu 
179527Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
1796260Set142600 	mmu_ctrl = CSR_XR(csr_base, MMU_CONTROL_AND_STATUS);
179727Sjchu 
1798260Set142600 	switch (err_bit_descr->bit) {
1799260Set142600 	case MMU_INTERRUPT_STATUS_BYP_ERR_P:
1800260Set142600 		mmu_enable_bit = BITMASK(MMU_CONTROL_AND_STATUS_BE);
1801260Set142600 		break;
1802260Set142600 	case MMU_INTERRUPT_STATUS_TRN_ERR_P:
1803260Set142600 		mmu_enable_bit = BITMASK(MMU_CONTROL_AND_STATUS_TE);
1804260Set142600 		break;
1805260Set142600 	default:
1806260Set142600 		mmu_enable_bit = 0;
1807260Set142600 		break;
1808260Set142600 	}
1809260Set142600 
1810260Set142600 	/*
1811260Set142600 	 * If the interrupts are enabled and Translation/Bypass Enable bit
1812260Set142600 	 * was set, then panic.  This error should not have occured.
1813260Set142600 	 */
1814260Set142600 	if (mmu_log_enable & mmu_intr_enable &
1815260Set142600 	    (mmu_ctrl & mmu_enable_bit)) {
181627Sjchu 		err = PX_FATAL_SW;
181727Sjchu 	} else {
1818739Sjchu 		if (!pri)
1819739Sjchu 			return (PX_FATAL_GOS);
1820739Sjchu 
182127Sjchu 		ret = px_handle_lookup(
182227Sjchu 			rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
182327Sjchu 		err = (ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL;
182427Sjchu 
182527Sjchu 		/*
182627Sjchu 		 * S/W bug - this error should always be enabled
182727Sjchu 		 */
182827Sjchu 
182927Sjchu 		/* enable error & intr reporting for this bit */
183027Sjchu 		CSR_XS(csr_base, MMU_ERROR_LOG_ENABLE, mmu_log_enable | mask);
183127Sjchu 		CSR_XS(csr_base, MMU_INTERRUPT_ENABLE, mmu_intr_enable | mask);
1832260Set142600 
1833260Set142600 		/* enable translation access/bypass enable */
1834260Set142600 		CSR_XS(csr_base, MMU_CONTROL_AND_STATUS,
1835260Set142600 		    mmu_ctrl | mmu_enable_bit);
183627Sjchu 	}
183727Sjchu 
183827Sjchu 	return (err);
183927Sjchu }
184027Sjchu 
184127Sjchu /* Generic error handling functions that involve MMU Translation Fault Addr */
184227Sjchu /* ARGSUSED */
184327Sjchu int
184427Sjchu px_err_mmu_tfa_handle(dev_info_t *rpdip, caddr_t csr_base,
184527Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
184627Sjchu 	px_err_bit_desc_t *err_bit_descr)
184727Sjchu {
1848739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
184927Sjchu 	uint64_t	mmu_tfa;
185027Sjchu 	uint_t		ret;
185127Sjchu 
1852739Sjchu 	if (!pri)
1853739Sjchu 		return (PX_FATAL_GOS);
1854739Sjchu 
185527Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
185627Sjchu 	ret = px_handle_lookup(
185727Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
185827Sjchu 
185927Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
186027Sjchu }
186127Sjchu 
186227Sjchu /* MMU Table walk errors */
186327Sjchu /* ARGSUSED */
186427Sjchu int
186527Sjchu px_err_mmu_tblwlk_handle(dev_info_t *rpdip, caddr_t csr_base,
186627Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
186727Sjchu 	px_err_bit_desc_t *err_bit_descr)
186827Sjchu {
1869739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
187027Sjchu 	uint64_t	mmu_tfa;
187127Sjchu 	uint_t		ret;
187227Sjchu 
1873739Sjchu 	if (!pri)
1874739Sjchu 		return (PX_FATAL_GOS);
1875739Sjchu 
187627Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
187727Sjchu 	ret = px_handle_lookup(
187827Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
187927Sjchu 
188027Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
188127Sjchu }
188227Sjchu 
1883118Sjchu /*
18841147Sjchu  * TLU LUP event - if caused by power management activity, then it is expected.
18851147Sjchu  * In all other cases, it is an error.
1886118Sjchu  */
1887118Sjchu /* ARGSUSED */
1888118Sjchu int
1889118Sjchu px_err_tlu_lup_handle(dev_info_t *rpdip, caddr_t csr_base,
1890118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1891118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1892118Sjchu {
1893118Sjchu 	px_t	*px_p = DIP_TO_STATE(rpdip);
1894118Sjchu 
1895118Sjchu 	/*
18961147Sjchu 	 * power management code is currently the only segment that sets
18971147Sjchu 	 * px_lup_pending to indicate its expectation for a healthy LUP
18981147Sjchu 	 * event.  For all other occasions, LUP event should be flaged as
18991147Sjchu 	 * error condition.
1900118Sjchu 	 */
19011147Sjchu 	return ((atomic_cas_32(&px_p->px_lup_pending, 1, 0) == 0) ?
19021147Sjchu 	    PX_NONFATAL : PX_OK);
19031147Sjchu }
1904118Sjchu 
19051147Sjchu /*
19061147Sjchu  * TLU LDN event - if caused by power management activity, then it is expected.
19071147Sjchu  * In all other cases, it is an error.
19081147Sjchu  */
19091147Sjchu /* ARGSUSED */
19101147Sjchu int
19111147Sjchu px_err_tlu_ldn_handle(dev_info_t *rpdip, caddr_t csr_base,
19121147Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
19131147Sjchu 	px_err_bit_desc_t *err_bit_descr)
19141147Sjchu {
19151147Sjchu 	px_t    *px_p = DIP_TO_STATE(rpdip);
19161147Sjchu 	return ((px_p->px_pm_flags & PX_LDN_EXPECTED) ? PX_OK : PX_NONFATAL);
1917118Sjchu }
1918118Sjchu 
191927Sjchu /* PEC ILU none - see io erpt doc, section 3.1 */
192027Sjchu PX_ERPT_SEND_DEC(pec_ilu)
192127Sjchu {
192227Sjchu 	char		buf[FM_MAX_CLASS];
1923739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
192427Sjchu 
192527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
192627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
192727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1928739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
192927Sjchu 	    FIRE_ILU_ELE, DATA_TYPE_UINT64,
193027Sjchu 	    CSR_XR(csr_base, ILU_ERROR_LOG_ENABLE),
193127Sjchu 	    FIRE_ILU_IE, DATA_TYPE_UINT64,
193227Sjchu 	    CSR_XR(csr_base, ILU_INTERRUPT_ENABLE),
193327Sjchu 	    FIRE_ILU_IS, DATA_TYPE_UINT64,
193427Sjchu 	    ss_reg,
193527Sjchu 	    FIRE_ILU_ESS, DATA_TYPE_UINT64,
193627Sjchu 	    CSR_XR(csr_base, ILU_ERROR_STATUS_SET),
193727Sjchu 	    NULL);
193827Sjchu 
193927Sjchu 	return (PX_OK);
194027Sjchu }
194127Sjchu 
1942383Set142600 /* PCIEX UE Errors */
1943383Set142600 /* ARGSUSED */
1944671Skrishnae int
1945383Set142600 px_err_pciex_ue_handle(dev_info_t *rpdip, caddr_t csr_base,
1946383Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1947383Set142600 	px_err_bit_desc_t *err_bit_descr)
1948383Set142600 {
1949383Set142600 	uint32_t	mask = (uint32_t)BITMASK(err_bit_descr->bit);
1950383Set142600 
1951383Set142600 	return ((err_bit_descr->bit >= 32 && px_fabric_die_rc_ue_gos) ?
1952383Set142600 	    PX_FATAL_GOS : PX_FABRIC_ERR_SEV(mask, px_fabric_die_rc_ue,
1953383Set142600 		px_fabric_die_rc_ue_gos));
1954383Set142600 }
1955383Set142600 
1956383Set142600 /* PCI-E Uncorrectable Errors - see io erpt doc, section 3.2 */
1957383Set142600 PX_ERPT_SEND_DEC(pciex_rx_ue)
1958383Set142600 {
1959383Set142600 	char		buf[FM_MAX_CLASS];
1960739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
1961383Set142600 
1962383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1963383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1964383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1965739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
1966383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
1967383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
1968383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
1969383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
1970383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
1971383Set142600 	    ss_reg,
1972383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
1973383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
1974383Set142600 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
1975383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG),
1976383Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
1977383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG),
1978383Set142600 	    NULL);
1979383Set142600 
1980383Set142600 	return (PX_OK);
1981383Set142600 }
1982383Set142600 
1983383Set142600 /* PCI-E Uncorrectable Errors - see io erpt doc, section 3.3 */
1984383Set142600 PX_ERPT_SEND_DEC(pciex_tx_ue)
1985383Set142600 {
1986383Set142600 	char		buf[FM_MAX_CLASS];
1987739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
1988383Set142600 
1989383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
1990383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
1991383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1992739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
1993383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
1994383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
1995383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
1996383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
1997383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
1998383Set142600 	    ss_reg,
1999383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2000383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2001383Set142600 	    FIRE_TLU_TUEH1L, DATA_TYPE_UINT64,
2002383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG),
2003383Set142600 	    FIRE_TLU_TUEH2L, DATA_TYPE_UINT64,
2004383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG),
2005383Set142600 	    NULL);
2006383Set142600 
2007383Set142600 	return (PX_OK);
2008383Set142600 }
2009383Set142600 
2010383Set142600 /* PCI-E Uncorrectable Errors - see io erpt doc, section 3.4 */
2011383Set142600 PX_ERPT_SEND_DEC(pciex_rx_tx_ue)
2012383Set142600 {
2013383Set142600 	char		buf[FM_MAX_CLASS];
2014739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
2015383Set142600 
2016383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
2017383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
2018383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2019739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
2020383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
2021383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
2022383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
2023383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
2024383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
2025383Set142600 	    ss_reg,
2026383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2027383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2028383Set142600 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
2029383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG),
2030383Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
2031383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG),
2032383Set142600 	    FIRE_TLU_TUEH1L, DATA_TYPE_UINT64,
2033383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG),
2034383Set142600 	    FIRE_TLU_TUEH2L, DATA_TYPE_UINT64,
2035383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG),
2036383Set142600 	    NULL);
2037383Set142600 
2038383Set142600 	return (PX_OK);
2039383Set142600 }
2040383Set142600 
2041383Set142600 /* PCI-E Uncorrectable Errors - see io erpt doc, section 3.5 */
2042383Set142600 PX_ERPT_SEND_DEC(pciex_ue)
2043383Set142600 {
2044383Set142600 	char		buf[FM_MAX_CLASS];
2045739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
2046383Set142600 
2047383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
2048383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
2049383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2050739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
2051383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
2052383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
2053383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
2054383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
2055383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
2056383Set142600 	    ss_reg,
2057383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2058383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2059383Set142600 	    NULL);
2060383Set142600 
2061383Set142600 	return (PX_OK);
2062383Set142600 }
2063383Set142600 
2064383Set142600 /* PCIEX UE Errors */
2065383Set142600 /* ARGSUSED */
2066671Skrishnae int
2067383Set142600 px_err_pciex_ce_handle(dev_info_t *rpdip, caddr_t csr_base,
2068383Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
2069383Set142600 	px_err_bit_desc_t *err_bit_descr)
2070383Set142600 {
2071383Set142600 	uint32_t	mask = (uint32_t)BITMASK(err_bit_descr->bit);
2072383Set142600 
2073383Set142600 	return ((err_bit_descr->bit >= 32 && px_fabric_die_rc_ce_gos) ?
2074383Set142600 	    PX_FATAL_GOS : PX_FABRIC_ERR_SEV(mask, px_fabric_die_rc_ce,
2075383Set142600 		px_fabric_die_rc_ce_gos));
2076383Set142600 }
2077383Set142600 
207827Sjchu /* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
207927Sjchu PX_ERPT_SEND_DEC(pciex_ce)
208027Sjchu {
208127Sjchu 	char		buf[FM_MAX_CLASS];
2082739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
208327Sjchu 
208427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
208527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
208627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2087739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
208827Sjchu 	    FIRE_TLU_CELE, DATA_TYPE_UINT64,
208927Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE),
209027Sjchu 	    FIRE_TLU_CIE, DATA_TYPE_UINT64,
209127Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE),
209227Sjchu 	    FIRE_TLU_CIS, DATA_TYPE_UINT64,
209327Sjchu 	    ss_reg,
209427Sjchu 	    FIRE_TLU_CESS, DATA_TYPE_UINT64,
209527Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_STATUS_SET),
209627Sjchu 	    NULL);
209727Sjchu 
209827Sjchu 	return (PX_OK);
209927Sjchu }
210027Sjchu 
210127Sjchu /* TLU Other Event Status (receive only) - see io erpt doc, section 3.7 */
210227Sjchu PX_ERPT_SEND_DEC(pciex_rx_oe)
210327Sjchu {
210427Sjchu 	char		buf[FM_MAX_CLASS];
2105739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
210627Sjchu 
210727Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
210827Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
210927Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2110739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
211127Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
211227Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
211327Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
211427Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
211527Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
211627Sjchu 	    ss_reg,
211727Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
211827Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
211927Sjchu 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
212027Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
2121260Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
212227Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
212327Sjchu 	    NULL);
212427Sjchu 
212527Sjchu 	return (PX_OK);
212627Sjchu }
212727Sjchu 
212827Sjchu /* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
212927Sjchu PX_ERPT_SEND_DEC(pciex_rx_tx_oe)
213027Sjchu {
213127Sjchu 	char		buf[FM_MAX_CLASS];
2132739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
213327Sjchu 
213427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
213527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
213627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2137739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
213827Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
213927Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
214027Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
214127Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
214227Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
214327Sjchu 	    ss_reg,
214427Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
214527Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
214627Sjchu 	    FIRE_TLU_ROEEH1L, DATA_TYPE_UINT64,
214727Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
214827Sjchu 	    FIRE_TLU_ROEEH2L, DATA_TYPE_UINT64,
214927Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
215027Sjchu 	    FIRE_TLU_TOEEH1L, DATA_TYPE_UINT64,
215127Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG),
2152260Set142600 	    FIRE_TLU_TOEEH2L, DATA_TYPE_UINT64,
215327Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG),
215427Sjchu 	    NULL);
215527Sjchu 
215627Sjchu 	return (PX_OK);
215727Sjchu }
215827Sjchu 
215927Sjchu /* TLU Other Event - see io erpt doc, section 3.9 */
216027Sjchu PX_ERPT_SEND_DEC(pciex_oe)
216127Sjchu {
2162739Sjchu 	char		buf[FM_MAX_CLASS];
2163739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
216427Sjchu 
216527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
216627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
216727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2168739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
216927Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
217027Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
217127Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
217227Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
217327Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
217427Sjchu 	    ss_reg,
217527Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
217627Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
217727Sjchu 	    NULL);
217827Sjchu 
217927Sjchu 	return (PX_OK);
218027Sjchu }
2181