xref: /onnv-gate/usr/src/uts/sun4u/io/px/px_err.c (revision 287:e2397de3bde0)
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) },
257*287Smg140465 	{ TLU_OE_BIT_DESC(LDN,		non_fatal,	pciex_ldn) },
258*287Smg140465 	{ 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 		}
84427Sjchu 		/* Log register status */
84527Sjchu 		if ((px_err_log_all) || (ss_reg & *log_mask))
84627Sjchu 			LOG(DBG_ERR_INTR, rpdip, "<%x>=%16llx %s\n",
84727Sjchu 			    status_addr, ss_reg, err_reg_tbl->msg);
84827Sjchu 
84927Sjchu 		/* Clear the register and error */
85027Sjchu 		CSR_XS(csr_base, clear_addr, ss_reg);
85127Sjchu 	}
85227Sjchu 
85327Sjchu 	return (err);
85427Sjchu }
85527Sjchu 
85627Sjchu /*
85727Sjchu  * px_err_check_severity:
85827Sjchu  * Check the severity of the fire error based on an earlier snapshot
85927Sjchu  *
86027Sjchu  * @param px_p		leaf in which to take the snap shot.
86127Sjchu  * @param derr		fm err in which the ereport is to be based on
86227Sjchu  * @param ss		pre-allocated memory to store the snap shot.
86327Sjchu  */
86427Sjchu static int
86527Sjchu px_err_check_severity(px_t *px_p, ddi_fm_error_t *derr, int err, int caller)
86627Sjchu {
86727Sjchu 	px_pec_t 	*pec_p = px_p->px_pec_p;
86827Sjchu 	boolean_t	is_safeacc = B_FALSE;
869118Sjchu 
870118Sjchu 	/* nothing to do if called with no error */
871118Sjchu 	if (err == PX_OK)
872118Sjchu 		return (err);
87327Sjchu 
87427Sjchu 	/* Cautious access error handling  */
87527Sjchu 	switch (derr->fme_flag) {
87627Sjchu 	case DDI_FM_ERR_EXPECTED:
87727Sjchu 		if (caller == PX_TRAP_CALL) {
87827Sjchu 			/*
87927Sjchu 			 * for ddi_caut_get treat all events as nonfatal
88027Sjchu 			 * The trampoline will set err_ena = 0,
88127Sjchu 			 * err_status = NONFATAL.
88227Sjchu 			 */
88327Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
88427Sjchu 			is_safeacc = B_TRUE;
88527Sjchu 		} else {
88627Sjchu 			/*
88727Sjchu 			 * For ddi_caut_put treat all events as nonfatal. Here
88827Sjchu 			 * we have the handle and can call ndi_fm_acc_err_set().
88927Sjchu 			 */
89027Sjchu 			derr->fme_status = DDI_FM_NONFATAL;
89127Sjchu 			ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr);
89227Sjchu 			is_safeacc = B_TRUE;
89327Sjchu 		}
89427Sjchu 		break;
89527Sjchu 	case DDI_FM_ERR_PEEK:
89627Sjchu 	case DDI_FM_ERR_POKE:
89727Sjchu 		/*
89827Sjchu 		 * For ddi_peek/poke treat all events as nonfatal.
89927Sjchu 		 */
90027Sjchu 		is_safeacc = B_TRUE;
90127Sjchu 		break;
90227Sjchu 	default:
90327Sjchu 		is_safeacc = B_FALSE;
90427Sjchu 	}
90527Sjchu 
90627Sjchu 	/*
90727Sjchu 	 * The third argument "err" is passed in as error status from checking
90827Sjchu 	 * Fire register, re-adjust error status from safe access.
90927Sjchu 	 */
91027Sjchu 	if (is_safeacc && !(err & PX_FATAL_GOS))
911118Sjchu 		return (PX_NONFATAL);
91227Sjchu 
913118Sjchu 	return (err);
91427Sjchu }
91527Sjchu 
91627Sjchu /* predefined convenience functions */
91727Sjchu /* ARGSUSED */
91827Sjchu int
91927Sjchu px_err_fatal_hw_handle(dev_info_t *rpdip, caddr_t csr_base,
92027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
92127Sjchu 	px_err_bit_desc_t *err_bit_descr)
92227Sjchu {
92327Sjchu 	return (PX_FATAL_HW);
92427Sjchu }
92527Sjchu 
92627Sjchu /* ARGSUSED */
92727Sjchu int
92827Sjchu px_err_fatal_gos_handle(dev_info_t *rpdip, caddr_t csr_base,
92927Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
93027Sjchu 	px_err_bit_desc_t *err_bit_descr)
93127Sjchu {
93227Sjchu 	return (PX_FATAL_GOS);
93327Sjchu }
93427Sjchu 
93527Sjchu /* ARGSUSED */
93627Sjchu int
93727Sjchu px_err_fatal_stuck_handle(dev_info_t *rpdip, caddr_t csr_base,
93827Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
93927Sjchu 	px_err_bit_desc_t *err_bit_descr)
94027Sjchu {
94127Sjchu 	return (PX_STUCK_FATAL);
94227Sjchu }
94327Sjchu 
94427Sjchu /* ARGSUSED */
94527Sjchu int
94627Sjchu px_err_fatal_sw_handle(dev_info_t *rpdip, caddr_t csr_base,
94727Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
94827Sjchu 	px_err_bit_desc_t *err_bit_descr)
94927Sjchu {
95027Sjchu 	return (PX_FATAL_SW);
95127Sjchu }
95227Sjchu 
95327Sjchu /* ARGSUSED */
95427Sjchu int
95527Sjchu px_err_non_fatal_handle(dev_info_t *rpdip, caddr_t csr_base,
95627Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
95727Sjchu 	px_err_bit_desc_t *err_bit_descr)
95827Sjchu {
95927Sjchu 	return (PX_NONFATAL);
96027Sjchu }
96127Sjchu 
96227Sjchu /* ARGSUSED */
96327Sjchu int
96427Sjchu px_err_ok_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
96527Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
96627Sjchu {
96727Sjchu 	return (PX_OK);
96827Sjchu }
96927Sjchu 
97027Sjchu /* ARGSUSED */
97127Sjchu int
97227Sjchu px_err_unknown_handle(dev_info_t *rpdip, caddr_t csr_base, ddi_fm_error_t *derr,
97327Sjchu 	px_err_reg_desc_t *err_reg_descr, px_err_bit_desc_t *err_bit_descr)
97427Sjchu {
97527Sjchu 	return (PX_ERR_UNKNOWN);
97627Sjchu }
97727Sjchu 
97827Sjchu /* JBC FATAL - see io erpt doc, section 1.1 */
97927Sjchu PX_ERPT_SEND_DEC(jbc_fatal)
98027Sjchu {
98127Sjchu 	char		buf[FM_MAX_CLASS];
98227Sjchu 
98327Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
98427Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
98527Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
98627Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
98727Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
98827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
98927Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
99027Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
99127Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
99227Sjchu 	    ss_reg,
99327Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
99427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
99527Sjchu 	    FIRE_JBC_FEL1, DATA_TYPE_UINT64,
99627Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_1),
99727Sjchu 	    FIRE_JBC_FEL2, DATA_TYPE_UINT64,
99827Sjchu 	    CSR_XR(csr_base, FATAL_ERROR_LOG_2),
99927Sjchu 	    NULL);
100027Sjchu 
100127Sjchu 	return (PX_OK);
100227Sjchu }
100327Sjchu 
100427Sjchu /* JBC MERGE - see io erpt doc, section 1.2 */
100527Sjchu PX_ERPT_SEND_DEC(jbc_merge)
100627Sjchu {
100727Sjchu 	char		buf[FM_MAX_CLASS];
100827Sjchu 
100927Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
101027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
101127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
101227Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
101327Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
101427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
101527Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
101627Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
101727Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
101827Sjchu 	    ss_reg,
101927Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
102027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
102127Sjchu 	    FIRE_JBC_MTEL, DATA_TYPE_UINT64,
102227Sjchu 	    CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG),
102327Sjchu 	    NULL);
102427Sjchu 
102527Sjchu 	return (PX_OK);
102627Sjchu }
102727Sjchu 
102827Sjchu /*
102927Sjchu  * JBC Merge buffer nonfatal errors:
103027Sjchu  *    Merge buffer parity error (rd_buf): dma:read:M:nonfatal
103127Sjchu  *    Merge buffer parity error (wr_buf): dma:write:M:nonfatal
103227Sjchu  */
103327Sjchu /* ARGSUSED */
103427Sjchu int
103527Sjchu px_err_jbc_merge_handle(dev_info_t *rpdip, caddr_t csr_base,
103627Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
103727Sjchu 	px_err_bit_desc_t *err_bit_descr)
103827Sjchu {
103927Sjchu 	uint64_t	paddr;
104027Sjchu 	int		ret;
104127Sjchu 
104227Sjchu 	paddr = CSR_XR(csr_base, MERGE_TRANSACTION_ERROR_LOG);
104327Sjchu 	paddr &= MERGE_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
104427Sjchu 
104527Sjchu 	ret = px_handle_lookup(
104627Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
104727Sjchu 
104827Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
104927Sjchu }
105027Sjchu 
105127Sjchu /* JBC Jbusint IN - see io erpt doc, section 1.3 */
105227Sjchu PX_ERPT_SEND_DEC(jbc_in)
105327Sjchu {
105427Sjchu 	char		buf[FM_MAX_CLASS];
105527Sjchu 
105627Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
105727Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
105827Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
105927Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
106027Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
106127Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
106227Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
106327Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
106427Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
106527Sjchu 	    ss_reg,
106627Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
106727Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
106827Sjchu 	    FIRE_JBC_JITEL1, DATA_TYPE_UINT64,
106927Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG),
107027Sjchu 	    FIRE_JBC_JITEL2, DATA_TYPE_UINT64,
107127Sjchu 	    CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG_2),
107227Sjchu 	    NULL);
107327Sjchu 
107427Sjchu 	return (PX_OK);
107527Sjchu }
107627Sjchu 
107727Sjchu /*
107827Sjchu  * JBC Jbusint IN nonfatal errors: PA logged in Jbusint In Transaction Error
107927Sjchu  * Log Reg[42:0].
108027Sjchu  *     CE async fault error: nonfatal
108127Sjchu  *     Jbus bus error: dma::nonfatal
108227Sjchu  *     Jbus unmapped error: pio|dma:rdwr:M:nonfatal
108327Sjchu  *     Write data parity error: pio/write:M:nonfatal
108427Sjchu  *     Read data parity error: pio/read:M:nonfatal
108527Sjchu  *     Illegal NCWR bytemask: pio:write:M:nonfatal
108627Sjchu  *     Illegal NCRD bytemask: pio:write:M:nonfatal
108727Sjchu  *     Invalid jbus transaction: nonfatal
108827Sjchu  */
108927Sjchu /* ARGSUSED */
109027Sjchu int
109127Sjchu px_err_jbc_jbusint_in_handle(dev_info_t *rpdip, caddr_t csr_base,
109227Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
109327Sjchu 	px_err_bit_desc_t *err_bit_descr)
109427Sjchu {
109527Sjchu 	uint64_t	paddr;
109627Sjchu 	int		ret;
109727Sjchu 
109827Sjchu 	paddr = CSR_XR(csr_base, JBCINT_IN_TRANSACTION_ERROR_LOG);
109927Sjchu 	paddr &= JBCINT_IN_TRANSACTION_ERROR_LOG_ADDRESS_MASK;
110027Sjchu 
110127Sjchu 	ret = px_handle_lookup(
110227Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
110327Sjchu 
110427Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
110527Sjchu }
110627Sjchu 
110727Sjchu 
110827Sjchu /* JBC Jbusint Out - see io erpt doc, section 1.4 */
110927Sjchu PX_ERPT_SEND_DEC(jbc_out)
111027Sjchu {
111127Sjchu 	char		buf[FM_MAX_CLASS];
111227Sjchu 
111327Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
111427Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
111527Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
111627Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
111727Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
111827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
111927Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
112027Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
112127Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
112227Sjchu 	    ss_reg,
112327Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
112427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
112527Sjchu 	    FIRE_JBC_JOTEL1, DATA_TYPE_UINT64,
112627Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG),
112727Sjchu 	    FIRE_JBC_JOTEL2, DATA_TYPE_UINT64,
112827Sjchu 	    CSR_XR(csr_base, JBCINT_OUT_TRANSACTION_ERROR_LOG_2),
112927Sjchu 	    NULL);
113027Sjchu 
113127Sjchu 	return (PX_OK);
113227Sjchu }
113327Sjchu 
113427Sjchu /* JBC Dmcint ODCD - see io erpt doc, section 1.5 */
113527Sjchu PX_ERPT_SEND_DEC(jbc_odcd)
113627Sjchu {
113727Sjchu 	char		buf[FM_MAX_CLASS];
113827Sjchu 
113927Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
114027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
114127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
114227Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
114327Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
114427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
114527Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
114627Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
114727Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
114827Sjchu 	    ss_reg,
114927Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
115027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
115127Sjchu 	    FIRE_JBC_DMC_ODCD, DATA_TYPE_UINT64,
115227Sjchu 	    CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG),
115327Sjchu 	    NULL);
115427Sjchu 
115527Sjchu 	return (PX_OK);
115627Sjchu }
115727Sjchu 
115827Sjchu /*
115927Sjchu  * JBC Dmcint ODCO nonfatal errer handling -
116027Sjchu  *    Unmapped PIO read error: pio:read:M:nonfatal
116127Sjchu  *    Unmapped PIO write error: pio:write:M:nonfatal
116227Sjchu  *    PIO data parity error: pio:write:M:nonfatal
116327Sjchu  *    Invalid PIO write to PCIe cfg/io, csr, ebus or i2c bus: pio:write:nonfatal
116427Sjchu  *    Invalid PIO read to PCIe cfg/io, csr, ebus or i2c bus: pio:read:nonfatal
116527Sjchu  */
116627Sjchu /* ARGSUSED */
116727Sjchu int
116827Sjchu px_err_jbc_dmcint_odcd_handle(dev_info_t *rpdip, caddr_t csr_base,
116927Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
117027Sjchu 	px_err_bit_desc_t *err_bit_descr)
117127Sjchu {
117227Sjchu 	uint64_t	paddr;
117327Sjchu 	int		ret;
117427Sjchu 
117527Sjchu 	paddr = CSR_XR(csr_base, DMCINT_ODCD_ERROR_LOG);
117627Sjchu 	paddr &= DMCINT_ODCD_ERROR_LOG_ADDRESS_MASK;
117727Sjchu 
117827Sjchu 	ret = px_handle_lookup(
117927Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
118027Sjchu 
118127Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
118227Sjchu }
118327Sjchu 
118427Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
118527Sjchu PX_ERPT_SEND_DEC(jbc_idc)
118627Sjchu {
118727Sjchu 	char		buf[FM_MAX_CLASS];
118827Sjchu 
118927Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
119027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
119127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
119227Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
119327Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
119427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
119527Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
119627Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
119727Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
119827Sjchu 	    ss_reg,
119927Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
120027Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
120127Sjchu 	    FIRE_JBC_DMC_IDC, DATA_TYPE_UINT64,
120227Sjchu 	    CSR_XR(csr_base, DMCINT_IDC_ERROR_LOG),
120327Sjchu 	    NULL);
120427Sjchu 
120527Sjchu 	return (PX_OK);
120627Sjchu }
120727Sjchu 
120827Sjchu /* JBC CSR - see io erpt doc, section 1.7 */
120927Sjchu PX_ERPT_SEND_DEC(jbc_csr)
121027Sjchu {
121127Sjchu 	char		buf[FM_MAX_CLASS];
121227Sjchu 
121327Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
121427Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
121527Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
121627Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
121727Sjchu 	    FIRE_JBC_ELE, DATA_TYPE_UINT64,
121827Sjchu 	    CSR_XR(csr_base, JBC_ERROR_LOG_ENABLE),
121927Sjchu 	    FIRE_JBC_IE, DATA_TYPE_UINT64,
122027Sjchu 	    CSR_XR(csr_base, JBC_INTERRUPT_ENABLE),
122127Sjchu 	    FIRE_JBC_IS, DATA_TYPE_UINT64,
122227Sjchu 	    ss_reg,
122327Sjchu 	    FIRE_JBC_ESS, DATA_TYPE_UINT64,
122427Sjchu 	    CSR_XR(csr_base, JBC_ERROR_STATUS_SET),
122527Sjchu 	    "jbc-error-reg", DATA_TYPE_UINT64,
122627Sjchu 	    CSR_XR(csr_base, CSR_ERROR_LOG),
122727Sjchu 	    NULL);
122827Sjchu 
122927Sjchu 	return (PX_OK);
123027Sjchu }
123127Sjchu 
123227Sjchu /*
123327Sjchu  * JBC CSR errer handling -
123427Sjchu  * Ebus ready timeout error: pio:rdwr:M:nonfatal
123527Sjchu  */
123627Sjchu /* ARGSUSED */
123727Sjchu int
123827Sjchu px_err_jbc_csr_handle(dev_info_t *rpdip, caddr_t csr_base,
123927Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
124027Sjchu 	px_err_bit_desc_t *err_bit_descr)
124127Sjchu {
124227Sjchu 	uint64_t	paddr;
124327Sjchu 	int		ret;
124427Sjchu 
124527Sjchu 	paddr = CSR_XR(csr_base, CSR_ERROR_LOG);
124627Sjchu 	paddr &= CSR_ERROR_LOG_ADDRESS_MASK;
124727Sjchu 
124827Sjchu 	ret = px_handle_lookup(
124927Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)paddr);
125027Sjchu 
125127Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
125227Sjchu }
125327Sjchu 
125427Sjchu /* JBC Dmcint IDC - see io erpt doc, section 1.6 */
125527Sjchu 
125627Sjchu /* DMC IMU RDS - see io erpt doc, section 2.1 */
125727Sjchu PX_ERPT_SEND_DEC(imu_rds)
125827Sjchu {
125927Sjchu 	char		buf[FM_MAX_CLASS];
126027Sjchu 
126127Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
126227Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
126327Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
126427Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
126527Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
126627Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
126727Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
126827Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
126927Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
127027Sjchu 	    ss_reg,
127127Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
127227Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
127327Sjchu 	    FIRE_IMU_RDS, DATA_TYPE_UINT64,
127427Sjchu 	    CSR_XR(csr_base, IMU_RDS_ERROR_LOG),
127527Sjchu 	    NULL);
127627Sjchu 
127727Sjchu 	return (PX_OK);
127827Sjchu }
127927Sjchu 
128027Sjchu /* imu function to handle all Received but Not Enabled errors */
128127Sjchu /* ARGSUSED */
128227Sjchu int
128327Sjchu px_err_imu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
128427Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
128527Sjchu 	px_err_bit_desc_t *err_bit_descr)
128627Sjchu {
128727Sjchu 	uint64_t	imu_log_enable, imu_intr_enable;
128827Sjchu 	int		mask = BITMASK(err_bit_descr->bit);
128927Sjchu 	int		err = PX_NONFATAL;
129027Sjchu 
129127Sjchu 	imu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
129227Sjchu 	imu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
129327Sjchu 
129427Sjchu 	if (imu_log_enable & imu_intr_enable & mask) {
129527Sjchu 		err = PX_FATAL_SW;
129627Sjchu 	} else {
129727Sjchu 		/*
129827Sjchu 		 * S/W bug - this error should always be enabled
129927Sjchu 		 */
130027Sjchu 
130127Sjchu 		/* enable error & intr reporting for this bit */
130227Sjchu 		CSR_XS(csr_base, IMU_ERROR_LOG_ENABLE, imu_log_enable | mask);
130327Sjchu 		CSR_XS(csr_base, IMU_INTERRUPT_ENABLE, imu_intr_enable | mask);
130427Sjchu 		err = PX_NONFATAL;
130527Sjchu 	}
130627Sjchu 
130727Sjchu 	return (err);
130827Sjchu }
130927Sjchu 
1310118Sjchu /*
1311118Sjchu  * No platforms uses PME. Any PME received is simply logged
1312118Sjchu  * for analysis.
1313118Sjchu  */
1314118Sjchu /* ARGSUSED */
1315118Sjchu int
1316118Sjchu px_err_imu_pme_handle(dev_info_t *rpdip, caddr_t csr_base,
1317118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1318118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1319118Sjchu {
1320118Sjchu 	px_t		*px_p = DIP_TO_STATE(rpdip);
1321118Sjchu 
1322118Sjchu 	px_p->px_pme_ignored++;
1323118Sjchu 	return (PX_NONFATAL);
1324118Sjchu }
1325118Sjchu 
132627Sjchu /* handle EQ overflow */
132727Sjchu /* ARGSUSED */
132827Sjchu int
132927Sjchu px_err_imu_eq_ovfl_handle(dev_info_t *rpdip, caddr_t csr_base,
133027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
133127Sjchu 	px_err_bit_desc_t *err_bit_descr)
133227Sjchu {
133327Sjchu 	px_t			*px_p = DIP_TO_STATE(rpdip);
133427Sjchu 	px_msiq_state_t 	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
133527Sjchu 	msiqid_t		eqno;
133627Sjchu 	pci_msiq_state_t	msiq_state;
133727Sjchu 	int			err = PX_NONFATAL;
133827Sjchu 	int			i;
133927Sjchu 
134027Sjchu 	eqno = msiq_state_p->msiq_1st_msiq_id;
134127Sjchu 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
134227Sjchu 		if (px_lib_msiq_getstate(rpdip, eqno, &msiq_state) ==
134327Sjchu 			DDI_SUCCESS) {
134427Sjchu 			if (msiq_state == PCI_MSIQ_STATE_ERROR) {
134527Sjchu 				err = PX_FATAL_SW;
134627Sjchu 			}
134727Sjchu 		}
134827Sjchu 	}
134927Sjchu 
135027Sjchu 	return (err);
135127Sjchu }
135227Sjchu 
135327Sjchu /* DMC IMU SCS - see io erpt doc, section 2.2 */
135427Sjchu PX_ERPT_SEND_DEC(imu_scs)
135527Sjchu {
135627Sjchu 	char		buf[FM_MAX_CLASS];
135727Sjchu 
135827Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
135927Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
136027Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
136127Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
136227Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
136327Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
136427Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
136527Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
136627Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
136727Sjchu 	    ss_reg,
136827Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
136927Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
137027Sjchu 	    FIRE_IMU_SCS, DATA_TYPE_UINT64,
137127Sjchu 	    CSR_XR(csr_base, IMU_SCS_ERROR_LOG),
137227Sjchu 	    NULL);
137327Sjchu 
137427Sjchu 	return (PX_OK);
137527Sjchu }
137627Sjchu 
137727Sjchu /* DMC IMU - see io erpt doc, section 2.3 */
137827Sjchu PX_ERPT_SEND_DEC(imu)
137927Sjchu {
138027Sjchu 	char		buf[FM_MAX_CLASS];
138127Sjchu 
138227Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
138327Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
138427Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
138527Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
138627Sjchu 	    FIRE_IMU_ELE, DATA_TYPE_UINT64,
138727Sjchu 	    CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE),
138827Sjchu 	    FIRE_IMU_IE, DATA_TYPE_UINT64,
138927Sjchu 	    CSR_XR(csr_base, IMU_INTERRUPT_ENABLE),
139027Sjchu 	    FIRE_IMU_IS, DATA_TYPE_UINT64,
139127Sjchu 	    ss_reg,
139227Sjchu 	    FIRE_IMU_ESS, DATA_TYPE_UINT64,
139327Sjchu 	    CSR_XR(csr_base, IMU_ERROR_STATUS_SET),
139427Sjchu 	    NULL);
139527Sjchu 
139627Sjchu 	return (PX_OK);
139727Sjchu }
139827Sjchu 
139927Sjchu /* DMC MMU TFAR/TFSR - see io erpt doc, section 2.4 */
140027Sjchu PX_ERPT_SEND_DEC(mmu_tfar_tfsr)
140127Sjchu {
140227Sjchu 	char		buf[FM_MAX_CLASS];
140327Sjchu 
140427Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
140527Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
140627Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
140727Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
140827Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
140927Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
141027Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
141127Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
141227Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
141327Sjchu 	    ss_reg,
141427Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
141527Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
141627Sjchu 	    FIRE_MMU_TFAR, DATA_TYPE_UINT64,
141727Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS),
141827Sjchu 	    FIRE_MMU_TFSR, DATA_TYPE_UINT64,
141927Sjchu 	    CSR_XR(csr_base, MMU_TRANSLATION_FAULT_STATUS),
142027Sjchu 	    NULL);
142127Sjchu 
142227Sjchu 	return (PX_OK);
142327Sjchu }
142427Sjchu 
142527Sjchu /* DMC MMU - see io erpt doc, section 2.5 */
142627Sjchu PX_ERPT_SEND_DEC(mmu)
142727Sjchu {
142827Sjchu 	char		buf[FM_MAX_CLASS];
142927Sjchu 
143027Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
143127Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
143227Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
143327Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
143427Sjchu 	    FIRE_MMU_ELE, DATA_TYPE_UINT64,
143527Sjchu 	    CSR_XR(csr_base, MMU_ERROR_LOG_ENABLE),
143627Sjchu 	    FIRE_MMU_IE, DATA_TYPE_UINT64,
143727Sjchu 	    CSR_XR(csr_base, MMU_INTERRUPT_ENABLE),
143827Sjchu 	    FIRE_MMU_IS, DATA_TYPE_UINT64,
143927Sjchu 	    ss_reg,
144027Sjchu 	    FIRE_MMU_ESS, DATA_TYPE_UINT64,
144127Sjchu 	    CSR_XR(csr_base, MMU_ERROR_STATUS_SET),
144227Sjchu 	    NULL);
144327Sjchu 
144427Sjchu 	return (PX_OK);
144527Sjchu }
144627Sjchu 
144727Sjchu /* imu function to handle all Received but Not Enabled errors */
144827Sjchu int
144927Sjchu px_err_mmu_rbne_handle(dev_info_t *rpdip, caddr_t csr_base,
145027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
145127Sjchu 	px_err_bit_desc_t *err_bit_descr)
145227Sjchu {
1453260Set142600 	uint64_t	mmu_log_enable, mmu_intr_enable;
145427Sjchu 	uint64_t	mask = BITMASK(err_bit_descr->bit);
1455260Set142600 	uint64_t	mmu_tfa, mmu_ctrl;
1456260Set142600 	uint64_t	mmu_enable_bit = 0;
145727Sjchu 	int		err = PX_NONFATAL;
145827Sjchu 	int		ret;
145927Sjchu 
146027Sjchu 	mmu_log_enable = CSR_XR(csr_base, err_reg_descr->log_addr);
146127Sjchu 	mmu_intr_enable = CSR_XR(csr_base, err_reg_descr->enable_addr);
146227Sjchu 
146327Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
1464260Set142600 	mmu_ctrl = CSR_XR(csr_base, MMU_CONTROL_AND_STATUS);
146527Sjchu 
1466260Set142600 	switch (err_bit_descr->bit) {
1467260Set142600 	case MMU_INTERRUPT_STATUS_BYP_ERR_P:
1468260Set142600 		mmu_enable_bit = BITMASK(MMU_CONTROL_AND_STATUS_BE);
1469260Set142600 		break;
1470260Set142600 	case MMU_INTERRUPT_STATUS_TRN_ERR_P:
1471260Set142600 		mmu_enable_bit = BITMASK(MMU_CONTROL_AND_STATUS_TE);
1472260Set142600 		break;
1473260Set142600 	default:
1474260Set142600 		mmu_enable_bit = 0;
1475260Set142600 		break;
1476260Set142600 	}
1477260Set142600 
1478260Set142600 	/*
1479260Set142600 	 * If the interrupts are enabled and Translation/Bypass Enable bit
1480260Set142600 	 * was set, then panic.  This error should not have occured.
1481260Set142600 	 */
1482260Set142600 	if (mmu_log_enable & mmu_intr_enable &
1483260Set142600 	    (mmu_ctrl & mmu_enable_bit)) {
148427Sjchu 		err = PX_FATAL_SW;
148527Sjchu 	} else {
148627Sjchu 		ret = px_handle_lookup(
148727Sjchu 			rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
148827Sjchu 		err = (ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL;
148927Sjchu 
149027Sjchu 		/*
149127Sjchu 		 * S/W bug - this error should always be enabled
149227Sjchu 		 */
149327Sjchu 
149427Sjchu 		/* enable error & intr reporting for this bit */
149527Sjchu 		CSR_XS(csr_base, MMU_ERROR_LOG_ENABLE, mmu_log_enable | mask);
149627Sjchu 		CSR_XS(csr_base, MMU_INTERRUPT_ENABLE, mmu_intr_enable | mask);
1497260Set142600 
1498260Set142600 		/* enable translation access/bypass enable */
1499260Set142600 		CSR_XS(csr_base, MMU_CONTROL_AND_STATUS,
1500260Set142600 		    mmu_ctrl | mmu_enable_bit);
150127Sjchu 	}
150227Sjchu 
150327Sjchu 	return (err);
150427Sjchu }
150527Sjchu 
150627Sjchu /* Generic error handling functions that involve MMU Translation Fault Addr */
150727Sjchu /* ARGSUSED */
150827Sjchu int
150927Sjchu px_err_mmu_tfa_handle(dev_info_t *rpdip, caddr_t csr_base,
151027Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
151127Sjchu 	px_err_bit_desc_t *err_bit_descr)
151227Sjchu {
151327Sjchu 	uint64_t	mmu_tfa;
151427Sjchu 	uint_t		ret;
151527Sjchu 
151627Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
151727Sjchu 	ret = px_handle_lookup(
151827Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
151927Sjchu 
152027Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
152127Sjchu }
152227Sjchu 
152327Sjchu /* MMU Table walk errors */
152427Sjchu /* ARGSUSED */
152527Sjchu int
152627Sjchu px_err_mmu_tblwlk_handle(dev_info_t *rpdip, caddr_t csr_base,
152727Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
152827Sjchu 	px_err_bit_desc_t *err_bit_descr)
152927Sjchu {
153027Sjchu 	uint64_t	mmu_tfa;
153127Sjchu 	uint_t		ret;
153227Sjchu 
153327Sjchu 	mmu_tfa = CSR_XR(csr_base, MMU_TRANSLATION_FAULT_ADDRESS);
153427Sjchu 	ret = px_handle_lookup(
153527Sjchu 		rpdip, DMA_HANDLE, derr->fme_ena, (void *)mmu_tfa);
153627Sjchu 
153727Sjchu 	return ((ret == DDI_FM_FATAL) ? PX_FATAL_GOS : PX_NONFATAL);
153827Sjchu }
153927Sjchu 
1540118Sjchu /*
1541118Sjchu  * TLU LUP event - power management code is interested in this event.
1542118Sjchu  */
1543118Sjchu /* ARGSUSED */
1544118Sjchu int
1545118Sjchu px_err_tlu_lup_handle(dev_info_t *rpdip, caddr_t csr_base,
1546118Sjchu 	ddi_fm_error_t *derr, px_err_reg_desc_t *err_reg_descr,
1547118Sjchu 	px_err_bit_desc_t *err_bit_descr)
1548118Sjchu {
1549118Sjchu 	px_t	*px_p = DIP_TO_STATE(rpdip);
1550118Sjchu 
1551118Sjchu 	/*
1552118Sjchu 	 * Existense of pm info indicates the power management
1553118Sjchu 	 * is interested in this event.
1554118Sjchu 	 */
1555118Sjchu 	if (!PCIE_PMINFO(rpdip) || !PCIE_NEXUS_PMINFO(rpdip))
1556118Sjchu 		return (PX_OK);
1557118Sjchu 
1558118Sjchu 	mutex_enter(&px_p->px_lup_lock);
1559118Sjchu 	px_p->px_lupsoft_pending++;
1560118Sjchu 	mutex_exit(&px_p->px_lup_lock);
1561118Sjchu 
1562118Sjchu 	/*
1563118Sjchu 	 * Post a soft interrupt to wake up threads waiting for this.
1564118Sjchu 	 */
1565118Sjchu 	ddi_trigger_softintr(px_p->px_lupsoft_id);
1566118Sjchu 
1567118Sjchu 	return (PX_OK);
1568118Sjchu }
1569118Sjchu 
157027Sjchu /* PEC ILU none - see io erpt doc, section 3.1 */
157127Sjchu PX_ERPT_SEND_DEC(pec_ilu)
157227Sjchu {
157327Sjchu 	char		buf[FM_MAX_CLASS];
157427Sjchu 
157527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
157627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
157727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
157827Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
157927Sjchu 	    FIRE_ILU_ELE, DATA_TYPE_UINT64,
158027Sjchu 	    CSR_XR(csr_base, ILU_ERROR_LOG_ENABLE),
158127Sjchu 	    FIRE_ILU_IE, DATA_TYPE_UINT64,
158227Sjchu 	    CSR_XR(csr_base, ILU_INTERRUPT_ENABLE),
158327Sjchu 	    FIRE_ILU_IS, DATA_TYPE_UINT64,
158427Sjchu 	    ss_reg,
158527Sjchu 	    FIRE_ILU_ESS, DATA_TYPE_UINT64,
158627Sjchu 	    CSR_XR(csr_base, ILU_ERROR_STATUS_SET),
158727Sjchu 	    NULL);
158827Sjchu 
158927Sjchu 	return (PX_OK);
159027Sjchu }
159127Sjchu 
159227Sjchu /* PCI-E Correctable Errors - see io erpt doc, section 3.6 */
159327Sjchu PX_ERPT_SEND_DEC(pciex_ce)
159427Sjchu {
159527Sjchu 	char		buf[FM_MAX_CLASS];
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,
160027Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
160127Sjchu 	    FIRE_TLU_CELE, DATA_TYPE_UINT64,
160227Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE),
160327Sjchu 	    FIRE_TLU_CIE, DATA_TYPE_UINT64,
160427Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE),
160527Sjchu 	    FIRE_TLU_CIS, DATA_TYPE_UINT64,
160627Sjchu 	    ss_reg,
160727Sjchu 	    FIRE_TLU_CESS, DATA_TYPE_UINT64,
160827Sjchu 	    CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_STATUS_SET),
160927Sjchu 	    NULL);
161027Sjchu 
161127Sjchu 	return (PX_OK);
161227Sjchu }
161327Sjchu 
161427Sjchu /* TLU Other Event Status (receive only) - see io erpt doc, section 3.7 */
161527Sjchu PX_ERPT_SEND_DEC(pciex_rx_oe)
161627Sjchu {
161727Sjchu 	char		buf[FM_MAX_CLASS];
161827Sjchu 
161927Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
162027Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
162127Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
162227Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
162327Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
162427Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
162527Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
162627Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
162727Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
162827Sjchu 	    ss_reg,
162927Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
163027Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
163127Sjchu 	    FIRE_TLU_RUEH1L, DATA_TYPE_UINT64,
163227Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
1633260Set142600 	    FIRE_TLU_RUEH2L, DATA_TYPE_UINT64,
163427Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
163527Sjchu 	    NULL);
163627Sjchu 
163727Sjchu 	return (PX_OK);
163827Sjchu }
163927Sjchu 
164027Sjchu /* TLU Other Event Status (rx + tx) - see io erpt doc, section 3.8 */
164127Sjchu PX_ERPT_SEND_DEC(pciex_rx_tx_oe)
164227Sjchu {
164327Sjchu 	char		buf[FM_MAX_CLASS];
164427Sjchu 
164527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
164627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
164727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
164827Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
164927Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
165027Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
165127Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
165227Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
165327Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
165427Sjchu 	    ss_reg,
165527Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
165627Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
165727Sjchu 	    FIRE_TLU_ROEEH1L, DATA_TYPE_UINT64,
165827Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG),
165927Sjchu 	    FIRE_TLU_ROEEH2L, DATA_TYPE_UINT64,
166027Sjchu 	    CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG),
166127Sjchu 	    FIRE_TLU_TOEEH1L, DATA_TYPE_UINT64,
166227Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG),
1663260Set142600 	    FIRE_TLU_TOEEH2L, DATA_TYPE_UINT64,
166427Sjchu 	    CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG),
166527Sjchu 	    NULL);
166627Sjchu 
166727Sjchu 	return (PX_OK);
166827Sjchu }
166927Sjchu 
167027Sjchu /* TLU Other Event - see io erpt doc, section 3.9 */
167127Sjchu PX_ERPT_SEND_DEC(pciex_oe)
167227Sjchu {
1673*287Smg140465 	char			buf[FM_MAX_CLASS];
167427Sjchu 
167527Sjchu 	(void) snprintf(buf, FM_MAX_CLASS, "%s", class_name);
167627Sjchu 	ddi_fm_ereport_post(rpdip, buf, derr->fme_ena,
167727Sjchu 	    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
167827Sjchu 	    FIRE_PRIMARY, DATA_TYPE_BOOLEAN_VALUE, B_TRUE,
167927Sjchu 	    FIRE_TLU_OEELE, DATA_TYPE_UINT64,
168027Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE),
168127Sjchu 	    FIRE_TLU_OEIE, DATA_TYPE_UINT64,
168227Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE),
168327Sjchu 	    FIRE_TLU_OEIS, DATA_TYPE_UINT64,
168427Sjchu 	    ss_reg,
168527Sjchu 	    FIRE_TLU_OEESS, DATA_TYPE_UINT64,
168627Sjchu 	    CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_SET),
168727Sjchu 	    NULL);
168827Sjchu 
168927Sjchu 	return (PX_OK);
169027Sjchu }
1691*287Smg140465 
1692*287Smg140465 /* TLU Other Event - Link Down see io erpt doc, section 3.9 */
1693*287Smg140465 PX_ERPT_SEND_DEC(pciex_ldn)
1694*287Smg140465 {
1695*287Smg140465 	px_t			*px_p = DIP_TO_STATE(rpdip);
1696*287Smg140465 
1697*287Smg140465 	/*
1698*287Smg140465 	 * Don't post ereport, if ldn event is due to
1699*287Smg140465 	 * power management.
1700*287Smg140465 	 */
1701*287Smg140465 	if (px_p->px_pm_flags & PX_LDN_EXPECTED) {
1702*287Smg140465 		px_p->px_pm_flags &= ~PX_LDN_EXPECTED;
1703*287Smg140465 		return (PX_OK);
1704*287Smg140465 	}
1705*287Smg140465 	return (PX_ERPT_SEND(pciex_oe)(rpdip, csr_base, ss_reg, derr,
1706*287Smg140465 	    class_name));
1707*287Smg140465 
1708*287Smg140465 }
1709*287Smg140465 
1710*287Smg140465 /* TLU Other Event - Link Up see io erpt doc, section 3.9 */
1711*287Smg140465 PX_ERPT_SEND_DEC(pciex_lup)
1712*287Smg140465 {
1713*287Smg140465 	px_t			*px_p = DIP_TO_STATE(rpdip);
1714*287Smg140465 
1715*287Smg140465 	/*
1716*287Smg140465 	 * Don't post ereport, if lup event is due to
1717*287Smg140465 	 * power management.
1718*287Smg140465 	 */
1719*287Smg140465 	if (px_p->px_pm_flags & PX_LUP_EXPECTED) {
1720*287Smg140465 		px_p->px_pm_flags &= ~PX_LUP_EXPECTED;
1721*287Smg140465 		return (PX_OK);
1722*287Smg140465 	}
1723*287Smg140465 
1724*287Smg140465 	return (PX_ERPT_SEND(pciex_oe)(rpdip, csr_base, ss_reg, derr,
1725*287Smg140465 	    class_name));
1726*287Smg140465 }
1727