14df55fdeSJanie Lu /* 24df55fdeSJanie Lu * CDDL HEADER START 34df55fdeSJanie Lu * 44df55fdeSJanie Lu * The contents of this file are subject to the terms of the 54df55fdeSJanie Lu * Common Development and Distribution License (the "License"). 64df55fdeSJanie Lu * You may not use this file except in compliance with the License. 74df55fdeSJanie Lu * 84df55fdeSJanie Lu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94df55fdeSJanie Lu * or http://www.opensolaris.org/os/licensing. 104df55fdeSJanie Lu * See the License for the specific language governing permissions 114df55fdeSJanie Lu * and limitations under the License. 124df55fdeSJanie Lu * 134df55fdeSJanie Lu * When distributing Covered Code, include this CDDL HEADER in each 144df55fdeSJanie Lu * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154df55fdeSJanie Lu * If applicable, add the following below this CDDL HEADER, with the 164df55fdeSJanie Lu * fields enclosed by brackets "[]" replaced with your own identifying 174df55fdeSJanie Lu * information: Portions Copyright [yyyy] [name of copyright owner] 184df55fdeSJanie Lu * 194df55fdeSJanie Lu * CDDL HEADER END 204df55fdeSJanie Lu */ 214df55fdeSJanie Lu 224df55fdeSJanie Lu /* 23b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 244df55fdeSJanie Lu * Use is subject to license terms. 254df55fdeSJanie Lu */ 264df55fdeSJanie Lu #include <stddef.h> 274df55fdeSJanie Lu #include <strings.h> 284df55fdeSJanie Lu #include <sys/fm/util.h> 294df55fdeSJanie Lu 304df55fdeSJanie Lu #include "fabric-xlate.h" 314df55fdeSJanie Lu 324df55fdeSJanie Lu #define FAB_LOOKUP(sz, name, field) \ 334df55fdeSJanie Lu (void) nvlist_lookup_uint ## sz(nvl, name, field) 344df55fdeSJanie Lu 354df55fdeSJanie Lu static boolean_t fab_xlate_fake_rp = B_TRUE; 364df55fdeSJanie Lu static fab_err_tbl_t *fab_master_err_tbl; 374df55fdeSJanie Lu 384df55fdeSJanie Lu /* 394df55fdeSJanie Lu * Translation tables for converting "fabric" error bits into "pci" ereports. 404df55fdeSJanie Lu * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function> 414df55fdeSJanie Lu */ 424df55fdeSJanie Lu 434df55fdeSJanie Lu /* MACRO for table entries with no TGT ereports */ 444df55fdeSJanie Lu #define NT(class, bit, prep) class, bit, prep, NULL 454df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pci.* */ 464df55fdeSJanie Lu fab_erpt_tbl_t fab_pci_erpt_tbl[] = { 474df55fdeSJanie Lu PCI_DET_PERR, PCI_STAT_PERROR, NULL, 484df55fdeSJanie Lu PCI_MDPE, PCI_STAT_S_PERROR, NULL, 494df55fdeSJanie Lu PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, 504df55fdeSJanie Lu PCI_MA, PCI_STAT_R_MAST_AB, NULL, 514df55fdeSJanie Lu PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, 524df55fdeSJanie Lu PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, 53*940f2f58SToomas Soome NULL, 0, NULL 544df55fdeSJanie Lu }; 554df55fdeSJanie Lu 564df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pci.sec-* */ 574df55fdeSJanie Lu static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = { 584df55fdeSJanie Lu PCI_DET_PERR, PCI_STAT_PERROR, NULL, 594df55fdeSJanie Lu PCI_MDPE, PCI_STAT_S_PERROR, NULL, 604df55fdeSJanie Lu PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, 614df55fdeSJanie Lu #ifdef sparc 624df55fdeSJanie Lu PCI_MA, PCI_STAT_R_MAST_AB, NULL, 634df55fdeSJanie Lu #endif 644df55fdeSJanie Lu PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, 654df55fdeSJanie Lu PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, 66*940f2f58SToomas Soome NULL, 0, NULL, 674df55fdeSJanie Lu }; 684df55fdeSJanie Lu 694df55fdeSJanie Lu 704df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pci.dto */ 714df55fdeSJanie Lu static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = { 724df55fdeSJanie Lu PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL, 73*940f2f58SToomas Soome NULL, 0, NULL 744df55fdeSJanie Lu }; 754df55fdeSJanie Lu 764df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */ 774df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = { 784df55fdeSJanie Lu PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL, 794df55fdeSJanie Lu PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL, 804df55fdeSJanie Lu PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL, 814df55fdeSJanie Lu PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL, 824df55fdeSJanie Lu PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL, 834df55fdeSJanie Lu PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL, 84*940f2f58SToomas Soome NULL, 0, NULL 854df55fdeSJanie Lu }; 864df55fdeSJanie Lu 874df55fdeSJanie Lu /* 884df55fdeSJanie Lu * Translate Fabric ereports to ereport.io.pciex.* 894df55fdeSJanie Lu * The Target Ereports for this section is only used on leaf devices, with the 904df55fdeSJanie Lu * exception of TO 914df55fdeSJanie Lu */ 924df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = { 934df55fdeSJanie Lu PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL, 944df55fdeSJanie Lu PCIEX_DLP, PCIE_AER_UCE_DLP, NULL, 954df55fdeSJanie Lu PCIEX_SD, PCIE_AER_UCE_SD, NULL, 964df55fdeSJanie Lu PCIEX_ROF, PCIE_AER_UCE_RO, NULL, 974df55fdeSJanie Lu PCIEX_FCP, PCIE_AER_UCE_FCP, NULL, 984df55fdeSJanie Lu PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL, 994df55fdeSJanie Lu PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA, 1004df55fdeSJanie Lu PCIEX_UC, PCIE_AER_UCE_UC, NULL, 1014df55fdeSJanie Lu PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL, 1024df55fdeSJanie Lu PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA, 1034df55fdeSJanie Lu #ifdef sparc 1044df55fdeSJanie Lu PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA, 1054df55fdeSJanie Lu #endif 1064df55fdeSJanie Lu PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE, 107*940f2f58SToomas Soome NULL, 0, NULL 1084df55fdeSJanie Lu }; 1094df55fdeSJanie Lu 1104df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */ 1114df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = { 1124df55fdeSJanie Lu PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA, 1134df55fdeSJanie Lu PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA, 1144df55fdeSJanie Lu PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA, 1154df55fdeSJanie Lu #ifdef sparc 1164df55fdeSJanie Lu PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA, 1174df55fdeSJanie Lu #endif 1184df55fdeSJanie Lu PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL, 1194df55fdeSJanie Lu PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA, 1204df55fdeSJanie Lu PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE, 1214df55fdeSJanie Lu PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE, 1224df55fdeSJanie Lu PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE, 1234df55fdeSJanie Lu PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL, 1244df55fdeSJanie Lu PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE, 1254df55fdeSJanie Lu PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL, 1264df55fdeSJanie Lu PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL, 127*940f2f58SToomas Soome NULL, 0, NULL 1284df55fdeSJanie Lu }; 1294df55fdeSJanie Lu 1304df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pcix.* */ 1314df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = { 1324df55fdeSJanie Lu PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, 1334df55fdeSJanie Lu PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, 1344df55fdeSJanie Lu PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, 135*940f2f58SToomas Soome NULL, 0, NULL 1364df55fdeSJanie Lu }; 1374df55fdeSJanie Lu static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl; 1384df55fdeSJanie Lu 1394df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pcix.sec-* */ 1404df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = { 1414df55fdeSJanie Lu PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, 1424df55fdeSJanie Lu PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, 1434df55fdeSJanie Lu PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, 1444df55fdeSJanie Lu PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, 145*940f2f58SToomas Soome NULL, 0, NULL 1464df55fdeSJanie Lu }; 1474df55fdeSJanie Lu 1484df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */ 1494df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = { 1504df55fdeSJanie Lu #ifdef sparc 1514df55fdeSJanie Lu PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL, 1524df55fdeSJanie Lu #endif 1534df55fdeSJanie Lu PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL, 1544df55fdeSJanie Lu PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL, 1554df55fdeSJanie Lu PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL, 156*940f2f58SToomas Soome NULL, 0, NULL 1574df55fdeSJanie Lu }; 1584df55fdeSJanie Lu 1594df55fdeSJanie Lu /* Translate Fabric ereports to ereport.io.pciex.* */ 1604df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = { 1614df55fdeSJanie Lu PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL, 1624df55fdeSJanie Lu PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL, 1634df55fdeSJanie Lu PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL, 1644df55fdeSJanie Lu PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL, 1654df55fdeSJanie Lu PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL, 166*940f2f58SToomas Soome NULL, 0, NULL 1674df55fdeSJanie Lu }; 1684df55fdeSJanie Lu 1694df55fdeSJanie Lu /* 1704df55fdeSJanie Lu * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages. 1714df55fdeSJanie Lu * If the RP is not a PCIe compliant RP or does not support AER, rely on the 1724df55fdeSJanie Lu * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC. 1734df55fdeSJanie Lu */ 1744df55fdeSJanie Lu static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = { 1754df55fdeSJanie Lu PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL, 1764df55fdeSJanie Lu PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL, 1774df55fdeSJanie Lu PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL, 178*940f2f58SToomas Soome NULL, 0, NULL, 1794df55fdeSJanie Lu }; 1804df55fdeSJanie Lu 1814df55fdeSJanie Lu /* ARGSUSED */ 1824df55fdeSJanie Lu void 1834df55fdeSJanie Lu fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) 1844df55fdeSJanie Lu { 1854df55fdeSJanie Lu data->nvl = nvl; 1864df55fdeSJanie Lu 1874df55fdeSJanie Lu /* Generic PCI device information */ 1884df55fdeSJanie Lu FAB_LOOKUP(16, "bdf", &data->bdf); 1894df55fdeSJanie Lu FAB_LOOKUP(16, "device_id", &data->device_id); 1904df55fdeSJanie Lu FAB_LOOKUP(16, "vendor_id", &data->vendor_id); 1914df55fdeSJanie Lu FAB_LOOKUP(8, "rev_id", &data->rev_id); 1924df55fdeSJanie Lu FAB_LOOKUP(16, "dev_type", &data->dev_type); 1934df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_off", &data->pcie_off); 1944df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_off", &data->pcix_off); 1954df55fdeSJanie Lu FAB_LOOKUP(16, "aer_off", &data->aer_off); 1964df55fdeSJanie Lu FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver); 1974df55fdeSJanie Lu 1984df55fdeSJanie Lu /* Misc ereport information */ 1994df55fdeSJanie Lu FAB_LOOKUP(32, "remainder", &data->remainder); 2004df55fdeSJanie Lu FAB_LOOKUP(32, "severity", &data->severity); 2014df55fdeSJanie Lu 2024df55fdeSJanie Lu /* PCI registers */ 2034df55fdeSJanie Lu FAB_LOOKUP(16, "pci_status", &data->pci_err_status); 2044df55fdeSJanie Lu FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm); 2054df55fdeSJanie Lu 2064df55fdeSJanie Lu /* PCI bridge registers */ 2074df55fdeSJanie Lu FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat); 2084df55fdeSJanie Lu FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl); 2094df55fdeSJanie Lu 2104df55fdeSJanie Lu /* PCIx registers */ 2114df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_status", &data->pcix_status); 2124df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_command", &data->pcix_command); 2134df55fdeSJanie Lu 2144df55fdeSJanie Lu /* PCIx ECC Registers */ 2154df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0); 2164df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0); 2174df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0); 2184df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0); 2194df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0); 2204df55fdeSJanie Lu 2214df55fdeSJanie Lu /* PCIx ECC Bridge Registers */ 2224df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1); 2234df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1); 2244df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1); 2254df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1); 2264df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1); 2274df55fdeSJanie Lu 2284df55fdeSJanie Lu /* PCIx Bridge */ 2294df55fdeSJanie Lu FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat); 2304df55fdeSJanie Lu FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat); 2314df55fdeSJanie Lu 2324df55fdeSJanie Lu /* PCIe registers */ 2334df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status); 2344df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl); 2354df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap); 2364df55fdeSJanie Lu 2374df55fdeSJanie Lu /* PCIe AER registers */ 2384df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl); 2394df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status); 2404df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask); 2414df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev); 2424df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]); 2434df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]); 2444df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]); 2454df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]); 2464df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status); 2474df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask); 2484df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans); 2494df55fdeSJanie Lu FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr); 2504df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf); 2514df55fdeSJanie Lu 2524df55fdeSJanie Lu /* PCIe BDG AER registers */ 2534df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl); 2544df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status); 2554df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask); 2564df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev); 2574df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]); 2584df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]); 2594df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]); 2604df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]); 2614df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans); 2624df55fdeSJanie Lu FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr); 2634df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf); 2644df55fdeSJanie Lu 2654df55fdeSJanie Lu /* PCIe RP registers */ 2664df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status); 2674df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl); 2684df55fdeSJanie Lu 2694df55fdeSJanie Lu /* PCIe RP AER registers */ 2704df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status); 2714df55fdeSJanie Lu FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd); 2724df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id); 2734df55fdeSJanie Lu FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id); 2744df55fdeSJanie Lu } 2754df55fdeSJanie Lu 2764df55fdeSJanie Lu static int 2774df55fdeSJanie Lu fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 2784df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 2794df55fdeSJanie Lu { 2804df55fdeSJanie Lu const char *class = tbl->err_class; 2814df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 2824df55fdeSJanie Lu 2834df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 2844df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 2854df55fdeSJanie Lu PCI_ERROR_SUBCLASS, class); 2864df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 2874df55fdeSJanie Lu 2884df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status); 2894df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm); 2904df55fdeSJanie Lu 2914df55fdeSJanie Lu return (err); 2924df55fdeSJanie Lu } 2934df55fdeSJanie Lu 2944df55fdeSJanie Lu static int 2954df55fdeSJanie Lu fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 2964df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 2974df55fdeSJanie Lu { 2984df55fdeSJanie Lu const char *class = tbl->err_class; 2994df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 3004df55fdeSJanie Lu 3014df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 3024df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s", 3034df55fdeSJanie Lu PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class); 3044df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 3054df55fdeSJanie Lu 3064df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 3074df55fdeSJanie Lu data->pci_bdg_sec_stat); 3084df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 3094df55fdeSJanie Lu 3104df55fdeSJanie Lu return (err); 3114df55fdeSJanie Lu } 3124df55fdeSJanie Lu 3134df55fdeSJanie Lu static int 3144df55fdeSJanie Lu fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 3154df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 3164df55fdeSJanie Lu { 3174df55fdeSJanie Lu const char *class = tbl->err_class; 3184df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 3194df55fdeSJanie Lu 3204df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 3214df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 3224df55fdeSJanie Lu PCI_ERROR_SUBCLASS, class); 3234df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 3244df55fdeSJanie Lu 3254df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 3264df55fdeSJanie Lu data->pci_bdg_sec_stat); 3274df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 3284df55fdeSJanie Lu 3294df55fdeSJanie Lu return (err); 3304df55fdeSJanie Lu } 3314df55fdeSJanie Lu 3324df55fdeSJanie Lu 3334df55fdeSJanie Lu static int 3344df55fdeSJanie Lu fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 3354df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 3364df55fdeSJanie Lu { 3374df55fdeSJanie Lu const char *class = tbl->err_class; 3384df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 3394df55fdeSJanie Lu 3404df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 3414df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 3424df55fdeSJanie Lu PCIEX_ERROR_SUBCLASS, class); 3434df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 3444df55fdeSJanie Lu 3454df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 3464df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG, 3474df55fdeSJanie Lu data->pcie_ce_status); 3484df55fdeSJanie Lu 3494df55fdeSJanie Lu return (err); 3504df55fdeSJanie Lu } 3514df55fdeSJanie Lu 3524df55fdeSJanie Lu static int 3534df55fdeSJanie Lu fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 3544df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 3554df55fdeSJanie Lu { 3564df55fdeSJanie Lu const char *class = tbl->err_class; 3574df55fdeSJanie Lu uint32_t first_err = 1 << (data->pcie_adv_ctl & 3584df55fdeSJanie Lu PCIE_AER_CTL_FST_ERR_PTR_MASK); 3594df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 3604df55fdeSJanie Lu 3614df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 3624df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 3634df55fdeSJanie Lu PCIEX_ERROR_SUBCLASS, class); 3644df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 3654df55fdeSJanie Lu 3664df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 3674df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG, 3684df55fdeSJanie Lu data->pcie_ue_status); 3694df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev); 3704df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl); 3714df55fdeSJanie Lu 3724df55fdeSJanie Lu fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 3734df55fdeSJanie Lu 3744df55fdeSJanie Lu if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) { 3754df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 3764df55fdeSJanie Lu data->pcie_ue_tgt_bdf); 3774df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 3784df55fdeSJanie Lu } else { 3794df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 3804df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 3814df55fdeSJanie Lu } 3824df55fdeSJanie Lu 3834df55fdeSJanie Lu if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt && 3844df55fdeSJanie Lu data->pcie_ue_tgt_trans) { 3854df55fdeSJanie Lu if (tbl->tgt_class) 3864df55fdeSJanie Lu fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE); 3874df55fdeSJanie Lu } 3884df55fdeSJanie Lu 3894df55fdeSJanie Lu return (err); 3904df55fdeSJanie Lu } 3914df55fdeSJanie Lu 3924df55fdeSJanie Lu static int 3934df55fdeSJanie Lu fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 3944df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 3954df55fdeSJanie Lu { 3964df55fdeSJanie Lu const char *class = tbl->err_class; 3974df55fdeSJanie Lu uint32_t first_err = 1 << (data->pcie_sue_ctl & 3984df55fdeSJanie Lu PCIE_AER_SCTL_FST_ERR_PTR_MASK); 3994df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 4004df55fdeSJanie Lu 4014df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 4024df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 4034df55fdeSJanie Lu PCIEX_ERROR_SUBCLASS, class); 4044df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 4054df55fdeSJanie Lu 4064df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS, 4074df55fdeSJanie Lu data->pcie_sue_status); 4084df55fdeSJanie Lu 4094df55fdeSJanie Lu fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 4104df55fdeSJanie Lu 4114df55fdeSJanie Lu if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) { 4124df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 4134df55fdeSJanie Lu data->pcie_sue_tgt_bdf); 4144df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 4154df55fdeSJanie Lu } else { 4164df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 4174df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 4184df55fdeSJanie Lu } 4194df55fdeSJanie Lu 4204df55fdeSJanie Lu if ((tbl->reg_bit == first_err) && !data->pcie_ue_no_tgt_erpt && 4214df55fdeSJanie Lu data->pcie_sue_tgt_trans) { 4224df55fdeSJanie Lu if (tbl->tgt_class) 4234df55fdeSJanie Lu fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE); 4244df55fdeSJanie Lu } 4254df55fdeSJanie Lu 4264df55fdeSJanie Lu return (err); 4274df55fdeSJanie Lu } 4284df55fdeSJanie Lu 4294df55fdeSJanie Lu static int 4304df55fdeSJanie Lu fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 4314df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 4324df55fdeSJanie Lu { 4334df55fdeSJanie Lu const char *class = tbl->err_class; 4344df55fdeSJanie Lu int err = 0; 4354df55fdeSJanie Lu 4364df55fdeSJanie Lu /* Only send if this is not a bridge */ 4374df55fdeSJanie Lu if (!data->pcix_status || data->pcix_bdg_sec_stat) 4384df55fdeSJanie Lu return (1); 4394df55fdeSJanie Lu 4404df55fdeSJanie Lu err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 4414df55fdeSJanie Lu 4424df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 4434df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 4444df55fdeSJanie Lu PCIX_ERROR_SUBCLASS, class); 4454df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 4464df55fdeSJanie Lu 4474df55fdeSJanie Lu (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command); 4484df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 4494df55fdeSJanie Lu 4504df55fdeSJanie Lu return (err); 4514df55fdeSJanie Lu } 4524df55fdeSJanie Lu 4534df55fdeSJanie Lu static void 4544df55fdeSJanie Lu fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 4554df55fdeSJanie Lu { 4564df55fdeSJanie Lu nvlist_t *erpt; 4574df55fdeSJanie Lu int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4; 4584df55fdeSJanie Lu int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR; 4594df55fdeSJanie Lu int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE; 4604df55fdeSJanie Lu int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE; 4614df55fdeSJanie Lu uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) | 4624df55fdeSJanie Lu data->pcix_ecc_status_0; 4634df55fdeSJanie Lu 4644df55fdeSJanie Lu switch (ecc_phase) { 4654df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_NOERR: 4664df55fdeSJanie Lu break; 4674df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_FADDR: 4684df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_SADDR: 4694df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 4704df55fdeSJanie Lu "%s.%s", PCIX_ERROR_SUBCLASS, 4714df55fdeSJanie Lu ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 4724df55fdeSJanie Lu break; 4734df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_ATTR: 4744df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 4754df55fdeSJanie Lu "%s.%s", PCIX_ERROR_SUBCLASS, 4764df55fdeSJanie Lu ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 4774df55fdeSJanie Lu break; 4784df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_DATA32: 4794df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_DATA64: 4804df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 4814df55fdeSJanie Lu "%s.%s", PCIX_ERROR_SUBCLASS, 4824df55fdeSJanie Lu ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 4834df55fdeSJanie Lu break; 4844df55fdeSJanie Lu } 4854df55fdeSJanie Lu 4864df55fdeSJanie Lu if (ecc_phase) { 4874df55fdeSJanie Lu if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 4884df55fdeSJanie Lu goto done; 4894df55fdeSJanie Lu (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 4904df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 4914df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 4924df55fdeSJanie Lu data->pcix_command); 4934df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 4944df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 4954df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 4964df55fdeSJanie Lu data->pcix_ecc_attr_0); 4974df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 4984df55fdeSJanie Lu fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 4994df55fdeSJanie Lu if (fmd_xprt_error(hdl, fab_fmd_xprt)) 5004df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 5014df55fdeSJanie Lu } 5024df55fdeSJanie Lu 5034df55fdeSJanie Lu if (sec_ce || sec_ue) { 5044df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 5054df55fdeSJanie Lu "%s.%s", PCIX_ERROR_SUBCLASS, 5064df55fdeSJanie Lu sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 5074df55fdeSJanie Lu if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 5084df55fdeSJanie Lu goto done; 5094df55fdeSJanie Lu (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 5104df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 5114df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 5124df55fdeSJanie Lu data->pcix_command); 5134df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 5144df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 5154df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 5164df55fdeSJanie Lu data->pcix_ecc_attr_0); 5174df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 5184df55fdeSJanie Lu fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 5194df55fdeSJanie Lu if (fmd_xprt_error(hdl, fab_fmd_xprt)) 5204df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 5214df55fdeSJanie Lu } 5224df55fdeSJanie Lu 5234df55fdeSJanie Lu return; 5244df55fdeSJanie Lu done: 5254df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 5264df55fdeSJanie Lu } 5274df55fdeSJanie Lu 5284df55fdeSJanie Lu static int 5294df55fdeSJanie Lu fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 5304df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 5314df55fdeSJanie Lu { 5324df55fdeSJanie Lu const char *class = tbl->err_class; 5334df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 5344df55fdeSJanie Lu 5354df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 5364df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s", 5374df55fdeSJanie Lu PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class); 5384df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 5394df55fdeSJanie Lu 5404df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 5414df55fdeSJanie Lu data->pcix_bdg_sec_stat); 5424df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 5434df55fdeSJanie Lu 5444df55fdeSJanie Lu return (err); 5454df55fdeSJanie Lu } 5464df55fdeSJanie Lu 5474df55fdeSJanie Lu static int 5484df55fdeSJanie Lu fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 5494df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 5504df55fdeSJanie Lu { 5514df55fdeSJanie Lu const char *class = tbl->err_class; 5524df55fdeSJanie Lu int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 5534df55fdeSJanie Lu 5544df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 5554df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 5564df55fdeSJanie Lu PCIX_ERROR_SUBCLASS, class); 5574df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 5584df55fdeSJanie Lu 5594df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 5604df55fdeSJanie Lu data->pcix_bdg_sec_stat); 5614df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 5624df55fdeSJanie Lu 5634df55fdeSJanie Lu return (err); 5644df55fdeSJanie Lu } 5654df55fdeSJanie Lu 5664df55fdeSJanie Lu static void 5674df55fdeSJanie Lu fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 5684df55fdeSJanie Lu { 5694df55fdeSJanie Lu nvlist_t *erpt; 5704df55fdeSJanie Lu int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4; 5714df55fdeSJanie Lu int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR; 5724df55fdeSJanie Lu int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE; 5734df55fdeSJanie Lu int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE; 5744df55fdeSJanie Lu uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) | 5754df55fdeSJanie Lu data->pcix_ecc_status_1; 5764df55fdeSJanie Lu 5774df55fdeSJanie Lu switch (ecc_phase) { 5784df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_NOERR: 5794df55fdeSJanie Lu break; 5804df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_FADDR: 5814df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_SADDR: 5824df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 5834df55fdeSJanie Lu "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 5844df55fdeSJanie Lu ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 5854df55fdeSJanie Lu break; 5864df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_ATTR: 5874df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 5884df55fdeSJanie Lu "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 5894df55fdeSJanie Lu ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 5904df55fdeSJanie Lu break; 5914df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_DATA32: 5924df55fdeSJanie Lu case PCI_PCIX_ECC_PHASE_DATA64: 5934df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 5944df55fdeSJanie Lu "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 5954df55fdeSJanie Lu ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 5964df55fdeSJanie Lu break; 5974df55fdeSJanie Lu } 5984df55fdeSJanie Lu if (ecc_phase) { 5994df55fdeSJanie Lu if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 6004df55fdeSJanie Lu goto done; 6014df55fdeSJanie Lu (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 6024df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 6034df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 6044df55fdeSJanie Lu data->pcix_bdg_sec_stat); 6054df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 6064df55fdeSJanie Lu data->pcix_bdg_stat); 6074df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 6084df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 6094df55fdeSJanie Lu data->pcix_ecc_attr_1); 6104df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 6114df55fdeSJanie Lu fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 6124df55fdeSJanie Lu if (fmd_xprt_error(hdl, fab_fmd_xprt)) 6134df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 6144df55fdeSJanie Lu } 6154df55fdeSJanie Lu 6164df55fdeSJanie Lu if (sec_ce || sec_ue) { 6174df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, 6184df55fdeSJanie Lu "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 6194df55fdeSJanie Lu sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 6204df55fdeSJanie Lu if (nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0) != 0) 6214df55fdeSJanie Lu goto done; 6224df55fdeSJanie Lu (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 6234df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 6244df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 6254df55fdeSJanie Lu data->pcix_bdg_sec_stat); 6264df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 6274df55fdeSJanie Lu data->pcix_bdg_stat); 6284df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 6294df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 6304df55fdeSJanie Lu data->pcix_ecc_attr_1); 6314df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 6324df55fdeSJanie Lu fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 6334df55fdeSJanie Lu if (fmd_xprt_error(hdl, fab_fmd_xprt)) 6344df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 6354df55fdeSJanie Lu } 6364df55fdeSJanie Lu return; 6374df55fdeSJanie Lu done: 6384df55fdeSJanie Lu fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 6394df55fdeSJanie Lu } 6404df55fdeSJanie Lu 6414df55fdeSJanie Lu static int 6424df55fdeSJanie Lu fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 6434df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 6444df55fdeSJanie Lu { 6454df55fdeSJanie Lu const char *class = tbl->err_class; 6464df55fdeSJanie Lu int err = 0; 6474df55fdeSJanie Lu 6484df55fdeSJanie Lu /* Don't send this for PCI device, Root Ports, or PCIe with AER */ 6494df55fdeSJanie Lu if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 6504df55fdeSJanie Lu (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 6514df55fdeSJanie Lu data->aer_off) 6524df55fdeSJanie Lu return (1); 6534df55fdeSJanie Lu 6544df55fdeSJanie Lu err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 6554df55fdeSJanie Lu 6564df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 6574df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 6584df55fdeSJanie Lu PCIEX_ERROR_SUBCLASS, class); 6594df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 6604df55fdeSJanie Lu 6614df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 6624df55fdeSJanie Lu 6634df55fdeSJanie Lu return (err); 6644df55fdeSJanie Lu } 6654df55fdeSJanie Lu 6664df55fdeSJanie Lu static int 6674df55fdeSJanie Lu fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 6684df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 6694df55fdeSJanie Lu { 6704df55fdeSJanie Lu const char *class = tbl->err_class; 6714df55fdeSJanie Lu uint32_t status = data->pcie_rp_err_status; 6724df55fdeSJanie Lu int err = 0; 6734df55fdeSJanie Lu int isFE = 0, isNFE = 0; 6744df55fdeSJanie Lu 6754df55fdeSJanie Lu fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class); 6764df55fdeSJanie Lu 6774df55fdeSJanie Lu if (!data->aer_off) 6784df55fdeSJanie Lu return (-1); 6794df55fdeSJanie Lu 6804df55fdeSJanie Lu /* Only send a FE Msg if the 1st UE error is FE */ 6814df55fdeSJanie Lu if (STRCMP(class, PCIEX_RC_FE_MSG)) 6824df55fdeSJanie Lu if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL)) 6834df55fdeSJanie Lu return (-1); 6844df55fdeSJanie Lu else 6854df55fdeSJanie Lu isFE = 1; 6864df55fdeSJanie Lu 6874df55fdeSJanie Lu /* Only send a NFE Msg is the 1st UE error is NFE */ 6884df55fdeSJanie Lu if (STRCMP(class, PCIEX_RC_NFE_MSG)) 6894df55fdeSJanie Lu if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL) 6904df55fdeSJanie Lu return (-1); 6914df55fdeSJanie Lu else 6924df55fdeSJanie Lu isNFE = 1; 6934df55fdeSJanie Lu 6944df55fdeSJanie Lu fmd_hdl_debug(hdl, "XLATE RP Error"); 6954df55fdeSJanie Lu 6964df55fdeSJanie Lu err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 6974df55fdeSJanie Lu 6984df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 6994df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 7004df55fdeSJanie Lu PCIEX_ERROR_SUBCLASS, class); 7014df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 7024df55fdeSJanie Lu 7034df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status); 7044df55fdeSJanie Lu if ((isFE || isNFE) && data->pcie_rp_ue_src_id) { 7054df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 7064df55fdeSJanie Lu data->pcie_rp_ue_src_id); 7074df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 7084df55fdeSJanie Lu } 7094df55fdeSJanie Lu if (STRCMP(class, PCIEX_RC_CE_MSG) && data->pcie_rp_ce_src_id) { 7104df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 7114df55fdeSJanie Lu data->pcie_rp_ce_src_id); 7124df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 7134df55fdeSJanie Lu } 7144df55fdeSJanie Lu 7154df55fdeSJanie Lu return (err); 7164df55fdeSJanie Lu } 7174df55fdeSJanie Lu 7184df55fdeSJanie Lu static int 7194df55fdeSJanie Lu fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 7204df55fdeSJanie Lu fab_erpt_tbl_t *tbl) 7214df55fdeSJanie Lu { 7224df55fdeSJanie Lu const char *class = tbl->err_class; 7234df55fdeSJanie Lu uint32_t rc_err_sts = 0; 7244df55fdeSJanie Lu int err = 0; 7254df55fdeSJanie Lu 7264df55fdeSJanie Lu /* 7274df55fdeSJanie Lu * Don't send this for PCI device or Root Ports. Only send it on 7284df55fdeSJanie Lu * systems with non-compliant RPs. 7294df55fdeSJanie Lu */ 7304df55fdeSJanie Lu if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 7314df55fdeSJanie Lu (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 7324df55fdeSJanie Lu (!fab_xlate_fake_rp)) 7334df55fdeSJanie Lu return (-1); 7344df55fdeSJanie Lu 7354df55fdeSJanie Lu err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE); 7364df55fdeSJanie Lu 7374df55fdeSJanie Lu /* Generate an ereport for this error bit. */ 7384df55fdeSJanie Lu (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 7394df55fdeSJanie Lu PCIEX_ERROR_SUBCLASS, class); 7404df55fdeSJanie Lu (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 7414df55fdeSJanie Lu 7424df55fdeSJanie Lu /* Send PCIe RC Ereports */ 7434df55fdeSJanie Lu if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) { 7444df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD; 7454df55fdeSJanie Lu } 7464df55fdeSJanie Lu 7474df55fdeSJanie Lu /* NFE/FE src id takes precedence over CE src id */ 7484df55fdeSJanie Lu if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) { 7494df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD; 7504df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 7514df55fdeSJanie Lu } 7524df55fdeSJanie Lu if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) { 7534df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD; 7544df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 7554df55fdeSJanie Lu } 7564df55fdeSJanie Lu if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) && 7574df55fdeSJanie Lu (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) { 7584df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL; 7594df55fdeSJanie Lu rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD; 7604df55fdeSJanie Lu } 7614df55fdeSJanie Lu 7624df55fdeSJanie Lu (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts); 7634df55fdeSJanie Lu 7644df55fdeSJanie Lu if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) { 7654df55fdeSJanie Lu (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf); 7664df55fdeSJanie Lu (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 7674df55fdeSJanie Lu } 7684df55fdeSJanie Lu 7694df55fdeSJanie Lu return (err); 7704df55fdeSJanie Lu } 7714df55fdeSJanie Lu 7724df55fdeSJanie Lu void 7734df55fdeSJanie Lu fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data) 7744df55fdeSJanie Lu { 7754df55fdeSJanie Lu fab_err_tbl_t *tbl; 7764df55fdeSJanie Lu 7774df55fdeSJanie Lu fmd_hdl_debug(hdl, "Sending Ereports Now"); 7784df55fdeSJanie Lu 7794df55fdeSJanie Lu /* Go through the error logs and send the relavant reports */ 7804df55fdeSJanie Lu for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) { 7814df55fdeSJanie Lu fab_send_erpt(hdl, data, tbl); 7824df55fdeSJanie Lu } 7834df55fdeSJanie Lu 7844df55fdeSJanie Lu /* Send PCI-X ECC Ereports */ 7854df55fdeSJanie Lu fab_send_pcix_ecc_erpt(hdl, data); 7864df55fdeSJanie Lu fab_send_pcix_bdg_ecc_erpt(hdl, data); 7874df55fdeSJanie Lu } 7884df55fdeSJanie Lu 7894df55fdeSJanie Lu void 7904df55fdeSJanie Lu fab_xlate_fabric_erpts(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class) 7914df55fdeSJanie Lu { 7924df55fdeSJanie Lu fab_data_t data = {0}; 7934df55fdeSJanie Lu 7944df55fdeSJanie Lu fmd_hdl_debug(hdl, "fabric ereport received: %s\n", class); 7954df55fdeSJanie Lu 7964df55fdeSJanie Lu fab_pci_fabric_to_data(hdl, nvl, &data); 7974df55fdeSJanie Lu fab_xlate_pcie_erpts(hdl, &data); 7984df55fdeSJanie Lu } 7994df55fdeSJanie Lu 800b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China void 801b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fab_set_fake_rp(fmd_hdl_t *hdl) 802b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China { 803b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China char *rppath = fab_get_rpdev(hdl), *str = NULL; 804b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China int count = 0; 805b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 806b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China if (!rppath) { 807b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fmd_hdl_debug(hdl, "Can't find root port dev path"); 808b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China return; 809b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China } 810b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 811b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China /* 812b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China * For the path '/pci@xxx' is fake root port, 813b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China * and '/pci@xxx/pci@y' is real root port. 814b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China */ 815b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China str = rppath; 816b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China while (*str) { 817b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China if (*str == '/') 818b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China count++; 819b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China str++; 820b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China } 821b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 822b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China if (count == 1) 823b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fab_xlate_fake_rp = B_TRUE; 824b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China else 825b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China /* 826b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China * If count is 0, then it should still be B_FALSE 827b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China */ 828b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fab_xlate_fake_rp = B_FALSE; 829b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 830b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China fmd_hdl_strfree(hdl, rppath); 831b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China } 832b344f6b3Sgongtian zhao - Sun Microsystems - Beijing China 8334df55fdeSJanie Lu #define SET_TBL(n, err, reg, sz) \ 8344df55fdeSJanie Lu fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \ 8354df55fdeSJanie Lu fab_master_err_tbl[n].reg_offset = offsetof(fab_data_t, reg); \ 8364df55fdeSJanie Lu fab_master_err_tbl[n].reg_size = sz; \ 8374df55fdeSJanie Lu fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt; 8384df55fdeSJanie Lu 8394df55fdeSJanie Lu void 8404df55fdeSJanie Lu fab_setup_master_table() 8414df55fdeSJanie Lu { 8424df55fdeSJanie Lu /* Setup the master error table */ 8434df55fdeSJanie Lu fab_master_err_tbl = (fab_err_tbl_t *)calloc(13, 8444df55fdeSJanie Lu sizeof (fab_err_tbl_t)); 8454df55fdeSJanie Lu 8464df55fdeSJanie Lu SET_TBL(0, pci, pci_err_status, 16); 8474df55fdeSJanie Lu SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16); 8484df55fdeSJanie Lu SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16); 8494df55fdeSJanie Lu SET_TBL(3, pcie_ce, pcie_ce_status, 32); 8504df55fdeSJanie Lu SET_TBL(4, pcie_ue, pcie_ue_status, 32); 8514df55fdeSJanie Lu SET_TBL(5, pcie_sue, pcie_sue_status, 32); 8524df55fdeSJanie Lu SET_TBL(6, pcix, pcix_status, 32); 8534df55fdeSJanie Lu SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16); 8544df55fdeSJanie Lu SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32); 8554df55fdeSJanie Lu SET_TBL(9, pcie_nadv, pcie_err_status, 16); 8564df55fdeSJanie Lu SET_TBL(10, pcie_rc, pcie_rp_err_status, 32); 8574df55fdeSJanie Lu SET_TBL(11, pcie_fake_rc, pcie_err_status, 16); 8584df55fdeSJanie Lu } 859