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