xref: /onnv-gate/usr/src/uts/sun4u/io/px/px_err.c (revision 11654:f27a426bf21b)
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  */
2111311SSurya.Prakki@Sun.COM 
2227Sjchu /*
23*11654SKrishna.Elango@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2427Sjchu  * Use is subject to license terms.
2527Sjchu  */
2627Sjchu 
2727Sjchu /*
2827Sjchu  * sun4u Fire Error Handling
2927Sjchu  */
3027Sjchu 
3127Sjchu #include <sys/types.h>
3227Sjchu #include <sys/ddi.h>
3327Sjchu #include <sys/sunddi.h>
346313Skrishnae #include <sys/sunndi.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>
431772Sjl139090 #include <sys/machcpuvar.h>
441772Sjl139090 #include <sys/platform_module.h>
4527Sjchu #include "px_lib4u.h"
4627Sjchu #include "px_err.h"
4727Sjchu #include "px_err_impl.h"
481772Sjl139090 #include "oberon_regs.h"
491772Sjl139090 
501772Sjl139090 uint64_t px_tlu_ue_intr_mask	= PX_ERR_EN_ALL;
511772Sjl139090 uint64_t px_tlu_ue_log_mask	= PX_ERR_EN_ALL;
521772Sjl139090 uint64_t px_tlu_ue_count_mask	= PX_ERR_EN_ALL;
531772Sjl139090 
541772Sjl139090 uint64_t px_tlu_ce_intr_mask	= PX_ERR_MASK_NONE;
551772Sjl139090 uint64_t px_tlu_ce_log_mask	= PX_ERR_MASK_NONE;
561772Sjl139090 uint64_t px_tlu_ce_count_mask	= PX_ERR_MASK_NONE;
571772Sjl139090 
581772Sjl139090 /*
591772Sjl139090  * Do not enable Link Interrupts
601772Sjl139090  */
611772Sjl139090 uint64_t px_tlu_oe_intr_mask	= PX_ERR_EN_ALL & ~0x80000000800;
621772Sjl139090 uint64_t px_tlu_oe_log_mask	= PX_ERR_EN_ALL & ~0x80000000800;
631772Sjl139090 uint64_t px_tlu_oe_count_mask	= PX_ERR_EN_ALL;
641772Sjl139090 
651772Sjl139090 uint64_t px_mmu_intr_mask	= PX_ERR_EN_ALL;
661772Sjl139090 uint64_t px_mmu_log_mask	= PX_ERR_EN_ALL;
671772Sjl139090 uint64_t px_mmu_count_mask	= PX_ERR_EN_ALL;
681772Sjl139090 
691772Sjl139090 uint64_t px_imu_intr_mask	= PX_ERR_EN_ALL;
701772Sjl139090 uint64_t px_imu_log_mask	= PX_ERR_EN_ALL;
711772Sjl139090 uint64_t px_imu_count_mask	= PX_ERR_EN_ALL;
721772Sjl139090 
731772Sjl139090 /*
741772Sjl139090  * (1ull << ILU_INTERRUPT_ENABLE_IHB_PE_S) |
751772Sjl139090  * (1ull << ILU_INTERRUPT_ENABLE_IHB_PE_P);
761772Sjl139090  */
771772Sjl139090 uint64_t px_ilu_intr_mask	= (((uint64_t)0x10 << 32) | 0x10);
781772Sjl139090 uint64_t px_ilu_log_mask	= (((uint64_t)0x10 << 32) | 0x10);
791772Sjl139090 uint64_t px_ilu_count_mask	= PX_ERR_EN_ALL;
801772Sjl139090 
811772Sjl139090 uint64_t px_ubc_intr_mask	= PX_ERR_EN_ALL;
821772Sjl139090 uint64_t px_ubc_log_mask		= PX_ERR_EN_ALL;
831772Sjl139090 uint64_t px_ubc_count_mask	= PX_ERR_EN_ALL;
841772Sjl139090 
851772Sjl139090 uint64_t px_jbc_intr_mask	= PX_ERR_EN_ALL;
861772Sjl139090 uint64_t px_jbc_log_mask		= PX_ERR_EN_ALL;
871772Sjl139090 uint64_t px_jbc_count_mask	= PX_ERR_EN_ALL;
881772Sjl139090 
891772Sjl139090 /*
901772Sjl139090  * LPU Intr Registers are reverse encoding from the registers above.
911772Sjl139090  * 1 = disable
921772Sjl139090  * 0 = enable
931772Sjl139090  *
941772Sjl139090  * Log and Count are however still the same.
951772Sjl139090  */
961772Sjl139090 uint64_t px_lpul_intr_mask	= LPU_INTR_DISABLE;
971772Sjl139090 uint64_t px_lpul_log_mask	= PX_ERR_EN_ALL;
981772Sjl139090 uint64_t px_lpul_count_mask	= PX_ERR_EN_ALL;
991772Sjl139090 
1001772Sjl139090 uint64_t px_lpup_intr_mask	= LPU_INTR_DISABLE;
1011772Sjl139090 uint64_t px_lpup_log_mask	= PX_ERR_EN_ALL;
1021772Sjl139090 uint64_t px_lpup_count_mask	= PX_ERR_EN_ALL;
1031772Sjl139090 
1041772Sjl139090 uint64_t px_lpur_intr_mask	= LPU_INTR_DISABLE;
1051772Sjl139090 uint64_t px_lpur_log_mask	= PX_ERR_EN_ALL;
1061772Sjl139090 uint64_t px_lpur_count_mask	= PX_ERR_EN_ALL;
1071772Sjl139090 
1081772Sjl139090 uint64_t px_lpux_intr_mask	= LPU_INTR_DISABLE;
1091772Sjl139090 uint64_t px_lpux_log_mask	= PX_ERR_EN_ALL;
1101772Sjl139090 uint64_t px_lpux_count_mask	= PX_ERR_EN_ALL;
1111772Sjl139090 
1121772Sjl139090 uint64_t px_lpus_intr_mask	= LPU_INTR_DISABLE;
1131772Sjl139090 uint64_t px_lpus_log_mask	= PX_ERR_EN_ALL;
1141772Sjl139090 uint64_t px_lpus_count_mask	= PX_ERR_EN_ALL;
1151772Sjl139090 
1161772Sjl139090 uint64_t px_lpug_intr_mask	= LPU_INTR_DISABLE;
1171772Sjl139090 uint64_t px_lpug_log_mask	= PX_ERR_EN_ALL;
1181772Sjl139090 uint64_t px_lpug_count_mask	= PX_ERR_EN_ALL;
11927Sjchu 
12027Sjchu /*
12127Sjchu  * JBC error bit table
12227Sjchu  */
12327Sjchu #define	JBC_BIT_DESC(bit, hdl, erpt) \
12427Sjchu 	JBC_INTERRUPT_STATUS_ ## bit ## _P, \
12527Sjchu 	0, \
12627Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
12727Sjchu 	PX_ERPT_SEND(erpt), \
128739Sjchu 	PX_ERR_JBC_CLASS(bit) }, \
129739Sjchu 	{ JBC_INTERRUPT_STATUS_ ## bit ## _S, \
130739Sjchu 	0, \
131739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
132739Sjchu 	PX_ERPT_SEND(erpt), \
13327Sjchu 	PX_ERR_JBC_CLASS(bit)
1341772Sjl139090 px_err_bit_desc_t px_err_jbc_tbl[] = {
1353274Set142600 	/* JBC FATAL */
1363274Set142600 	{ JBC_BIT_DESC(MB_PEA,	hw_reset,	jbc_fatal) },
1373274Set142600 	{ JBC_BIT_DESC(CPE,	hw_reset,	jbc_fatal) },
1383274Set142600 	{ JBC_BIT_DESC(APE,	hw_reset,	jbc_fatal) },
1393274Set142600 	{ JBC_BIT_DESC(PIO_CPE,	hw_reset,	jbc_fatal) },
1403274Set142600 	{ JBC_BIT_DESC(JTCEEW,	hw_reset,	jbc_fatal) },
1413274Set142600 	{ JBC_BIT_DESC(JTCEEI,	hw_reset,	jbc_fatal) },
1423274Set142600 	{ JBC_BIT_DESC(JTCEER,	hw_reset,	jbc_fatal) },
14327Sjchu 
1443274Set142600 	/* JBC MERGE */
14527Sjchu 	{ JBC_BIT_DESC(MB_PER,	jbc_merge,	jbc_merge) },
14627Sjchu 	{ JBC_BIT_DESC(MB_PEW,	jbc_merge,	jbc_merge) },
14727Sjchu 
1483274Set142600 	/* JBC Jbusint IN */
1493274Set142600 	{ JBC_BIT_DESC(UE_ASYN,	panic,		jbc_in) },
1503274Set142600 	{ JBC_BIT_DESC(CE_ASYN,	no_error,	jbc_in) },
1513274Set142600 	{ JBC_BIT_DESC(JTE,	panic,		jbc_in) },
1523274Set142600 	{ JBC_BIT_DESC(JBE,	panic,		jbc_in) },
1533274Set142600 	{ JBC_BIT_DESC(JUE,	panic,		jbc_in) },
1543274Set142600 	{ JBC_BIT_DESC(ICISE,	panic,		jbc_in) },
15527Sjchu 	{ JBC_BIT_DESC(WR_DPE,	jbc_jbusint_in,	jbc_in) },
15627Sjchu 	{ JBC_BIT_DESC(RD_DPE,	jbc_jbusint_in,	jbc_in) },
1573274Set142600 	{ JBC_BIT_DESC(ILL_BMW,	panic,		jbc_in) },
1583274Set142600 	{ JBC_BIT_DESC(ILL_BMR,	panic,		jbc_in) },
1593274Set142600 	{ JBC_BIT_DESC(BJC,	panic,		jbc_in) },
16027Sjchu 
1613274Set142600 	/* JBC Jbusint Out */
1623274Set142600 	{ JBC_BIT_DESC(IJP,	panic,		jbc_out) },
16327Sjchu 
1642276Sschwartz 	/*
1653274Set142600 	 * JBC Dmcint ODCD
1662276Sschwartz 	 *
1672276Sschwartz 	 * Error bits which can be set via a bad PCItool access go through
1682276Sschwartz 	 * jbc_safe_acc instead.
1692276Sschwartz 	 */
1702276Sschwartz 	{ JBC_BIT_DESC(PIO_UNMAP_RD,	jbc_safe_acc,		jbc_odcd) },
1712276Sschwartz 	{ JBC_BIT_DESC(ILL_ACC_RD,	jbc_safe_acc,		jbc_odcd) },
1722276Sschwartz 	{ JBC_BIT_DESC(PIO_UNMAP,	jbc_safe_acc,		jbc_odcd) },
17327Sjchu 	{ JBC_BIT_DESC(PIO_DPE,		jbc_dmcint_odcd,	jbc_odcd) },
1743274Set142600 	{ JBC_BIT_DESC(PIO_CPE,		hw_reset,		jbc_odcd) },
1752276Sschwartz 	{ JBC_BIT_DESC(ILL_ACC,		jbc_safe_acc,		jbc_odcd) },
17627Sjchu 
1773274Set142600 	/* JBC Dmcint IDC */
1783274Set142600 	{ JBC_BIT_DESC(UNSOL_RD,	no_panic,	jbc_idc) },
1793274Set142600 	{ JBC_BIT_DESC(UNSOL_INTR,	no_panic,	jbc_idc) },
18027Sjchu 
1813274Set142600 	/* JBC CSR */
1823274Set142600 	{ JBC_BIT_DESC(EBUS_TO,		panic,		jbc_csr) }
18327Sjchu };
18427Sjchu 
1851772Sjl139090 #define	px_err_jbc_keys \
1861772Sjl139090 	(sizeof (px_err_jbc_tbl)) / (sizeof (px_err_bit_desc_t))
1871772Sjl139090 
1881772Sjl139090 /*
1891772Sjl139090  * UBC error bit table
1901772Sjl139090  */
1911772Sjl139090 #define	UBC_BIT_DESC(bit, hdl, erpt) \
1921772Sjl139090 	UBC_INTERRUPT_STATUS_ ## bit ## _P, \
1931772Sjl139090 	0, \
1941772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
1951772Sjl139090 	PX_ERPT_SEND(erpt), \
1961772Sjl139090 	PX_ERR_UBC_CLASS(bit) }, \
1971772Sjl139090 	{ UBC_INTERRUPT_STATUS_ ## bit ## _S, \
1981772Sjl139090 	0, \
1991772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
2001772Sjl139090 	PX_ERPT_SEND(erpt), \
2011772Sjl139090 	PX_ERR_UBC_CLASS(bit)
2021772Sjl139090 px_err_bit_desc_t px_err_ubc_tbl[] = {
2031772Sjl139090 	/* UBC FATAL  */
2043274Set142600 	{ UBC_BIT_DESC(DMARDUEA,	no_panic,	ubc_fatal) },
2053274Set142600 	{ UBC_BIT_DESC(DMAWTUEA,	panic,		ubc_fatal) },
2063274Set142600 	{ UBC_BIT_DESC(MEMRDAXA,	panic,		ubc_fatal) },
2073274Set142600 	{ UBC_BIT_DESC(MEMWTAXA,	panic,		ubc_fatal) },
2083274Set142600 	{ UBC_BIT_DESC(DMARDUEB,	no_panic,	ubc_fatal) },
2093274Set142600 	{ UBC_BIT_DESC(DMAWTUEB,	panic,		ubc_fatal) },
2103274Set142600 	{ UBC_BIT_DESC(MEMRDAXB,	panic,		ubc_fatal) },
2113274Set142600 	{ UBC_BIT_DESC(MEMWTAXB,	panic,		ubc_fatal) },
2123274Set142600 	{ UBC_BIT_DESC(PIOWTUE,		panic,		ubc_fatal) },
2133274Set142600 	{ UBC_BIT_DESC(PIOWBEUE,	panic,		ubc_fatal) },
2143274Set142600 	{ UBC_BIT_DESC(PIORBEUE,	panic,		ubc_fatal) }
2151772Sjl139090 };
2161772Sjl139090 
2171772Sjl139090 #define	px_err_ubc_keys \
2181772Sjl139090 	(sizeof (px_err_ubc_tbl)) / (sizeof (px_err_bit_desc_t))
2191772Sjl139090 
2201772Sjl139090 
2211772Sjl139090 char *ubc_class_eid_qualifier[] = {
2221772Sjl139090 	"-mem",
2231772Sjl139090 	"-channel",
2241772Sjl139090 	"-cpu",
2251772Sjl139090 	"-path"
2261772Sjl139090 };
2271772Sjl139090 
22827Sjchu 
22927Sjchu /*
23027Sjchu  * DMC error bit tables
23127Sjchu  */
23227Sjchu #define	IMU_BIT_DESC(bit, hdl, erpt) \
23327Sjchu 	IMU_INTERRUPT_STATUS_ ## bit ## _P, \
23427Sjchu 	0, \
23527Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
23627Sjchu 	PX_ERPT_SEND(erpt), \
237739Sjchu 	PX_ERR_DMC_CLASS(bit) }, \
238739Sjchu 	{ IMU_INTERRUPT_STATUS_ ## bit ## _S, \
239739Sjchu 	0, \
240739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
241739Sjchu 	PX_ERPT_SEND(erpt), \
24227Sjchu 	PX_ERR_DMC_CLASS(bit)
24327Sjchu px_err_bit_desc_t px_err_imu_tbl[] = {
2443274Set142600 	/* DMC IMU RDS */
2453274Set142600 	{ IMU_BIT_DESC(MSI_MAL_ERR,		panic,		imu_rds) },
2463274Set142600 	{ IMU_BIT_DESC(MSI_PAR_ERR,		panic,		imu_rds) },
2473274Set142600 	{ IMU_BIT_DESC(PMEACK_MES_NOT_EN,	panic,		imu_rds) },
2483274Set142600 	{ IMU_BIT_DESC(PMPME_MES_NOT_EN,	panic,		imu_rds) },
2493274Set142600 	{ IMU_BIT_DESC(FATAL_MES_NOT_EN,	panic,		imu_rds) },
2503274Set142600 	{ IMU_BIT_DESC(NONFATAL_MES_NOT_EN,	panic,		imu_rds) },
2513274Set142600 	{ IMU_BIT_DESC(COR_MES_NOT_EN,		panic,		imu_rds) },
2523274Set142600 	{ IMU_BIT_DESC(MSI_NOT_EN,		panic,		imu_rds) },
25327Sjchu 
2543274Set142600 	/* DMC IMU SCS */
2553421Sjchu 	{ IMU_BIT_DESC(EQ_NOT_EN,		panic,		imu_scs) },
25627Sjchu 
2573274Set142600 	/* DMC IMU */
25827Sjchu 	{ IMU_BIT_DESC(EQ_OVER,			imu_eq_ovfl,	imu) }
25927Sjchu };
26027Sjchu 
26127Sjchu #define	px_err_imu_keys (sizeof (px_err_imu_tbl)) / (sizeof (px_err_bit_desc_t))
26227Sjchu 
26327Sjchu /* mmu errors */
26427Sjchu #define	MMU_BIT_DESC(bit, hdl, erpt) \
26527Sjchu 	MMU_INTERRUPT_STATUS_ ## bit ## _P, \
26627Sjchu 	0, \
26727Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
26827Sjchu 	PX_ERPT_SEND(erpt), \
269739Sjchu 	PX_ERR_DMC_CLASS(bit) }, \
270739Sjchu 	{ MMU_INTERRUPT_STATUS_ ## bit ## _S, \
271739Sjchu 	0, \
272739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
273739Sjchu 	PX_ERPT_SEND(erpt), \
27427Sjchu 	PX_ERR_DMC_CLASS(bit)
27527Sjchu px_err_bit_desc_t px_err_mmu_tbl[] = {
2763274Set142600 	/* DMC MMU TFAR/TFSR */
27727Sjchu 	{ MMU_BIT_DESC(BYP_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
27827Sjchu 	{ MMU_BIT_DESC(BYP_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
2793274Set142600 	{ MMU_BIT_DESC(TRN_ERR,		panic,		mmu_tfar_tfsr) },
28027Sjchu 	{ MMU_BIT_DESC(TRN_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
28127Sjchu 	{ MMU_BIT_DESC(TTE_INV,		mmu_tfa,	mmu_tfar_tfsr) },
28227Sjchu 	{ MMU_BIT_DESC(TTE_PRT,		mmu_tfa,	mmu_tfar_tfsr) },
2833274Set142600 	{ MMU_BIT_DESC(TTC_DPE,		mmu_parity,	mmu_tfar_tfsr) },
2843274Set142600 	{ MMU_BIT_DESC(TBW_DME,		panic,		mmu_tfar_tfsr) },
2853274Set142600 	{ MMU_BIT_DESC(TBW_UDE,		panic,		mmu_tfar_tfsr) },
2863274Set142600 	{ MMU_BIT_DESC(TBW_ERR,		panic,		mmu_tfar_tfsr) },
2873274Set142600 	{ MMU_BIT_DESC(TBW_DPE,		mmu_parity,	mmu_tfar_tfsr) },
28827Sjchu 
2893274Set142600 	/* DMC MMU */
2903274Set142600 	{ MMU_BIT_DESC(TTC_CAE,		panic,		mmu) }
29127Sjchu };
29227Sjchu #define	px_err_mmu_keys (sizeof (px_err_mmu_tbl)) / (sizeof (px_err_bit_desc_t))
29327Sjchu 
2941772Sjl139090 
29527Sjchu /*
29627Sjchu  * PEC error bit tables
29727Sjchu  */
29827Sjchu #define	ILU_BIT_DESC(bit, hdl, erpt) \
29927Sjchu 	ILU_INTERRUPT_STATUS_ ## bit ## _P, \
30027Sjchu 	0, \
30127Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
30227Sjchu 	PX_ERPT_SEND(erpt), \
303739Sjchu 	PX_ERR_PEC_CLASS(bit) }, \
304739Sjchu 	{ ILU_INTERRUPT_STATUS_ ## bit ## _S, \
305739Sjchu 	0, \
306739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
307739Sjchu 	PX_ERPT_SEND(erpt), \
30827Sjchu 	PX_ERR_PEC_CLASS(bit)
30927Sjchu px_err_bit_desc_t px_err_ilu_tbl[] = {
3103274Set142600 	/* PEC ILU none */
3113274Set142600 	{ ILU_BIT_DESC(IHB_PE,		panic,		pec_ilu) }
31227Sjchu };
31327Sjchu #define	px_err_ilu_keys \
31427Sjchu 	(sizeof (px_err_ilu_tbl)) / (sizeof (px_err_bit_desc_t))
31527Sjchu 
31627Sjchu /*
31727Sjchu  * PEC UE errors implementation is incomplete pending PCIE generic
318383Set142600  * fabric rules.  Must handle both PRIMARY and SECONDARY errors.
31927Sjchu  */
32027Sjchu /* pec ue errors */
32127Sjchu #define	TLU_UC_BIT_DESC(bit, hdl, erpt) \
32227Sjchu 	TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
32327Sjchu 	0, \
324383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
325383Set142600 	PX_ERPT_SEND(erpt), \
326383Set142600 	PX_ERR_PEC_CLASS(bit) }, \
327383Set142600 	{ TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _S, \
328383Set142600 	0, \
329383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
330383Set142600 	PX_ERPT_SEND(erpt), \
331383Set142600 	PX_ERR_PEC_CLASS(bit)
3321772Sjl139090 #define	TLU_UC_OB_BIT_DESC(bit, hdl, erpt) \
3331772Sjl139090 	TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
3341772Sjl139090 	0, \
3351772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
3361772Sjl139090 	PX_ERPT_SEND(erpt), \
3371772Sjl139090 	PX_ERR_PEC_OB_CLASS(bit) }, \
3381772Sjl139090 	{ TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _S, \
3391772Sjl139090 	0, \
3401772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
3411772Sjl139090 	PX_ERPT_SEND(erpt), \
3425654Sdanice 	PX_ERR_PEC_OB_CLASS(bit)
34327Sjchu px_err_bit_desc_t px_err_tlu_ue_tbl[] = {
3443274Set142600 	/* PCI-E Receive Uncorrectable Errors */
345383Set142600 	{ TLU_UC_BIT_DESC(UR,		pciex_ue,	pciex_rx_ue) },
346383Set142600 	{ TLU_UC_BIT_DESC(UC,		pciex_ue,	pciex_rx_ue) },
34727Sjchu 
3483274Set142600 	/* PCI-E Transmit Uncorrectable Errors */
3491772Sjl139090 	{ TLU_UC_OB_BIT_DESC(ECRC,	pciex_ue,	pciex_rx_ue) },
350383Set142600 	{ TLU_UC_BIT_DESC(CTO,		pciex_ue,	pciex_tx_ue) },
351383Set142600 	{ TLU_UC_BIT_DESC(ROF,		pciex_ue,	pciex_tx_ue) },
35227Sjchu 
3533274Set142600 	/* PCI-E Rx/Tx Uncorrectable Errors */
354383Set142600 	{ TLU_UC_BIT_DESC(MFP,		pciex_ue,	pciex_rx_tx_ue) },
355383Set142600 	{ TLU_UC_BIT_DESC(PP,		pciex_ue,	pciex_rx_tx_ue) },
35627Sjchu 
3573274Set142600 	/* Other PCI-E Uncorrectable Errors */
358383Set142600 	{ TLU_UC_BIT_DESC(FCP,		pciex_ue,	pciex_ue) },
359383Set142600 	{ TLU_UC_BIT_DESC(DLP,		pciex_ue,	pciex_ue) },
360383Set142600 	{ TLU_UC_BIT_DESC(TE,		pciex_ue,	pciex_ue) },
361383Set142600 
362383Set142600 	/* Not used */
363383Set142600 	{ TLU_UC_BIT_DESC(CA,		pciex_ue,	do_not) }
36427Sjchu };
36527Sjchu #define	px_err_tlu_ue_keys \
36627Sjchu 	(sizeof (px_err_tlu_ue_tbl)) / (sizeof (px_err_bit_desc_t))
36727Sjchu 
3681772Sjl139090 
36927Sjchu /*
37027Sjchu  * PEC CE errors implementation is incomplete pending PCIE generic
37127Sjchu  * fabric rules.
37227Sjchu  */
37327Sjchu /* pec ce errors */
37427Sjchu #define	TLU_CE_BIT_DESC(bit, hdl, erpt) \
37527Sjchu 	TLU_CORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
37627Sjchu 	0, \
377383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
378383Set142600 	PX_ERPT_SEND(erpt), \
379383Set142600 	PX_ERR_PEC_CLASS(bit) }, \
380383Set142600 	{ TLU_CORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _S, \
381383Set142600 	0, \
382383Set142600 	PX_ERR_BIT_HANDLE(hdl), \
383383Set142600 	PX_ERPT_SEND(erpt), \
384383Set142600 	PX_ERR_PEC_CLASS(bit)
38527Sjchu px_err_bit_desc_t px_err_tlu_ce_tbl[] = {
3863274Set142600 	/* PCI-E Correctable Errors */
387383Set142600 	{ TLU_CE_BIT_DESC(RTO,		pciex_ce,	pciex_ce) },
388383Set142600 	{ TLU_CE_BIT_DESC(RNR,		pciex_ce,	pciex_ce) },
389383Set142600 	{ TLU_CE_BIT_DESC(BDP,		pciex_ce,	pciex_ce) },
390383Set142600 	{ TLU_CE_BIT_DESC(BTP,		pciex_ce,	pciex_ce) },
391383Set142600 	{ TLU_CE_BIT_DESC(RE,		pciex_ce,	pciex_ce) }
39227Sjchu };
39327Sjchu #define	px_err_tlu_ce_keys \
39427Sjchu 	(sizeof (px_err_tlu_ce_tbl)) / (sizeof (px_err_bit_desc_t))
39527Sjchu 
3961772Sjl139090 
39727Sjchu /* pec oe errors */
39827Sjchu #define	TLU_OE_BIT_DESC(bit, hdl, erpt) \
39927Sjchu 	TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _P, \
40027Sjchu 	0, \
40127Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
40227Sjchu 	PX_ERPT_SEND(erpt), \
403739Sjchu 	PX_ERR_PEC_CLASS(bit) }, \
404739Sjchu 	{ TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _S, \
405739Sjchu 	0, \
406739Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
407739Sjchu 	PX_ERPT_SEND(erpt), \
40827Sjchu 	PX_ERR_PEC_CLASS(bit)
4091772Sjl139090 #define	TLU_OE_OB_BIT_DESC(bit, hdl, erpt) \
4101772Sjl139090 	TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _P, \
4111772Sjl139090 	0, \
4121772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
4131772Sjl139090 	PX_ERPT_SEND(erpt), \
4141772Sjl139090 	PX_ERR_PEC_OB_CLASS(bit) }, \
4151772Sjl139090 	{ TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _S, \
4161772Sjl139090 	0, \
4171772Sjl139090 	PX_ERR_BIT_HANDLE(hdl), \
4181772Sjl139090 	PX_ERPT_SEND(erpt), \
4191772Sjl139090 	PX_ERR_PEC_OB_CLASS(bit)
42027Sjchu px_err_bit_desc_t px_err_tlu_oe_tbl[] = {
4213274Set142600 	/* TLU Other Event Status (receive only) */
4223274Set142600 	{ TLU_OE_BIT_DESC(MRC,		hw_reset,	pciex_rx_oe) },
4233274Set142600 
4243274Set142600 	/* TLU Other Event Status (rx + tx) */
4253274Set142600 	{ TLU_OE_BIT_DESC(WUC,		wuc_ruc,	pciex_rx_tx_oe) },
4263274Set142600 	{ TLU_OE_BIT_DESC(RUC,		wuc_ruc,	pciex_rx_tx_oe) },
4273274Set142600 	{ TLU_OE_BIT_DESC(CRS,		no_panic,	pciex_rx_tx_oe) },
42827Sjchu 
4293274Set142600 	/* TLU Other Event */
4303274Set142600 	{ TLU_OE_BIT_DESC(IIP,		panic,		pciex_oe) },
4313274Set142600 	{ TLU_OE_BIT_DESC(EDP,		panic,		pciex_oe) },
4323274Set142600 	{ TLU_OE_BIT_DESC(EHP,		panic,		pciex_oe) },
4333274Set142600 	{ TLU_OE_OB_BIT_DESC(TLUEITMO,	panic,		pciex_oe) },
4343274Set142600 	{ TLU_OE_BIT_DESC(LIN,		no_panic,	pciex_oe) },
4353274Set142600 	{ TLU_OE_BIT_DESC(LRS,		no_panic,	pciex_oe) },
4361147Sjchu 	{ TLU_OE_BIT_DESC(LDN,		tlu_ldn,	pciex_oe) },
4371147Sjchu 	{ TLU_OE_BIT_DESC(LUP,		tlu_lup,	pciex_oe) },
4383274Set142600 	{ TLU_OE_BIT_DESC(ERU,		panic,		pciex_oe) },
4393274Set142600 	{ TLU_OE_BIT_DESC(ERO,		panic,		pciex_oe) },
4403274Set142600 	{ TLU_OE_BIT_DESC(EMP,		panic,		pciex_oe) },
4413274Set142600 	{ TLU_OE_BIT_DESC(EPE,		panic,		pciex_oe) },
4423274Set142600 	{ TLU_OE_BIT_DESC(ERP,		panic,		pciex_oe) },
4433274Set142600 	{ TLU_OE_BIT_DESC(EIP,		panic,		pciex_oe) }
44427Sjchu };
44527Sjchu 
44627Sjchu #define	px_err_tlu_oe_keys \
44727Sjchu 	(sizeof (px_err_tlu_oe_tbl)) / (sizeof (px_err_bit_desc_t))
44827Sjchu 
4491772Sjl139090 
45027Sjchu /*
45127Sjchu  * All the following tables below are for LPU Interrupts.  These interrupts
45227Sjchu  * are *NOT* error interrupts, but event status interrupts.
45327Sjchu  *
45427Sjchu  * These events are probably of most interest to:
45527Sjchu  * o Hotplug
45627Sjchu  * o Power Management
45727Sjchu  * o etc...
45827Sjchu  *
45927Sjchu  * There are also a few events that would be interresting for FMA.
46027Sjchu  * Again none of the regiseters below state that an error has occured
46127Sjchu  * or that data has been lost.  If anything, they give status that an
46227Sjchu  * error is *about* to occur.  examples
46327Sjchu  * o INT_SKP_ERR - indicates clock between fire and child is too far
46427Sjchu  *		   off and is most unlikely able to compensate
46527Sjchu  * o INT_TX_PAR_ERR - A parity error occured in ONE lane.  This is
46627Sjchu  *		      HW recoverable, but will like end up as a future
46727Sjchu  *		      fabric error as well.
46827Sjchu  *
46927Sjchu  * For now, we don't care about any of these errors and should be ignore,
47027Sjchu  * but cleared.
47127Sjchu  */
47227Sjchu 
47327Sjchu /* LPU Link Interrupt Table */
47427Sjchu #define	LPUL_BIT_DESC(bit, hdl, erpt) \
47527Sjchu 	LPU_LINK_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
47627Sjchu 	0, \
47727Sjchu 	NULL, \
47827Sjchu 	NULL, \
47927Sjchu 	""
48027Sjchu px_err_bit_desc_t px_err_lpul_tbl[] = {
48127Sjchu 	{ LPUL_BIT_DESC(LINK_ERR_ACT,	NULL,		NULL) }
48227Sjchu };
48327Sjchu #define	px_err_lpul_keys \
48427Sjchu 	(sizeof (px_err_lpul_tbl)) / (sizeof (px_err_bit_desc_t))
48527Sjchu 
48627Sjchu /* LPU Physical Interrupt Table */
48727Sjchu #define	LPUP_BIT_DESC(bit, hdl, erpt) \
48827Sjchu 	LPU_PHY_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
48927Sjchu 	0, \
49027Sjchu 	NULL, \
49127Sjchu 	NULL, \
49227Sjchu 	""
49327Sjchu px_err_bit_desc_t px_err_lpup_tbl[] = {
49427Sjchu 	{ LPUP_BIT_DESC(PHY_LAYER_ERR,	NULL,		NULL) }
49527Sjchu };
49627Sjchu #define	px_err_lpup_keys \
49727Sjchu 	(sizeof (px_err_lpup_tbl)) / (sizeof (px_err_bit_desc_t))
49827Sjchu 
49927Sjchu /* LPU Receive Interrupt Table */
50027Sjchu #define	LPUR_BIT_DESC(bit, hdl, erpt) \
50127Sjchu 	LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
50227Sjchu 	0, \
50327Sjchu 	NULL, \
50427Sjchu 	NULL, \
50527Sjchu 	""
50627Sjchu px_err_bit_desc_t px_err_lpur_tbl[] = {
50727Sjchu 	{ LPUR_BIT_DESC(RCV_PHY,	NULL,		NULL) }
50827Sjchu };
50927Sjchu #define	px_err_lpur_keys \
51027Sjchu 	(sizeof (px_err_lpur_tbl)) / (sizeof (px_err_bit_desc_t))
51127Sjchu 
51227Sjchu /* LPU Transmit Interrupt Table */
51327Sjchu #define	LPUX_BIT_DESC(bit, hdl, erpt) \
51427Sjchu 	LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
51527Sjchu 	0, \
51627Sjchu 	NULL, \
51727Sjchu 	NULL, \
51827Sjchu 	""
51927Sjchu px_err_bit_desc_t px_err_lpux_tbl[] = {
52027Sjchu 	{ LPUX_BIT_DESC(UNMSK,		NULL,		NULL) }
52127Sjchu };
52227Sjchu #define	px_err_lpux_keys \
52327Sjchu 	(sizeof (px_err_lpux_tbl)) / (sizeof (px_err_bit_desc_t))
52427Sjchu 
52527Sjchu /* LPU LTSSM Interrupt Table */
52627Sjchu #define	LPUS_BIT_DESC(bit, hdl, erpt) \
52727Sjchu 	LPU_LTSSM_INTERRUPT_AND_STATUS_INT_ ## bit, \
52827Sjchu 	0, \
52927Sjchu 	NULL, \
53027Sjchu 	NULL, \
53127Sjchu 	""
53227Sjchu px_err_bit_desc_t px_err_lpus_tbl[] = {
53327Sjchu 	{ LPUS_BIT_DESC(ANY,		NULL,		NULL) }
53427Sjchu };
53527Sjchu #define	px_err_lpus_keys \
53627Sjchu 	(sizeof (px_err_lpus_tbl)) / (sizeof (px_err_bit_desc_t))
53727Sjchu 
53827Sjchu /* LPU Gigablaze Glue Interrupt Table */
53927Sjchu #define	LPUG_BIT_DESC(bit, hdl, erpt) \
54027Sjchu 	LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_INT_ ## bit, \
54127Sjchu 	0, \
54227Sjchu 	NULL, \
54327Sjchu 	NULL, \
54427Sjchu 	""
54527Sjchu px_err_bit_desc_t px_err_lpug_tbl[] = {
54627Sjchu 	{ LPUG_BIT_DESC(GLOBL_UNMSK,	NULL,		NULL) }
54727Sjchu };
54827Sjchu #define	px_err_lpug_keys \
54927Sjchu 	(sizeof (px_err_lpug_tbl)) / (sizeof (px_err_bit_desc_t))
55027Sjchu 
55127Sjchu 
55227Sjchu /* Mask and Tables */
5532509Sschwartz #define	MnT6X(pre) \
55427Sjchu 	&px_ ## pre ## _intr_mask, \
55527Sjchu 	&px_ ## pre ## _log_mask, \
55627Sjchu 	&px_ ## pre ## _count_mask, \
55727Sjchu 	px_err_ ## pre ## _tbl, \
55827Sjchu 	px_err_ ## pre ## _keys, \
5592509Sschwartz 	PX_REG_XBC, \
56027Sjchu 	0
56127Sjchu 
5622509Sschwartz #define	MnT6(pre) \
5631772Sjl139090 	&px_ ## pre ## _intr_mask, \
5641772Sjl139090 	&px_ ## pre ## _log_mask, \
5651772Sjl139090 	&px_ ## pre ## _count_mask, \
5662509Sschwartz 	px_err_ ## pre ## _tbl, \
5672509Sschwartz 	px_err_ ## pre ## _keys, \
5682509Sschwartz 	PX_REG_CSR, \
5691772Sjl139090 	0
5701772Sjl139090 
57127Sjchu /* LPU Registers Addresses */
57227Sjchu #define	LR4(pre) \
57327Sjchu 	NULL, \
57427Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
57527Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS, \
57627Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS
57727Sjchu 
57827Sjchu /* LPU Registers Addresses with Irregularities */
57927Sjchu #define	LR4_FIXME(pre) \
58027Sjchu 	NULL, \
58127Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
58227Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS, \
58327Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS
58427Sjchu 
58527Sjchu /* TLU Registers Addresses */
58627Sjchu #define	TR4(pre) \
58727Sjchu 	TLU_ ## pre ## _LOG_ENABLE, \
58827Sjchu 	TLU_ ## pre ## _INTERRUPT_ENABLE, \
58927Sjchu 	TLU_ ## pre ## _INTERRUPT_STATUS, \
59027Sjchu 	TLU_ ## pre ## _STATUS_CLEAR
59127Sjchu 
5921772Sjl139090 /* Registers Addresses for JBC, UBC, MMU, IMU and ILU */
59327Sjchu #define	R4(pre) \
59427Sjchu 	pre ## _ERROR_LOG_ENABLE, \
59527Sjchu 	pre ## _INTERRUPT_ENABLE, \
59627Sjchu 	pre ## _INTERRUPT_STATUS, \
59727Sjchu 	pre ## _ERROR_STATUS_CLEAR
59827Sjchu 
5992509Sschwartz /* Bits in chip_mask, set according to type. */
6002509Sschwartz #define	CHP_O	BITMASK(PX_CHIP_OBERON)
6012509Sschwartz #define	CHP_F	BITMASK(PX_CHIP_FIRE)
6022509Sschwartz #define	CHP_FO	(CHP_F | CHP_O)
6032509Sschwartz 
60427Sjchu /*
60527Sjchu  * Register error handling tables.
60627Sjchu  * The ID Field (first field) is identified by an enum px_err_id_t.
60727Sjchu  * It is located in px_err.h
60827Sjchu  */
6092509Sschwartz static const
61027Sjchu px_err_reg_desc_t px_err_reg_tbl[] = {
6112509Sschwartz 	{ CHP_F,  MnT6X(jbc),	R4(JBC),		  "JBC Error"},
6122509Sschwartz 	{ CHP_O,  MnT6X(ubc),	R4(UBC),		  "UBC Error"},
6132509Sschwartz 	{ CHP_FO, MnT6(mmu),	R4(MMU),		  "MMU Error"},
6142509Sschwartz 	{ CHP_FO, MnT6(imu),	R4(IMU),		  "IMU Error"},
6152509Sschwartz 	{ CHP_FO, MnT6(tlu_ue),	TR4(UNCORRECTABLE_ERROR), "TLU UE"},
6162509Sschwartz 	{ CHP_FO, MnT6(tlu_ce),	TR4(CORRECTABLE_ERROR),	  "TLU CE"},
6172509Sschwartz 	{ CHP_FO, MnT6(tlu_oe),	TR4(OTHER_EVENT),	  "TLU OE"},
6182509Sschwartz 	{ CHP_FO, MnT6(ilu),	R4(ILU),		  "ILU Error"},
6192509Sschwartz 	{ CHP_F,  MnT6(lpul),	LR4(LINK_LAYER),	  "LPU Link Layer"},
6202509Sschwartz 	{ CHP_F,  MnT6(lpup),	LR4_FIXME(PHY),		  "LPU Phy Layer"},
6212509Sschwartz 	{ CHP_F,  MnT6(lpur),	LR4(RECEIVE_PHY),	  "LPU RX Phy Layer"},
6222509Sschwartz 	{ CHP_F,  MnT6(lpux),	LR4(TRANSMIT_PHY),	  "LPU TX Phy Layer"},
6232509Sschwartz 	{ CHP_F,  MnT6(lpus),	LR4(LTSSM),		  "LPU LTSSM"},
6242509Sschwartz 	{ CHP_F,  MnT6(lpug),	LR4(GIGABLAZE_GLUE),	  "LPU GigaBlaze Glue"},
62527Sjchu };
6262509Sschwartz 
6272509Sschwartz #define	PX_ERR_REG_KEYS	(sizeof (px_err_reg_tbl)) / (sizeof (px_err_reg_tbl[0]))
62827Sjchu 
62927Sjchu typedef struct px_err_ss {
63027Sjchu 	uint64_t err_status[PX_ERR_REG_KEYS];
63127Sjchu } px_err_ss_t;
63227Sjchu 
6333274Set142600 static void px_err_snapshot(px_t *px_p, px_err_ss_t *ss, int block);
63427Sjchu static int  px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr,
63527Sjchu     px_err_ss_t *ss);
63627Sjchu static int  px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr,
63727Sjchu     int err, int caller);
63827Sjchu 
63927Sjchu /*
64027Sjchu  * px_err_cb_intr:
6411772Sjl139090  * Interrupt handler for the JBC/UBC block.
64227Sjchu  * o lock
64327Sjchu  * o create derr
6443274Set142600  * o px_err_cmn_intr
64527Sjchu  * o unlock
64627Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
64727Sjchu  */
64827Sjchu uint_t
px_err_cb_intr(caddr_t arg)64927Sjchu px_err_cb_intr(caddr_t arg)
65027Sjchu {
65127Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
65227Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
65327Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
6543274Set142600 	int		err;
65527Sjchu 	ddi_fm_error_t	derr;
65627Sjchu 
65727Sjchu 	/* Create the derr */
65827Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
65927Sjchu 	derr.fme_version = DDI_FME_VERSION;
66027Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
66127Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
66227Sjchu 
6636313Skrishnae 	if (px_fm_enter(px_p) != DDI_SUCCESS)
6646313Skrishnae 		goto done;
66527Sjchu 
6663274Set142600 	err = px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_HOST);
66727Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
66827Sjchu 	    INTR_IDLE_STATE);
66927Sjchu 
6706313Skrishnae 	px_err_panic(err, PX_HB, PX_NO_ERROR, B_TRUE);
6716313Skrishnae 	px_fm_exit(px_p);
6726313Skrishnae 	px_err_panic(err, PX_HB, PX_NO_ERROR, B_FALSE);
67327Sjchu 
6746313Skrishnae done:
67527Sjchu 	return (DDI_INTR_CLAIMED);
67627Sjchu }
67727Sjchu 
67827Sjchu /*
67927Sjchu  * px_err_dmc_pec_intr:
68027Sjchu  * Interrupt handler for the DMC/PEC block.
68127Sjchu  * o lock
68227Sjchu  * o create derr
6833274Set142600  * o px_err_cmn_intr(leaf, with out cb)
6843274Set142600  * o pcie_scan_fabric (leaf)
68527Sjchu  * o unlock
68627Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
68727Sjchu  */
68827Sjchu uint_t
px_err_dmc_pec_intr(caddr_t arg)68927Sjchu px_err_dmc_pec_intr(caddr_t arg)
69027Sjchu {
69127Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
69227Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
69327Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
6946313Skrishnae 	int		rc_err, fab_err;
69527Sjchu 	ddi_fm_error_t	derr;
69627Sjchu 
69727Sjchu 	/* Create the derr */
69827Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
69927Sjchu 	derr.fme_version = DDI_FME_VERSION;
70027Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
70127Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
70227Sjchu 
7036313Skrishnae 	if (px_fm_enter(px_p) != DDI_SUCCESS)
7046313Skrishnae 		goto done;
70527Sjchu 
70627Sjchu 	/* send ereport/handle/clear fire registers */
7073274Set142600 	rc_err = px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_PCIE);
70827Sjchu 
70927Sjchu 	/* Check all child devices for errors */
7106313Skrishnae 	fab_err = px_scan_fabric(px_p, rpdip, &derr);
71127Sjchu 
71227Sjchu 	/* Set the interrupt state to idle */
71327Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
71427Sjchu 	    INTR_IDLE_STATE);
71527Sjchu 
7166313Skrishnae 	px_err_panic(rc_err, PX_RC, fab_err, B_TRUE);
7176313Skrishnae 	px_fm_exit(px_p);
7186313Skrishnae 	px_err_panic(rc_err, PX_RC, fab_err, B_FALSE);
71927Sjchu 
7206313Skrishnae done:
72127Sjchu 	return (DDI_INTR_CLAIMED);
72227Sjchu }
72327Sjchu 
72427Sjchu /*
7252509Sschwartz  * Proper csr_base is responsibility of the caller. (Called from px_lib_dev_init
7262509Sschwartz  * via px_err_reg_setup_all for pcie error registers;  called from
7272509Sschwartz  * px_cb_add_intr for jbc/ubc from px_cb_attach.)
7282509Sschwartz  *
7292509Sschwartz  * Note: reg_id is passed in instead of reg_desc since this function is called
7302509Sschwartz  * from px_lib4u.c, which doesn't know about the structure of the table.
73127Sjchu  */
73227Sjchu void
px_err_reg_enable(px_err_id_t reg_id,caddr_t csr_base)7332509Sschwartz px_err_reg_enable(px_err_id_t reg_id, caddr_t csr_base)
73427Sjchu {
7352509Sschwartz 	const px_err_reg_desc_t	*reg_desc_p = &px_err_reg_tbl[reg_id];
7362509Sschwartz 	uint64_t 		intr_mask = *reg_desc_p->intr_mask_p;
7372509Sschwartz 	uint64_t 		log_mask = *reg_desc_p->log_mask_p;
73827Sjchu 
73927Sjchu 	/* Enable logs if it exists */
7402509Sschwartz 	if (reg_desc_p->log_addr != NULL)
7412509Sschwartz 		CSR_XS(csr_base, reg_desc_p->log_addr, log_mask);
74227Sjchu 
74327Sjchu 	/*
74427Sjchu 	 * For readability you in code you set 1 to enable an interrupt.
74527Sjchu 	 * But in Fire it's backwards.  You set 1 to *disable* an intr.
74627Sjchu 	 * Reverse the user tunable intr mask field.
74727Sjchu 	 *
74827Sjchu 	 * Disable All Errors
74927Sjchu 	 * Clear All Errors
75027Sjchu 	 * Enable Errors
75127Sjchu 	 */
7522509Sschwartz 	CSR_XS(csr_base, reg_desc_p->enable_addr, 0);
7532509Sschwartz 	CSR_XS(csr_base, reg_desc_p->clear_addr, -1);
7542509Sschwartz 	CSR_XS(csr_base, reg_desc_p->enable_addr, intr_mask);
7552509Sschwartz 	DBG(DBG_ATTACH, NULL, "%s Mask: 0x%llx\n", reg_desc_p->msg,
7562509Sschwartz 	    CSR_XR(csr_base, reg_desc_p->enable_addr));
7572509Sschwartz 	DBG(DBG_ATTACH, NULL, "%s Status: 0x%llx\n", reg_desc_p->msg,
7582509Sschwartz 	    CSR_XR(csr_base, reg_desc_p->status_addr));
7592509Sschwartz 	DBG(DBG_ATTACH, NULL, "%s Clear: 0x%llx\n", reg_desc_p->msg,
7602509Sschwartz 	    CSR_XR(csr_base, reg_desc_p->clear_addr));
7612509Sschwartz 	if (reg_desc_p->log_addr != NULL) {
7622509Sschwartz 		DBG(DBG_ATTACH, NULL, "%s Log: 0x%llx\n", reg_desc_p->msg,
7632509Sschwartz 		    CSR_XR(csr_base, reg_desc_p->log_addr));
76427Sjchu 	}
76527Sjchu }
76627Sjchu 
76727Sjchu void
px_err_reg_disable(px_err_id_t reg_id,caddr_t csr_base)7682509Sschwartz px_err_reg_disable(px_err_id_t reg_id, caddr_t csr_base)
76927Sjchu {
7702509Sschwartz 	const px_err_reg_desc_t	*reg_desc_p = &px_err_reg_tbl[reg_id];
7712509Sschwartz 	uint64_t		val = (reg_id >= PX_ERR_LPU_LINK) ? -1 : 0;
77227Sjchu 
7732509Sschwartz 	if (reg_desc_p->log_addr != NULL)
7742509Sschwartz 		CSR_XS(csr_base, reg_desc_p->log_addr, val);
7752509Sschwartz 	CSR_XS(csr_base, reg_desc_p->enable_addr, val);
7762509Sschwartz }
77727Sjchu 
7782509Sschwartz /*
7792509Sschwartz  * Set up pcie error registers.
7802509Sschwartz  */
7812509Sschwartz void
px_err_reg_setup_pcie(uint8_t chip_mask,caddr_t csr_base,boolean_t enable)7822509Sschwartz px_err_reg_setup_pcie(uint8_t chip_mask, caddr_t csr_base, boolean_t enable)
7832509Sschwartz {
7842509Sschwartz 	px_err_id_t		reg_id;
7852509Sschwartz 	const px_err_reg_desc_t	*reg_desc_p;
7862509Sschwartz 	void (*px_err_reg_func)(px_err_id_t, caddr_t);
7872509Sschwartz 
7882509Sschwartz 	/*
7892509Sschwartz 	 * JBC or XBC are enabled during adding of common block interrupts,
7902509Sschwartz 	 * not done here.
7912509Sschwartz 	 */
7922509Sschwartz 	px_err_reg_func = (enable ? px_err_reg_enable : px_err_reg_disable);
7932509Sschwartz 	for (reg_id = 0; reg_id < PX_ERR_REG_KEYS; reg_id++) {
7942509Sschwartz 		reg_desc_p = &px_err_reg_tbl[reg_id];
7952509Sschwartz 		if ((reg_desc_p->chip_mask & chip_mask) &&
7962509Sschwartz 		    (reg_desc_p->reg_bank == PX_REG_CSR))
7972509Sschwartz 			px_err_reg_func(reg_id, csr_base);
79827Sjchu 	}
79927Sjchu }
80027Sjchu 
80127Sjchu /*
8023274Set142600  * px_err_cmn_intr:
80327Sjchu  * Common function called by trap, mondo and fabric intr.
80427Sjchu  * o Snap shot current fire registers
80527Sjchu  * o check for safe access
80627Sjchu  * o send ereport and clear snap shot registers
8073274Set142600  * o create and queue RC info for later use in fabric scan.
8083274Set142600  *   o RUC/WUC, PTLP, MMU Errors(CA), UR
80927Sjchu  * o check severity of snap shot registers
81027Sjchu  *
81127Sjchu  * @param px_p		leaf in which to check access
81227Sjchu  * @param derr		fm err data structure to be updated
81327Sjchu  * @param caller	PX_TRAP_CALL | PX_INTR_CALL
8143274Set142600  * @param block		PX_FM_BLOCK_HOST | PX_FM_BLOCK_PCIE | PX_FM_BLOCK_ALL
8153274Set142600  * @return err		PX_NO_PANIC | PX_PANIC | PX_HW_RESET | PX_PROTECTED
81627Sjchu  */
81727Sjchu int
px_err_cmn_intr(px_t * px_p,ddi_fm_error_t * derr,int caller,int block)8183274Set142600 px_err_cmn_intr(px_t *px_p, ddi_fm_error_t *derr, int caller, int block)
81927Sjchu {
8202509Sschwartz 	px_err_ss_t		ss = {0};
8213274Set142600 	int			err;
82227Sjchu 
8231648Sjchu 	ASSERT(MUTEX_HELD(&px_p->px_fm_mutex));
82427Sjchu 
8253613Set142600 	/* check for safe access */
8263613Set142600 	px_err_safeacc_check(px_p, derr);
8273613Set142600 
82827Sjchu 	/* snap shot the current fire registers */
8293274Set142600 	px_err_snapshot(px_p, &ss, block);
83027Sjchu 
83127Sjchu 	/* send ereports/handle/clear registers */
83227Sjchu 	err = px_err_erpt_and_clr(px_p, derr, &ss);
83327Sjchu 
83427Sjchu 	/* check for error severity */
83527Sjchu 	err = px_err_check_severity(px_p, derr, err, caller);
83627Sjchu 
83727Sjchu 	/* Mark the On Trap Handle if an error occured */
8383274Set142600 	if (err != PX_NO_ERROR) {
83927Sjchu 		px_pec_t	*pec_p = px_p->px_pec_p;
84027Sjchu 		on_trap_data_t	*otd = pec_p->pec_ontrap_data;
84127Sjchu 
842118Sjchu 		if ((otd != NULL) && (otd->ot_prot & OT_DATA_ACCESS))
84327Sjchu 			otd->ot_trap |= OT_DATA_ACCESS;
84427Sjchu 	}
84527Sjchu 
84627Sjchu 	return (err);
84727Sjchu }
84827Sjchu 
84927Sjchu /*
85027Sjchu  * Static function
85127Sjchu  */
85227Sjchu 
85327Sjchu /*
85427Sjchu  * px_err_snapshot:
85527Sjchu  * Take a current snap shot of all the fire error registers.  This includes
8563274Set142600  * JBC/UBC, DMC, and PEC depending on the block flag
85727Sjchu  *
85827Sjchu  * @param px_p		leaf in which to take the snap shot.
85927Sjchu  * @param ss		pre-allocated memory to store the snap shot.
8601772Sjl139090  * @param chk_cb	boolean on whether to store jbc/ubc register.
86127Sjchu  */
86227Sjchu static void
px_err_snapshot(px_t * px_p,px_err_ss_t * ss_p,int block)8633274Set142600 px_err_snapshot(px_t *px_p, px_err_ss_t *ss_p, int block)
86427Sjchu {
86527Sjchu 	pxu_t	*pxu_p = (pxu_t *)px_p->px_plat_p;
86627Sjchu 	caddr_t	xbc_csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
86727Sjchu 	caddr_t	pec_csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
8683274Set142600 	caddr_t	csr_base;
8692509Sschwartz 	uint8_t chip_mask = 1 << PX_CHIP_TYPE(pxu_p);
8702509Sschwartz 	const px_err_reg_desc_t *reg_desc_p = px_err_reg_tbl;
8712509Sschwartz 	px_err_id_t reg_id;
8721772Sjl139090 
8732509Sschwartz 	for (reg_id = 0; reg_id < PX_ERR_REG_KEYS; reg_id++, reg_desc_p++) {
8742509Sschwartz 		if (!(reg_desc_p->chip_mask & chip_mask))
8752509Sschwartz 			continue;
8763274Set142600 
8773274Set142600 		if ((block & PX_FM_BLOCK_HOST) &&
8783274Set142600 		    (reg_desc_p->reg_bank == PX_REG_XBC))
8793274Set142600 			csr_base = xbc_csr_base;
8803274Set142600 		else if ((block & PX_FM_BLOCK_PCIE) &&
8813274Set142600 		    (reg_desc_p->reg_bank == PX_REG_CSR))
8823274Set142600 			csr_base = pec_csr_base;
8833274Set142600 		else {
8843274Set142600 			ss_p->err_status[reg_id] = 0;
8853274Set142600 			continue;
8863274Set142600 		}
8873274Set142600 
8883274Set142600 		ss_p->err_status[reg_id] = CSR_XR(csr_base,
8893274Set142600 		    reg_desc_p->status_addr);
89027Sjchu 	}
89127Sjchu }
89227Sjchu 
89327Sjchu /*
89427Sjchu  * px_err_erpt_and_clr:
89527Sjchu  * This function does the following thing to all the fire registers based
89627Sjchu  * on an earlier snap shot.
89727Sjchu  * o Send ereport
89827Sjchu  * o Handle the error
89927Sjchu  * o Clear the error
90027Sjchu  *
90127Sjchu  * @param px_p		leaf in which to take the snap shot.
90227Sjchu  * @param derr		fm err in which the ereport is to be based on
9032509Sschwartz  * @param ss_p		pre-allocated memory to store the snap shot.
90427Sjchu  */
90527Sjchu static int
px_err_erpt_and_clr(px_t * px_p,ddi_fm_error_t * derr,px_err_ss_t * ss_p)9062509Sschwartz px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr, px_err_ss_t *ss_p)
90727Sjchu {
90827Sjchu 	dev_info_t		*rpdip = px_p->px_dip;
90927Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
91027Sjchu 	caddr_t			csr_base;
9112509Sschwartz 	const px_err_reg_desc_t	*err_reg_tbl;
91227Sjchu 	px_err_bit_desc_t	*err_bit_tbl;
91327Sjchu 	px_err_bit_desc_t	*err_bit_desc;
91427Sjchu 
9153274Set142600 	uint64_t		*count_mask;
9163274Set142600 	uint64_t		clear_addr;
91727Sjchu 	uint64_t		ss_reg;
91827Sjchu 
91927Sjchu 	int			(*err_handler)();
92027Sjchu 	int			(*erpt_handler)();
9213274Set142600 	int			reg_id, key;
9223274Set142600 	int			err = PX_NO_ERROR;
9233274Set142600 	int			biterr = 0;
92427Sjchu 
9251648Sjchu 	ASSERT(MUTEX_HELD(&px_p->px_fm_mutex));
92627Sjchu 
92727Sjchu 	/* send erport/handle/clear JBC errors */
9282509Sschwartz 	for (reg_id = 0; reg_id < PX_ERR_REG_KEYS; reg_id++) {
92927Sjchu 		/* Get the correct register description table */
93027Sjchu 		err_reg_tbl = &px_err_reg_tbl[reg_id];
93127Sjchu 
9321772Sjl139090 		/* Only look at enabled groups. */
9332509Sschwartz 		if (!(BIT_TST(err_reg_tbl->chip_mask, PX_CHIP_TYPE(pxu_p))))
9341772Sjl139090 			continue;
9351772Sjl139090 
93627Sjchu 		/* Get the correct CSR BASE */
9372509Sschwartz 		csr_base = (caddr_t)pxu_p->px_address[err_reg_tbl->reg_bank];
93827Sjchu 
9393274Set142600 		/* If there are no errors in this register, continue */
9403274Set142600 		ss_reg = ss_p->err_status[reg_id];
9413274Set142600 		if (!ss_reg)
9423274Set142600 			continue;
9433274Set142600 
9443272Sdduvall 		/* Get pointers to masks and register addresses */
9453272Sdduvall 		count_mask = err_reg_tbl->count_mask_p;
9463272Sdduvall 		clear_addr = err_reg_tbl->clear_addr;
94727Sjchu 
94827Sjchu 		/* Get the register BIT description table */
94927Sjchu 		err_bit_tbl = err_reg_tbl->err_bit_tbl;
95027Sjchu 
95127Sjchu 		/* For each known bit in the register send erpt and handle */
9522509Sschwartz 		for (key = 0; key < err_reg_tbl->err_bit_keys; key++) {
95327Sjchu 			/*
95427Sjchu 			 * If the ss_reg is set for this bit,
95527Sjchu 			 * send ereport and handle
95627Sjchu 			 */
9573274Set142600 			err_bit_desc = &err_bit_tbl[key];
9583274Set142600 			if (!BIT_TST(ss_reg, err_bit_desc->bit))
9593274Set142600 				continue;
96027Sjchu 
9613274Set142600 			/* Increment the counter if necessary */
9623274Set142600 			if (BIT_TST(*count_mask, err_bit_desc->bit)) {
9633274Set142600 				err_bit_desc->counter++;
9643274Set142600 			}
96527Sjchu 
9663274Set142600 			/* Error Handle for this bit */
9673274Set142600 			err_handler = err_bit_desc->err_handler;
9683274Set142600 			if (err_handler) {
9693274Set142600 				biterr = err_handler(rpdip, csr_base, derr,
9703274Set142600 				    err_reg_tbl, err_bit_desc);
9713274Set142600 				err |= biterr;
97227Sjchu 			}
9733274Set142600 
9743274Set142600 			/*
9753274Set142600 			 * Send the ereport if it's an UNEXPECTED err.
9763274Set142600 			 * This is the only place where PX_EXPECTED is utilized.
9773274Set142600 			 */
9783274Set142600 			erpt_handler = err_bit_desc->erpt_handler;
9793274Set142600 			if ((derr->fme_flag != DDI_FM_ERR_UNEXPECTED) ||
9803274Set142600 			    (biterr == PX_EXPECTED))
9813274Set142600 				continue;
9823274Set142600 
9833274Set142600 			if (erpt_handler)
9843274Set142600 				(void) erpt_handler(rpdip, csr_base, ss_reg,
9853274Set142600 				    derr, err_bit_desc->bit,
9863274Set142600 				    err_bit_desc->class_name);
98727Sjchu 		}
98827Sjchu 
98927Sjchu 		/* Clear the register and error */
99027Sjchu 		CSR_XS(csr_base, clear_addr, ss_reg);
99127Sjchu 	}
99227Sjchu 
99327Sjchu 	return (err);
99427Sjchu }
99527Sjchu 
99627Sjchu /*
99727Sjchu  * px_err_check_severity:
99827Sjchu  * Check the severity of the fire error based on an earlier snapshot
99927Sjchu  *
100027Sjchu  * @param px_p		leaf in which to take the snap shot.
100127Sjchu  * @param derr		fm err in which the ereport is to be based on
10022509Sschwartz  * @param err		fire register error status
10032509Sschwartz  * @param caller	PX_TRAP_CALL | PX_INTR_CALL | PX_LIB_CALL
100427Sjchu  */
100527Sjchu static int
px_err_check_severity(px_t * px_p,ddi_fm_error_t * derr,int err,int caller)100627Sjchu px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr, int err, int caller)
100727Sjchu {
100827Sjchu 	px_pec_t 	*pec_p = px_p->px_pec_p;
100927Sjchu 	boolean_t	is_safeacc = B_FALSE;
1010118Sjchu 
10113274Set142600 	/*
10123274Set142600 	 * Nothing to do if called with no error.
10133274Set142600 	 * The err could have already been set to PX_NO_PANIC, which means the
10143274Set142600 	 * system doesn't need to panic, but PEEK/POKE still failed.
10153274Set142600 	 */
10163274Set142600 	if (err == PX_NO_ERROR)
1017118Sjchu 		return (err);
101827Sjchu 
101927Sjchu 	/* Cautious access error handling  */
102027Sjchu 	switch (derr->fme_flag) {
102127Sjchu 	case DDI_FM_ERR_EXPECTED:
102227Sjchu 		if (caller == PX_TRAP_CALL) {
102327Sjchu 			/*
102427Sjchu 			 * for ddi_caut_get treat all events as nonfatal
102527Sjchu 			 * The trampoline will set err_ena = 0,
102627Sjchu 			 * err_status = NONFATAL.
102727Sjchu 			 */
102827Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
102927Sjchu 			is_safeacc = B_TRUE;
103027Sjchu 		} else {
103127Sjchu 			/*
103227Sjchu 			 * For ddi_caut_put treat all events as nonfatal. Here
103327Sjchu 			 * we have the handle and can call ndi_fm_acc_err_set().
103427Sjchu 			 */
103527Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
103627Sjchu 			ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr);
103727Sjchu 			is_safeacc = B_TRUE;
103827Sjchu 		}
103927Sjchu 		break;
104027Sjchu 	case DDI_FM_ERR_PEEK:
104127Sjchu 	case DDI_FM_ERR_POKE:
104227Sjchu 		/*
104327Sjchu 		 * For ddi_peek/poke treat all events as nonfatal.
104427Sjchu 		 */
104527Sjchu 		is_safeacc = B_TRUE;
104627Sjchu 		break;
104727Sjchu 	default:
104827Sjchu 		is_safeacc = B_FALSE;
104927Sjchu 	}
105027Sjchu 
10513274Set142600 	/* re-adjust error status from safe access, forgive all errors */
10523274Set142600 	if (is_safeacc)
10533274Set142600 		return (PX_NO_PANIC);
105427Sjchu 
1055118Sjchu 	return (err);
105627Sjchu }
105727Sjchu 
105827Sjchu /* predefined convenience functions */
105927Sjchu /* ARGSUSED */
10603274Set142600 void
px_err_log_handle(dev_info_t * rpdip,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr,char * msg)10613274Set142600 px_err_log_handle(dev_info_t *rpdip, px_err_reg_desc_t *err_reg_descr,
10623274Set142600 	px_err_bit_desc_t *err_bit_descr, char *msg)
106327Sjchu {
10643274Set142600 	DBG(DBG_ERR_INTR, rpdip,
10653274Set142600 	    "Bit %d, %s, at %s(0x%x) has occured %d times with a severity "
10663274Set142600 	    "of \"%s\"\n",
10673274Set142600 	    err_bit_descr->bit, err_bit_descr->class_name,
10683274Set142600 	    err_reg_descr->msg, err_reg_descr->status_addr,
10693274Set142600 	    err_bit_descr->counter, msg);
107027Sjchu }
107127Sjchu 
107227Sjchu /* ARGSUSED */
107327Sjchu int
px_err_hw_reset_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)10743274Set142600 px_err_hw_reset_handle(dev_info_t *rpdip, caddr_t csr_base,
107527Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
107627Sjchu 	px_err_bit_desc_t *err_bit_descr)
107727Sjchu {
10783274Set142600 	if (px_log & PX_HW_RESET) {
10793274Set142600 		px_err_log_handle(rpdip, err_reg_descr, err_bit_descr,
10803274Set142600 		    "HW RESET");
10813274Set142600 	}
108227Sjchu 
10833274Set142600 	return (PX_HW_RESET);
108427Sjchu }
108527Sjchu 
108627Sjchu /* ARGSUSED */
108727Sjchu int
px_err_panic_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)10883274Set142600 px_err_panic_handle(dev_info_t *rpdip, caddr_t csr_base,
108927Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
109027Sjchu 	px_err_bit_desc_t *err_bit_descr)
109127Sjchu {
10923274Set142600 	if (px_log & PX_PANIC) {
10933274Set142600 		px_err_log_handle(rpdip, err_reg_descr, err_bit_descr, "PANIC");
10943274Set142600 	}
10953274Set142600 
10963274Set142600 	return (PX_PANIC);
109727Sjchu }
109827Sjchu 
109927Sjchu /* ARGSUSED */
110027Sjchu int
px_err_protected_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)11013274Set142600 px_err_protected_handle(dev_info_t *rpdip, caddr_t csr_base,
110227Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
110327Sjchu 	px_err_bit_desc_t *err_bit_descr)
110427Sjchu {
11053274Set142600 	if (px_log & PX_PROTECTED) {
11063274Set142600 		px_err_log_handle(rpdip, err_reg_descr, err_bit_descr,
11073274Set142600 		    "PROTECTED");
11083274Set142600 	}
11093274Set142600 
11103274Set142600 	return (PX_PROTECTED);
111127Sjchu }
111227Sjchu 
111327Sjchu /* ARGSUSED */
111427Sjchu int
px_err_no_panic_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)11153274Set142600 px_err_no_panic_handle(dev_info_t *rpdip, caddr_t csr_base,
11163274Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
11173274Set142600 	px_err_bit_desc_t *err_bit_descr)
111827Sjchu {
11193274Set142600 	if (px_log & PX_NO_PANIC) {
11203274Set142600 		px_err_log_handle(rpdip, err_reg_descr, err_bit_descr,
11213274Set142600 		    "NO PANIC");
11223274Set142600 	}
11233274Set142600 
11243274Set142600 	return (PX_NO_PANIC);
112527Sjchu }
112627Sjchu 
112727Sjchu /* ARGSUSED */
112827Sjchu int
px_err_no_error_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)11293274Set142600 px_err_no_error_handle(dev_info_t *rpdip, caddr_t csr_base,
11303274Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
11313274Set142600 	px_err_bit_desc_t *err_bit_descr)
113227Sjchu {
11333274Set142600 	if (px_log & PX_NO_ERROR) {
11343274Set142600 		px_err_log_handle(rpdip, err_reg_descr, err_bit_descr,
11353274Set142600 		    "NO ERROR");
11363274Set142600 	}
11373274Set142600 
11383274Set142600 	return (PX_NO_ERROR);
113927Sjchu }
114027Sjchu 
1141383Set142600 /* ARGSUSED */
PX_ERPT_SEND_DEC(do_not)1142383Set142600 PX_ERPT_SEND_DEC(do_not)
1143383Set142600 {
11443274Set142600 	return (PX_NO_ERROR);
1145383Set142600 }
1146383Set142600 
11475168Sarutz /*
11485168Sarutz  * Search the px_cb_list_t embedded in the px_cb_t for the
11495168Sarutz  * px_t of the specified Leaf (leaf_id).  Return its associated dip.
11505168Sarutz  */
11515168Sarutz static dev_info_t *
px_err_search_cb(px_cb_t * px_cb_p,uint_t leaf_id)11525168Sarutz px_err_search_cb(px_cb_t *px_cb_p, uint_t leaf_id)
11535168Sarutz {
11545168Sarutz 	int		i;
11555168Sarutz 	px_cb_list_t	*pxl_elemp;
11565168Sarutz 
11575168Sarutz 	for (i = px_cb_p->attachcnt, pxl_elemp = px_cb_p->pxl; i > 0;
11585168Sarutz 	    i--, pxl_elemp = pxl_elemp->next) {
11595168Sarutz 		if ((((pxu_t *)pxl_elemp->pxp->px_plat_p)->portid &
11605168Sarutz 		    OBERON_PORT_ID_LEAF_MASK) == leaf_id) {
11615168Sarutz 			return (pxl_elemp->pxp->px_dip);
11625168Sarutz 		}
11635168Sarutz 	}
11645168Sarutz 	return (NULL);
11655168Sarutz }
11663274Set142600 
11671772Sjl139090 /* UBC FATAL - see io erpt doc, section 1.1 */
11681772Sjl139090 /* ARGSUSED */
PX_ERPT_SEND_DEC(ubc_fatal)11691772Sjl139090 PX_ERPT_SEND_DEC(ubc_fatal)
11701772Sjl139090 {
11711772Sjl139090 	char		buf[FM_MAX_CLASS];
11721772Sjl139090 	uint64_t	memory_ue_log, marked;
11731772Sjl139090 	char		unum[FM_MAX_CLASS];
11741772Sjl139090 	int		unum_length;
11751772Sjl139090 	uint64_t	device_id = 0;
11761772Sjl139090 	uint8_t		cpu_version = 0;
11771772Sjl139090 	nvlist_t	*resource = NULL;
11785168Sarutz 	uint64_t	ubc_intr_status;
11795168Sarutz 	px_t		*px_p;
11805168Sarutz 	px_cb_t		*px_cb_p;
11815168Sarutz 	dev_info_t	*actual_dip;
11821772Sjl139090 
11831772Sjl139090 	unum[0] = '\0';
11841772Sjl139090 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
11851772Sjl139090 
11861772Sjl139090 	memory_ue_log = CSR_XR(csr_base, UBC_MEMORY_UE_LOG);
11871772Sjl139090 	marked = (memory_ue_log >> UBC_MEMORY_UE_LOG_MARKED) &
11881772Sjl139090 	    UBC_MEMORY_UE_LOG_MARKED_MASK;
11891772Sjl139090 
11901772Sjl139090 	if ((strstr(class_name, "ubc.piowtue") != NULL) ||
11911772Sjl139090 	    (strstr(class_name, "ubc.piowbeue") != NULL) ||
11921772Sjl139090 	    (strstr(class_name, "ubc.piorbeue") != NULL) ||
11931772Sjl139090 	    (strstr(class_name, "ubc.dmarduea") != NULL) ||
11941772Sjl139090 	    (strstr(class_name, "ubc.dmardueb") != NULL)) {
11951772Sjl139090 		int eid = (memory_ue_log >> UBC_MEMORY_UE_LOG_EID) &
11961772Sjl139090 		    UBC_MEMORY_UE_LOG_EID_MASK;
11971772Sjl139090 		(void) strncat(buf, ubc_class_eid_qualifier[eid],
11981772Sjl139090 		    FM_MAX_CLASS);
11991772Sjl139090 
12001772Sjl139090 		if (eid == UBC_EID_MEM) {
12011772Sjl139090 			uint64_t phys_addr = memory_ue_log &
12021772Sjl139090 			    MMU_OBERON_PADDR_MASK;
12031772Sjl139090 			uint64_t offset = (uint64_t)-1;
12041772Sjl139090 
12051772Sjl139090 			resource = fm_nvlist_create(NULL);
12061772Sjl139090 			if (&plat_get_mem_unum) {
12071772Sjl139090 				if ((plat_get_mem_unum(0,
12081772Sjl139090 				    phys_addr, 0, B_TRUE, 0, unum,
12091772Sjl139090 				    FM_MAX_CLASS, &unum_length)) != 0)
12101772Sjl139090 					unum[0] = '\0';
12111772Sjl139090 			}
12121772Sjl139090 			fm_fmri_mem_set(resource, FM_MEM_SCHEME_VERSION,
12134853Segillett 			    NULL, unum, NULL, offset);
12141772Sjl139090 
12151772Sjl139090 		} else if (eid == UBC_EID_CPU) {
12161772Sjl139090 			int cpuid = (marked & UBC_MARKED_MAX_CPUID_MASK);
12171772Sjl139090 			char sbuf[21]; /* sizeof (UINT64_MAX) + '\0' */
12181772Sjl139090 
12191772Sjl139090 			resource = fm_nvlist_create(NULL);
12201772Sjl139090 			cpu_version = cpunodes[cpuid].version;
12211772Sjl139090 			device_id = cpunodes[cpuid].device_id;
12221772Sjl139090 			(void) snprintf(sbuf, sizeof (sbuf), "%lX",
12231772Sjl139090 			    device_id);
12241772Sjl139090 			(void) fm_fmri_cpu_set(resource,
12251772Sjl139090 			    FM_CPU_SCHEME_VERSION, NULL, cpuid,
12261772Sjl139090 			    &cpu_version, sbuf);
12271772Sjl139090 		}
12281772Sjl139090 	}
12291772Sjl139090 
12305168Sarutz 	/*
12315168Sarutz 	 * For most of the errors represented in the UBC Interrupt Status
12325168Sarutz 	 * register, one can compute the dip of the actual Leaf that was
12335168Sarutz 	 * involved in the error.  To do this, find the px_cb_t structure
12345168Sarutz 	 * that is shared between a pair of Leaves (eg, LeafA and LeafB).
12355168Sarutz 	 *
12365168Sarutz 	 * If any of the error bits for LeafA are set in the hardware
12375168Sarutz 	 * register, search the list of px_t's rooted in the px_cb_t for
12385168Sarutz 	 * the one corresponding to LeafA.  If error bits for LeafB are set,
12395168Sarutz 	 * search the list for LeafB's px_t.  The px_t references its
12405168Sarutz 	 * associated dip.
12415168Sarutz 	 */
12425168Sarutz 	px_p = DIP_TO_STATE(rpdip);
12435168Sarutz 	px_cb_p = ((pxu_t *)px_p->px_plat_p)->px_cb_p;
12445168Sarutz 
12455168Sarutz 	/* read hardware register */
12465168Sarutz 	ubc_intr_status = CSR_XR(csr_base, UBC_INTERRUPT_STATUS);
12475168Sarutz 
12485168Sarutz 	if ((ubc_intr_status & UBC_INTERRUPT_STATUS_LEAFA) != 0) {
12495168Sarutz 		/* then Leaf A is involved in the error */
12505168Sarutz 		actual_dip = px_err_search_cb(px_cb_p, OBERON_PORT_ID_LEAF_A);
12515168Sarutz 		ASSERT(actual_dip != NULL);
12525168Sarutz 		rpdip = actual_dip;
12535168Sarutz 	} else if ((ubc_intr_status & UBC_INTERRUPT_STATUS_LEAFB) != 0) {
12545168Sarutz 		/* then Leaf B is involved in the error */
12555168Sarutz 		actual_dip = px_err_search_cb(px_cb_p, OBERON_PORT_ID_LEAF_B);
12565168Sarutz 		ASSERT(actual_dip != NULL);
12575168Sarutz 		rpdip = actual_dip;
12585168Sarutz 	} /* else error cannot be associated with a Leaf */
12595168Sarutz 
12601772Sjl139090 	if (resource) {
12611772Sjl139090 		ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
12621772Sjl139090 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
12631772Sjl139090 		    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
12641772Sjl139090 		    OBERON_UBC_ELE, DATA_TYPE_UINT64,
12651772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_LOG_ENABLE),
12661772Sjl139090 		    OBERON_UBC_IE, DATA_TYPE_UINT64,
12671772Sjl139090 		    CSR_XR(csr_base, UBC_INTERRUPT_ENABLE),
12685168Sarutz 		    OBERON_UBC_IS, DATA_TYPE_UINT64, ubc_intr_status,
12691772Sjl139090 		    OBERON_UBC_ESS, DATA_TYPE_UINT64,
12701772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_STATUS_SET),
12711772Sjl139090 		    OBERON_UBC_MUE, DATA_TYPE_UINT64, memory_ue_log,
12721772Sjl139090 		    OBERON_UBC_UNUM, DATA_TYPE_STRING, unum,
12731772Sjl139090 		    OBERON_UBC_DID, DATA_TYPE_UINT64, device_id,
12741772Sjl139090 		    OBERON_UBC_CPUV, DATA_TYPE_UINT32, cpu_version,
12751772Sjl139090 		    OBERON_UBC_RESOURCE, DATA_TYPE_NVLIST, resource,
12761772Sjl139090 		    NULL);
12771772Sjl139090 		fm_nvlist_destroy(resource, FM_NVA_FREE);
12781772Sjl139090 	} else {
12791772Sjl139090 		ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
12801772Sjl139090 		    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
12811772Sjl139090 		    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
12821772Sjl139090 		    OBERON_UBC_ELE, DATA_TYPE_UINT64,
12831772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_LOG_ENABLE),
12841772Sjl139090 		    OBERON_UBC_IE, DATA_TYPE_UINT64,
12851772Sjl139090 		    CSR_XR(csr_base, UBC_INTERRUPT_ENABLE),
12865168Sarutz 		    OBERON_UBC_IS, DATA_TYPE_UINT64, ubc_intr_status,
12871772Sjl139090 		    OBERON_UBC_ESS, DATA_TYPE_UINT64,
12881772Sjl139090 		    CSR_XR(csr_base, UBC_ERROR_STATUS_SET),
12891772Sjl139090 		    OBERON_UBC_MUE, DATA_TYPE_UINT64, memory_ue_log,
12901772Sjl139090 		    OBERON_UBC_UNUM, DATA_TYPE_STRING, unum,
12911772Sjl139090 		    OBERON_UBC_DID, DATA_TYPE_UINT64, device_id,
12921772Sjl139090 		    OBERON_UBC_CPUV, DATA_TYPE_UINT32, cpu_version,
12931772Sjl139090 		    NULL);
12941772Sjl139090 	}
12951772Sjl139090 
12963274Set142600 	return (PX_NO_PANIC);
12971772Sjl139090 }
1298383Set142600 
12993274Set142600 /* JBC FATAL */
PX_ERPT_SEND_DEC(jbc_fatal)130027Sjchu PX_ERPT_SEND_DEC(jbc_fatal)
130127Sjchu {
130227Sjchu 	char		buf[FM_MAX_CLASS];
1303739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
130427Sjchu 
130527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
130627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
130727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1308739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
130927Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
131027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
131127Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
131227Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
131327Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
131427Sjchu 	    ss_reg,
131527Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
131627Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
131727Sjchu 	    FIRE_JBC_FEL1, DATA_TYPE_UINT64,
131827Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_1),
131927Sjchu 	    FIRE_JBC_FEL2, DATA_TYPE_UINT64,
132027Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_2),
132127Sjchu 	    NULL);
132227Sjchu 
13233274Set142600 	return (PX_NO_PANIC);
132427Sjchu }
132527Sjchu 
13263274Set142600 /* JBC MERGE */
PX_ERPT_SEND_DEC(jbc_merge)132727Sjchu PX_ERPT_SEND_DEC(jbc_merge)
132827Sjchu {
132927Sjchu 	char		buf[FM_MAX_CLASS];
1330739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
133127Sjchu 
133227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
133327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
133427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1335739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
133627Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
133727Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
133827Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
133927Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
134027Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
134127Sjchu 	    ss_reg,
134227Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
134327Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
134427Sjchu 	    FIRE_JBC_MTEL, DATA_TYPE_UINT64,
134527Sjchu 	    CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG),
134627Sjchu 	    NULL);
134727Sjchu 
13483274Set142600 	return (PX_NO_PANIC);
134927Sjchu }
135027Sjchu 
135127Sjchu /*
13523274Set142600  * JBC Merge buffer retryable errors:
13533274Set142600  *    Merge buffer parity error (rd_buf): PIO or DMA
13543274Set142600  *    Merge buffer parity error (wr_buf): PIO or DMA
135527Sjchu  */
135627Sjchu /* ARGSUSED */
135727Sjchu int
px_err_jbc_merge_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)135827Sjchu px_err_jbc_merge_handle(dev_info_t *rpdip, caddr_t csr_base,
13593274Set142600     ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
13603274Set142600     px_err_bit_desc_t *err_bit_descr)
136127Sjchu {
13623274Set142600 	/*
13633274Set142600 	 * Holder function to attempt error recovery.  When the features
13643274Set142600 	 * are in place, look up the address of the transaction in:
13653274Set142600 	 *
13663274Set142600 	 * paddr = CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG);
13673274Set142600 	 * paddr &= MERGE_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
13683274Set142600 	 *
13693274Set142600 	 * If the error is a secondary error, there is no log information
13703274Set142600 	 * just panic as it is unknown which address has been affected.
13713274Set142600 	 *
13723274Set142600 	 * Remember the address is pretranslation and might be hard to look
13733274Set142600 	 * up the appropriate driver based on the PA.
13743274Set142600 	 */
13753274Set142600 	return (px_err_panic_handle(rpdip, csr_base, derr, err_reg_descr,
13764853Segillett 	    err_bit_descr));
137727Sjchu }
137827Sjchu 
13793274Set142600 /* JBC Jbusint IN */
PX_ERPT_SEND_DEC(jbc_in)138027Sjchu PX_ERPT_SEND_DEC(jbc_in)
138127Sjchu {
138227Sjchu 	char		buf[FM_MAX_CLASS];
1383739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
138427Sjchu 
138527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
138627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
138727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1388739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
138927Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
139027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
139127Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
139227Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
139327Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
139427Sjchu 	    ss_reg,
139527Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
139627Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
139727Sjchu 	    FIRE_JBC_JITEL1, DATA_TYPE_UINT64,
139827Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG),
139927Sjchu 	    FIRE_JBC_JITEL2, DATA_TYPE_UINT64,
140027Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG_2),
140127Sjchu 	    NULL);
140227Sjchu 
14033274Set142600 	return (PX_NO_PANIC);
140427Sjchu }
140527Sjchu 
140627Sjchu /*
14073274Set142600  * JBC Jbusint IN retryable errors
140827Sjchu  * Log Reg[42:0].
14093274Set142600  *    Write Data Parity Error: PIO Writes
14103274Set142600  *    Read Data Parity Error: DMA Reads
141127Sjchu  */
141227Sjchu int
px_err_jbc_jbusint_in_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)141327Sjchu px_err_jbc_jbusint_in_handle(dev_info_t *rpdip, caddr_t csr_base,
141427Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
141527Sjchu 	px_err_bit_desc_t *err_bit_descr)
141627Sjchu {
14173274Set142600 	/*
14183274Set142600 	 * Holder function to attempt error recovery.  When the features
14193274Set142600 	 * are in place, look up the address of the transaction in:
14203274Set142600 	 *
14213274Set142600 	 * paddr = CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG);
14223274Set142600 	 * paddr &= JBCINT_IN_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
14233274Set142600 	 *
14243274Set142600 	 * If the error is a secondary error, there is no log information
14253274Set142600 	 * just panic as it is unknown which address has been affected.
14263274Set142600 	 *
14273274Set142600 	 * Remember the address is pretranslation and might be hard to look
14283274Set142600 	 * up the appropriate driver based on the PA.
14293274Set142600 	 */
14303274Set142600 	return (px_err_panic_handle(rpdip, csr_base, derr, err_reg_descr,
14314853Segillett 	    err_bit_descr));
143227Sjchu }
143327Sjchu 
143427Sjchu 
14353274Set142600 /* JBC Jbusint Out */
PX_ERPT_SEND_DEC(jbc_out)143627Sjchu PX_ERPT_SEND_DEC(jbc_out)
143727Sjchu {
143827Sjchu 	char		buf[FM_MAX_CLASS];
1439739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
144027Sjchu 
144127Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
144227Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
144327Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1444739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
144527Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
144627Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
144727Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
144827Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
144927Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
145027Sjchu 	    ss_reg,
145127Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
145227Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
145327Sjchu 	    FIRE_JBC_JOTEL1, DATA_TYPE_UINT64,
145427Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG),
145527Sjchu 	    FIRE_JBC_JOTEL2, DATA_TYPE_UINT64,
145627Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG_2),
145727Sjchu 	    NULL);
145827Sjchu 
14593274Set142600 	return (PX_NO_PANIC);
146027Sjchu }
146127Sjchu 
14623274Set142600 /* JBC Dmcint ODCD */
PX_ERPT_SEND_DEC(jbc_odcd)146327Sjchu PX_ERPT_SEND_DEC(jbc_odcd)
146427Sjchu {
146527Sjchu 	char		buf[FM_MAX_CLASS];
1466739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
146727Sjchu 
146827Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
146927Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
147027Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1471739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
147227Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
147327Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
147427Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
147527Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
147627Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
147727Sjchu 	    ss_reg,
147827Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
147927Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
148027Sjchu 	    FIRE_JBC_DMC_ODCD, DATA_TYPE_UINT64,
148127Sjchu 	    CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG),
148227Sjchu 	    NULL);
148327Sjchu 
14843274Set142600 	return (PX_NO_PANIC);
148527Sjchu }
148627Sjchu 
148727Sjchu /*
148827Sjchu  * JBC Dmcint ODCO nonfatal errer handling -
14893274Set142600  *    PIO data parity error: PIO
149027Sjchu  */
149127Sjchu /* ARGSUSED */
149227Sjchu int
px_err_jbc_dmcint_odcd_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)149327Sjchu px_err_jbc_dmcint_odcd_handle(dev_info_t *rpdip, caddr_t csr_base,
149427Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
149527Sjchu 	px_err_bit_desc_t *err_bit_descr)
149627Sjchu {
14973274Set142600 	/*
14983274Set142600 	 * Holder function to attempt error recovery.  When the features
14993274Set142600 	 * are in place, look up the address of the transaction in:
15003274Set142600 	 *
15013274Set142600 	 * paddr = CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG);
15023274Set142600 	 * paddr &= DMCINT_ODCD_ERROR_LOG_ADDRESS_MASK;
15033274Set142600 	 *
15043274Set142600 	 * If the error is a secondary error, there is no log information
15053274Set142600 	 * just panic as it is unknown which address has been affected.
15063274Set142600 	 *
15073274Set142600 	 * Remember the address is pretranslation and might be hard to look
15083274Set142600 	 * up the appropriate driver based on the PA.
15093274Set142600 	 */
15103274Set142600 	return (px_err_panic_handle(rpdip, csr_base, derr, err_reg_descr,
15114853Segillett 	    err_bit_descr));
151227Sjchu }
151327Sjchu 
15142276Sschwartz /* Does address in DMCINT error log register match address of pcitool access? */
15152276Sschwartz static boolean_t
px_jbc_pcitool_addr_match(dev_info_t * rpdip,caddr_t csr_base)15162276Sschwartz px_jbc_pcitool_addr_match(dev_info_t *rpdip, caddr_t csr_base)
15172276Sschwartz {
15182276Sschwartz 	px_t	*px_p = DIP_TO_STATE(rpdip);
15192276Sschwartz 	pxu_t	*pxu_p = (pxu_t *)px_p->px_plat_p;
15202276Sschwartz 	caddr_t	pcitool_addr = pxu_p->pcitool_addr;
15212276Sschwartz 	caddr_t errlog_addr =
15222276Sschwartz 	    (caddr_t)CSR_FR(csr_base, DMCINT_ODCD_ERROR_LOG, ADDRESS);
15232276Sschwartz 
15242276Sschwartz 	return (pcitool_addr == errlog_addr);
15252276Sschwartz }
15262276Sschwartz 
15272276Sschwartz /*
15282276Sschwartz  * JBC Dmcint ODCD errer handling for errors which are forgivable during a safe
15292276Sschwartz  * access.  (This will be most likely be a PCItool access.)  If not a safe
15302276Sschwartz  * access context, treat like jbc_dmcint_odcd.
15312276Sschwartz  *    Unmapped PIO read error: pio:read:M:nonfatal
15322276Sschwartz  *    Unmapped PIO write error: pio:write:M:nonfatal
15332276Sschwartz  *    Invalid PIO write to PCIe cfg/io, csr, ebus or i2c bus: pio:write:nonfatal
15342276Sschwartz  *    Invalid PIO read to PCIe cfg/io, csr, ebus or i2c bus: pio:read:nonfatal
15352276Sschwartz  */
15362276Sschwartz /* ARGSUSED */
15372276Sschwartz int
px_err_jbc_safe_acc_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)15382276Sschwartz px_err_jbc_safe_acc_handle(dev_info_t *rpdip, caddr_t csr_base,
15392276Sschwartz 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
15402276Sschwartz 	px_err_bit_desc_t *err_bit_descr)
15412276Sschwartz {
15422276Sschwartz 	boolean_t	pri = PX_ERR_IS_PRI(err_bit_descr->bit);
15432276Sschwartz 
15442276Sschwartz 	if (!pri)
15453274Set142600 		return (px_err_panic_handle(rpdip, csr_base, derr,
15464853Segillett 		    err_reg_descr, err_bit_descr));
15472276Sschwartz 	/*
15482276Sschwartz 	 * Got an error which is forgivable during a PCItool access.
15492276Sschwartz 	 *
15502276Sschwartz 	 * Don't do handler check since the error may otherwise be unfairly
15512276Sschwartz 	 * attributed to a device.  Just return.
15522276Sschwartz 	 *
15532276Sschwartz 	 * Note: There is a hole here in that a legitimate error can come in
15542276Sschwartz 	 * while a PCItool access is in play and be forgiven.  This is possible
15552276Sschwartz 	 * though not likely.
15562276Sschwartz 	 */
15572276Sschwartz 	if ((derr->fme_flag != DDI_FM_ERR_UNEXPECTED) &&
15582276Sschwartz 	    (px_jbc_pcitool_addr_match(rpdip, csr_base)))
15593274Set142600 		return (px_err_protected_handle(rpdip, csr_base, derr,
15604853Segillett 		    err_reg_descr, err_bit_descr));
15612276Sschwartz 
15622276Sschwartz 	return (px_err_jbc_dmcint_odcd_handle(rpdip, csr_base, derr,
15632276Sschwartz 	    err_reg_descr, err_bit_descr));
15642276Sschwartz }
15652276Sschwartz 
15663274Set142600 /* JBC Dmcint IDC */
PX_ERPT_SEND_DEC(jbc_idc)156727Sjchu PX_ERPT_SEND_DEC(jbc_idc)
156827Sjchu {
156927Sjchu 	char		buf[FM_MAX_CLASS];
1570739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
157127Sjchu 
157227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
157327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
157427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1575739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
157627Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
157727Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
157827Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
157927Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
158027Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
158127Sjchu 	    ss_reg,
158227Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
158327Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
158427Sjchu 	    FIRE_JBC_DMC_IDC, DATA_TYPE_UINT64,
158527Sjchu 	    CSR_XR(csr_base, DMCINT_IDC_ERROR_LOG),
158627Sjchu 	    NULL);
158727Sjchu 
15883274Set142600 	return (PX_NO_PANIC);
158927Sjchu }
159027Sjchu 
15913274Set142600 /* JBC CSR */
PX_ERPT_SEND_DEC(jbc_csr)159227Sjchu PX_ERPT_SEND_DEC(jbc_csr)
159327Sjchu {
159427Sjchu 	char		buf[FM_MAX_CLASS];
1595739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
159627Sjchu 
159727Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
159827Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
159927Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1600739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
160127Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
160227Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
160327Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
160427Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
160527Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
160627Sjchu 	    ss_reg,
160727Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
160827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
160927Sjchu 	    "jbc-error-reg", DATA_TYPE_UINT64,
161027Sjchu 	    CSR_XR(csr_base, CSR_ERROR_LOG),
161127Sjchu 	    NULL);
161227Sjchu 
16133274Set142600 	return (PX_NO_PANIC);
161427Sjchu }
161527Sjchu 
16163274Set142600 /* DMC IMU RDS */
PX_ERPT_SEND_DEC(imu_rds)161727Sjchu PX_ERPT_SEND_DEC(imu_rds)
161827Sjchu {
161927Sjchu 	char		buf[FM_MAX_CLASS];
1620739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
162127Sjchu 
162227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
162327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
162427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1625739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
162627Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
162727Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
162827Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
162927Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
163027Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
163127Sjchu 	    ss_reg,
163227Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
163327Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
163427Sjchu 	    FIRE_IMU_RDS, DATA_TYPE_UINT64,
163527Sjchu 	    CSR_XR(csr_base, IMU_RDS_ERROR_LOG),
163627Sjchu 	    NULL);
163727Sjchu 
16383274Set142600 	return (PX_NO_PANIC);
1639118Sjchu }
1640118Sjchu 
164127Sjchu /* handle EQ overflow */
164227Sjchu /* ARGSUSED */
164327Sjchu int
px_err_imu_eq_ovfl_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)164427Sjchu px_err_imu_eq_ovfl_handle(dev_info_t *rpdip, caddr_t csr_base,
164527Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
164627Sjchu 	px_err_bit_desc_t *err_bit_descr)
164727Sjchu {
16483274Set142600 	px_t	*px_p = DIP_TO_STATE(rpdip);
16493274Set142600 	pxu_t	*pxu_p = (pxu_t *)px_p->px_plat_p;
16503274Set142600 	int	err = px_err_check_eq(rpdip);
165127Sjchu 
16523274Set142600 	if ((err == PX_PANIC) && (pxu_p->cpr_flag == PX_NOT_CPR)) {
16533274Set142600 		return (px_err_panic_handle(rpdip, csr_base, derr,
16544853Segillett 		    err_reg_descr, err_bit_descr));
16553274Set142600 	} else {
16563274Set142600 		return (px_err_no_panic_handle(rpdip, csr_base, derr,
16574853Segillett 		    err_reg_descr, err_bit_descr));
165827Sjchu 	}
165927Sjchu }
166027Sjchu 
16613274Set142600 /* DMC IMU SCS */
PX_ERPT_SEND_DEC(imu_scs)166227Sjchu PX_ERPT_SEND_DEC(imu_scs)
166327Sjchu {
166427Sjchu 	char		buf[FM_MAX_CLASS];
1665739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
166627Sjchu 
166727Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
166827Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
166927Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1670739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
167127Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
167227Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
167327Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
167427Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
167527Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
167627Sjchu 	    ss_reg,
167727Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
167827Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
167927Sjchu 	    FIRE_IMU_SCS, DATA_TYPE_UINT64,
168027Sjchu 	    CSR_XR(csr_base, IMU_SCS_ERROR_LOG),
168127Sjchu 	    NULL);
168227Sjchu 
16833274Set142600 	return (PX_NO_PANIC);
168427Sjchu }
168527Sjchu 
16863274Set142600 /* DMC IMU */
PX_ERPT_SEND_DEC(imu)168727Sjchu PX_ERPT_SEND_DEC(imu)
168827Sjchu {
168927Sjchu 	char		buf[FM_MAX_CLASS];
1690739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
169127Sjchu 
169227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
169327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
169427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1695739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
169627Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
169727Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
169827Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
169927Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
170027Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
170127Sjchu 	    ss_reg,
170227Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
170327Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
170427Sjchu 	    NULL);
170527Sjchu 
17063274Set142600 	return (PX_NO_PANIC);
170727Sjchu }
170827Sjchu 
17093274Set142600 /* DMC MMU TFAR/TFSR */
PX_ERPT_SEND_DEC(mmu_tfar_tfsr)171027Sjchu PX_ERPT_SEND_DEC(mmu_tfar_tfsr)
171127Sjchu {
171227Sjchu 	char		buf[FM_MAX_CLASS];
1713739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
17143274Set142600 	px_t		*px_p = DIP_TO_STATE(rpdip);
17159921SKrishna.Elango@Sun.COM 	pcie_req_id_t	fault_bdf = PCIE_INVALID_BDF;
17163274Set142600 	uint16_t	s_status = 0;
17173274Set142600 
17183274Set142600 	if (pri) {
17193274Set142600 		fault_bdf = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_STATUS)
17203274Set142600 		    & (MMU_TRANSLATION_FAULT_STATUS_ID_MASK <<
17213274Set142600 		    MMU_TRANSLATION_FAULT_STATUS_ID);
17223274Set142600 		s_status = PCI_STAT_S_TARG_AB;
17233274Set142600 
17243274Set142600 		/* Only PIO Fault Addresses are valid, this is DMA */
17253274Set142600 		(void) px_rp_en_q(px_p, fault_bdf, NULL, s_status);
17263274Set142600 	}
172727Sjchu 
172827Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
17291772Sjl139090 
173027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
173127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1732739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
173327Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
173427Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
173527Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
173627Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
173727Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
173827Sjchu 	    ss_reg,
173927Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
174027Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
174127Sjchu 	    FIRE_MMU_TFAR, DATA_TYPE_UINT64,
174227Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS),
174327Sjchu 	    FIRE_MMU_TFSR, DATA_TYPE_UINT64,
174427Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_STATUS),
174527Sjchu 	    NULL);
174627Sjchu 
17473274Set142600 	return (PX_NO_PANIC);
174827Sjchu }
174927Sjchu 
17503274Set142600 /* DMC MMU */
PX_ERPT_SEND_DEC(mmu)175127Sjchu PX_ERPT_SEND_DEC(mmu)
175227Sjchu {
175327Sjchu 	char		buf[FM_MAX_CLASS];
1754739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
175527Sjchu 
175627Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
175727Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
175827Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1759739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
176027Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
176127Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
176227Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
176327Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
176427Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
176527Sjchu 	    ss_reg,
176627Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
176727Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
176827Sjchu 	    NULL);
176927Sjchu 
17703274Set142600 	return (PX_NO_PANIC);
177127Sjchu }
177227Sjchu 
17733274Set142600 /*
17743274Set142600  * IMU function to handle all Received but Not Enabled errors.
17753274Set142600  *
17763274Set142600  * These errors are due to transactions modes in which the PX driver was not
17773274Set142600  * setup to be able to do.  If possible, inform the driver that their DMA has
17783274Set142600  * failed by marking their DMA handle as failed, but do not panic the system.
17793274Set142600  * Most likely the address is not valid, as Fire wasn't setup to handle them in
17803274Set142600  * the first place.
17813274Set142600  *
17823274Set142600  * These errors are not retryable, unless the PX mode has changed, otherwise the
17833274Set142600  * same error will occur again.
17843274Set142600  */
178527Sjchu int
px_err_mmu_rbne_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)178627Sjchu px_err_mmu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
178727Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
178827Sjchu 	px_err_bit_desc_t *err_bit_descr)
178927Sjchu {
17903274Set142600 	pcie_req_id_t bdf;
179127Sjchu 
17923274Set142600 	if (!PX_ERR_IS_PRI(err_bit_descr->bit))
17933274Set142600 		goto done;
1794260Set142600 
17953274Set142600 	bdf = (pcie_req_id_t)CSR_FR(csr_base, MMU_TRANSLATION_FAULT_STATUS, ID);
17966313Skrishnae 	(void) pf_hdl_lookup(rpdip, derr->fme_ena, PF_ADDR_DMA, NULL,
17973274Set142600 	    bdf);
179827Sjchu 
17993274Set142600 done:
18003274Set142600 	return (px_err_no_panic_handle(rpdip, csr_base, derr, err_reg_descr,
18014853Segillett 	    err_bit_descr));
180227Sjchu }
180327Sjchu 
18043274Set142600 /*
18053274Set142600  * IMU function to handle all invalid address errors.
18063274Set142600  *
18073274Set142600  * These errors are due to transactions in which the address is not recognized.
18083274Set142600  * If possible, inform the driver that all DMAs have failed by marking their DMA
18093274Set142600  * handles.  Fire should not panic the system, it'll be up to the driver to
18103274Set142600  * panic.  The address logged is invalid.
18113274Set142600  *
18123274Set142600  * These errors are not retryable since retrying the same transaction with the
18133274Set142600  * same invalid address will result in the same error.
18143274Set142600  */
181527Sjchu /* ARGSUSED */
181627Sjchu int
px_err_mmu_tfa_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)181727Sjchu px_err_mmu_tfa_handle(dev_info_t *rpdip, caddr_t csr_base,
181827Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
181927Sjchu 	px_err_bit_desc_t *err_bit_descr)
182027Sjchu {
18213274Set142600 	pcie_req_id_t bdf;
18223274Set142600 
18233274Set142600 	if (!PX_ERR_IS_PRI(err_bit_descr->bit))
18243274Set142600 		goto done;
182527Sjchu 
18263274Set142600 	bdf = (pcie_req_id_t)CSR_FR(csr_base, MMU_TRANSLATION_FAULT_STATUS, ID);
18276313Skrishnae 	(void) pf_hdl_lookup(rpdip, derr->fme_ena, PF_ADDR_DMA, NULL,
18283274Set142600 	    bdf);
1829739Sjchu 
18303274Set142600 done:
18313274Set142600 	return (px_err_no_panic_handle(rpdip, csr_base, derr, err_reg_descr,
18324853Segillett 	    err_bit_descr));
183327Sjchu }
183427Sjchu 
18353274Set142600 /*
18363274Set142600  * IMU function to handle normal transactions that encounter a parity error.
18373274Set142600  *
18383274Set142600  * These errors are due to transactions that enouter a parity error. If
18393274Set142600  * possible, inform the driver that their DMA have failed and that they should
18403274Set142600  * retry.  If Fire is unable to contact the leaf driver, panic the system.
18413274Set142600  * Otherwise, it'll be up to the device to determine is this is a panicable
18423274Set142600  * error.
18433274Set142600  */
184427Sjchu /* ARGSUSED */
184527Sjchu int
px_err_mmu_parity_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)18463274Set142600 px_err_mmu_parity_handle(dev_info_t *rpdip, caddr_t csr_base,
184727Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
184827Sjchu 	px_err_bit_desc_t *err_bit_descr)
184927Sjchu {
18503274Set142600 	uint64_t mmu_tfa;
18513274Set142600 	pcie_req_id_t bdf;
18524853Segillett 	int status = PF_HDL_NOTFOUND;
185327Sjchu 
18543274Set142600 	if (!PX_ERR_IS_PRI(err_bit_descr->bit))
18553274Set142600 		goto done;
1856739Sjchu 
185727Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
18583274Set142600 	bdf = (pcie_req_id_t)CSR_FR(csr_base, MMU_TRANSLATION_FAULT_STATUS, ID);
18596313Skrishnae 	status = pf_hdl_lookup(rpdip, derr->fme_ena, PF_ADDR_DMA,
18603274Set142600 	    (uint32_t)mmu_tfa, bdf);
18613274Set142600 
18623274Set142600 done:
18634853Segillett 	if (status == PF_HDL_NOTFOUND)
18643274Set142600 		return (px_err_panic_handle(rpdip, csr_base, derr,
18654853Segillett 		    err_reg_descr, err_bit_descr));
18663274Set142600 	else
18673274Set142600 		return (px_err_no_panic_handle(rpdip, csr_base, derr,
18684853Segillett 		    err_reg_descr, err_bit_descr));
18693274Set142600 }
18703274Set142600 
18713274Set142600 /*
18723274Set142600  * wuc/ruc event - Mark the handle of the failed PIO access.  Return "no_panic"
18733274Set142600  */
18743274Set142600 /* ARGSUSED */
18753274Set142600 int
px_err_wuc_ruc_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)18763274Set142600 px_err_wuc_ruc_handle(dev_info_t *rpdip, caddr_t csr_base,
18773274Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
18783274Set142600 	px_err_bit_desc_t *err_bit_descr)
18793274Set142600 {
18803274Set142600 	px_t		*px_p = DIP_TO_STATE(rpdip);
18813274Set142600 	pxu_t		*pxu_p = (pxu_t *)px_p->px_plat_p;
18823274Set142600 	uint64_t 	data;
18836313Skrishnae 	pf_pcie_adv_err_regs_t adv_reg;
18846313Skrishnae 	int		sts;
188527Sjchu 
18863274Set142600 	if (!PX_ERR_IS_PRI(err_bit_descr->bit))
18873274Set142600 		goto done;
18883274Set142600 
18893274Set142600 	data = CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG);
18906313Skrishnae 	adv_reg.pcie_ue_hdr[0] = (uint32_t)(data >> 32);
18916313Skrishnae 	adv_reg.pcie_ue_hdr[1] = (uint32_t)(data & 0xFFFFFFFF);
18923274Set142600 	data = CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG);
18936313Skrishnae 	adv_reg.pcie_ue_hdr[2] = (uint32_t)(data >> 32);
18946313Skrishnae 	adv_reg.pcie_ue_hdr[3] = (uint32_t)(data & 0xFFFFFFFF);
18953274Set142600 
189611311SSurya.Prakki@Sun.COM 	(void) pf_tlp_decode(PCIE_DIP2BUS(rpdip), &adv_reg);
18976313Skrishnae 	sts = pf_hdl_lookup(rpdip, derr->fme_ena, adv_reg.pcie_ue_tgt_trans,
18986313Skrishnae 	    adv_reg.pcie_ue_tgt_addr, adv_reg.pcie_ue_tgt_bdf);
18993274Set142600 done:
19003274Set142600 	if ((sts == PF_HDL_NOTFOUND) && (pxu_p->cpr_flag == PX_NOT_CPR))
19013274Set142600 		return (px_err_protected_handle(rpdip, csr_base, derr,
19024853Segillett 		    err_reg_descr, err_bit_descr));
19033274Set142600 
19043274Set142600 	return (px_err_no_panic_handle(rpdip, csr_base, derr,
19054853Segillett 	    err_reg_descr, err_bit_descr));
190627Sjchu }
190727Sjchu 
1908118Sjchu /*
19091147Sjchu  * TLU LUP event - if caused by power management activity, then it is expected.
19101147Sjchu  * In all other cases, it is an error.
1911118Sjchu  */
1912118Sjchu /* ARGSUSED */
1913118Sjchu int
px_err_tlu_lup_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)1914118Sjchu px_err_tlu_lup_handle(dev_info_t *rpdip, caddr_t csr_base,
1915118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1916118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1917118Sjchu {
1918118Sjchu 	px_t	*px_p = DIP_TO_STATE(rpdip);
1919118Sjchu 
1920118Sjchu 	/*
19211147Sjchu 	 * power management code is currently the only segment that sets
19221147Sjchu 	 * px_lup_pending to indicate its expectation for a healthy LUP
19231147Sjchu 	 * event.  For all other occasions, LUP event should be flaged as
19241147Sjchu 	 * error condition.
1925118Sjchu 	 */
19261147Sjchu 	return ((atomic_cas_32(&px_p->px_lup_pending, 1, 0) == 0) ?
19273274Set142600 	    PX_NO_PANIC : PX_EXPECTED);
19281147Sjchu }
1929118Sjchu 
19301147Sjchu /*
19311147Sjchu  * TLU LDN event - if caused by power management activity, then it is expected.
19321147Sjchu  * In all other cases, it is an error.
19331147Sjchu  */
19341147Sjchu /* ARGSUSED */
19351147Sjchu int
px_err_tlu_ldn_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)19361147Sjchu px_err_tlu_ldn_handle(dev_info_t *rpdip, caddr_t csr_base,
19371147Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
19381147Sjchu 	px_err_bit_desc_t *err_bit_descr)
19391147Sjchu {
19401147Sjchu 	px_t    *px_p = DIP_TO_STATE(rpdip);
19413274Set142600 	return ((px_p->px_pm_flags & PX_LDN_EXPECTED) ? PX_EXPECTED :
19423274Set142600 	    PX_NO_PANIC);
1943118Sjchu }
1944118Sjchu 
194527Sjchu /* PEC ILU none - see io erpt doc, section 3.1 */
PX_ERPT_SEND_DEC(pec_ilu)194627Sjchu PX_ERPT_SEND_DEC(pec_ilu)
194727Sjchu {
194827Sjchu 	char		buf[FM_MAX_CLASS];
1949739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
195027Sjchu 
195127Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
195227Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
195327Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
1954739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
195527Sjchu 	    FIRE_ILU_ELE, DATA_TYPE_UINT64,
195627Sjchu 	    CSR_XR(csr_base, ILU_ERROR_LOG_ENABLE),
195727Sjchu 	    FIRE_ILU_IE, DATA_TYPE_UINT64,
195827Sjchu 	    CSR_XR(csr_base, ILU_INTERRUPT_ENABLE),
195927Sjchu 	    FIRE_ILU_IS, DATA_TYPE_UINT64,
196027Sjchu 	    ss_reg,
196127Sjchu 	    FIRE_ILU_ESS, DATA_TYPE_UINT64,
196227Sjchu 	    CSR_XR(csr_base, ILU_ERROR_STATUS_SET),
196327Sjchu 	    NULL);
196427Sjchu 
19653274Set142600 	return (PX_NO_PANIC);
196627Sjchu }
196727Sjchu 
1968383Set142600 /* PCIEX UE Errors */
1969383Set142600 /* ARGSUSED */
1970671Skrishnae int
px_err_pciex_ue_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)1971383Set142600 px_err_pciex_ue_handle(dev_info_t *rpdip, caddr_t csr_base,
1972383Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1973383Set142600 	px_err_bit_desc_t *err_bit_descr)
1974383Set142600 {
19753274Set142600 	px_err_pcie_t	regs = {0};
19763274Set142600 	uint32_t	err_bit;
19773274Set142600 	int		err;
19783274Set142600 	uint64_t	log;
19793274Set142600 
19803274Set142600 	if (err_bit_descr->bit < 32) {
19813274Set142600 		err_bit = (uint32_t)BITMASK(err_bit_descr->bit);
19823274Set142600 		regs.ue_reg = err_bit;
19833274Set142600 		regs.primary_ue = err_bit;
19843274Set142600 
19853274Set142600 		/*
19866313Skrishnae 		 * Log the Received Log for PTLP, UR and UC.
19873274Set142600 		 */
19886313Skrishnae 		if ((PCIE_AER_UCE_PTLP | PCIE_AER_UCE_UR | PCIE_AER_UCE_UC) &
19896313Skrishnae 		    err_bit) {
19903274Set142600 			log = CSR_XR(csr_base,
19913274Set142600 			    TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG);
19923274Set142600 			regs.rx_hdr1 = (uint32_t)(log >> 32);
19936313Skrishnae 			regs.rx_hdr2 = (uint32_t)(log & 0xFFFFFFFF);
1994383Set142600 
19953274Set142600 			log = CSR_XR(csr_base,
19963274Set142600 			    TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG);
19973274Set142600 			regs.rx_hdr3 = (uint32_t)(log >> 32);
19986313Skrishnae 			regs.rx_hdr4 = (uint32_t)(log & 0xFFFFFFFF);
19993274Set142600 		}
20003274Set142600 	} else {
20013274Set142600 		regs.ue_reg = (uint32_t)BITMASK(err_bit_descr->bit - 32);
20023274Set142600 	}
20033274Set142600 
2004*11654SKrishna.Elango@Sun.COM 	err = px_err_check_pcie(rpdip, derr, &regs, PF_INTR_TYPE_INTERNAL);
20053274Set142600 
20064410Skrishnae 	if (err & PX_PANIC) {
20073274Set142600 		return (px_err_panic_handle(rpdip, csr_base, derr,
20084853Segillett 		    err_reg_descr, err_bit_descr));
20093274Set142600 	} else {
20103274Set142600 		return (px_err_no_panic_handle(rpdip, csr_base, derr,
20114853Segillett 		    err_reg_descr, err_bit_descr));
20123274Set142600 	}
2013383Set142600 }
2014383Set142600 
20153274Set142600 /* PCI-E Uncorrectable Errors */
PX_ERPT_SEND_DEC(pciex_rx_ue)2016383Set142600 PX_ERPT_SEND_DEC(pciex_rx_ue)
2017383Set142600 {
2018383Set142600 	char		buf[FM_MAX_CLASS];
2019739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
2020383Set142600 
2021383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
2022383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
2023383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2024739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
2025383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
2026383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
2027383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
2028383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
2029383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
2030383Set142600 	    ss_reg,
2031383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2032383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2033383Set142600 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
2034383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG),
2035383Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
2036383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG),
2037383Set142600 	    NULL);
2038383Set142600 
20393274Set142600 	return (PX_NO_PANIC);
2040383Set142600 }
2041383Set142600 
20423274Set142600 /* PCI-E Uncorrectable Errors */
PX_ERPT_SEND_DEC(pciex_tx_ue)2043383Set142600 PX_ERPT_SEND_DEC(pciex_tx_ue)
2044383Set142600 {
2045383Set142600 	char		buf[FM_MAX_CLASS];
2046739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
2047383Set142600 
2048383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
2049383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
2050383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2051739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
2052383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
2053383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
2054383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
2055383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
2056383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
2057383Set142600 	    ss_reg,
2058383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2059383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2060383Set142600 	    FIRE_TLU_TUEH1L, DATA_TYPE_UINT64,
2061383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG),
2062383Set142600 	    FIRE_TLU_TUEH2L, DATA_TYPE_UINT64,
2063383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG),
2064383Set142600 	    NULL);
2065383Set142600 
20663274Set142600 	return (PX_NO_PANIC);
2067383Set142600 }
2068383Set142600 
20693274Set142600 /* PCI-E Uncorrectable Errors */
PX_ERPT_SEND_DEC(pciex_rx_tx_ue)2070383Set142600 PX_ERPT_SEND_DEC(pciex_rx_tx_ue)
2071383Set142600 {
2072383Set142600 	char		buf[FM_MAX_CLASS];
2073739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
2074383Set142600 
2075383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
2076383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
2077383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2078739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
2079383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
2080383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
2081383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
2082383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
2083383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
2084383Set142600 	    ss_reg,
2085383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2086383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2087383Set142600 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
2088383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG),
2089383Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
2090383Set142600 	    CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG),
2091383Set142600 	    FIRE_TLU_TUEH1L, DATA_TYPE_UINT64,
2092383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG),
2093383Set142600 	    FIRE_TLU_TUEH2L, DATA_TYPE_UINT64,
2094383Set142600 	    CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG),
2095383Set142600 	    NULL);
2096383Set142600 
20973274Set142600 	return (PX_NO_PANIC);
2098383Set142600 }
2099383Set142600 
21003274Set142600 /* PCI-E Uncorrectable Errors */
PX_ERPT_SEND_DEC(pciex_ue)2101383Set142600 PX_ERPT_SEND_DEC(pciex_ue)
2102383Set142600 {
2103383Set142600 	char		buf[FM_MAX_CLASS];
2104739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
2105383Set142600 
2106383Set142600 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
2107383Set142600 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
2108383Set142600 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2109739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
2110383Set142600 	    FIRE_TLU_UELE, DATA_TYPE_UINT64,
2111383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE),
2112383Set142600 	    FIRE_TLU_UIE, DATA_TYPE_UINT64,
2113383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE),
2114383Set142600 	    FIRE_TLU_UIS, DATA_TYPE_UINT64,
2115383Set142600 	    ss_reg,
2116383Set142600 	    FIRE_TLU_UESS, DATA_TYPE_UINT64,
2117383Set142600 	    CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_SET),
2118383Set142600 	    NULL);
2119383Set142600 
21203274Set142600 	return (PX_NO_PANIC);
2121383Set142600 }
2122383Set142600 
2123383Set142600 /* PCIEX UE Errors */
2124383Set142600 /* ARGSUSED */
2125671Skrishnae int
px_err_pciex_ce_handle(dev_info_t * rpdip,caddr_t csr_base,ddi_fm_error_t * derr,px_err_reg_desc_t * err_reg_descr,px_err_bit_desc_t * err_bit_descr)2126383Set142600 px_err_pciex_ce_handle(dev_info_t *rpdip, caddr_t csr_base,
2127383Set142600 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
2128383Set142600 	px_err_bit_desc_t *err_bit_descr)
2129383Set142600 {
21303274Set142600 	px_err_pcie_t	regs = {0};
21313274Set142600 	int		err;
21323274Set142600 
21333274Set142600 	if (err_bit_descr->bit < 32)
21343274Set142600 		regs.ce_reg = (uint32_t)BITMASK(err_bit_descr->bit);
21353274Set142600 	else
21363274Set142600 		regs.ce_reg = (uint32_t)BITMASK(err_bit_descr->bit - 32);
2137383Set142600 
2138*11654SKrishna.Elango@Sun.COM 	err = px_err_check_pcie(rpdip, derr, &regs, PF_INTR_TYPE_INTERNAL);
21393274Set142600 
21404410Skrishnae 	if (err & PX_PANIC) {
21413274Set142600 		return (px_err_panic_handle(rpdip, csr_base, derr,
21424853Segillett 		    err_reg_descr, err_bit_descr));
21433274Set142600 	} else {
21443274Set142600 		return (px_err_no_panic_handle(rpdip, csr_base, derr,
21454853Segillett 		    err_reg_descr, err_bit_descr));
21463274Set142600 	}
2147383Set142600 }
2148383Set142600 
214927Sjchu /* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
PX_ERPT_SEND_DEC(pciex_ce)215027Sjchu PX_ERPT_SEND_DEC(pciex_ce)
215127Sjchu {
215227Sjchu 	char		buf[FM_MAX_CLASS];
2153739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
215427Sjchu 
215527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
215627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
215727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2158739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
215927Sjchu 	    FIRE_TLU_CELE, DATA_TYPE_UINT64,
216027Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE),
216127Sjchu 	    FIRE_TLU_CIE, DATA_TYPE_UINT64,
216227Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE),
216327Sjchu 	    FIRE_TLU_CIS, DATA_TYPE_UINT64,
216427Sjchu 	    ss_reg,
216527Sjchu 	    FIRE_TLU_CESS, DATA_TYPE_UINT64,
216627Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_STATUS_SET),
216727Sjchu 	    NULL);
216827Sjchu 
21693274Set142600 	return (PX_NO_PANIC);
217027Sjchu }
217127Sjchu 
217227Sjchu /* TLU Other Event Status (receive only) - see io erpt doc, section 3.7 */
PX_ERPT_SEND_DEC(pciex_rx_oe)217327Sjchu PX_ERPT_SEND_DEC(pciex_rx_oe)
217427Sjchu {
217527Sjchu 	char		buf[FM_MAX_CLASS];
2176739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
217727Sjchu 
217827Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
217927Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
218027Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2181739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
218227Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
218327Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
218427Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
218527Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
218627Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
218727Sjchu 	    ss_reg,
218827Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
218927Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
219027Sjchu 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
219127Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
2192260Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
219327Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
219427Sjchu 	    NULL);
219527Sjchu 
21963274Set142600 	return (PX_NO_PANIC);
219727Sjchu }
219827Sjchu 
219927Sjchu /* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
PX_ERPT_SEND_DEC(pciex_rx_tx_oe)220027Sjchu PX_ERPT_SEND_DEC(pciex_rx_tx_oe)
220127Sjchu {
220227Sjchu 	char		buf[FM_MAX_CLASS];
2203739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
22043274Set142600 	px_t		*px_p = DIP_TO_STATE(rpdip);
22053274Set142600 	uint64_t	rx_h1, rx_h2, tx_h1, tx_h2;
22063274Set142600 	uint16_t	s_status;
22073274Set142600 	int		sts;
22083274Set142600 	pcie_cpl_t	*cpl;
22096313Skrishnae 	pf_pcie_adv_err_regs_t adv_reg;
22103274Set142600 
22113274Set142600 	rx_h1 = CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG);
22123274Set142600 	rx_h2 = CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG);
22133274Set142600 	tx_h1 = CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG);
22143274Set142600 	tx_h2 = CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG);
22153274Set142600 
22163274Set142600 	if ((bit == TLU_OTHER_EVENT_STATUS_SET_RUC_P) ||
22173274Set142600 	    (bit == TLU_OTHER_EVENT_STATUS_SET_WUC_P)) {
22186313Skrishnae 		adv_reg.pcie_ue_hdr[0] = (uint32_t)(rx_h1 >> 32);
22196313Skrishnae 		adv_reg.pcie_ue_hdr[1] = (uint32_t)rx_h1;
22206313Skrishnae 		adv_reg.pcie_ue_hdr[2] = (uint32_t)(rx_h2 >> 32);
22216313Skrishnae 		adv_reg.pcie_ue_hdr[3] = (uint32_t)rx_h2;
22223274Set142600 
22233274Set142600 		/* get completer bdf (fault bdf) from rx logs */
22246313Skrishnae 		cpl = (pcie_cpl_t *)&adv_reg.pcie_ue_hdr[1];
22253274Set142600 
22263274Set142600 		/* Figure out if UR/CA from rx logs */
22273274Set142600 		if (cpl->status == PCIE_CPL_STS_UR)
22283274Set142600 			s_status = PCI_STAT_R_MAST_AB;
22293274Set142600 		else if (cpl->status == PCIE_CPL_STS_CA)
22303274Set142600 			s_status = PCI_STAT_R_TARG_AB;
22313274Set142600 
22326313Skrishnae 		adv_reg.pcie_ue_hdr[0] = (uint32_t)(tx_h1 >> 32);
22336313Skrishnae 		adv_reg.pcie_ue_hdr[1] = (uint32_t)tx_h1;
22346313Skrishnae 		adv_reg.pcie_ue_hdr[2] = (uint32_t)(tx_h2 >> 32);
22356313Skrishnae 		adv_reg.pcie_ue_hdr[3] = (uint32_t)tx_h2;
22363274Set142600 
22373274Set142600 		/* get fault addr from tx logs */
22386313Skrishnae 		sts = pf_tlp_decode(PCIE_DIP2BUS(rpdip), &adv_reg);
22393274Set142600 
22403274Set142600 		if (sts == DDI_SUCCESS)
22416313Skrishnae 			(void) px_rp_en_q(px_p, adv_reg.pcie_ue_tgt_bdf,
22426313Skrishnae 			    adv_reg.pcie_ue_tgt_addr, s_status);
22433274Set142600 	}
224427Sjchu 
224527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
224627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
224727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2248739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
224927Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
225027Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
225127Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
225227Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
225327Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
225427Sjchu 	    ss_reg,
225527Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
225627Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
22573274Set142600 	    FIRE_TLU_ROEEH1L, DATA_TYPE_UINT64, rx_h1,
22583274Set142600 	    FIRE_TLU_ROEEH2L, DATA_TYPE_UINT64, rx_h2,
22593274Set142600 	    FIRE_TLU_TOEEH1L, DATA_TYPE_UINT64, tx_h1,
22603274Set142600 	    FIRE_TLU_TOEEH2L, DATA_TYPE_UINT64, tx_h2,
226127Sjchu 	    NULL);
226227Sjchu 
22633274Set142600 	return (PX_NO_PANIC);
226427Sjchu }
226527Sjchu 
226627Sjchu /* TLU Other Event - see io erpt doc, section 3.9 */
PX_ERPT_SEND_DEC(pciex_oe)226727Sjchu PX_ERPT_SEND_DEC(pciex_oe)
226827Sjchu {
2269739Sjchu 	char		buf[FM_MAX_CLASS];
2270739Sjchu 	boolean_t	pri = PX_ERR_IS_PRI(bit);
227127Sjchu 
227227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
227327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
227427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
2275739Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, pri,
227627Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
227727Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
227827Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
227927Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
228027Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
228127Sjchu 	    ss_reg,
228227Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
228327Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
228427Sjchu 	    NULL);
228527Sjchu 
22863274Set142600 	return (PX_NO_PANIC);
228727Sjchu }
2288