xref: /onnv-gate/usr/src/uts/sun4u/io/px/px_err.c (revision 332:be7c0e50511c)
127Sjchu /*
227Sjchu  * CDDL HEADER START
327Sjchu  *
427Sjchu  * The contents of this file are subject to the terms of the
527Sjchu  * Common Development and Distribution License, Version 1.0 only
627Sjchu  * (the "License").  You may not use this file except in compliance
727Sjchu  * with the License.
827Sjchu  *
927Sjchu  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1027Sjchu  * or http://www.opensolaris.org/os/licensing.
1127Sjchu  * See the License for the specific language governing permissions
1227Sjchu  * and limitations under the License.
1327Sjchu  *
1427Sjchu  * When distributing Covered Code, include this CDDL HEADER in each
1527Sjchu  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1627Sjchu  * If applicable, add the following below this CDDL HEADER, with the
1727Sjchu  * fields enclosed by brackets "[]" replaced with your own identifying
1827Sjchu  * information: Portions Copyright [yyyy] [name of copyright owner]
1927Sjchu  *
2027Sjchu  * CDDL HEADER END
2127Sjchu  */
2227Sjchu /*
2327Sjchu  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
2427Sjchu  * Use is subject to license terms.
2527Sjchu  */
2627Sjchu 
2727Sjchu #pragma ident	"%Z%%M%	%I%	%E% SMI"
2827Sjchu 
2927Sjchu /*
3027Sjchu  * sun4u Fire Error Handling
3127Sjchu  */
3227Sjchu 
3327Sjchu #include <sys/types.h>
3427Sjchu #include <sys/ddi.h>
3527Sjchu #include <sys/sunddi.h>
3627Sjchu #include <sys/fm/protocol.h>
3727Sjchu #include <sys/fm/util.h>
3827Sjchu #include <sys/pcie.h>
3927Sjchu #include <sys/pcie_impl.h>
4027Sjchu #include "px_obj.h"
4127Sjchu #include <px_regs.h>
4227Sjchu #include <px_csr.h>
4327Sjchu #include <sys/membar.h>
44118Sjchu #include "pcie_pwr.h"
4527Sjchu #include "px_lib4u.h"
4627Sjchu #include "px_err.h"
4727Sjchu #include "px_err_impl.h"
4827Sjchu 
4927Sjchu /*
5027Sjchu  * JBC error bit table
5127Sjchu  */
5227Sjchu #define	JBC_BIT_DESC(bit, hdl, erpt) \
5327Sjchu 	JBC_INTERRUPT_STATUS_ ## bit ## _P, \
5427Sjchu 	0, \
5527Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
5627Sjchu 	PX_ERPT_SEND(erpt), \
5727Sjchu 	PX_ERR_JBC_CLASS(bit)
5827Sjchu px_err_bit_desc_t px_err_cb_tbl[] = {
5927Sjchu 	/* JBC FATAL - see io erpt doc, section 1.1 */
6027Sjchu 	{ JBC_BIT_DESC(MB_PEA,	fatal_hw,	jbc_fatal) },
6127Sjchu 	{ JBC_BIT_DESC(CPE,	fatal_hw,	jbc_fatal) },
6227Sjchu 	{ JBC_BIT_DESC(APE,	fatal_hw,	jbc_fatal) },
6327Sjchu 	{ JBC_BIT_DESC(PIO_CPE,	fatal_hw,	jbc_fatal) },
6427Sjchu 	{ JBC_BIT_DESC(JTCEEW,	fatal_hw,	jbc_fatal) },
6527Sjchu 	{ JBC_BIT_DESC(JTCEEI,	fatal_hw,	jbc_fatal) },
6627Sjchu 	{ JBC_BIT_DESC(JTCEER,	fatal_hw,	jbc_fatal) },
6727Sjchu 
6827Sjchu 	/* JBC MERGE - see io erpt doc, section 1.2 */
6927Sjchu 	{ JBC_BIT_DESC(MB_PER,	jbc_merge,	jbc_merge) },
7027Sjchu 	{ JBC_BIT_DESC(MB_PEW,	jbc_merge,	jbc_merge) },
7127Sjchu 
7227Sjchu 	/* JBC Jbusint IN - see io erpt doc, section 1.3 */
7327Sjchu 	{ JBC_BIT_DESC(UE_ASYN,	fatal_gos,	jbc_in) },
7427Sjchu 	{ JBC_BIT_DESC(CE_ASYN,	jbc_jbusint_in,	jbc_in) },
7527Sjchu 	{ JBC_BIT_DESC(JTE,	fatal_gos,	jbc_in) },
7627Sjchu 	{ JBC_BIT_DESC(JBE,	jbc_jbusint_in,	jbc_in) },
7727Sjchu 	{ JBC_BIT_DESC(JUE,	jbc_jbusint_in,	jbc_in) },
7827Sjchu 	{ JBC_BIT_DESC(ICISE,	fatal_gos,	jbc_in) },
7927Sjchu 	{ JBC_BIT_DESC(WR_DPE,	jbc_jbusint_in,	jbc_in) },
8027Sjchu 	{ JBC_BIT_DESC(RD_DPE,	jbc_jbusint_in,	jbc_in) },
8127Sjchu 	{ JBC_BIT_DESC(ILL_BMW,	jbc_jbusint_in,	jbc_in) },
8227Sjchu 	{ JBC_BIT_DESC(ILL_BMR,	jbc_jbusint_in,	jbc_in) },
8327Sjchu 	{ JBC_BIT_DESC(BJC,	jbc_jbusint_in,	jbc_in) },
8427Sjchu 
8527Sjchu 	/* JBC Jbusint Out - see io erpt doc, section 1.4 */
8627Sjchu 	{ JBC_BIT_DESC(IJP,	fatal_gos,	jbc_out) },
8727Sjchu 
8827Sjchu 	/* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
8927Sjchu 	{ JBC_BIT_DESC(PIO_UNMAP_RD,	jbc_dmcint_odcd,	jbc_odcd) },
9027Sjchu 	{ JBC_BIT_DESC(ILL_ACC_RD,	jbc_dmcint_odcd,	jbc_odcd) },
9127Sjchu 	{ JBC_BIT_DESC(PIO_UNMAP,	jbc_dmcint_odcd,	jbc_odcd) },
9227Sjchu 	{ JBC_BIT_DESC(PIO_DPE,		jbc_dmcint_odcd,	jbc_odcd) },
9327Sjchu 	{ JBC_BIT_DESC(PIO_CPE,		non_fatal,		jbc_odcd) },
9427Sjchu 	{ JBC_BIT_DESC(ILL_ACC,		jbc_dmcint_odcd,	jbc_odcd) },
9527Sjchu 
9627Sjchu 	/* JBC Dmcint IDC - see io erpt doc, section 1.6 */
9727Sjchu 	{ JBC_BIT_DESC(UNSOL_RD,	non_fatal,	jbc_idc) },
9827Sjchu 	{ JBC_BIT_DESC(UNSOL_INTR,	non_fatal,	jbc_idc) },
9927Sjchu 
10027Sjchu 	/* JBC CSR - see io erpt doc, section 1.7 */
10127Sjchu 	{ JBC_BIT_DESC(EBUS_TO,	jbc_csr,	jbc_csr) }
10227Sjchu };
10327Sjchu 
10427Sjchu #define	px_err_cb_keys \
10527Sjchu 	(sizeof (px_err_cb_tbl)) / (sizeof (px_err_bit_desc_t))
10627Sjchu 
10727Sjchu /*
10827Sjchu  * DMC error bit tables
10927Sjchu  */
11027Sjchu #define	IMU_BIT_DESC(bit, hdl, erpt) \
11127Sjchu 	IMU_INTERRUPT_STATUS_ ## bit ## _P, \
11227Sjchu 	0, \
11327Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
11427Sjchu 	PX_ERPT_SEND(erpt), \
11527Sjchu 	PX_ERR_DMC_CLASS(bit)
11627Sjchu px_err_bit_desc_t px_err_imu_tbl[] = {
11727Sjchu 	/* DMC IMU RDS - see io erpt doc, section 2.1 */
11827Sjchu 	{ IMU_BIT_DESC(MSI_MAL_ERR,		non_fatal,	imu_rds) },
11927Sjchu 	{ IMU_BIT_DESC(MSI_PAR_ERR,		fatal_stuck,	imu_rds) },
12027Sjchu 	{ IMU_BIT_DESC(PMEACK_MES_NOT_EN,	imu_rbne,	imu_rds) },
121118Sjchu 	{ IMU_BIT_DESC(PMPME_MES_NOT_EN,	imu_pme,	imu_rds) },
12227Sjchu 	{ IMU_BIT_DESC(FATAL_MES_NOT_EN,	imu_rbne,	imu_rds) },
12327Sjchu 	{ IMU_BIT_DESC(NONFATAL_MES_NOT_EN,	imu_rbne,	imu_rds) },
12427Sjchu 	{ IMU_BIT_DESC(COR_MES_NOT_EN,		imu_rbne,	imu_rds) },
12527Sjchu 	{ IMU_BIT_DESC(MSI_NOT_EN,		imu_rbne,	imu_rds) },
12627Sjchu 
12727Sjchu 	/* DMC IMU SCS - see io erpt doc, section 2.2 */
12827Sjchu 	{ IMU_BIT_DESC(EQ_NOT_EN,		imu_rbne,	imu_rds) },
12927Sjchu 
13027Sjchu 	/* DMC IMU - see io erpt doc, section 2.3 */
13127Sjchu 	{ IMU_BIT_DESC(EQ_OVER,			imu_eq_ovfl,	imu) }
13227Sjchu };
13327Sjchu 
13427Sjchu #define	px_err_imu_keys (sizeof (px_err_imu_tbl)) / (sizeof (px_err_bit_desc_t))
13527Sjchu 
13627Sjchu /* mmu errors */
13727Sjchu #define	MMU_BIT_DESC(bit, hdl, erpt) \
13827Sjchu 	MMU_INTERRUPT_STATUS_ ## bit ## _P, \
13927Sjchu 	0, \
14027Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
14127Sjchu 	PX_ERPT_SEND(erpt), \
14227Sjchu 	PX_ERR_DMC_CLASS(bit)
14327Sjchu px_err_bit_desc_t px_err_mmu_tbl[] = {
14427Sjchu 	/* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
14527Sjchu 	{ MMU_BIT_DESC(BYP_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
14627Sjchu 	{ MMU_BIT_DESC(BYP_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
14727Sjchu 	{ MMU_BIT_DESC(TRN_ERR,		mmu_rbne,	mmu_tfar_tfsr) },
14827Sjchu 	{ MMU_BIT_DESC(TRN_OOR,		mmu_tfa,	mmu_tfar_tfsr) },
14927Sjchu 	{ MMU_BIT_DESC(TTE_INV,		mmu_tfa,	mmu_tfar_tfsr) },
15027Sjchu 	{ MMU_BIT_DESC(TTE_PRT,		mmu_tfa,	mmu_tfar_tfsr) },
15127Sjchu 	{ MMU_BIT_DESC(TTC_DPE,		mmu_tfa,	mmu_tfar_tfsr) },
15227Sjchu 	{ MMU_BIT_DESC(TBW_DME,		mmu_tblwlk,	mmu_tfar_tfsr) },
15327Sjchu 	{ MMU_BIT_DESC(TBW_UDE,		mmu_tblwlk,	mmu_tfar_tfsr) },
15427Sjchu 	{ MMU_BIT_DESC(TBW_ERR,		mmu_tblwlk,	mmu_tfar_tfsr) },
15527Sjchu 	{ MMU_BIT_DESC(TBW_DPE,		mmu_tblwlk,	mmu_tfar_tfsr) },
15627Sjchu 
15727Sjchu 	/* DMC MMU - see io erpt doc, section 2.5 */
15827Sjchu 	{ MMU_BIT_DESC(TTC_CAE,		non_fatal,	mmu) }
15927Sjchu };
16027Sjchu #define	px_err_mmu_keys (sizeof (px_err_mmu_tbl)) / (sizeof (px_err_bit_desc_t))
16127Sjchu 
16227Sjchu /*
16327Sjchu  * PEC error bit tables
16427Sjchu  */
16527Sjchu #define	ILU_BIT_DESC(bit, hdl, erpt) \
16627Sjchu 	ILU_INTERRUPT_STATUS_ ## bit ## _P, \
16727Sjchu 	0, \
16827Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
16927Sjchu 	PX_ERPT_SEND(erpt), \
17027Sjchu 	PX_ERR_PEC_CLASS(bit)
17127Sjchu px_err_bit_desc_t px_err_ilu_tbl[] = {
17227Sjchu 	/* PEC ILU none - see io erpt doc, section 3.1 */
17327Sjchu 	{ ILU_BIT_DESC(IHB_PE,		fatal_gos,	pec_ilu) }
17427Sjchu };
17527Sjchu #define	px_err_ilu_keys \
17627Sjchu 	(sizeof (px_err_ilu_tbl)) / (sizeof (px_err_bit_desc_t))
17727Sjchu 
17827Sjchu /*
17927Sjchu  * PEC UE errors implementation is incomplete pending PCIE generic
18027Sjchu  * fabric rules.
18127Sjchu  */
18227Sjchu /* pec ue errors */
18327Sjchu #define	TLU_UC_BIT_DESC(bit, hdl, erpt) \
18427Sjchu 	TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
18527Sjchu 	0, \
18627Sjchu 	NULL, \
18727Sjchu 	NULL, \
18827Sjchu 	""
18927Sjchu px_err_bit_desc_t px_err_tlu_ue_tbl[] = {
19027Sjchu 	/* PCI-E Receive Uncorrectable Errors - see io erpt doc, section 3.2 */
19127Sjchu 	{ TLU_UC_BIT_DESC(UR,		NULL,		NULL) },
19227Sjchu 	{ TLU_UC_BIT_DESC(ROF,		NULL,		NULL) },
19327Sjchu 	{ TLU_UC_BIT_DESC(UC,		NULL,		NULL) },
19427Sjchu 
19527Sjchu 	/* PCI-E Transmit Uncorrectable Errors - see io erpt doc, section 3.3 */
19627Sjchu 	{ TLU_UC_BIT_DESC(CTO,		NULL,		NULL) },
19727Sjchu 
19827Sjchu 	/* PCI-E Rx/Tx Uncorrectable Errors - see io erpt doc, section 3.4 */
19927Sjchu 	{ TLU_UC_BIT_DESC(MFP,		NULL,		NULL) },
20027Sjchu 	{ TLU_UC_BIT_DESC(PP,		NULL,		NULL) },
20127Sjchu 
20227Sjchu 	/* Other PCI-E Uncorrectable Errors - see io erpt doc, section 3.5 */
20327Sjchu 	{ TLU_UC_BIT_DESC(FCP,		NULL,		NULL) },
20427Sjchu 	{ TLU_UC_BIT_DESC(DLP,		NULL,		NULL) },
20527Sjchu 	{ TLU_UC_BIT_DESC(TE,		NULL,		NULL) },
20627Sjchu 	{ TLU_UC_BIT_DESC(CA,		NULL,		NULL) }
20727Sjchu };
20827Sjchu #define	px_err_tlu_ue_keys \
20927Sjchu 	(sizeof (px_err_tlu_ue_tbl)) / (sizeof (px_err_bit_desc_t))
21027Sjchu 
21127Sjchu /*
21227Sjchu  * PEC CE errors implementation is incomplete pending PCIE generic
21327Sjchu  * fabric rules.
21427Sjchu  */
21527Sjchu /* pec ce errors */
21627Sjchu #define	TLU_CE_BIT_DESC(bit, hdl, erpt) \
21727Sjchu 	TLU_CORRECTABLE_ERROR_STATUS_CLEAR_ ## bit ## _P, \
21827Sjchu 	0, \
21927Sjchu 	NULL, \
22027Sjchu 	NULL, \
22127Sjchu 	""
22227Sjchu px_err_bit_desc_t px_err_tlu_ce_tbl[] = {
22327Sjchu 	/* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
22427Sjchu 	{ TLU_CE_BIT_DESC(RTO,		NULL,		NULL) },
22527Sjchu 	{ TLU_CE_BIT_DESC(RNR,		NULL,		NULL) },
22627Sjchu 	{ TLU_CE_BIT_DESC(BDP,		NULL,		NULL) },
22727Sjchu 	{ TLU_CE_BIT_DESC(BTP,		NULL,		NULL) },
22827Sjchu 	{ TLU_CE_BIT_DESC(RE,		NULL,		NULL) }
22927Sjchu };
23027Sjchu #define	px_err_tlu_ce_keys \
23127Sjchu 	(sizeof (px_err_tlu_ce_tbl)) / (sizeof (px_err_bit_desc_t))
23227Sjchu 
23327Sjchu /* pec oe errors */
23427Sjchu #define	TLU_OE_BIT_DESC(bit, hdl, erpt) \
23527Sjchu 	TLU_OTHER_EVENT_STATUS_CLEAR_ ## bit ## _P, \
23627Sjchu 	0, \
23727Sjchu 	PX_ERR_BIT_HANDLE(hdl), \
23827Sjchu 	PX_ERPT_SEND(erpt), \
23927Sjchu 	PX_ERR_PEC_CLASS(bit)
24027Sjchu px_err_bit_desc_t px_err_tlu_oe_tbl[] = {
24127Sjchu 	/*
24227Sjchu 	 * TLU Other Event Status (receive only) - see io erpt doc, section 3.7
24327Sjchu 	 */
24427Sjchu 	{ TLU_OE_BIT_DESC(MRC,		fatal_hw,	pciex_rx_oe) },
24527Sjchu 
24627Sjchu 	/* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
24727Sjchu 	{ TLU_OE_BIT_DESC(WUC,		fatal_stuck,	pciex_rx_tx_oe) },
24827Sjchu 	{ TLU_OE_BIT_DESC(RUC,		fatal_stuck,	pciex_rx_tx_oe) },
24927Sjchu 	{ TLU_OE_BIT_DESC(CRS,		non_fatal,	pciex_rx_tx_oe) },
25027Sjchu 
25127Sjchu 	/* TLU Other Event - see io erpt doc, section 3.9 */
25227Sjchu 	{ TLU_OE_BIT_DESC(IIP,		fatal_gos,	pciex_oe) },
25327Sjchu 	{ TLU_OE_BIT_DESC(EDP,		fatal_gos,	pciex_oe) },
25427Sjchu 	{ TLU_OE_BIT_DESC(EHP,		fatal_gos,	pciex_oe) },
25527Sjchu 	{ TLU_OE_BIT_DESC(LIN,		non_fatal,	pciex_oe) },
25627Sjchu 	{ TLU_OE_BIT_DESC(LRS,		non_fatal,	pciex_oe) },
257287Smg140465 	{ TLU_OE_BIT_DESC(LDN,		non_fatal,	pciex_ldn) },
258287Smg140465 	{ TLU_OE_BIT_DESC(LUP,		tlu_lup,	pciex_lup) },
25927Sjchu 	{ TLU_OE_BIT_DESC(ERU,		fatal_gos,	pciex_oe) },
26027Sjchu 	{ TLU_OE_BIT_DESC(ERO,		fatal_gos,	pciex_oe) },
26127Sjchu 	{ TLU_OE_BIT_DESC(EMP,		fatal_gos,	pciex_oe) },
26227Sjchu 	{ TLU_OE_BIT_DESC(EPE,		fatal_gos,	pciex_oe) },
26327Sjchu 	{ TLU_OE_BIT_DESC(ERP,		fatal_gos,	pciex_oe) },
26427Sjchu 	{ TLU_OE_BIT_DESC(EIP,		fatal_gos,	pciex_oe) }
26527Sjchu };
26627Sjchu 
26727Sjchu #define	px_err_tlu_oe_keys \
26827Sjchu 	(sizeof (px_err_tlu_oe_tbl)) / (sizeof (px_err_bit_desc_t))
26927Sjchu 
27027Sjchu /*
27127Sjchu  * All the following tables below are for LPU Interrupts.  These interrupts
27227Sjchu  * are *NOT* error interrupts, but event status interrupts.
27327Sjchu  *
27427Sjchu  * These events are probably of most interest to:
27527Sjchu  * o Hotplug
27627Sjchu  * o Power Management
27727Sjchu  * o etc...
27827Sjchu  *
27927Sjchu  * There are also a few events that would be interresting for FMA.
28027Sjchu  * Again none of the regiseters below state that an error has occured
28127Sjchu  * or that data has been lost.  If anything, they give status that an
28227Sjchu  * error is *about* to occur.  examples
28327Sjchu  * o INT_SKP_ERR - indicates clock between fire and child is too far
28427Sjchu  *		   off and is most unlikely able to compensate
28527Sjchu  * o INT_TX_PAR_ERR - A parity error occured in ONE lane.  This is
28627Sjchu  *		      HW recoverable, but will like end up as a future
28727Sjchu  *		      fabric error as well.
28827Sjchu  *
28927Sjchu  * For now, we don't care about any of these errors and should be ignore,
29027Sjchu  * but cleared.
29127Sjchu  */
29227Sjchu 
29327Sjchu /* LPU Link Interrupt Table */
29427Sjchu #define	LPUL_BIT_DESC(bit, hdl, erpt) \
29527Sjchu 	LPU_LINK_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
29627Sjchu 	0, \
29727Sjchu 	NULL, \
29827Sjchu 	NULL, \
29927Sjchu 	""
30027Sjchu px_err_bit_desc_t px_err_lpul_tbl[] = {
30127Sjchu 	{ LPUL_BIT_DESC(LINK_ERR_ACT,	NULL,		NULL) }
30227Sjchu };
30327Sjchu #define	px_err_lpul_keys \
30427Sjchu 	(sizeof (px_err_lpul_tbl)) / (sizeof (px_err_bit_desc_t))
30527Sjchu 
30627Sjchu /* LPU Physical Interrupt Table */
30727Sjchu #define	LPUP_BIT_DESC(bit, hdl, erpt) \
30827Sjchu 	LPU_PHY_LAYER_INTERRUPT_AND_STATUS_INT_ ## bit, \
30927Sjchu 	0, \
31027Sjchu 	NULL, \
31127Sjchu 	NULL, \
31227Sjchu 	""
31327Sjchu px_err_bit_desc_t px_err_lpup_tbl[] = {
31427Sjchu 	{ LPUP_BIT_DESC(PHY_LAYER_ERR,	NULL,		NULL) }
31527Sjchu };
31627Sjchu #define	px_err_lpup_keys \
31727Sjchu 	(sizeof (px_err_lpup_tbl)) / (sizeof (px_err_bit_desc_t))
31827Sjchu 
31927Sjchu /* LPU Receive Interrupt Table */
32027Sjchu #define	LPUR_BIT_DESC(bit, hdl, erpt) \
32127Sjchu 	LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
32227Sjchu 	0, \
32327Sjchu 	NULL, \
32427Sjchu 	NULL, \
32527Sjchu 	""
32627Sjchu px_err_bit_desc_t px_err_lpur_tbl[] = {
32727Sjchu 	{ LPUR_BIT_DESC(RCV_PHY,	NULL,		NULL) }
32827Sjchu };
32927Sjchu #define	px_err_lpur_keys \
33027Sjchu 	(sizeof (px_err_lpur_tbl)) / (sizeof (px_err_bit_desc_t))
33127Sjchu 
33227Sjchu /* LPU Transmit Interrupt Table */
33327Sjchu #define	LPUX_BIT_DESC(bit, hdl, erpt) \
33427Sjchu 	LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_INT_ ## bit, \
33527Sjchu 	0, \
33627Sjchu 	NULL, \
33727Sjchu 	NULL, \
33827Sjchu 	""
33927Sjchu px_err_bit_desc_t px_err_lpux_tbl[] = {
34027Sjchu 	{ LPUX_BIT_DESC(UNMSK,		NULL,		NULL) }
34127Sjchu };
34227Sjchu #define	px_err_lpux_keys \
34327Sjchu 	(sizeof (px_err_lpux_tbl)) / (sizeof (px_err_bit_desc_t))
34427Sjchu 
34527Sjchu /* LPU LTSSM Interrupt Table */
34627Sjchu #define	LPUS_BIT_DESC(bit, hdl, erpt) \
34727Sjchu 	LPU_LTSSM_INTERRUPT_AND_STATUS_INT_ ## bit, \
34827Sjchu 	0, \
34927Sjchu 	NULL, \
35027Sjchu 	NULL, \
35127Sjchu 	""
35227Sjchu px_err_bit_desc_t px_err_lpus_tbl[] = {
35327Sjchu 	{ LPUS_BIT_DESC(ANY,		NULL,		NULL) }
35427Sjchu };
35527Sjchu #define	px_err_lpus_keys \
35627Sjchu 	(sizeof (px_err_lpus_tbl)) / (sizeof (px_err_bit_desc_t))
35727Sjchu 
35827Sjchu /* LPU Gigablaze Glue Interrupt Table */
35927Sjchu #define	LPUG_BIT_DESC(bit, hdl, erpt) \
36027Sjchu 	LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_INT_ ## bit, \
36127Sjchu 	0, \
36227Sjchu 	NULL, \
36327Sjchu 	NULL, \
36427Sjchu 	""
36527Sjchu px_err_bit_desc_t px_err_lpug_tbl[] = {
36627Sjchu 	{ LPUG_BIT_DESC(GLOBL_UNMSK,	NULL,		NULL) }
36727Sjchu };
36827Sjchu #define	px_err_lpug_keys \
36927Sjchu 	(sizeof (px_err_lpug_tbl)) / (sizeof (px_err_bit_desc_t))
37027Sjchu 
37127Sjchu 
37227Sjchu /* Mask and Tables */
37327Sjchu #define	MnT6(pre) \
37427Sjchu 	B_FALSE, \
37527Sjchu 	&px_ ## pre ## _intr_mask, \
37627Sjchu 	&px_ ## pre ## _log_mask, \
37727Sjchu 	&px_ ## pre ## _count_mask, \
37827Sjchu 	px_err_ ## pre ## _tbl, \
37927Sjchu 	px_err_ ## pre ## _keys, \
38027Sjchu 	0
38127Sjchu 
38227Sjchu /* LPU Registers Addresses */
38327Sjchu #define	LR4(pre) \
38427Sjchu 	NULL, \
38527Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
38627Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS, \
38727Sjchu 	LPU_ ## pre ## _INTERRUPT_AND_STATUS
38827Sjchu 
38927Sjchu /* LPU Registers Addresses with Irregularities */
39027Sjchu #define	LR4_FIXME(pre) \
39127Sjchu 	NULL, \
39227Sjchu 	LPU_ ## pre ## _INTERRUPT_MASK, \
39327Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS, \
39427Sjchu 	LPU_ ## pre ## _LAYER_INTERRUPT_AND_STATUS
39527Sjchu 
39627Sjchu /* TLU Registers Addresses */
39727Sjchu #define	TR4(pre) \
39827Sjchu 	TLU_ ## pre ## _LOG_ENABLE, \
39927Sjchu 	TLU_ ## pre ## _INTERRUPT_ENABLE, \
40027Sjchu 	TLU_ ## pre ## _INTERRUPT_STATUS, \
40127Sjchu 	TLU_ ## pre ## _STATUS_CLEAR
40227Sjchu 
40327Sjchu /* Registers Addresses for JBC, MMU, IMU and ILU */
40427Sjchu #define	R4(pre) \
40527Sjchu 	pre ## _ERROR_LOG_ENABLE, \
40627Sjchu 	pre ## _INTERRUPT_ENABLE, \
40727Sjchu 	pre ## _INTERRUPT_STATUS, \
40827Sjchu 	pre ## _ERROR_STATUS_CLEAR
40927Sjchu 
41027Sjchu /*
41127Sjchu  * Register error handling tables.
41227Sjchu  * The ID Field (first field) is identified by an enum px_err_id_t.
41327Sjchu  * It is located in px_err.h
41427Sjchu  */
41527Sjchu px_err_reg_desc_t px_err_reg_tbl[] = {
41627Sjchu 	{ MnT6(cb),	R4(JBC),		  "JBC Error"},
41727Sjchu 	{ MnT6(mmu),	R4(MMU),		  "IMU Error"},
41827Sjchu 	{ MnT6(imu),	R4(IMU),		  "ILU Error"},
41927Sjchu 	{ MnT6(tlu_ue),	TR4(UNCORRECTABLE_ERROR), "TLU UE"},
42027Sjchu 	{ MnT6(tlu_ce), TR4(CORRECTABLE_ERROR),	  "TLU CE"},
42127Sjchu 	{ MnT6(tlu_oe), TR4(OTHER_EVENT),	  "TLU OE"},
42227Sjchu 	{ MnT6(ilu),	R4(ILU),		  "MMU Error"},
42327Sjchu 	{ MnT6(lpul),	LR4(LINK_LAYER),	  "LPU Link Layer"},
42427Sjchu 	{ MnT6(lpup),	LR4_FIXME(PHY),		  "LPU Phy Layer"},
42527Sjchu 	{ MnT6(lpur),	LR4(RECEIVE_PHY),	  "LPU RX Phy Layer"},
42627Sjchu 	{ MnT6(lpux),	LR4(TRANSMIT_PHY),	  "LPU TX Phy Layer"},
42727Sjchu 	{ MnT6(lpus),	LR4(LTSSM),		  "LPU LTSSM"},
42827Sjchu 	{ MnT6(lpug),	LR4(GIGABLAZE_GLUE),	  "LPU GigaBlaze Glue"}
42927Sjchu };
43027Sjchu #define	PX_ERR_REG_KEYS (sizeof (px_err_reg_tbl)) / (sizeof (px_err_reg_tbl[0]))
43127Sjchu 
43227Sjchu typedef struct px_err_ss {
43327Sjchu 	uint64_t err_status[PX_ERR_REG_KEYS];
43427Sjchu } px_err_ss_t;
43527Sjchu 
43627Sjchu static void px_err_snapshot(px_t *px_p, px_err_ss_t *ss, boolean_t chkjbc);
43727Sjchu static int  px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr,
43827Sjchu     px_err_ss_t *ss);
43927Sjchu static int  px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr,
44027Sjchu     int err, int caller);
44127Sjchu 
44227Sjchu /*
44327Sjchu  * px_err_cb_intr:
44427Sjchu  * Interrupt handler for the JBC block.
44527Sjchu  * o lock
44627Sjchu  * o create derr
44727Sjchu  * o px_err_handle(leaf1, with jbc)
44827Sjchu  * o px_err_handle(leaf2, without jbc)
44927Sjchu  * o dispatch (leaf1)
45027Sjchu  * o dispatch (leaf2)
45127Sjchu  * o unlock
45227Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
45327Sjchu  */
45427Sjchu uint_t
45527Sjchu px_err_cb_intr(caddr_t arg)
45627Sjchu {
45727Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
45827Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
45927Sjchu 	dev_info_t	*leafdip;
46027Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
46127Sjchu 	px_cb_t		*cb_p = px_p->px_cb_p;
462118Sjchu 	int		err = PX_OK;
463118Sjchu 	int		ret = DDI_FM_OK;
46427Sjchu 	int		fatal = 0;
46527Sjchu 	int		nonfatal = 0;
46627Sjchu 	int		unknown = 0;
46727Sjchu 	int		i;
46827Sjchu 	boolean_t	chkjbc = B_TRUE;
46927Sjchu 	ddi_fm_error_t	derr;
47027Sjchu 
47127Sjchu 	/* Create the derr */
47227Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
47327Sjchu 	derr.fme_version = DDI_FME_VERSION;
47427Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
47527Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
47627Sjchu 
47727Sjchu 	mutex_enter(&cb_p->xbc_fm_mutex);
47827Sjchu 
47927Sjchu 	/* send ereport/handle/clear for ALL fire leaves */
48027Sjchu 	for (i = 0; i < PX_CB_MAX_LEAF; i++) {
48127Sjchu 		if ((px_p = cb_p->xbc_px_list[i]) == NULL)
48227Sjchu 			continue;
48327Sjchu 
48427Sjchu 		err |= px_err_handle(px_p, &derr, PX_INTR_CALL, chkjbc);
48527Sjchu 		chkjbc = B_FALSE;
48627Sjchu 	}
48727Sjchu 
48827Sjchu 	/* Check all child devices for errors on ALL fire leaves */
48927Sjchu 	for (i = 0; i < PX_CB_MAX_LEAF; i++) {
49027Sjchu 		if ((px_p = cb_p->xbc_px_list[i]) != NULL) {
49127Sjchu 			leafdip = px_p->px_dip;
49227Sjchu 			ret = ndi_fm_handler_dispatch(leafdip, NULL, &derr);
49327Sjchu 			switch (ret) {
49427Sjchu 			case DDI_FM_FATAL:
49527Sjchu 				fatal++;
49627Sjchu 				break;
49727Sjchu 			case DDI_FM_NONFATAL:
49827Sjchu 				nonfatal++;
49927Sjchu 				break;
50027Sjchu 			case DDI_FM_UNKNOWN:
50127Sjchu 				unknown++;
50227Sjchu 				break;
50327Sjchu 			default:
50427Sjchu 				break;
50527Sjchu 			}
50627Sjchu 		}
50727Sjchu 	}
50827Sjchu 
50927Sjchu 	/* Set the intr state to idle for the leaf that received the mondo */
51027Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
51127Sjchu 	    INTR_IDLE_STATE);
51227Sjchu 
51327Sjchu 	mutex_exit(&cb_p->xbc_fm_mutex);
51427Sjchu 
51527Sjchu 	/*
51627Sjchu 	 * PX_FATAL_HW error is diagnosed after system recovered from
51727Sjchu 	 * HW initiated reset, therefore no furthur handling is required.
51827Sjchu 	 */
51927Sjchu 	if (fatal || err & (PX_FATAL_GOS | PX_FATAL_SW))
52027Sjchu 		fm_panic("Fatal System Bus Error has occurred\n");
52127Sjchu 
52227Sjchu 	return (DDI_INTR_CLAIMED);
52327Sjchu }
52427Sjchu 
52527Sjchu /*
52627Sjchu  * px_err_dmc_pec_intr:
52727Sjchu  * Interrupt handler for the DMC/PEC block.
52827Sjchu  * o lock
52927Sjchu  * o create derr
53027Sjchu  * o px_err_handle(leaf, with jbc)
53127Sjchu  * o dispatch (leaf)
53227Sjchu  * o unlock
53327Sjchu  * o handle error: fatal? fm_panic() : return INTR_CLAIMED)
53427Sjchu  */
53527Sjchu uint_t
53627Sjchu px_err_dmc_pec_intr(caddr_t arg)
53727Sjchu {
53827Sjchu 	px_fault_t	*px_fault_p = (px_fault_t *)arg;
53927Sjchu 	dev_info_t	*rpdip = px_fault_p->px_fh_dip;
54027Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
54127Sjchu 	px_cb_t		*cb_p = px_p->px_cb_p;
542118Sjchu 	int		err = PX_OK;
543118Sjchu 	int		ret = DDI_FM_OK;
54427Sjchu 	ddi_fm_error_t	derr;
54527Sjchu 
54627Sjchu 	/* Create the derr */
54727Sjchu 	bzero(&derr, sizeof (ddi_fm_error_t));
54827Sjchu 	derr.fme_version = DDI_FME_VERSION;
54927Sjchu 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
55027Sjchu 	derr.fme_flag = DDI_FM_ERR_UNEXPECTED;
55127Sjchu 
55227Sjchu 	mutex_enter(&cb_p->xbc_fm_mutex);
55327Sjchu 
55427Sjchu 	/* send ereport/handle/clear fire registers */
55527Sjchu 	err |= px_err_handle(px_p, &derr, PX_INTR_CALL, B_TRUE);
55627Sjchu 
55727Sjchu 	/* Check all child devices for errors */
55827Sjchu 	ret = ndi_fm_handler_dispatch(rpdip, NULL, &derr);
55927Sjchu 
56027Sjchu 	/* Set the interrupt state to idle */
56127Sjchu 	(void) px_lib_intr_setstate(rpdip, px_fault_p->px_fh_sysino,
56227Sjchu 	    INTR_IDLE_STATE);
56327Sjchu 
56427Sjchu 	mutex_exit(&cb_p->xbc_fm_mutex);
56527Sjchu 
56627Sjchu 	/*
56727Sjchu 	 * PX_FATAL_HW indicates a condition recovered from Fatal-Reset,
56827Sjchu 	 * therefore it does not cause panic.
56927Sjchu 	 */
57027Sjchu 	if ((err & (PX_FATAL_GOS | PX_FATAL_SW)) || (ret == DDI_FM_FATAL))
57127Sjchu 		fm_panic("Fatal System Port Error has occurred\n");
57227Sjchu 
57327Sjchu 	return (DDI_INTR_CLAIMED);
57427Sjchu }
57527Sjchu 
57627Sjchu /*
57727Sjchu  * Error register are being handled by px_hlib xxx_init functions.
57827Sjchu  * They are also called again by px_err_add_intr for mondo62 and 63
57927Sjchu  * from px_cb_attach and px_attach
58027Sjchu  */
58127Sjchu void
58227Sjchu px_err_reg_enable(px_t *px_p, px_err_id_t id)
58327Sjchu {
58427Sjchu 	px_err_reg_desc_t	*reg_desc = &px_err_reg_tbl[id];
58527Sjchu 	uint64_t 		intr_mask = *reg_desc->intr_mask_p;
58627Sjchu 	uint64_t 		log_mask = *reg_desc->log_mask_p;
58727Sjchu 	caddr_t			csr_base;
58827Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
58927Sjchu 
59027Sjchu 	if (id == PX_ERR_JBC)
59127Sjchu 		csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
59227Sjchu 	else
59327Sjchu 		csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
59427Sjchu 
59527Sjchu 	reg_desc->enabled = B_TRUE;
59627Sjchu 
59727Sjchu 	/* Enable logs if it exists */
59827Sjchu 	if (reg_desc->log_addr != NULL)
59927Sjchu 		CSR_XS(csr_base, reg_desc->log_addr, log_mask);
60027Sjchu 
60127Sjchu 	/*
60227Sjchu 	 * For readability you in code you set 1 to enable an interrupt.
60327Sjchu 	 * But in Fire it's backwards.  You set 1 to *disable* an intr.
60427Sjchu 	 * Reverse the user tunable intr mask field.
60527Sjchu 	 *
60627Sjchu 	 * Disable All Errors
60727Sjchu 	 * Clear All Errors
60827Sjchu 	 * Enable Errors
60927Sjchu 	 */
61027Sjchu 	CSR_XS(csr_base, reg_desc->enable_addr, 0);
61127Sjchu 	CSR_XS(csr_base, reg_desc->clear_addr, -1);
61227Sjchu 	CSR_XS(csr_base, reg_desc->enable_addr, intr_mask);
61327Sjchu 	DBG(DBG_ATTACH, NULL, "%s Mask: 0x%llx\n",
61427Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->enable_addr));
61527Sjchu 	DBG(DBG_ATTACH, NULL, "%s Status: 0x%llx\n",
61627Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->status_addr));
61727Sjchu 	DBG(DBG_ATTACH, NULL, "%s Clear: 0x%llx\n",
61827Sjchu 	    reg_desc->msg, CSR_XR(csr_base, reg_desc->clear_addr));
61927Sjchu 	if (reg_desc->log_addr != NULL) {
62027Sjchu 		DBG(DBG_ATTACH, NULL, "%s Log: 0x%llx\n",
62127Sjchu 		    reg_desc->msg, CSR_XR(csr_base, reg_desc->log_addr));
62227Sjchu 	}
62327Sjchu }
62427Sjchu 
62527Sjchu void
62627Sjchu px_err_reg_disable(px_t *px_p, px_err_id_t id)
62727Sjchu {
62827Sjchu 	px_err_reg_desc_t	*reg_desc = &px_err_reg_tbl[id];
62927Sjchu 	caddr_t			csr_base;
63027Sjchu 
63127Sjchu 	if (id == PX_ERR_JBC)
63227Sjchu 		csr_base = (caddr_t)px_p->px_inos[PX_INTR_XBC];
63327Sjchu 	else
63427Sjchu 		csr_base = (caddr_t)px_p->px_inos[PX_INTR_PEC];
63527Sjchu 
63627Sjchu 	reg_desc->enabled = B_FALSE;
63727Sjchu 
63827Sjchu 	switch (id) {
63927Sjchu 	case PX_ERR_JBC:
64027Sjchu 	case PX_ERR_MMU:
64127Sjchu 	case PX_ERR_IMU:
64227Sjchu 	case PX_ERR_TLU_UE:
64327Sjchu 	case PX_ERR_TLU_CE:
64427Sjchu 	case PX_ERR_TLU_OE:
64527Sjchu 	case PX_ERR_ILU:
64627Sjchu 		if (reg_desc->log_addr != NULL) {
64727Sjchu 			CSR_XS(csr_base, reg_desc->log_addr, 0);
64827Sjchu 		}
64927Sjchu 		CSR_XS(csr_base, reg_desc->enable_addr, 0);
65027Sjchu 		break;
65127Sjchu 	case PX_ERR_LPU_LINK:
65227Sjchu 	case PX_ERR_LPU_PHY:
65327Sjchu 	case PX_ERR_LPU_RX:
65427Sjchu 	case PX_ERR_LPU_TX:
65527Sjchu 	case PX_ERR_LPU_LTSSM:
65627Sjchu 	case PX_ERR_LPU_GIGABLZ:
65727Sjchu 		if (reg_desc->log_addr != NULL) {
65827Sjchu 			CSR_XS(csr_base, reg_desc->log_addr, -1);
65927Sjchu 		}
66027Sjchu 		CSR_XS(csr_base, reg_desc->enable_addr, -1);
66127Sjchu 		break;
66227Sjchu 	}
66327Sjchu }
66427Sjchu 
66527Sjchu /*
66627Sjchu  * px_err_handle:
66727Sjchu  * Common function called by trap, mondo and fabric intr.
66827Sjchu  * o Snap shot current fire registers
66927Sjchu  * o check for safe access
67027Sjchu  * o send ereport and clear snap shot registers
67127Sjchu  * o check severity of snap shot registers
67227Sjchu  *
67327Sjchu  * @param px_p		leaf in which to check access
67427Sjchu  * @param derr		fm err data structure to be updated
67527Sjchu  * @param caller	PX_TRAP_CALL | PX_INTR_CALL
67627Sjchu  * @param chkjbc	whether to handle jbc registers
67727Sjchu  * @return err		PX_OK | PX_NONFATAL |
67827Sjchu  *                      PX_FATAL_GOS | PX_FATAL_HW | PX_STUCK_FATAL
67927Sjchu  */
68027Sjchu int
68127Sjchu px_err_handle(px_t *px_p, ddi_fm_error_t *derr, int caller,
68227Sjchu     boolean_t chkjbc)
68327Sjchu {
68427Sjchu 	px_cb_t			*cb_p = px_p->px_cb_p; /* for fm_mutex */
68527Sjchu 	px_err_ss_t		ss;
686118Sjchu 	int			err = PX_OK;
68727Sjchu 
68827Sjchu 	ASSERT(MUTEX_HELD(&cb_p->xbc_fm_mutex));
68927Sjchu 
69027Sjchu 	/* snap shot the current fire registers */
69127Sjchu 	px_err_snapshot(px_p, &ss, chkjbc);
69227Sjchu 
69327Sjchu 	/* check for safe access */
69427Sjchu 	px_err_safeacc_check(px_p, derr);
69527Sjchu 
69627Sjchu 	/* send ereports/handle/clear registers */
69727Sjchu 	err = px_err_erpt_and_clr(px_p, derr, &ss);
69827Sjchu 
69927Sjchu 	/* check for error severity */
70027Sjchu 	err = px_err_check_severity(px_p, derr, err, caller);
70127Sjchu 
70227Sjchu 	/* Mark the On Trap Handle if an error occured */
70327Sjchu 	if (err != PX_OK) {
70427Sjchu 		px_pec_t	*pec_p = px_p->px_pec_p;
70527Sjchu 		on_trap_data_t	*otd = pec_p->pec_ontrap_data;
70627Sjchu 
707118Sjchu 		if ((otd != NULL) && (otd->ot_prot & OT_DATA_ACCESS))
70827Sjchu 			otd->ot_trap |= OT_DATA_ACCESS;
70927Sjchu 	}
71027Sjchu 
71127Sjchu 	return (err);
71227Sjchu }
71327Sjchu 
71427Sjchu /*
71527Sjchu  * Static function
71627Sjchu  */
71727Sjchu 
71827Sjchu /*
71927Sjchu  * px_err_snapshot:
72027Sjchu  * Take a current snap shot of all the fire error registers.  This includes
72127Sjchu  * JBC, DMC, and PEC, unless chkjbc == false;
72227Sjchu  *
72327Sjchu  * @param px_p		leaf in which to take the snap shot.
72427Sjchu  * @param ss		pre-allocated memory to store the snap shot.
72527Sjchu  * @param chkjbc	boolean on whether to store jbc register.
72627Sjchu  */
72727Sjchu static void
72827Sjchu px_err_snapshot(px_t *px_p, px_err_ss_t *ss, boolean_t chkjbc)
72927Sjchu {
73027Sjchu 	pxu_t	*pxu_p = (pxu_t *)px_p->px_plat_p;
73127Sjchu 	caddr_t	xbc_csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
73227Sjchu 	caddr_t	pec_csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
73327Sjchu 	px_err_reg_desc_t *reg_desc;
73427Sjchu 	int reg_id;
73527Sjchu 
73627Sjchu 	/* snapshot JBC interrupt status */
73727Sjchu 	reg_id = PX_ERR_JBC;
73827Sjchu 	if (chkjbc == B_TRUE) {
73927Sjchu 		reg_desc = &px_err_reg_tbl[reg_id];
74027Sjchu 		ss->err_status[reg_id] = CSR_XR(xbc_csr_base,
74127Sjchu 		    reg_desc->status_addr);
74227Sjchu 	} else {
74327Sjchu 		ss->err_status[reg_id] = 0;
74427Sjchu 	}
74527Sjchu 
74627Sjchu 	/* snapshot DMC/PEC interrupt status */
74727Sjchu 	for (reg_id = 1; reg_id < PX_ERR_REG_KEYS; reg_id += 1) {
74827Sjchu 		reg_desc = &px_err_reg_tbl[reg_id];
74927Sjchu 		ss->err_status[reg_id] = CSR_XR(pec_csr_base,
75027Sjchu 		    reg_desc->status_addr);
75127Sjchu 	}
75227Sjchu }
75327Sjchu 
75427Sjchu /*
75527Sjchu  * px_err_erpt_and_clr:
75627Sjchu  * This function does the following thing to all the fire registers based
75727Sjchu  * on an earlier snap shot.
75827Sjchu  * o Send ereport
75927Sjchu  * o Handle the error
76027Sjchu  * o Clear the error
76127Sjchu  *
76227Sjchu  * @param px_p		leaf in which to take the snap shot.
76327Sjchu  * @param derr		fm err in which the ereport is to be based on
76427Sjchu  * @param ss		pre-allocated memory to store the snap shot.
76527Sjchu  */
76627Sjchu static int
76727Sjchu px_err_erpt_and_clr(px_t *px_p, ddi_fm_error_t *derr, px_err_ss_t *ss)
76827Sjchu {
76927Sjchu 	dev_info_t		*rpdip = px_p->px_dip;
77027Sjchu 	px_cb_t			*cb_p = px_p->px_cb_p; /* for fm_mutex */
77127Sjchu 	pxu_t			*pxu_p = (pxu_t *)px_p->px_plat_p;
77227Sjchu 	caddr_t			csr_base;
77327Sjchu 	px_err_reg_desc_t	*err_reg_tbl;
77427Sjchu 	px_err_bit_desc_t	*err_bit_tbl;
77527Sjchu 	px_err_bit_desc_t	*err_bit_desc;
77627Sjchu 
77727Sjchu 	uint64_t		*log_mask, *count_mask;
77827Sjchu 	uint64_t		status_addr, clear_addr;
77927Sjchu 	uint64_t		ss_reg;
78027Sjchu 
78127Sjchu 	int			(*err_handler)();
78227Sjchu 	int			(*erpt_handler)();
78327Sjchu 	int			reg_id, key;
78427Sjchu 	int			err = PX_OK;
78527Sjchu 
78627Sjchu 	ASSERT(MUTEX_HELD(&cb_p->xbc_fm_mutex));
78727Sjchu 
78827Sjchu 	/* send erport/handle/clear JBC errors */
78927Sjchu 	for (reg_id = 0; reg_id < PX_ERR_REG_KEYS; reg_id += 1) {
79027Sjchu 		/* Get the correct register description table */
79127Sjchu 		err_reg_tbl = &px_err_reg_tbl[reg_id];
79227Sjchu 
79327Sjchu 		/* Get the correct CSR BASE */
79427Sjchu 		if (reg_id == PX_ERR_JBC) {
79527Sjchu 			csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
79627Sjchu 		} else {
79727Sjchu 			csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
79827Sjchu 		}
79927Sjchu 
80027Sjchu 		/* Get pointers to masks and register addresses */
80127Sjchu 		log_mask = err_reg_tbl->log_mask_p;
80227Sjchu 		count_mask = err_reg_tbl->count_mask_p;
80327Sjchu 		status_addr = err_reg_tbl->status_addr;
80427Sjchu 		clear_addr = err_reg_tbl->clear_addr;
80527Sjchu 		ss_reg = ss->err_status[reg_id];
80627Sjchu 
80727Sjchu 		/* Get the register BIT description table */
80827Sjchu 		err_bit_tbl = err_reg_tbl->err_bit_tbl;
80927Sjchu 
81027Sjchu 		/* For each known bit in the register send erpt and handle */
81127Sjchu 		for (key = 0; key < err_reg_tbl->err_bit_keys; key += 1) {
81227Sjchu 			/* Get the bit description table for this register */
81327Sjchu 			err_bit_desc = &err_bit_tbl[key];
81427Sjchu 
81527Sjchu 			/*
81627Sjchu 			 * If the ss_reg is set for this bit,
81727Sjchu 			 * send ereport and handle
81827Sjchu 			 */
81927Sjchu 			if (BIT_TST(ss_reg, err_bit_desc->bit)) {
82027Sjchu 				/* Increment the counter if necessary */
82127Sjchu 				if (BIT_TST(*count_mask, err_bit_desc->bit)) {
82227Sjchu 					err_bit_desc->counter++;
82327Sjchu 				}
82427Sjchu 
82527Sjchu 				/* Error Handle for this bit */
82627Sjchu 				err_handler = err_bit_desc->err_handler;
82727Sjchu 				if (err_handler)
82827Sjchu 					err |= err_handler(rpdip,
82927Sjchu 					    csr_base,
83027Sjchu 					    derr,
83127Sjchu 					    err_reg_tbl,
83227Sjchu 					    err_bit_desc);
83327Sjchu 
83427Sjchu 				/* Send the ereport for this bit */
83527Sjchu 				erpt_handler = err_bit_desc->erpt_handler;
83627Sjchu 				if (erpt_handler)
83727Sjchu 					(void) erpt_handler(rpdip,
83827Sjchu 					    csr_base,
83927Sjchu 					    ss_reg,
84027Sjchu 					    derr,
84127Sjchu 					    err_bit_desc->class_name);
84227Sjchu 			}
84327Sjchu 		}
844*332Sjchu 
845*332Sjchu 		/* Print register status */
846*332Sjchu 		if (ss_reg & *log_mask)
847*332Sjchu 			DBG(DBG_ERR_INTR, rpdip, "<%x>=%16llx %s\n",
84827Sjchu 			    status_addr, ss_reg, err_reg_tbl->msg);
84927Sjchu 
85027Sjchu 		/* Clear the register and error */
85127Sjchu 		CSR_XS(csr_base, clear_addr, ss_reg);
85227Sjchu 	}
85327Sjchu 
85427Sjchu 	return (err);
85527Sjchu }
85627Sjchu 
85727Sjchu /*
85827Sjchu  * px_err_check_severity:
85927Sjchu  * Check the severity of the fire error based on an earlier snapshot
86027Sjchu  *
86127Sjchu  * @param px_p		leaf in which to take the snap shot.
86227Sjchu  * @param derr		fm err in which the ereport is to be based on
86327Sjchu  * @param ss		pre-allocated memory to store the snap shot.
86427Sjchu  */
86527Sjchu static int
86627Sjchu px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr, int err, int caller)
86727Sjchu {
86827Sjchu 	px_pec_t 	*pec_p = px_p->px_pec_p;
86927Sjchu 	boolean_t	is_safeacc = B_FALSE;
870118Sjchu 
871118Sjchu 	/* nothing to do if called with no error */
872118Sjchu 	if (err == PX_OK)
873118Sjchu 		return (err);
87427Sjchu 
87527Sjchu 	/* Cautious access error handling  */
87627Sjchu 	switch (derr->fme_flag) {
87727Sjchu 	case DDI_FM_ERR_EXPECTED:
87827Sjchu 		if (caller == PX_TRAP_CALL) {
87927Sjchu 			/*
88027Sjchu 			 * for ddi_caut_get treat all events as nonfatal
88127Sjchu 			 * The trampoline will set err_ena = 0,
88227Sjchu 			 * err_status = NONFATAL.
88327Sjchu 			 */
88427Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
88527Sjchu 			is_safeacc = B_TRUE;
88627Sjchu 		} else {
88727Sjchu 			/*
88827Sjchu 			 * For ddi_caut_put treat all events as nonfatal. Here
88927Sjchu 			 * we have the handle and can call ndi_fm_acc_err_set().
89027Sjchu 			 */
89127Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
89227Sjchu 			ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr);
89327Sjchu 			is_safeacc = B_TRUE;
89427Sjchu 		}
89527Sjchu 		break;
89627Sjchu 	case DDI_FM_ERR_PEEK:
89727Sjchu 	case DDI_FM_ERR_POKE:
89827Sjchu 		/*
89927Sjchu 		 * For ddi_peek/poke treat all events as nonfatal.
90027Sjchu 		 */
90127Sjchu 		is_safeacc = B_TRUE;
90227Sjchu 		break;
90327Sjchu 	default:
90427Sjchu 		is_safeacc = B_FALSE;
90527Sjchu 	}
90627Sjchu 
90727Sjchu 	/*
90827Sjchu 	 * The third argument "err" is passed in as error status from checking
90927Sjchu 	 * Fire register, re-adjust error status from safe access.
91027Sjchu 	 */
91127Sjchu 	if (is_safeacc && !(err & PX_FATAL_GOS))
912118Sjchu 		return (PX_NONFATAL);
91327Sjchu 
914118Sjchu 	return (err);
91527Sjchu }
91627Sjchu 
91727Sjchu /* predefined convenience functions */
91827Sjchu /* ARGSUSED */
91927Sjchu int
92027Sjchu px_err_fatal_hw_handle(dev_info_t *rpdip, caddr_t csr_base,
92127Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
92227Sjchu 	px_err_bit_desc_t *err_bit_descr)
92327Sjchu {
92427Sjchu 	return (PX_FATAL_HW);
92527Sjchu }
92627Sjchu 
92727Sjchu /* ARGSUSED */
92827Sjchu int
92927Sjchu px_err_fatal_gos_handle(dev_info_t *rpdip, caddr_t csr_base,
93027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
93127Sjchu 	px_err_bit_desc_t *err_bit_descr)
93227Sjchu {
93327Sjchu 	return (PX_FATAL_GOS);
93427Sjchu }
93527Sjchu 
93627Sjchu /* ARGSUSED */
93727Sjchu int
93827Sjchu px_err_fatal_stuck_handle(dev_info_t *rpdip, caddr_t csr_base,
93927Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
94027Sjchu 	px_err_bit_desc_t *err_bit_descr)
94127Sjchu {
94227Sjchu 	return (PX_STUCK_FATAL);
94327Sjchu }
94427Sjchu 
94527Sjchu /* ARGSUSED */
94627Sjchu int
94727Sjchu px_err_fatal_sw_handle(dev_info_t *rpdip, caddr_t csr_base,
94827Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
94927Sjchu 	px_err_bit_desc_t *err_bit_descr)
95027Sjchu {
95127Sjchu 	return (PX_FATAL_SW);
95227Sjchu }
95327Sjchu 
95427Sjchu /* ARGSUSED */
95527Sjchu int
95627Sjchu px_err_non_fatal_handle(dev_info_t *rpdip, caddr_t csr_base,
95727Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
95827Sjchu 	px_err_bit_desc_t *err_bit_descr)
95927Sjchu {
96027Sjchu 	return (PX_NONFATAL);
96127Sjchu }
96227Sjchu 
96327Sjchu /* ARGSUSED */
96427Sjchu int
96527Sjchu px_err_ok_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
96627Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
96727Sjchu {
96827Sjchu 	return (PX_OK);
96927Sjchu }
97027Sjchu 
97127Sjchu /* ARGSUSED */
97227Sjchu int
97327Sjchu px_err_unknown_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
97427Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
97527Sjchu {
97627Sjchu 	return (PX_ERR_UNKNOWN);
97727Sjchu }
97827Sjchu 
97927Sjchu /* JBC FATAL - see io erpt doc, section 1.1 */
98027Sjchu PX_ERPT_SEND_DEC(jbc_fatal)
98127Sjchu {
98227Sjchu 	char		buf[FM_MAX_CLASS];
98327Sjchu 
98427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
98527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
98627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
98727Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
98827Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
98927Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
99027Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
99127Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
99227Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
99327Sjchu 	    ss_reg,
99427Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
99527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
99627Sjchu 	    FIRE_JBC_FEL1, DATA_TYPE_UINT64,
99727Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_1),
99827Sjchu 	    FIRE_JBC_FEL2, DATA_TYPE_UINT64,
99927Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_2),
100027Sjchu 	    NULL);
100127Sjchu 
100227Sjchu 	return (PX_OK);
100327Sjchu }
100427Sjchu 
100527Sjchu /* JBC MERGE - see io erpt doc, section 1.2 */
100627Sjchu PX_ERPT_SEND_DEC(jbc_merge)
100727Sjchu {
100827Sjchu 	char		buf[FM_MAX_CLASS];
100927Sjchu 
101027Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
101127Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
101227Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
101327Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
101427Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
101527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
101627Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
101727Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
101827Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
101927Sjchu 	    ss_reg,
102027Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
102127Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
102227Sjchu 	    FIRE_JBC_MTEL, DATA_TYPE_UINT64,
102327Sjchu 	    CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG),
102427Sjchu 	    NULL);
102527Sjchu 
102627Sjchu 	return (PX_OK);
102727Sjchu }
102827Sjchu 
102927Sjchu /*
103027Sjchu  * JBC Merge buffer nonfatal errors:
103127Sjchu  *    Merge buffer parity error (rd_buf): dma:read:M:nonfatal
103227Sjchu  *    Merge buffer parity error (wr_buf): dma:write:M:nonfatal
103327Sjchu  */
103427Sjchu /* ARGSUSED */
103527Sjchu int
103627Sjchu px_err_jbc_merge_handle(dev_info_t *rpdip, caddr_t csr_base,
103727Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
103827Sjchu 	px_err_bit_desc_t *err_bit_descr)
103927Sjchu {
104027Sjchu 	uint64_t	paddr;
104127Sjchu 	int		ret;
104227Sjchu 
104327Sjchu 	paddr = CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG);
104427Sjchu 	paddr &= MERGE_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
104527Sjchu 
104627Sjchu 	ret = px_handle_lookup(
104727Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
104827Sjchu 
104927Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
105027Sjchu }
105127Sjchu 
105227Sjchu /* JBC Jbusint IN - see io erpt doc, section 1.3 */
105327Sjchu PX_ERPT_SEND_DEC(jbc_in)
105427Sjchu {
105527Sjchu 	char		buf[FM_MAX_CLASS];
105627Sjchu 
105727Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
105827Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
105927Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
106027Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
106127Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
106227Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
106327Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
106427Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
106527Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
106627Sjchu 	    ss_reg,
106727Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
106827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
106927Sjchu 	    FIRE_JBC_JITEL1, DATA_TYPE_UINT64,
107027Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG),
107127Sjchu 	    FIRE_JBC_JITEL2, DATA_TYPE_UINT64,
107227Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG_2),
107327Sjchu 	    NULL);
107427Sjchu 
107527Sjchu 	return (PX_OK);
107627Sjchu }
107727Sjchu 
107827Sjchu /*
107927Sjchu  * JBC Jbusint IN nonfatal errors: PA logged in Jbusint In Transaction Error
108027Sjchu  * Log Reg[42:0].
108127Sjchu  *     CE async fault error: nonfatal
108227Sjchu  *     Jbus bus error: dma::nonfatal
108327Sjchu  *     Jbus unmapped error: pio|dma:rdwr:M:nonfatal
108427Sjchu  *     Write data parity error: pio/write:M:nonfatal
108527Sjchu  *     Read data parity error: pio/read:M:nonfatal
108627Sjchu  *     Illegal NCWR bytemask: pio:write:M:nonfatal
108727Sjchu  *     Illegal NCRD bytemask: pio:write:M:nonfatal
108827Sjchu  *     Invalid jbus transaction: nonfatal
108927Sjchu  */
109027Sjchu /* ARGSUSED */
109127Sjchu int
109227Sjchu px_err_jbc_jbusint_in_handle(dev_info_t *rpdip, caddr_t csr_base,
109327Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
109427Sjchu 	px_err_bit_desc_t *err_bit_descr)
109527Sjchu {
109627Sjchu 	uint64_t	paddr;
109727Sjchu 	int		ret;
109827Sjchu 
109927Sjchu 	paddr = CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG);
110027Sjchu 	paddr &= JBCINT_IN_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
110127Sjchu 
110227Sjchu 	ret = px_handle_lookup(
110327Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
110427Sjchu 
110527Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
110627Sjchu }
110727Sjchu 
110827Sjchu 
110927Sjchu /* JBC Jbusint Out - see io erpt doc, section 1.4 */
111027Sjchu PX_ERPT_SEND_DEC(jbc_out)
111127Sjchu {
111227Sjchu 	char		buf[FM_MAX_CLASS];
111327Sjchu 
111427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
111527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
111627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
111727Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
111827Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
111927Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
112027Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
112127Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
112227Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
112327Sjchu 	    ss_reg,
112427Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
112527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
112627Sjchu 	    FIRE_JBC_JOTEL1, DATA_TYPE_UINT64,
112727Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG),
112827Sjchu 	    FIRE_JBC_JOTEL2, DATA_TYPE_UINT64,
112927Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG_2),
113027Sjchu 	    NULL);
113127Sjchu 
113227Sjchu 	return (PX_OK);
113327Sjchu }
113427Sjchu 
113527Sjchu /* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
113627Sjchu PX_ERPT_SEND_DEC(jbc_odcd)
113727Sjchu {
113827Sjchu 	char		buf[FM_MAX_CLASS];
113927Sjchu 
114027Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
114127Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
114227Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
114327Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
114427Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
114527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
114627Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
114727Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
114827Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
114927Sjchu 	    ss_reg,
115027Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
115127Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
115227Sjchu 	    FIRE_JBC_DMC_ODCD, DATA_TYPE_UINT64,
115327Sjchu 	    CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG),
115427Sjchu 	    NULL);
115527Sjchu 
115627Sjchu 	return (PX_OK);
115727Sjchu }
115827Sjchu 
115927Sjchu /*
116027Sjchu  * JBC Dmcint ODCO nonfatal errer handling -
116127Sjchu  *    Unmapped PIO read error: pio:read:M:nonfatal
116227Sjchu  *    Unmapped PIO write error: pio:write:M:nonfatal
116327Sjchu  *    PIO data parity error: pio:write:M:nonfatal
116427Sjchu  *    Invalid PIO write to PCIe cfg/io, csr, ebus or i2c bus: pio:write:nonfatal
116527Sjchu  *    Invalid PIO read to PCIe cfg/io, csr, ebus or i2c bus: pio:read:nonfatal
116627Sjchu  */
116727Sjchu /* ARGSUSED */
116827Sjchu int
116927Sjchu px_err_jbc_dmcint_odcd_handle(dev_info_t *rpdip, caddr_t csr_base,
117027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
117127Sjchu 	px_err_bit_desc_t *err_bit_descr)
117227Sjchu {
117327Sjchu 	uint64_t	paddr;
117427Sjchu 	int		ret;
117527Sjchu 
117627Sjchu 	paddr = CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG);
117727Sjchu 	paddr &= DMCINT_ODCD_ERROR_LOG_ADDRESS_MASK;
117827Sjchu 
117927Sjchu 	ret = px_handle_lookup(
118027Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
118127Sjchu 
118227Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
118327Sjchu }
118427Sjchu 
118527Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
118627Sjchu PX_ERPT_SEND_DEC(jbc_idc)
118727Sjchu {
118827Sjchu 	char		buf[FM_MAX_CLASS];
118927Sjchu 
119027Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
119127Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
119227Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
119327Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
119427Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
119527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
119627Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
119727Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
119827Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
119927Sjchu 	    ss_reg,
120027Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
120127Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
120227Sjchu 	    FIRE_JBC_DMC_IDC, DATA_TYPE_UINT64,
120327Sjchu 	    CSR_XR(csr_base, DMCINT_IDC_ERROR_LOG),
120427Sjchu 	    NULL);
120527Sjchu 
120627Sjchu 	return (PX_OK);
120727Sjchu }
120827Sjchu 
120927Sjchu /* JBC CSR - see io erpt doc, section 1.7 */
121027Sjchu PX_ERPT_SEND_DEC(jbc_csr)
121127Sjchu {
121227Sjchu 	char		buf[FM_MAX_CLASS];
121327Sjchu 
121427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
121527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
121627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
121727Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
121827Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
121927Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
122027Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
122127Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
122227Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
122327Sjchu 	    ss_reg,
122427Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
122527Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
122627Sjchu 	    "jbc-error-reg", DATA_TYPE_UINT64,
122727Sjchu 	    CSR_XR(csr_base, CSR_ERROR_LOG),
122827Sjchu 	    NULL);
122927Sjchu 
123027Sjchu 	return (PX_OK);
123127Sjchu }
123227Sjchu 
123327Sjchu /*
123427Sjchu  * JBC CSR errer handling -
123527Sjchu  * Ebus ready timeout error: pio:rdwr:M:nonfatal
123627Sjchu  */
123727Sjchu /* ARGSUSED */
123827Sjchu int
123927Sjchu px_err_jbc_csr_handle(dev_info_t *rpdip, caddr_t csr_base,
124027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
124127Sjchu 	px_err_bit_desc_t *err_bit_descr)
124227Sjchu {
124327Sjchu 	uint64_t	paddr;
124427Sjchu 	int		ret;
124527Sjchu 
124627Sjchu 	paddr = CSR_XR(csr_base, CSR_ERROR_LOG);
124727Sjchu 	paddr &= CSR_ERROR_LOG_ADDRESS_MASK;
124827Sjchu 
124927Sjchu 	ret = px_handle_lookup(
125027Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
125127Sjchu 
125227Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
125327Sjchu }
125427Sjchu 
125527Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
125627Sjchu 
125727Sjchu /* DMC IMU RDS - see io erpt doc, section 2.1 */
125827Sjchu PX_ERPT_SEND_DEC(imu_rds)
125927Sjchu {
126027Sjchu 	char		buf[FM_MAX_CLASS];
126127Sjchu 
126227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
126327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
126427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
126527Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
126627Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
126727Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
126827Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
126927Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
127027Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
127127Sjchu 	    ss_reg,
127227Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
127327Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
127427Sjchu 	    FIRE_IMU_RDS, DATA_TYPE_UINT64,
127527Sjchu 	    CSR_XR(csr_base, IMU_RDS_ERROR_LOG),
127627Sjchu 	    NULL);
127727Sjchu 
127827Sjchu 	return (PX_OK);
127927Sjchu }
128027Sjchu 
128127Sjchu /* imu function to handle all Received but Not Enabled errors */
128227Sjchu /* ARGSUSED */
128327Sjchu int
128427Sjchu px_err_imu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
128527Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
128627Sjchu 	px_err_bit_desc_t *err_bit_descr)
128727Sjchu {
128827Sjchu 	uint64_t	imu_log_enable, imu_intr_enable;
128927Sjchu 	int		mask = BITMASK(err_bit_descr->bit);
129027Sjchu 	int		err = PX_NONFATAL;
129127Sjchu 
129227Sjchu 	imu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
129327Sjchu 	imu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
129427Sjchu 
129527Sjchu 	if (imu_log_enable & imu_intr_enable & mask) {
129627Sjchu 		err = PX_FATAL_SW;
129727Sjchu 	} else {
129827Sjchu 		/*
129927Sjchu 		 * S/W bug - this error should always be enabled
130027Sjchu 		 */
130127Sjchu 
130227Sjchu 		/* enable error & intr reporting for this bit */
130327Sjchu 		CSR_XS(csr_base, IMU_ERROR_LOG_ENABLE, imu_log_enable | mask);
130427Sjchu 		CSR_XS(csr_base, IMU_INTERRUPT_ENABLE, imu_intr_enable | mask);
130527Sjchu 		err = PX_NONFATAL;
130627Sjchu 	}
130727Sjchu 
130827Sjchu 	return (err);
130927Sjchu }
131027Sjchu 
1311118Sjchu /*
1312118Sjchu  * No platforms uses PME. Any PME received is simply logged
1313118Sjchu  * for analysis.
1314118Sjchu  */
1315118Sjchu /* ARGSUSED */
1316118Sjchu int
1317118Sjchu px_err_imu_pme_handle(dev_info_t *rpdip, caddr_t csr_base,
1318118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1319118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1320118Sjchu {
1321118Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
1322118Sjchu 
1323118Sjchu 	px_p->px_pme_ignored++;
1324118Sjchu 	return (PX_NONFATAL);
1325118Sjchu }
1326118Sjchu 
132727Sjchu /* handle EQ overflow */
132827Sjchu /* ARGSUSED */
132927Sjchu int
133027Sjchu px_err_imu_eq_ovfl_handle(dev_info_t *rpdip, caddr_t csr_base,
133127Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
133227Sjchu 	px_err_bit_desc_t *err_bit_descr)
133327Sjchu {
133427Sjchu 	px_t			*px_p = DIP_TO_STATE(rpdip);
133527Sjchu 	px_msiq_state_t 	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
133627Sjchu 	msiqid_t		eqno;
133727Sjchu 	pci_msiq_state_t	msiq_state;
133827Sjchu 	int			err = PX_NONFATAL;
133927Sjchu 	int			i;
134027Sjchu 
134127Sjchu 	eqno = msiq_state_p->msiq_1st_msiq_id;
134227Sjchu 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
134327Sjchu 		if (px_lib_msiq_getstate(rpdip, eqno, &msiq_state) ==
134427Sjchu 			DDI_SUCCESS) {
134527Sjchu 			if (msiq_state == PCI_MSIQ_STATE_ERROR) {
134627Sjchu 				err = PX_FATAL_SW;
134727Sjchu 			}
134827Sjchu 		}
134927Sjchu 	}
135027Sjchu 
135127Sjchu 	return (err);
135227Sjchu }
135327Sjchu 
135427Sjchu /* DMC IMU SCS - see io erpt doc, section 2.2 */
135527Sjchu PX_ERPT_SEND_DEC(imu_scs)
135627Sjchu {
135727Sjchu 	char		buf[FM_MAX_CLASS];
135827Sjchu 
135927Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
136027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
136127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
136227Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
136327Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
136427Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
136527Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
136627Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
136727Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
136827Sjchu 	    ss_reg,
136927Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
137027Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
137127Sjchu 	    FIRE_IMU_SCS, DATA_TYPE_UINT64,
137227Sjchu 	    CSR_XR(csr_base, IMU_SCS_ERROR_LOG),
137327Sjchu 	    NULL);
137427Sjchu 
137527Sjchu 	return (PX_OK);
137627Sjchu }
137727Sjchu 
137827Sjchu /* DMC IMU - see io erpt doc, section 2.3 */
137927Sjchu PX_ERPT_SEND_DEC(imu)
138027Sjchu {
138127Sjchu 	char		buf[FM_MAX_CLASS];
138227Sjchu 
138327Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
138427Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
138527Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
138627Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
138727Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
138827Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
138927Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
139027Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
139127Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
139227Sjchu 	    ss_reg,
139327Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
139427Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
139527Sjchu 	    NULL);
139627Sjchu 
139727Sjchu 	return (PX_OK);
139827Sjchu }
139927Sjchu 
140027Sjchu /* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
140127Sjchu PX_ERPT_SEND_DEC(mmu_tfar_tfsr)
140227Sjchu {
140327Sjchu 	char		buf[FM_MAX_CLASS];
140427Sjchu 
140527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
140627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
140727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
140827Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
140927Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
141027Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
141127Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
141227Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
141327Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
141427Sjchu 	    ss_reg,
141527Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
141627Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
141727Sjchu 	    FIRE_MMU_TFAR, DATA_TYPE_UINT64,
141827Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS),
141927Sjchu 	    FIRE_MMU_TFSR, DATA_TYPE_UINT64,
142027Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_STATUS),
142127Sjchu 	    NULL);
142227Sjchu 
142327Sjchu 	return (PX_OK);
142427Sjchu }
142527Sjchu 
142627Sjchu /* DMC MMU - see io erpt doc, section 2.5 */
142727Sjchu PX_ERPT_SEND_DEC(mmu)
142827Sjchu {
142927Sjchu 	char		buf[FM_MAX_CLASS];
143027Sjchu 
143127Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
143227Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
143327Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
143427Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
143527Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
143627Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
143727Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
143827Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
143927Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
144027Sjchu 	    ss_reg,
144127Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
144227Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
144327Sjchu 	    NULL);
144427Sjchu 
144527Sjchu 	return (PX_OK);
144627Sjchu }
144727Sjchu 
144827Sjchu /* imu function to handle all Received but Not Enabled errors */
144927Sjchu int
145027Sjchu px_err_mmu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
145127Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
145227Sjchu 	px_err_bit_desc_t *err_bit_descr)
145327Sjchu {
1454260Set142600 	uint64_t	mmu_log_enable, mmu_intr_enable;
145527Sjchu 	uint64_t	mask = BITMASK(err_bit_descr->bit);
1456260Set142600 	uint64_t	mmu_tfa, mmu_ctrl;
1457260Set142600 	uint64_t	mmu_enable_bit = 0;
145827Sjchu 	int		err = PX_NONFATAL;
145927Sjchu 	int		ret;
146027Sjchu 
146127Sjchu 	mmu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
146227Sjchu 	mmu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
146327Sjchu 
146427Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
1465260Set142600 	mmu_ctrl = CSR_XR(csr_base, MMU_CONTROL_AND_STATUS);
146627Sjchu 
1467260Set142600 	switch (err_bit_descr->bit) {
1468260Set142600 	case MMU_INTERRUPT_STATUS_BYP_ERR_P:
1469260Set142600 		mmu_enable_bit = BITMASK(MMU_CONTROL_AND_STATUS_BE);
1470260Set142600 		break;
1471260Set142600 	case MMU_INTERRUPT_STATUS_TRN_ERR_P:
1472260Set142600 		mmu_enable_bit = BITMASK(MMU_CONTROL_AND_STATUS_TE);
1473260Set142600 		break;
1474260Set142600 	default:
1475260Set142600 		mmu_enable_bit = 0;
1476260Set142600 		break;
1477260Set142600 	}
1478260Set142600 
1479260Set142600 	/*
1480260Set142600 	 * If the interrupts are enabled and Translation/Bypass Enable bit
1481260Set142600 	 * was set, then panic.  This error should not have occured.
1482260Set142600 	 */
1483260Set142600 	if (mmu_log_enable & mmu_intr_enable &
1484260Set142600 	    (mmu_ctrl & mmu_enable_bit)) {
148527Sjchu 		err = PX_FATAL_SW;
148627Sjchu 	} else {
148727Sjchu 		ret = px_handle_lookup(
148827Sjchu 			rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
148927Sjchu 		err = (ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL;
149027Sjchu 
149127Sjchu 		/*
149227Sjchu 		 * S/W bug - this error should always be enabled
149327Sjchu 		 */
149427Sjchu 
149527Sjchu 		/* enable error & intr reporting for this bit */
149627Sjchu 		CSR_XS(csr_base, MMU_ERROR_LOG_ENABLE, mmu_log_enable | mask);
149727Sjchu 		CSR_XS(csr_base, MMU_INTERRUPT_ENABLE, mmu_intr_enable | mask);
1498260Set142600 
1499260Set142600 		/* enable translation access/bypass enable */
1500260Set142600 		CSR_XS(csr_base, MMU_CONTROL_AND_STATUS,
1501260Set142600 		    mmu_ctrl | mmu_enable_bit);
150227Sjchu 	}
150327Sjchu 
150427Sjchu 	return (err);
150527Sjchu }
150627Sjchu 
150727Sjchu /* Generic error handling functions that involve MMU Translation Fault Addr */
150827Sjchu /* ARGSUSED */
150927Sjchu int
151027Sjchu px_err_mmu_tfa_handle(dev_info_t *rpdip, caddr_t csr_base,
151127Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
151227Sjchu 	px_err_bit_desc_t *err_bit_descr)
151327Sjchu {
151427Sjchu 	uint64_t	mmu_tfa;
151527Sjchu 	uint_t		ret;
151627Sjchu 
151727Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
151827Sjchu 	ret = px_handle_lookup(
151927Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
152027Sjchu 
152127Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
152227Sjchu }
152327Sjchu 
152427Sjchu /* MMU Table walk errors */
152527Sjchu /* ARGSUSED */
152627Sjchu int
152727Sjchu px_err_mmu_tblwlk_handle(dev_info_t *rpdip, caddr_t csr_base,
152827Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
152927Sjchu 	px_err_bit_desc_t *err_bit_descr)
153027Sjchu {
153127Sjchu 	uint64_t	mmu_tfa;
153227Sjchu 	uint_t		ret;
153327Sjchu 
153427Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
153527Sjchu 	ret = px_handle_lookup(
153627Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
153727Sjchu 
153827Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
153927Sjchu }
154027Sjchu 
1541118Sjchu /*
1542118Sjchu  * TLU LUP event - power management code is interested in this event.
1543118Sjchu  */
1544118Sjchu /* ARGSUSED */
1545118Sjchu int
1546118Sjchu px_err_tlu_lup_handle(dev_info_t *rpdip, caddr_t csr_base,
1547118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1548118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1549118Sjchu {
1550118Sjchu 	px_t	*px_p = DIP_TO_STATE(rpdip);
1551118Sjchu 
1552118Sjchu 	/*
1553118Sjchu 	 * Existense of pm info indicates the power management
1554118Sjchu 	 * is interested in this event.
1555118Sjchu 	 */
1556118Sjchu 	if (!PCIE_PMINFO(rpdip) || !PCIE_NEXUS_PMINFO(rpdip))
1557118Sjchu 		return (PX_OK);
1558118Sjchu 
1559118Sjchu 	mutex_enter(&px_p->px_lup_lock);
1560118Sjchu 	px_p->px_lupsoft_pending++;
1561118Sjchu 	mutex_exit(&px_p->px_lup_lock);
1562118Sjchu 
1563118Sjchu 	/*
1564118Sjchu 	 * Post a soft interrupt to wake up threads waiting for this.
1565118Sjchu 	 */
1566118Sjchu 	ddi_trigger_softintr(px_p->px_lupsoft_id);
1567118Sjchu 
1568118Sjchu 	return (PX_OK);
1569118Sjchu }
1570118Sjchu 
157127Sjchu /* PEC ILU none - see io erpt doc, section 3.1 */
157227Sjchu PX_ERPT_SEND_DEC(pec_ilu)
157327Sjchu {
157427Sjchu 	char		buf[FM_MAX_CLASS];
157527Sjchu 
157627Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
157727Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
157827Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
157927Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
158027Sjchu 	    FIRE_ILU_ELE, DATA_TYPE_UINT64,
158127Sjchu 	    CSR_XR(csr_base, ILU_ERROR_LOG_ENABLE),
158227Sjchu 	    FIRE_ILU_IE, DATA_TYPE_UINT64,
158327Sjchu 	    CSR_XR(csr_base, ILU_INTERRUPT_ENABLE),
158427Sjchu 	    FIRE_ILU_IS, DATA_TYPE_UINT64,
158527Sjchu 	    ss_reg,
158627Sjchu 	    FIRE_ILU_ESS, DATA_TYPE_UINT64,
158727Sjchu 	    CSR_XR(csr_base, ILU_ERROR_STATUS_SET),
158827Sjchu 	    NULL);
158927Sjchu 
159027Sjchu 	return (PX_OK);
159127Sjchu }
159227Sjchu 
159327Sjchu /* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
159427Sjchu PX_ERPT_SEND_DEC(pciex_ce)
159527Sjchu {
159627Sjchu 	char		buf[FM_MAX_CLASS];
159727Sjchu 
159827Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
159927Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
160027Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
160127Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
160227Sjchu 	    FIRE_TLU_CELE, DATA_TYPE_UINT64,
160327Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE),
160427Sjchu 	    FIRE_TLU_CIE, DATA_TYPE_UINT64,
160527Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE),
160627Sjchu 	    FIRE_TLU_CIS, DATA_TYPE_UINT64,
160727Sjchu 	    ss_reg,
160827Sjchu 	    FIRE_TLU_CESS, DATA_TYPE_UINT64,
160927Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_STATUS_SET),
161027Sjchu 	    NULL);
161127Sjchu 
161227Sjchu 	return (PX_OK);
161327Sjchu }
161427Sjchu 
161527Sjchu /* TLU Other Event Status (receive only) - see io erpt doc, section 3.7 */
161627Sjchu PX_ERPT_SEND_DEC(pciex_rx_oe)
161727Sjchu {
161827Sjchu 	char		buf[FM_MAX_CLASS];
161927Sjchu 
162027Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
162127Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
162227Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
162327Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
162427Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
162527Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
162627Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
162727Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
162827Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
162927Sjchu 	    ss_reg,
163027Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
163127Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
163227Sjchu 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
163327Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
1634260Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
163527Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
163627Sjchu 	    NULL);
163727Sjchu 
163827Sjchu 	return (PX_OK);
163927Sjchu }
164027Sjchu 
164127Sjchu /* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
164227Sjchu PX_ERPT_SEND_DEC(pciex_rx_tx_oe)
164327Sjchu {
164427Sjchu 	char		buf[FM_MAX_CLASS];
164527Sjchu 
164627Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
164727Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
164827Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
164927Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
165027Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
165127Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
165227Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
165327Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
165427Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
165527Sjchu 	    ss_reg,
165627Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
165727Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
165827Sjchu 	    FIRE_TLU_ROEEH1L, DATA_TYPE_UINT64,
165927Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
166027Sjchu 	    FIRE_TLU_ROEEH2L, DATA_TYPE_UINT64,
166127Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
166227Sjchu 	    FIRE_TLU_TOEEH1L, DATA_TYPE_UINT64,
166327Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG),
1664260Set142600 	    FIRE_TLU_TOEEH2L, DATA_TYPE_UINT64,
166527Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG),
166627Sjchu 	    NULL);
166727Sjchu 
166827Sjchu 	return (PX_OK);
166927Sjchu }
167027Sjchu 
167127Sjchu /* TLU Other Event - see io erpt doc, section 3.9 */
167227Sjchu PX_ERPT_SEND_DEC(pciex_oe)
167327Sjchu {
1674287Smg140465 	char			buf[FM_MAX_CLASS];
167527Sjchu 
167627Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
167727Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
167827Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
167927Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
168027Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
168127Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
168227Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
168327Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
168427Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
168527Sjchu 	    ss_reg,
168627Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
168727Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
168827Sjchu 	    NULL);
168927Sjchu 
169027Sjchu 	return (PX_OK);
169127Sjchu }
1692287Smg140465 
1693287Smg140465 /* TLU Other Event - Link Down see io erpt doc, section 3.9 */
1694287Smg140465 PX_ERPT_SEND_DEC(pciex_ldn)
1695287Smg140465 {
1696287Smg140465 	px_t			*px_p = DIP_TO_STATE(rpdip);
1697287Smg140465 
1698287Smg140465 	/*
1699287Smg140465 	 * Don't post ereport, if ldn event is due to
1700287Smg140465 	 * power management.
1701287Smg140465 	 */
1702287Smg140465 	if (px_p->px_pm_flags & PX_LDN_EXPECTED) {
1703287Smg140465 		px_p->px_pm_flags &= ~PX_LDN_EXPECTED;
1704287Smg140465 		return (PX_OK);
1705287Smg140465 	}
1706287Smg140465 	return (PX_ERPT_SEND(pciex_oe)(rpdip, csr_base, ss_reg, derr,
1707287Smg140465 	    class_name));
1708287Smg140465 
1709287Smg140465 }
1710287Smg140465 
1711287Smg140465 /* TLU Other Event - Link Up see io erpt doc, section 3.9 */
1712287Smg140465 PX_ERPT_SEND_DEC(pciex_lup)
1713287Smg140465 {
1714287Smg140465 	px_t			*px_p = DIP_TO_STATE(rpdip);
1715287Smg140465 
1716287Smg140465 	/*
1717287Smg140465 	 * Don't post ereport, if lup event is due to
1718287Smg140465 	 * power management.
1719287Smg140465 	 */
1720287Smg140465 	if (px_p->px_pm_flags & PX_LUP_EXPECTED) {
1721287Smg140465 		px_p->px_pm_flags &= ~PX_LUP_EXPECTED;
1722287Smg140465 		return (PX_OK);
1723287Smg140465 	}
1724287Smg140465 
1725287Smg140465 	return (PX_ERPT_SEND(pciex_oe)(rpdip, csr_base, ss_reg, derr,
1726287Smg140465 	    class_name));
1727287Smg140465 }
1728