1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <assert.h> 29 #include <stddef.h> 30 #include <strings.h> 31 #include <fm/fmd_api.h> 32 #include <fm/libtopo.h> 33 #include <sys/fm/util.h> 34 #include <sys/fm/protocol.h> 35 #include <sys/fm/io/pci.h> 36 #include <sys/fm/io/sun4_fire.h> 37 #include <sys/pci.h> 38 #include <sys/pcie.h> 39 #include <sys/nvpair.h> 40 #include <sys/nvpair_impl.h> 41 42 #include <libxml/xpath.h> 43 #include <libxml/parser.h> 44 #include <libxml/xpathInternals.h> 45 #include <libxml/tree.h> 46 47 /* PCI-E config space data for error handling and fabric ereports */ 48 typedef struct fab_data { 49 /* Original ereport NVL */ 50 nvlist_t *nvl; 51 52 /* Device Information */ 53 uint16_t bdf; 54 uint16_t device_id; 55 uint16_t vendor_id; 56 uint8_t rev_id; 57 uint16_t dev_type; 58 uint16_t pcie_off; 59 uint16_t pcix_off; 60 uint16_t aer_off; 61 uint16_t ecc_ver; 62 63 /* Ereport Information */ 64 uint32_t remainder; 65 uint32_t severity; 66 67 /* Error Registers */ 68 uint16_t pci_err_status; /* pci status register */ 69 uint16_t pci_cfg_comm; /* pci command register */ 70 71 uint16_t pci_bdg_sec_stat; /* PCI secondary status reg */ 72 uint16_t pci_bdg_ctrl; /* PCI bridge control reg */ 73 74 uint16_t pcix_command; /* pcix command register */ 75 uint32_t pcix_status; /* pcix status register */ 76 77 uint16_t pcix_bdg_sec_stat; /* pcix bridge secondary status reg */ 78 uint32_t pcix_bdg_stat; /* pcix bridge status reg */ 79 80 uint16_t pcix_ecc_control_0; /* pcix ecc control status reg */ 81 uint16_t pcix_ecc_status_0; /* pcix ecc control status reg */ 82 uint32_t pcix_ecc_fst_addr_0; /* pcix ecc first address reg */ 83 uint32_t pcix_ecc_sec_addr_0; /* pcix ecc second address reg */ 84 uint32_t pcix_ecc_attr_0; /* pcix ecc attributes reg */ 85 uint16_t pcix_ecc_control_1; /* pcix ecc control status reg */ 86 uint16_t pcix_ecc_status_1; /* pcix ecc control status reg */ 87 uint32_t pcix_ecc_fst_addr_1; /* pcix ecc first address reg */ 88 uint32_t pcix_ecc_sec_addr_1; /* pcix ecc second address reg */ 89 uint32_t pcix_ecc_attr_1; /* pcix ecc attributes reg */ 90 91 uint16_t pcie_err_status; /* pcie device status register */ 92 uint16_t pcie_err_ctl; /* pcie error control register */ 93 uint32_t pcie_dev_cap; /* pcie device capabilities register */ 94 95 uint32_t pcie_adv_ctl; /* pcie advanced control reg */ 96 uint32_t pcie_ue_status; /* pcie ue error status reg */ 97 uint32_t pcie_ue_mask; /* pcie ue error mask reg */ 98 uint32_t pcie_ue_sev; /* pcie ue error severity reg */ 99 uint32_t pcie_ue_hdr[4]; /* pcie ue header log */ 100 uint32_t pcie_ce_status; /* pcie ce error status reg */ 101 uint32_t pcie_ce_mask; /* pcie ce error mask reg */ 102 uint32_t pcie_ue_tgt_trans; /* Fault trans type from AER Logs */ 103 uint64_t pcie_ue_tgt_addr; /* Fault addr from AER Logs */ 104 pcie_req_id_t pcie_ue_tgt_bdf; /* Fault bdf from SAER Logs */ 105 106 uint32_t pcie_sue_ctl; /* pcie bridge secondary ue control */ 107 uint32_t pcie_sue_status; /* pcie bridge secondary ue status */ 108 uint32_t pcie_sue_mask; /* pcie bridge secondary ue mask */ 109 uint32_t pcie_sue_sev; /* pcie bridge secondary ue severity */ 110 uint32_t pcie_sue_hdr[4]; /* pcie bridge secondary ue hdr log */ 111 uint32_t pcie_sue_tgt_trans; /* Fault trans type from AER Logs */ 112 uint64_t pcie_sue_tgt_addr; /* Fault addr from AER Logs */ 113 pcie_req_id_t pcie_sue_tgt_bdf; /* Fault bdf from SAER Logs */ 114 115 uint32_t pcie_rp_status; /* root complex status register */ 116 uint16_t pcie_rp_ctl; /* root complex control register */ 117 uint32_t pcie_rp_err_status; /* pcie root complex error status reg */ 118 uint32_t pcie_rp_err_cmd; /* pcie root complex error cmd reg */ 119 uint16_t pcie_rp_ce_src_id; /* pcie root complex ce sourpe id */ 120 uint16_t pcie_rp_ue_src_id; /* pcie root complex ue sourpe id */ 121 } fab_data_t; 122 123 /* 124 * These values are used for the xxx_tgt_trans value in fab_data_t. They are 125 * originally set in pcie_fault.c and originally defined in pcie_impl.h. 126 */ 127 #define PF_ADDR_DMA (1 << 0) 128 #define PF_ADDR_PIO (1 << 1) 129 #define PF_ADDR_CFG (1 << 2) 130 131 typedef struct fab_erpt_tbl { 132 const char *err_class; /* Final Ereport Class */ 133 uint32_t reg_bit; /* Error Bit Mask */ 134 /* Pointer to function that prepares the ereport body */ 135 const char *tgt_class; /* Target Ereport Class */ 136 } fab_erpt_tbl_t; 137 138 typedef struct fab_err_tbl { 139 fab_erpt_tbl_t *erpt_tbl; /* ereport table */ 140 uint32_t reg_offset; /* sts reg for ereport table offset */ 141 uint32_t reg_size; /* size of the status register */ 142 /* Pointer to function that prepares the ereport body */ 143 int (*fab_prep)(fmd_hdl_t *, fab_data_t *, nvlist_t *, 144 fab_erpt_tbl_t *); 145 } fab_err_tbl_t; 146 147 typedef struct fab_fire_tbl { 148 const char *err_class; 149 uint32_t fire_bit; /* Fire error bit */ 150 uint16_t pci_err_sts; /* Equivalent PCI Error Status */ 151 uint16_t pci_bdg_sts; /* Equivalent PCI Bridge Status */ 152 } fab_fire_tbl_t; 153 154 /* Static FM Topo XML Format and XML XPath Context */ 155 static xmlDocPtr fab_doc = NULL; 156 static xmlXPathContextPtr fab_xpathCtx = NULL; 157 static int fab_valid_topo = 0; 158 #define XMLTOPOFILE "/tmp/fab-xlate-topo.xml" 159 160 /* Functions that convert ereports to a common C data structure */ 161 static void fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, 162 fab_data_t *data); 163 static void fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data); 164 165 /* Common functions for sending translated ereports */ 166 static int fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, 167 boolean_t isRC); 168 static void fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath); 169 static char *fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr); 170 static char *fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf); 171 static void fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, 172 const char *class, boolean_t isPrimary); 173 static void fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl); 174 175 /* 176 * Common functions for converting pci.fabric classes of 177 * ereports 178 */ 179 static int fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, 180 nvlist_t *erpt, fab_erpt_tbl_t *table); 181 static int fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, 182 nvlist_t *erpt, fab_erpt_tbl_t *table); 183 static int fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, 184 nvlist_t *erpt, fab_erpt_tbl_t *table); 185 static int fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, 186 nvlist_t *erpt, fab_erpt_tbl_t *table); 187 static int fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, 188 nvlist_t *erpt, fab_erpt_tbl_t *table); 189 static int fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, 190 nvlist_t *erpt, fab_erpt_tbl_t *table); 191 static int fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, 192 nvlist_t *erpt, fab_erpt_tbl_t *table); 193 static int fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, 194 nvlist_t *erpt, fab_erpt_tbl_t *table); 195 static void fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data); 196 static int fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, 197 nvlist_t *erpt, fab_erpt_tbl_t *table); 198 static void fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data); 199 static int fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, 200 nvlist_t *erpt, fab_erpt_tbl_t *table); 201 static int fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, 202 nvlist_t *erpt, fab_erpt_tbl_t *table); 203 204 /* Functions for converting fire specific error registers */ 205 static int fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 206 const char *class); 207 static int fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 208 const char *class); 209 static int fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 210 const char *class); 211 static int fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 212 const char *class); 213 214 /* Main functions for converting "fabric" ereports */ 215 static void fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data); 216 static void fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, 217 nvlist_t *nvl, const char *class); 218 219 /* 220 * Translation tables for converting "fabric" error bits into "pci" ereports. 221 * <Ereport Class Name>, <Error Bit Mask>, <Preparation Function> 222 */ 223 224 /* MACRO for table entries with no TGT ereports */ 225 #define NT(class, bit, prep) class, bit, prep, NULL 226 /* Translate Fabric ereports to ereport.io.pci.* */ 227 static fab_erpt_tbl_t fab_pci_erpt_tbl[] = { 228 PCI_DET_PERR, PCI_STAT_PERROR, NULL, 229 PCI_MDPE, PCI_STAT_S_PERROR, NULL, 230 PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, 231 PCI_MA, PCI_STAT_R_MAST_AB, NULL, 232 PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, 233 PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, 234 NULL, NULL, NULL 235 }; 236 237 /* Translate Fabric ereports to ereport.io.pci.sec-* */ 238 static fab_erpt_tbl_t fab_pci_bdg_erpt_tbl[] = { 239 PCI_DET_PERR, PCI_STAT_PERROR, NULL, 240 PCI_MDPE, PCI_STAT_S_PERROR, NULL, 241 PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, 242 #ifdef sparc 243 PCI_MA, PCI_STAT_R_MAST_AB, NULL, 244 #endif 245 PCI_REC_TA, PCI_STAT_R_TARG_AB, NULL, 246 PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, 247 NULL, NULL, NULL, NULL, 248 }; 249 250 251 /* Translate Fabric ereports to ereport.io.pci.dto */ 252 static fab_erpt_tbl_t fab_pci_bdg_ctl_erpt_tbl[] = { 253 PCI_DTO, PCI_BCNF_BCNTRL_DTO_STAT, NULL, 254 NULL, NULL, NULL 255 }; 256 257 /* Translate Fabric ereports to ereport.io.pciex.* */ 258 static fab_erpt_tbl_t fab_pcie_ce_erpt_tbl[] = { 259 PCIEX_RE, PCIE_AER_CE_RECEIVER_ERR, NULL, 260 PCIEX_RNR, PCIE_AER_CE_REPLAY_ROLLOVER, NULL, 261 PCIEX_RTO, PCIE_AER_CE_REPLAY_TO, NULL, 262 PCIEX_BDP, PCIE_AER_CE_BAD_DLLP, NULL, 263 PCIEX_BTP, PCIE_AER_CE_BAD_TLP, NULL, 264 PCIEX_ANFE, PCIE_AER_CE_AD_NFE, NULL, 265 NULL, NULL, NULL 266 }; 267 268 /* Translate Fabric ereports to ereport.io.pciex.* */ 269 static fab_erpt_tbl_t fab_pcie_ue_erpt_tbl[] = { 270 PCIEX_TE, PCIE_AER_UCE_TRAINING, NULL, 271 PCIEX_DLP, PCIE_AER_UCE_DLP, NULL, 272 PCIEX_SD, PCIE_AER_UCE_SD, NULL, 273 PCIEX_ROF, PCIE_AER_UCE_RO, NULL, 274 PCIEX_FCP, PCIE_AER_UCE_FCP, NULL, 275 PCIEX_MFP, PCIE_AER_UCE_MTLP, NULL, 276 PCIEX_CTO, PCIE_AER_UCE_TO, PCI_TARG_MA, 277 PCIEX_UC, PCIE_AER_UCE_UC, NULL, 278 PCIEX_ECRC, PCIE_AER_UCE_ECRC, NULL, 279 PCIEX_CA, PCIE_AER_UCE_CA, PCI_TARG_REC_TA, 280 #ifdef sparc 281 PCIEX_UR, PCIE_AER_UCE_UR, PCI_TARG_MA, 282 #endif 283 PCIEX_POIS, PCIE_AER_UCE_PTLP, PCI_TARG_MDPE, 284 NULL, NULL, NULL 285 }; 286 287 /* Translate Fabric ereports to ereport.io.pciex.* */ 288 static fab_erpt_tbl_t fab_pcie_sue_erpt_tbl[] = { 289 PCIEX_S_TA_SC, PCIE_AER_SUCE_TA_ON_SC, PCI_TARG_REC_TA, 290 PCIEX_S_MA_SC, PCIE_AER_SUCE_MA_ON_SC, PCI_TARG_MA, 291 PCIEX_S_RTA, PCIE_AER_SUCE_RCVD_TA, PCI_TARG_REC_TA, 292 #ifdef sparc 293 PCIEX_S_RMA, PCIE_AER_SUCE_RCVD_MA, PCI_TARG_MA, 294 #endif 295 PCIEX_S_USC, PCIE_AER_SUCE_USC_ERR, NULL, 296 PCIEX_S_USCMD, PCIE_AER_SUCE_USC_MSG_DATA_ERR, PCI_TARG_REC_TA, 297 PCIEX_S_UDE, PCIE_AER_SUCE_UC_DATA_ERR, PCI_TARG_MDPE, 298 PCIEX_S_UAT, PCIE_AER_SUCE_UC_ATTR_ERR, PCI_TARG_MDPE, 299 PCIEX_S_UADR, PCIE_AER_SUCE_UC_ADDR_ERR, PCI_TARG_MDPE, 300 PCIEX_S_TEX, PCIE_AER_SUCE_TIMER_EXPIRED, NULL, 301 PCIEX_S_PERR, PCIE_AER_SUCE_PERR_ASSERT, PCI_TARG_MDPE, 302 PCIEX_S_SERR, PCIE_AER_SUCE_SERR_ASSERT, NULL, 303 PCIEX_INTERR, PCIE_AER_SUCE_INTERNAL_ERR, NULL, 304 NULL, NULL, NULL 305 }; 306 307 /* Translate Fabric ereports to ereport.io.pcix.* */ 308 static fab_erpt_tbl_t fab_pcix_erpt_tbl[] = { 309 PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, 310 PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, 311 PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, 312 NULL, NULL, NULL 313 }; 314 static fab_erpt_tbl_t *fab_pcix_bdg_erpt_tbl = fab_pcix_erpt_tbl; 315 316 /* Translate Fabric ereports to ereport.io.pcix.sec-* */ 317 static fab_erpt_tbl_t fab_pcix_bdg_sec_erpt_tbl[] = { 318 PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, 319 PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, 320 PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, 321 PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, 322 NULL, NULL, NULL 323 }; 324 325 /* Translate Fabric ereports to ereport.io.pciex.* */ 326 static fab_erpt_tbl_t fab_pcie_nadv_erpt_tbl[] = { 327 #ifdef sparc 328 PCIEX_UR, PCIE_DEVSTS_UR_DETECTED, NULL, 329 #endif 330 PCIEX_FAT, PCIE_DEVSTS_FE_DETECTED, NULL, 331 PCIEX_NONFAT, PCIE_DEVSTS_NFE_DETECTED, NULL, 332 PCIEX_CORR, PCIE_DEVSTS_CE_DETECTED, NULL, 333 NULL, NULL, NULL 334 }; 335 336 /* Translate Fabric ereports to ereport.io.pciex.* */ 337 static fab_erpt_tbl_t fab_pcie_rc_erpt_tbl[] = { 338 PCIEX_RC_FE_MSG, PCIE_AER_RE_STS_FE_MSGS_RCVD, NULL, 339 PCIEX_RC_NFE_MSG, PCIE_AER_RE_STS_NFE_MSGS_RCVD, NULL, 340 PCIEX_RC_CE_MSG, PCIE_AER_RE_STS_CE_RCVD, NULL, 341 PCIEX_RC_MCE_MSG, PCIE_AER_RE_STS_MUL_CE_RCVD, NULL, 342 PCIEX_RC_MUE_MSG, PCIE_AER_RE_STS_MUL_FE_NFE_RCVD, NULL, 343 NULL, NULL, NULL 344 }; 345 346 /* 347 * Translate Fabric ereports to pseudo ereport.io.pciex.* RC Fabric Messages. 348 * If the RP is not a PCIe compliant RP or does not support AER, rely on the 349 * leaf fabric ereport to help create a xxx_MSG ereport coming from the RC. 350 */ 351 static fab_erpt_tbl_t fab_pcie_fake_rc_erpt_tbl[] = { 352 PCIEX_RC_FE_MSG, PCIE_DEVSTS_FE_DETECTED, NULL, 353 PCIEX_RC_NFE_MSG, PCIE_DEVSTS_NFE_DETECTED, NULL, 354 PCIEX_RC_CE_MSG, PCIE_DEVSTS_CE_DETECTED, NULL, 355 NULL, NULL, NULL, 356 }; 357 358 static fab_err_tbl_t *fab_master_err_tbl; 359 360 /* 361 * Translation tables for converting fire error bits into "pci" ereports. 362 * <Fire Bit> 363 * <pci ereport Class> 364 * <pci error status reg> 365 * <pci bridge status reg> 366 * <pci target class> 367 */ 368 #define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb 369 #define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb 370 #define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb 371 #define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb 372 373 #define FAB_FIRE_UE(fb, bit, sts, bdg) \ 374 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg 375 #define FAB_OB_UE(fb, bit, sts, bdg) \ 376 FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg 377 static fab_fire_tbl_t fab_fire_pec_ue_tbl[] = { 378 FAB_FIRE_UE(UR, UR, PCI_STAT_S_SYSERR, 0), 379 FAB_FIRE_UE(UC, UC, PCI_STAT_S_SYSERR, 0), 380 FAB_OB_UE(ECRC, ECRC, PCI_STAT_S_SYSERR, 0), 381 FAB_FIRE_UE(CTO, TO, PCI_STAT_S_SYSERR, 0), 382 FAB_FIRE_UE(ROF, RO, PCI_STAT_S_SYSERR, 0), 383 FAB_FIRE_UE(MFP, MTLP, PCI_STAT_S_SYSERR, 0), 384 FAB_FIRE_UE(PP, PTLP, PCI_STAT_S_PERROR, 385 (PCI_STAT_S_SYSERR | PCI_STAT_PERROR)), 386 FAB_FIRE_UE(FCP, FCP, PCI_STAT_S_SYSERR, 0), 387 FAB_FIRE_UE(DLP, DLP, PCI_STAT_S_SYSERR, 0), 388 FAB_FIRE_UE(TE, TRAINING, PCI_STAT_S_SYSERR, 0), 389 FAB_FIRE_UE(CA, CA, PCI_STAT_S_TARG_AB, 390 PCI_STAT_S_TARG_AB), 391 NULL, NULL, NULL, 392 }; 393 394 #define FAB_FIRE_CE(fb, bit) \ 395 FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0 396 static fab_fire_tbl_t fab_fire_pec_ce_tbl[] = { 397 FAB_FIRE_CE(RTO, REPLAY_TO), 398 FAB_FIRE_CE(RNR, REPLAY_ROLLOVER), 399 FAB_FIRE_CE(BDP, BAD_DLLP), 400 FAB_FIRE_CE(BTP, BAD_TLP), 401 FAB_FIRE_CE(RE, RECEIVER_ERR), 402 NULL, NULL, NULL, 403 }; 404 405 /* 406 * WUC/RUC will need to be special cased for the target ereports, because you 407 * need to decode the tlp log. 408 */ 409 #define FAB_FIRE_WUCRUC(fb) \ 410 FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR) 411 #define FAB_FIRE_OE(fb, bit) \ 412 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 413 #define FAB_OB_OE(fb, bit) \ 414 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0 415 static fab_fire_tbl_t fab_fire_pec_oe_tbl[] = { 416 FAB_FIRE_WUCRUC(WUC), 417 FAB_FIRE_WUCRUC(RUC), 418 FAB_FIRE_OE(ERU, DLP), 419 FAB_FIRE_OE(ERO, DLP), 420 FAB_FIRE_OE(EMP, DLP), 421 FAB_FIRE_OE(EPE, DLP), 422 NULL, NULL, NULL, 423 }; 424 425 #define FAB_FIRE_DMC(fb) \ 426 FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB 427 #define FAB_N2_DMU(fb) \ 428 FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB 429 static fab_fire_tbl_t fab_fire_dmc_tbl[] = { 430 FAB_FIRE_DMC(BYP_ERR), 431 FAB_FIRE_DMC(BYP_OOR), 432 FAB_FIRE_DMC(TRN_OOR), 433 FAB_FIRE_DMC(TTE_INV), 434 FAB_FIRE_DMC(TTE_PRT), 435 FAB_N2_DMU("iotsbdesc_inv"), 436 FAB_N2_DMU("sun4v_adj_va_uf"), 437 FAB_N2_DMU("sun4v_inv_pg_sz"), 438 FAB_N2_DMU("sun4v_key_err"), 439 FAB_N2_DMU("sun4v_va_oor"), 440 NULL, NULL, NULL 441 }; 442 443 static fmd_xprt_t *fab_fmd_xprt = NULL; /* FMD transport layer handle */ 444 static char fab_buf[FM_MAX_CLASS]; 445 static boolean_t fab_xlate_fake_rp = B_TRUE; 446 447 #define HAS_PROP(node, name) xmlHasProp(node, (const xmlChar *)name) 448 #define GET_PROP(node, name) ((char *)xmlGetProp(node, (const xmlChar *)name)) 449 #define STRCMP(s1, s2) (strcmp((const char *)s1, (const char *)s2) == 0) 450 451 #define FAB_LOOKUP(sz, name, field) \ 452 (void) nvlist_lookup_uint ## sz(nvl, name, field) 453 /* ARGSUSED */ 454 static void 455 fab_pci_fabric_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { 456 data->nvl = nvl; 457 458 /* Generic PCI device information */ 459 FAB_LOOKUP(16, "bdf", &data->bdf); 460 FAB_LOOKUP(16, "device_id", &data->device_id); 461 FAB_LOOKUP(16, "vendor_id", &data->vendor_id); 462 FAB_LOOKUP(8, "rev_id", &data->rev_id); 463 FAB_LOOKUP(16, "dev_type", &data->dev_type); 464 FAB_LOOKUP(16, "pcie_off", &data->pcie_off); 465 FAB_LOOKUP(16, "pcix_off", &data->pcix_off); 466 FAB_LOOKUP(16, "aer_off", &data->aer_off); 467 FAB_LOOKUP(16, "ecc_ver", &data->ecc_ver); 468 469 /* Misc ereport information */ 470 FAB_LOOKUP(32, "remainder", &data->remainder); 471 FAB_LOOKUP(32, "severity", &data->severity); 472 473 /* PCI registers */ 474 FAB_LOOKUP(16, "pci_status", &data->pci_err_status); 475 FAB_LOOKUP(16, "pci_command", &data->pci_cfg_comm); 476 477 /* PCI bridge registers */ 478 FAB_LOOKUP(16, "pci_bdg_sec_status", &data->pci_bdg_sec_stat); 479 FAB_LOOKUP(16, "pci_bdg_ctrl", &data->pci_bdg_ctrl); 480 481 /* PCIx registers */ 482 FAB_LOOKUP(32, "pcix_status", &data->pcix_status); 483 FAB_LOOKUP(16, "pcix_command", &data->pcix_command); 484 485 /* PCIx ECC Registers */ 486 FAB_LOOKUP(16, "pcix_ecc_control_0", &data->pcix_ecc_control_0); 487 FAB_LOOKUP(16, "pcix_ecc_status_0", &data->pcix_ecc_status_0); 488 FAB_LOOKUP(32, "pcix_ecc_fst_addr_0", &data->pcix_ecc_fst_addr_0); 489 FAB_LOOKUP(32, "pcix_ecc_sec_addr_0", &data->pcix_ecc_sec_addr_0); 490 FAB_LOOKUP(32, "pcix_ecc_attr_0", &data->pcix_ecc_attr_0); 491 492 /* PCIx ECC Bridge Registers */ 493 FAB_LOOKUP(16, "pcix_ecc_control_1", &data->pcix_ecc_control_1); 494 FAB_LOOKUP(16, "pcix_ecc_status_1", &data->pcix_ecc_status_1); 495 FAB_LOOKUP(32, "pcix_ecc_fst_addr_1", &data->pcix_ecc_fst_addr_1); 496 FAB_LOOKUP(32, "pcix_ecc_sec_addr_1", &data->pcix_ecc_sec_addr_1); 497 FAB_LOOKUP(32, "pcix_ecc_attr_1", &data->pcix_ecc_attr_1); 498 499 /* PCIx Bridge */ 500 FAB_LOOKUP(32, "pcix_bdg_status", &data->pcix_bdg_stat); 501 FAB_LOOKUP(16, "pcix_bdg_sec_status", &data->pcix_bdg_sec_stat); 502 503 /* PCIe registers */ 504 FAB_LOOKUP(16, "pcie_status", &data->pcie_err_status); 505 FAB_LOOKUP(16, "pcie_command", &data->pcie_err_ctl); 506 FAB_LOOKUP(32, "pcie_dev_cap", &data->pcie_dev_cap); 507 508 /* PCIe AER registers */ 509 FAB_LOOKUP(32, "pcie_adv_ctl", &data->pcie_adv_ctl); 510 FAB_LOOKUP(32, "pcie_ue_status", &data->pcie_ue_status); 511 FAB_LOOKUP(32, "pcie_ue_mask", &data->pcie_ue_mask); 512 FAB_LOOKUP(32, "pcie_ue_sev", &data->pcie_ue_sev); 513 FAB_LOOKUP(32, "pcie_ue_hdr0", &data->pcie_ue_hdr[0]); 514 FAB_LOOKUP(32, "pcie_ue_hdr1", &data->pcie_ue_hdr[1]); 515 FAB_LOOKUP(32, "pcie_ue_hdr2", &data->pcie_ue_hdr[2]); 516 FAB_LOOKUP(32, "pcie_ue_hdr3", &data->pcie_ue_hdr[3]); 517 FAB_LOOKUP(32, "pcie_ce_status", &data->pcie_ce_status); 518 FAB_LOOKUP(32, "pcie_ce_mask", &data->pcie_ce_mask); 519 FAB_LOOKUP(32, "pcie_ue_tgt_trans", &data->pcie_ue_tgt_trans); 520 FAB_LOOKUP(64, "pcie_ue_tgt_addr", &data->pcie_ue_tgt_addr); 521 FAB_LOOKUP(16, "pcie_ue_tgt_bdf", &data->pcie_ue_tgt_bdf); 522 523 /* PCIe BDG AER registers */ 524 FAB_LOOKUP(32, "pcie_sue_adv_ctl", &data->pcie_sue_ctl); 525 FAB_LOOKUP(32, "pcie_sue_status", &data->pcie_sue_status); 526 FAB_LOOKUP(32, "pcie_sue_mask", &data->pcie_sue_mask); 527 FAB_LOOKUP(32, "pcie_sue_sev", &data->pcie_sue_sev); 528 FAB_LOOKUP(32, "pcie_sue_hdr0", &data->pcie_sue_hdr[0]); 529 FAB_LOOKUP(32, "pcie_sue_hdr1", &data->pcie_sue_hdr[1]); 530 FAB_LOOKUP(32, "pcie_sue_hdr2", &data->pcie_sue_hdr[2]); 531 FAB_LOOKUP(32, "pcie_sue_hdr3", &data->pcie_sue_hdr[3]); 532 FAB_LOOKUP(32, "pcie_sue_tgt_trans", &data->pcie_sue_tgt_trans); 533 FAB_LOOKUP(64, "pcie_sue_tgt_addr", &data->pcie_sue_tgt_addr); 534 FAB_LOOKUP(16, "pcie_sue_tgt_bdf", &data->pcie_sue_tgt_bdf); 535 536 /* PCIe RP registers */ 537 FAB_LOOKUP(32, "pcie_rp_status", &data->pcie_rp_status); 538 FAB_LOOKUP(16, "pcie_rp_control", &data->pcie_rp_ctl); 539 540 /* PCIe RP AER registers */ 541 FAB_LOOKUP(32, "pcie_adv_rp_status", &data->pcie_rp_err_status); 542 FAB_LOOKUP(32, "pcie_adv_rp_command", &data->pcie_rp_err_cmd); 543 FAB_LOOKUP(16, "pcie_adv_rp_ce_src_id", &data->pcie_rp_ce_src_id); 544 FAB_LOOKUP(16, "pcie_adv_rp_ue_src_id", &data->pcie_rp_ue_src_id); 545 546 /* 547 * If the system has a PCIe complaint RP with AER, turn off translating 548 * fake RP ereports. 549 */ 550 if (fab_xlate_fake_rp && 551 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) && 552 data->aer_off) 553 fab_xlate_fake_rp = B_FALSE; 554 } 555 556 /* ARGSUSED */ 557 static void 558 fab_fire_to_data(fmd_hdl_t *hdl, nvlist_t *nvl, fab_data_t *data) { 559 data->nvl = nvl; 560 561 /* Always Root Complex */ 562 data->dev_type = PCIE_PCIECAP_DEV_TYPE_ROOT; 563 564 data->pcie_ue_sev = (PCIE_AER_UCE_DLP | PCIE_AER_UCE_SD | 565 PCIE_AER_UCE_FCP | PCIE_AER_UCE_RO | PCIE_AER_UCE_MTLP); 566 } 567 568 /* ARGSUSED */ 569 static int 570 fab_prep_basic_erpt(fmd_hdl_t *hdl, nvlist_t *nvl, nvlist_t *erpt, 571 boolean_t isRC) { 572 uint64_t *now; 573 uint64_t ena; 574 uint_t nelem; 575 nvlist_t *detector, *new_detector; 576 char rcpath[255]; 577 int err = 0; 578 579 /* Grab the tod, ena and detector(FMRI) */ 580 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); 581 err |= nvlist_lookup_uint64(nvl, "ena", &ena); 582 err |= nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector); 583 584 /* Make a copy of the detector */ 585 err |= nvlist_dup(detector, &new_detector, NV_UNIQUE_NAME); 586 587 /* Copy the tod and ena to erpt */ 588 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); 589 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); 590 591 /* 592 * Create the correct ROOT FMRI from PCIe leaf fabric ereports. Used 593 * only by fab_prep_fake_rc_erpt. See the fab_pciex_fake_rc_erpt_tbl 594 * comments for more information. 595 */ 596 if (isRC) { 597 fab_get_rcpath(hdl, nvl, rcpath); 598 599 /* Create the correct PCIe RC new_detector aka FMRI */ 600 (void) nvlist_remove(new_detector, FM_FMRI_DEV_PATH, 601 DATA_TYPE_STRING); 602 (void) nvlist_add_string(new_detector, FM_FMRI_DEV_PATH, 603 rcpath); 604 } 605 606 /* Copy the FMRI to erpt */ 607 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, new_detector); 608 609 return (err); 610 } 611 612 static void 613 fab_send_tgt_erpt(fmd_hdl_t *hdl, fab_data_t *data, const char *class, 614 boolean_t isPrimary) 615 { 616 nvlist_t *nvl = data->nvl; 617 nvlist_t *erpt; 618 char *fmri = NULL; 619 uint32_t tgt_trans; 620 uint64_t tgt_addr; 621 uint16_t tgt_bdf; 622 623 if (isPrimary) { 624 tgt_trans = data->pcie_ue_tgt_trans; 625 tgt_addr = data->pcie_ue_tgt_addr; 626 tgt_bdf = data->pcie_ue_tgt_bdf; 627 } else { 628 tgt_trans = data->pcie_sue_tgt_trans; 629 tgt_addr = data->pcie_sue_tgt_addr; 630 tgt_bdf = data->pcie_sue_tgt_bdf; 631 } 632 633 fmd_hdl_debug(hdl, "Sending Target Ereport: " 634 "type 0x%x addr 0x%llx fltbdf 0x%x\n", 635 tgt_trans, tgt_addr, tgt_bdf); 636 637 if (!tgt_trans) 638 return; 639 640 if ((tgt_trans == PF_ADDR_PIO) && tgt_addr) 641 fmri = fab_find_addr(hdl, nvl, tgt_addr); 642 else if ((tgt_trans == PF_ADDR_CFG) && tgt_bdf) 643 fmri = fab_find_bdf(hdl, nvl, tgt_bdf); 644 645 if (fmri) { 646 uint64_t *now; 647 uint64_t ena; 648 uint_t nelem; 649 nvlist_t *detector; 650 int err = 0; 651 652 /* Allocate space for new erpt */ 653 (void) nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0); 654 655 /* Generate the target ereport class */ 656 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 657 PCI_ERROR_SUBCLASS, class); 658 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 659 660 /* Grab the tod, ena and detector(FMRI) */ 661 err |= nvlist_lookup_uint64_array(nvl, "__tod", &now, &nelem); 662 err |= nvlist_lookup_uint64(nvl, "ena", &ena); 663 664 /* Copy the tod and ena to erpt */ 665 (void) nvlist_add_uint64(erpt, FM_EREPORT_ENA, ena); 666 (void) nvlist_add_uint64_array(erpt, "__tod", now, nelem); 667 668 /* Create the correct FMRI */ 669 (void) nvlist_alloc(&detector, NV_UNIQUE_NAME, 0); 670 (void) nvlist_add_string(detector, FM_VERSION, 671 FM_DEV_SCHEME_VERSION); 672 (void) nvlist_add_string(detector, FM_FMRI_SCHEME, 673 FM_FMRI_SCHEME_DEV); 674 (void) nvlist_add_string(detector, FM_FMRI_DEV_PATH, fmri); 675 (void) nvlist_add_nvlist(erpt, FM_EREPORT_DETECTOR, detector); 676 677 /* Add the address payload */ 678 (void) nvlist_add_uint64(erpt, PCI_PA, tgt_addr); 679 680 fmd_hdl_debug(hdl, "Sending target ereport: %s 0x%x\n", 681 fab_buf, tgt_addr); 682 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 683 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 684 fmd_hdl_debug(hdl, "Failed to send Target PCI ereport"); 685 } else { 686 fmd_hdl_debug(hdl, "Cannot find Target FMRI addr:0x%llx", 687 tgt_addr); 688 } 689 } 690 691 static void 692 fab_send_erpt(fmd_hdl_t *hdl, fab_data_t *data, fab_err_tbl_t *tbl) 693 { 694 fab_erpt_tbl_t *erpt_tbl, *entry; 695 nvlist_t *erpt; 696 uint32_t reg; 697 698 erpt_tbl = tbl->erpt_tbl; 699 if (tbl->reg_size == 16) { 700 reg = (uint32_t)*((uint16_t *) 701 ((uint32_t)data + tbl->reg_offset)); 702 } else { 703 reg = *((uint32_t *)((uint32_t)data + tbl->reg_offset)); 704 } 705 706 for (entry = erpt_tbl; entry->err_class; entry++) { 707 if (!(reg & entry->reg_bit)) 708 continue; 709 710 (void) nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0); 711 if (tbl->fab_prep(hdl, data, erpt, entry) != 0) { 712 fmd_hdl_debug(hdl, "Prepping ereport failed\n"); 713 nvlist_free(erpt); 714 continue; 715 } 716 717 fmd_hdl_debug(hdl, "Sending ereport: %s 0x%x\n", fab_buf, reg); 718 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 719 if (fmd_xprt_error(hdl, fab_fmd_xprt)) { 720 fmd_hdl_debug(hdl, "Failed to send PCI ereport\n"); 721 return; 722 } 723 } 724 } 725 726 static int 727 fab_prep_pci_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 728 fab_erpt_tbl_t *tbl) 729 { 730 const char *class = tbl->err_class; 731 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 732 733 /* Generate an ereport for this error bit. */ 734 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 735 PCI_ERROR_SUBCLASS, class); 736 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 737 738 (void) nvlist_add_uint16(erpt, PCI_CONFIG_STATUS, data->pci_err_status); 739 (void) nvlist_add_uint16(erpt, PCI_CONFIG_COMMAND, data->pci_cfg_comm); 740 741 return (err); 742 } 743 744 static int 745 fab_prep_pci_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 746 fab_erpt_tbl_t *tbl) 747 { 748 const char *class = tbl->err_class; 749 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 750 751 /* Generate an ereport for this error bit. */ 752 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s-%s", 753 PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, class); 754 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 755 756 (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 757 data->pci_bdg_sec_stat); 758 (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 759 760 return (err); 761 } 762 763 static int 764 fab_prep_pci_bdg_ctl_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 765 fab_erpt_tbl_t *tbl) 766 { 767 const char *class = tbl->err_class; 768 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 769 770 /* Generate an ereport for this error bit. */ 771 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 772 PCI_ERROR_SUBCLASS, class); 773 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 774 775 (void) nvlist_add_uint16(erpt, PCI_SEC_CONFIG_STATUS, 776 data->pci_bdg_sec_stat); 777 (void) nvlist_add_uint16(erpt, PCI_BCNTRL, data->pci_bdg_ctrl); 778 779 return (err); 780 } 781 782 783 static int 784 fab_prep_pcie_ce_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 785 fab_erpt_tbl_t *tbl) 786 { 787 const char *class = tbl->err_class; 788 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 789 790 /* Generate an ereport for this error bit. */ 791 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 792 PCIEX_ERROR_SUBCLASS, class); 793 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 794 795 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 796 (void) nvlist_add_uint32(erpt, PCIEX_CE_STATUS_REG, 797 data->pcie_ce_status); 798 799 return (err); 800 } 801 802 static int 803 fab_prep_pcie_ue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 804 fab_erpt_tbl_t *tbl) 805 { 806 const char *class = tbl->err_class; 807 uint32_t first_err = 1 << (data->pcie_adv_ctl & 808 PCIE_AER_CTL_FST_ERR_PTR_MASK); 809 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 810 811 /* Generate an ereport for this error bit. */ 812 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 813 PCIEX_ERROR_SUBCLASS, class); 814 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 815 816 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 817 (void) nvlist_add_uint32(erpt, PCIEX_UE_STATUS_REG, 818 data->pcie_ue_status); 819 (void) nvlist_add_uint32(erpt, PCIEX_UE_SEV_REG, data->pcie_ue_sev); 820 (void) nvlist_add_uint32(erpt, PCIEX_ADV_CTL, data->pcie_adv_ctl); 821 822 fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 823 824 if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_bdf) { 825 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 826 data->pcie_ue_tgt_bdf); 827 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 828 } else { 829 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 830 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 831 } 832 833 if ((tbl->reg_bit == first_err) && data->pcie_ue_tgt_trans) { 834 if (tbl->tgt_class) 835 fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_TRUE); 836 } 837 838 return (err); 839 } 840 841 static int 842 fab_prep_pcie_sue_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 843 fab_erpt_tbl_t *tbl) 844 { 845 const char *class = tbl->err_class; 846 uint32_t first_err = 1 << (data->pcie_sue_ctl & 847 PCIE_AER_SCTL_FST_ERR_PTR_MASK); 848 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 849 850 /* Generate an ereport for this error bit. */ 851 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 852 PCIEX_ERROR_SUBCLASS, class); 853 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 854 855 (void) nvlist_add_uint32(erpt, PCIEX_SEC_UE_STATUS, 856 data->pcie_sue_status); 857 858 fmd_hdl_debug(hdl, "Bit 0x%x First Err 0x%x", tbl->reg_bit, first_err); 859 860 if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_bdf) { 861 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 862 data->pcie_sue_tgt_bdf); 863 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 864 } else { 865 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 0); 866 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_FALSE); 867 } 868 869 if ((tbl->reg_bit == first_err) && data->pcie_sue_tgt_trans) { 870 if (tbl->tgt_class) 871 fab_send_tgt_erpt(hdl, data, tbl->tgt_class, B_FALSE); 872 } 873 874 return (err); 875 } 876 877 static int 878 fab_prep_pcix_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 879 fab_erpt_tbl_t *tbl) 880 { 881 const char *class = tbl->err_class; 882 int err = 0; 883 884 /* Only send if this is not a bridge */ 885 if (!data->pcix_status || data->pcix_bdg_sec_stat) 886 return (1); 887 888 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 889 890 /* Generate an ereport for this error bit. */ 891 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 892 PCIX_ERROR_SUBCLASS, class); 893 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 894 895 (void) nvlist_add_uint8(erpt, PCIX_COMMAND, data->pcix_command); 896 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 897 898 return (err); 899 } 900 901 static void 902 fab_send_pcix_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 903 { 904 nvlist_t *erpt; 905 int ecc_phase = (data->pcix_ecc_status_0 & PCI_PCIX_ECC_PHASE) >> 0x4; 906 int ecc_corr = data->pcix_ecc_status_0 & PCI_PCIX_ECC_CORR; 907 int sec_ue = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_UE; 908 int sec_ce = data->pcix_ecc_status_0 & PCI_PCIX_ECC_S_CE; 909 uint32_t ctlstat = (data->pcix_ecc_control_0 << 16) | 910 data->pcix_ecc_status_0; 911 912 switch (ecc_phase) { 913 case PCI_PCIX_ECC_PHASE_NOERR: 914 break; 915 case PCI_PCIX_ECC_PHASE_FADDR: 916 case PCI_PCIX_ECC_PHASE_SADDR: 917 (void) snprintf(fab_buf, FM_MAX_CLASS, 918 "%s.%s", PCIX_ERROR_SUBCLASS, 919 ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 920 break; 921 case PCI_PCIX_ECC_PHASE_ATTR: 922 (void) snprintf(fab_buf, FM_MAX_CLASS, 923 "%s.%s", PCIX_ERROR_SUBCLASS, 924 ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 925 break; 926 case PCI_PCIX_ECC_PHASE_DATA32: 927 case PCI_PCIX_ECC_PHASE_DATA64: 928 (void) snprintf(fab_buf, FM_MAX_CLASS, 929 "%s.%s", PCIX_ERROR_SUBCLASS, 930 ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 931 break; 932 } 933 934 if (ecc_phase) { 935 (void) nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0); 936 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 937 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 938 (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 939 data->pcix_command); 940 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 941 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 942 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 943 data->pcix_ecc_attr_0); 944 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 945 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 946 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 947 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 948 } 949 950 if (sec_ce || sec_ue) { 951 (void) snprintf(fab_buf, FM_MAX_CLASS, 952 "%s.%s", PCIX_ERROR_SUBCLASS, 953 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 954 (void) nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0); 955 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 956 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 957 (void) nvlist_add_uint16(erpt, PCIX_COMMAND, 958 data->pcix_command); 959 (void) nvlist_add_uint32(erpt, PCIX_STATUS, data->pcix_status); 960 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 961 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 962 data->pcix_ecc_attr_0); 963 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 964 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 965 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 966 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 967 } 968 } 969 970 static int 971 fab_prep_pcix_bdg_sec_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 972 fab_erpt_tbl_t *tbl) 973 { 974 const char *class = tbl->err_class; 975 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 976 977 /* Generate an ereport for this error bit. */ 978 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s%s", 979 PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, class); 980 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 981 982 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 983 data->pcix_bdg_sec_stat); 984 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 985 986 return (err); 987 } 988 989 static int 990 fab_prep_pcix_bdg_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 991 fab_erpt_tbl_t *tbl) 992 { 993 const char *class = tbl->err_class; 994 int err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 995 996 /* Generate an ereport for this error bit. */ 997 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 998 PCIX_ERROR_SUBCLASS, class); 999 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1000 1001 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1002 data->pcix_bdg_sec_stat); 1003 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, data->pcix_bdg_stat); 1004 1005 return (err); 1006 } 1007 1008 static void 1009 fab_send_pcix_bdg_ecc_erpt(fmd_hdl_t *hdl, fab_data_t *data) 1010 { 1011 nvlist_t *erpt; 1012 int ecc_phase = (data->pcix_ecc_status_1 & PCI_PCIX_ECC_PHASE) >> 0x4; 1013 int ecc_corr = data->pcix_ecc_status_1 & PCI_PCIX_ECC_CORR; 1014 int sec_ue = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_UE; 1015 int sec_ce = data->pcix_ecc_status_1 & PCI_PCIX_ECC_S_CE; 1016 uint32_t ctlstat = (data->pcix_ecc_control_1 << 16) | 1017 data->pcix_ecc_status_1; 1018 1019 switch (ecc_phase) { 1020 case PCI_PCIX_ECC_PHASE_NOERR: 1021 break; 1022 case PCI_PCIX_ECC_PHASE_FADDR: 1023 case PCI_PCIX_ECC_PHASE_SADDR: 1024 (void) snprintf(fab_buf, FM_MAX_CLASS, 1025 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1026 ecc_corr ? PCIX_ECC_CE_ADDR : PCIX_ECC_UE_ADDR); 1027 break; 1028 case PCI_PCIX_ECC_PHASE_ATTR: 1029 (void) snprintf(fab_buf, FM_MAX_CLASS, 1030 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1031 ecc_corr ? PCIX_ECC_CE_ATTR : PCIX_ECC_UE_ATTR); 1032 break; 1033 case PCI_PCIX_ECC_PHASE_DATA32: 1034 case PCI_PCIX_ECC_PHASE_DATA64: 1035 (void) snprintf(fab_buf, FM_MAX_CLASS, 1036 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1037 ecc_corr ? PCIX_ECC_CE_DATA : PCIX_ECC_UE_DATA); 1038 break; 1039 } 1040 if (ecc_phase) { 1041 (void) nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0); 1042 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1043 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1044 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1045 data->pcix_bdg_sec_stat); 1046 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 1047 data->pcix_bdg_stat); 1048 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 1049 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 1050 data->pcix_ecc_attr_1); 1051 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 1052 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 1053 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 1054 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1055 } 1056 1057 if (sec_ce || sec_ue) { 1058 (void) snprintf(fab_buf, FM_MAX_CLASS, 1059 "%s.%s%s", PCIX_ERROR_SUBCLASS, PCIX_SEC_ERROR_SUBCLASS, 1060 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 1061 (void) nvlist_alloc(&erpt, NV_UNIQUE_NAME, 0); 1062 (void) fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1063 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1064 (void) nvlist_add_uint16(erpt, PCIX_SEC_STATUS, 1065 data->pcix_bdg_sec_stat); 1066 (void) nvlist_add_uint32(erpt, PCIX_BDG_STAT, 1067 data->pcix_bdg_stat); 1068 (void) nvlist_add_uint32(erpt, PCIX_ECC_CTLSTAT, ctlstat); 1069 (void) nvlist_add_uint32(erpt, PCIX_ECC_ATTR, 1070 data->pcix_ecc_attr_1); 1071 fmd_hdl_debug(hdl, "Sending ecc ereport: %s\n", fab_buf); 1072 fmd_xprt_post(hdl, fab_fmd_xprt, erpt, 0); 1073 if (fmd_xprt_error(hdl, fab_fmd_xprt)) 1074 fmd_hdl_debug(hdl, "Failed to send ECC ereport\n"); 1075 } 1076 } 1077 1078 static int 1079 fab_prep_pcie_nadv_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1080 fab_erpt_tbl_t *tbl) 1081 { 1082 const char *class = tbl->err_class; 1083 int err = 0; 1084 1085 /* Don't send this for PCI device, Root Ports, or PCIe with AER */ 1086 if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 1087 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 1088 data->aer_off) 1089 return (1); 1090 1091 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1092 1093 /* Generate an ereport for this error bit. */ 1094 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1095 PCIEX_ERROR_SUBCLASS, class); 1096 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1097 1098 (void) nvlist_add_uint16(erpt, PCIEX_DEVSTS_REG, data->pcie_err_status); 1099 1100 return (err); 1101 } 1102 1103 static int 1104 fab_prep_pcie_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1105 fab_erpt_tbl_t *tbl) 1106 { 1107 const char *class = tbl->err_class; 1108 uint32_t status = data->pcie_rp_err_status; 1109 int err = 0; 1110 int isFE = 0, isNFE = 0; 1111 1112 fmd_hdl_debug(hdl, "XLATE RP Error Class %s", class); 1113 1114 if (!data->aer_off) 1115 return (-1); 1116 1117 /* Only send a FE Msg if the 1st UE error is FE */ 1118 if (strcmp(class, PCIEX_RC_FE_MSG) == 0) 1119 if (!(status & PCIE_AER_RE_STS_FIRST_UC_FATAL)) 1120 return (-1); 1121 else 1122 isFE = 1; 1123 1124 /* Only send a NFE Msg is the 1st UE error is NFE */ 1125 if (strcmp(class, PCIEX_RC_NFE_MSG) == 0) 1126 if (status & PCIE_AER_RE_STS_FIRST_UC_FATAL) 1127 return (-1); 1128 else 1129 isNFE = 1; 1130 1131 fmd_hdl_debug(hdl, "XLATE RP Error"); 1132 1133 err |= fab_prep_basic_erpt(hdl, data->nvl, erpt, B_FALSE); 1134 1135 /* Generate an ereport for this error bit. */ 1136 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1137 PCIEX_ERROR_SUBCLASS, class); 1138 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1139 1140 (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, status); 1141 if ((isFE || isNFE) && data->pcie_rp_ue_src_id) { 1142 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 1143 data->pcie_rp_ue_src_id); 1144 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1145 } 1146 if ((strcmp(class, PCIEX_RC_CE_MSG) == 0) && data->pcie_rp_ce_src_id) { 1147 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, 1148 data->pcie_rp_ce_src_id); 1149 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1150 } 1151 1152 return (err); 1153 } 1154 1155 static int 1156 fab_prep_pcie_fake_rc_erpt(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1157 fab_erpt_tbl_t *tbl) 1158 { 1159 const char *class = tbl->err_class; 1160 uint32_t rc_err_sts = 0; 1161 int err = 0; 1162 1163 /* 1164 * Don't send this for PCI device or Root Ports. Only send it on 1165 * systems with non-compliant RPs. 1166 */ 1167 if ((data->dev_type == PCIE_PCIECAP_DEV_TYPE_PCI_DEV) || 1168 (data->dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) || 1169 (!fab_xlate_fake_rp)) 1170 return (-1); 1171 1172 err = fab_prep_basic_erpt(hdl, data->nvl, erpt, B_TRUE); 1173 1174 /* Generate an ereport for this error bit. */ 1175 (void) snprintf(fab_buf, FM_MAX_CLASS, "ereport.io.%s.%s", 1176 PCIEX_ERROR_SUBCLASS, class); 1177 (void) nvlist_add_string(erpt, FM_CLASS, fab_buf); 1178 1179 /* Send PCIe RC Ereports */ 1180 if (data->pcie_err_status & PCIE_DEVSTS_CE_DETECTED) { 1181 rc_err_sts |= PCIE_AER_RE_STS_CE_RCVD; 1182 } 1183 1184 /* NFE/FE src id takes precedence over CE src id */ 1185 if (data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) { 1186 rc_err_sts |= PCIE_AER_RE_STS_NFE_MSGS_RCVD; 1187 rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 1188 } 1189 if (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED) { 1190 rc_err_sts |= PCIE_AER_RE_STS_FE_MSGS_RCVD; 1191 rc_err_sts |= PCIE_AER_RE_STS_FE_NFE_RCVD; 1192 } 1193 if ((data->pcie_err_status & PCIE_DEVSTS_NFE_DETECTED) && 1194 (data->pcie_err_status & PCIE_DEVSTS_FE_DETECTED)) { 1195 rc_err_sts |= PCIE_AER_RE_STS_FIRST_UC_FATAL; 1196 rc_err_sts |= PCIE_AER_RE_STS_MUL_FE_NFE_RCVD; 1197 } 1198 1199 (void) nvlist_add_uint32(erpt, PCIEX_ROOT_ERRSTS_REG, rc_err_sts); 1200 1201 if (!(rc_err_sts & PCIE_AER_RE_STS_MUL_FE_NFE_RCVD)) { 1202 (void) nvlist_add_uint16(erpt, PCIEX_SRC_ID, data->bdf); 1203 (void) nvlist_add_boolean_value(erpt, PCIEX_SRC_VALID, B_TRUE); 1204 } 1205 1206 return (err); 1207 } 1208 1209 static int 1210 fab_xlate_fire_ce(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1211 const char *class) 1212 { 1213 fab_fire_tbl_t *entry; 1214 uint64_t reg; 1215 1216 for (entry = fab_fire_pec_ce_tbl; entry->err_class; entry++) { 1217 if (strcmp(class, entry->err_class) == 0) 1218 goto send; 1219 } 1220 1221 return (0); 1222 1223 send: 1224 fmd_hdl_debug(hdl, "Translate Fire CE %s\n", class); 1225 1226 /* Fill in the device status register */ 1227 data->pcie_err_status = PCIE_DEVSTS_CE_DETECTED; 1228 1229 /* Fill in the AER CE register */ 1230 if (nvlist_lookup_uint64(erpt, "tlu-cess", ®) == 0) { 1231 data->pcie_ce_status = (uint32_t)reg | (uint32_t)(reg >> 32); 1232 } 1233 1234 return (1); 1235 } 1236 1237 static int 1238 fab_xlate_fire_ue(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1239 const char *class) 1240 { 1241 fab_fire_tbl_t *entry; 1242 uint64_t reg; 1243 uint32_t temp; 1244 pcie_tlp_hdr_t *hdr; 1245 1246 for (entry = fab_fire_pec_ue_tbl; entry->err_class; entry++) { 1247 if (strcmp(class, entry->err_class) == 0) 1248 goto send; 1249 } 1250 1251 return (0); 1252 1253 send: 1254 fmd_hdl_debug(hdl, "Translate Fire UE %s\n", class); 1255 1256 /* Fill in PCI Status Register */ 1257 data->pci_err_status = entry->pci_err_sts; 1258 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1259 1260 /* Fill in the device status register */ 1261 if (entry->fire_bit & data->pcie_ue_sev) 1262 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 1263 else 1264 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1265 1266 if (entry->fire_bit == PCIE_AER_UCE_UR) 1267 data->pcie_err_status |= PCIE_DEVSTS_UR_DETECTED; 1268 1269 /* Fill in the AER UE register */ 1270 if (nvlist_lookup_uint64(erpt, "tlu-uess", ®) == 0) { 1271 data->pcie_ue_status = (uint32_t)reg | (uint32_t)(reg >> 32); 1272 } 1273 1274 /* Fill in the AER Control register */ 1275 if ((reg & (uint64_t)entry->fire_bit) && 1276 nvlist_lookup_boolean(erpt, "primary")) { 1277 temp = entry->fire_bit; 1278 for (data->pcie_adv_ctl = (uint32_t)-1; temp; 1279 data->pcie_adv_ctl++) 1280 temp = temp >> 1; 1281 } 1282 1283 /* If CTO create target information */ 1284 if (entry->fire_bit == PCIE_AER_UCE_TO && 1285 nvlist_lookup_boolean(erpt, "primary")) { 1286 if (nvlist_lookup_uint64(erpt, "tlu-tueh1l", ®) == 0) { 1287 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1288 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1289 } 1290 if (nvlist_lookup_uint64(erpt, "tlu-tueh2l", ®) == 0) { 1291 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1292 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1293 } 1294 1295 hdr = (pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]); 1296 switch (hdr->type) { 1297 case PCIE_TLP_TYPE_IO: 1298 case PCIE_TLP_TYPE_MEM: 1299 case PCIE_TLP_TYPE_MEMLK: 1300 data->pcie_ue_tgt_trans = PF_ADDR_PIO; 1301 if (hdr->fmt & 0x1) { 1302 data->pcie_ue_tgt_addr = reg; 1303 } else { 1304 data->pcie_ue_tgt_addr = data->pcie_ue_hdr[2]; 1305 } 1306 break; 1307 case PCIE_TLP_TYPE_CFG0: 1308 case PCIE_TLP_TYPE_CFG1: 1309 data->pcie_ue_tgt_trans = PF_ADDR_CFG; 1310 data->pcie_ue_tgt_bdf = data->pcie_ue_hdr[2] >> 16; 1311 break; 1312 } 1313 } 1314 1315 /* Fill in the AER Header registers */ 1316 if (nvlist_lookup_uint64(erpt, "tlu-rueh1l", ®) == 0) { 1317 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1318 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1319 } 1320 if (nvlist_lookup_uint64(erpt, "tlu-rueh2l", ®) == 0) { 1321 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1322 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1323 } 1324 1325 return (1); 1326 } 1327 1328 static int 1329 fab_xlate_fire_oe(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1330 const char *class) 1331 { 1332 fab_fire_tbl_t *entry; 1333 uint64_t reg; 1334 1335 for (entry = fab_fire_pec_oe_tbl; entry->err_class; entry++) { 1336 if (strcmp(class, entry->err_class) == 0) 1337 goto send; 1338 } 1339 1340 return (0); 1341 1342 send: 1343 fmd_hdl_debug(hdl, "Translate Fire OE %s\n", class); 1344 1345 /* Fill in PCI Status Register */ 1346 if (entry->fire_bit) { 1347 data->pci_err_status = entry->pci_err_sts; 1348 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1349 } else { 1350 if (nvlist_lookup_uint64(erpt, "tlu-roeeh1l", ®) == 0) { 1351 data->pcie_ue_hdr[0] = (uint32_t)(reg >> 32); 1352 data->pcie_ue_hdr[1] = (uint32_t)(reg); 1353 } 1354 if (nvlist_lookup_uint64(erpt, "tlu-roeeh2l", ®) == 0) { 1355 data->pcie_ue_hdr[2] = (uint32_t)(reg >> 32); 1356 data->pcie_ue_hdr[3] = (uint32_t)(reg); 1357 } 1358 1359 if (((pcie_tlp_hdr_t *)(&data->pcie_ue_hdr[0]))->type == 1360 PCIE_TLP_TYPE_CPL) { 1361 pcie_cpl_t *cpl = (pcie_cpl_t *)&data->pcie_ue_hdr[1]; 1362 switch (cpl->status) { 1363 case PCIE_CPL_STS_UR: 1364 data->pci_err_status = 0; 1365 data->pci_bdg_sec_stat = PCI_STAT_R_MAST_AB | 1366 PCI_STAT_S_SYSERR; 1367 break; 1368 case PCIE_CPL_STS_CA: 1369 data->pci_err_status = 0; 1370 data->pci_bdg_sec_stat = PCI_STAT_R_TARG_AB | 1371 PCI_STAT_S_SYSERR; 1372 break; 1373 } 1374 } 1375 } 1376 1377 /* Fill in the device status register */ 1378 if (entry->fire_bit & data->pcie_ue_sev) 1379 data->pcie_err_status = PCIE_DEVSTS_FE_DETECTED; 1380 else 1381 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1382 1383 /* Fill in the AER UE register */ 1384 data->pcie_ue_status = entry->fire_bit; 1385 1386 return (1); 1387 } 1388 1389 static int 1390 fab_xlate_fire_dmc(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *erpt, 1391 const char *class) 1392 { 1393 fab_fire_tbl_t *entry; 1394 uint64_t reg; 1395 uint32_t temp; 1396 1397 for (entry = fab_fire_dmc_tbl; entry->err_class; entry++) { 1398 fmd_hdl_debug(hdl, "Matching %s\n", entry->err_class); 1399 if ((strcmp(class, entry->err_class) == 0) && 1400 nvlist_lookup_boolean(erpt, "primary")) 1401 goto send; 1402 } 1403 1404 return (0); 1405 1406 send: 1407 fmd_hdl_debug(hdl, "Translate Fire DMC %s\n", class); 1408 1409 /* Fill in PCI Status Register */ 1410 data->pci_err_status = entry->pci_err_sts; 1411 data->pci_bdg_sec_stat = entry->pci_bdg_sts; 1412 1413 /* Fill in the device status register */ 1414 data->pcie_err_status = PCIE_DEVSTS_NFE_DETECTED; 1415 1416 /* Fill in the AER UE register */ 1417 data->pcie_ue_status = entry->fire_bit; 1418 1419 /* Fill in the AER Control register */ 1420 temp = entry->fire_bit; 1421 for (data->pcie_adv_ctl = (uint32_t)-1; temp; data->pcie_adv_ctl++) 1422 temp = temp >> 1; 1423 1424 /* Fill in the AER Header registers */ 1425 if (nvlist_lookup_uint64(erpt, "mmu-tfsr", ®) == 0) { 1426 fmd_hdl_debug(hdl, "tfsr 0x%llx\n", reg); 1427 /* Get the trans type */ 1428 temp = (reg & 0x3F0000) >> 16; 1429 data->pcie_ue_hdr[0] = (uint32_t)(temp << 24); 1430 data->pcie_ue_tgt_trans = PF_ADDR_DMA; 1431 /* Get the req id */ 1432 temp = (reg & 0xFFFF); 1433 data->pcie_ue_hdr[1] = (uint32_t)(temp << 16); 1434 data->pcie_ue_tgt_bdf = temp; 1435 } 1436 1437 if (nvlist_lookup_uint64(erpt, "mmu-tfar", ®) == 0) { 1438 fmd_hdl_debug(hdl, "tfar 0x%llx\n", reg); 1439 /* Get the address */ 1440 data->pcie_ue_hdr[2] = reg; 1441 data->pcie_ue_hdr[3] = 0; 1442 data->pcie_ue_tgt_addr = reg; 1443 } 1444 1445 fmd_hdl_debug(hdl, "HEADER 0 0x%x\n", data->pcie_ue_hdr[0]); 1446 fmd_hdl_debug(hdl, "HEADER 1 0x%x\n", data->pcie_ue_hdr[1]); 1447 fmd_hdl_debug(hdl, "HEADER 2 0x%x\n", data->pcie_ue_hdr[2]); 1448 fmd_hdl_debug(hdl, "HEADER 3 0x%x\n", data->pcie_ue_hdr[3]); 1449 1450 return (1); 1451 } 1452 1453 static void 1454 fab_xlate_pcie_erpts(fmd_hdl_t *hdl, fab_data_t *data) 1455 { 1456 fab_err_tbl_t *tbl; 1457 1458 fmd_hdl_debug(hdl, "Sending Ereports Now"); 1459 1460 /* Go through the error logs and send the relavant reports */ 1461 for (tbl = fab_master_err_tbl; tbl->erpt_tbl; tbl++) { 1462 fab_send_erpt(hdl, data, tbl); 1463 } 1464 1465 /* Send PCI-X ECC Ereports */ 1466 fab_send_pcix_ecc_erpt(hdl, data); 1467 fab_send_pcix_bdg_ecc_erpt(hdl, data); 1468 } 1469 1470 static void 1471 fab_xlate_fire_erpts(fmd_hdl_t *hdl, fab_data_t *data, nvlist_t *nvl, 1472 const char *class) 1473 { 1474 if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.pec.*")) { 1475 if (fab_xlate_fire_ce(hdl, data, nvl, class)) 1476 return; 1477 1478 if (fab_xlate_fire_ue(hdl, data, nvl, class)) 1479 return; 1480 1481 if (fab_xlate_fire_oe(hdl, data, nvl, class)) 1482 return; 1483 } else if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.dmc.*") || 1484 fmd_nvl_class_match(hdl, nvl, "ereport.io.n2.dmu.*")) { 1485 if (fab_xlate_fire_dmc(hdl, data, nvl, class)) 1486 return; 1487 } 1488 } 1489 1490 static void 1491 fab_update_topo(fmd_hdl_t *hdl) 1492 { 1493 topo_hdl_t *thp = NULL; 1494 FILE *fp; 1495 int err = 0; 1496 1497 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) { 1498 fmd_hdl_debug(hdl, "Failed to hold topo\n"); 1499 } 1500 1501 fp = fopen(XMLTOPOFILE, "w"); 1502 1503 if (topo_xml_print(thp, fp, FM_FMRI_SCHEME_HC, &err) < 0) { 1504 fmd_hdl_debug(hdl, "Failed to get XML topo\n"); 1505 } 1506 1507 (void) fclose(fp); 1508 1509 fmd_hdl_topo_rele(hdl, thp); 1510 1511 /* Load xml document */ 1512 fab_doc = xmlParseFile(XMLTOPOFILE); 1513 1514 /* Init xpath */ 1515 fab_xpathCtx = xmlXPathNewContext(fab_doc); 1516 1517 fab_valid_topo = 1; 1518 } 1519 1520 /* ARGSUSED */ 1521 static void 1522 fab_get_rcpath(fmd_hdl_t *hdl, nvlist_t *nvl, char *rcpath) { 1523 nvlist_t *detector; 1524 char *path; 1525 int i; 1526 1527 (void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &detector); 1528 (void) nvlist_lookup_string(detector, FM_FMRI_DEV_PATH, &path); 1529 (void) strncpy(rcpath, path, FM_MAX_CLASS); 1530 for (i = 1; (i < FM_MAX_CLASS) && (rcpath[i] != '/') && 1531 (rcpath[i] != '\0'); i++); 1532 rcpath[i] = '\0'; 1533 } 1534 1535 static char * 1536 fab_find_bdf(fmd_hdl_t *hdl, nvlist_t *nvl, pcie_req_id_t bdf) { 1537 xmlXPathObjectPtr xpathObj; 1538 xmlNodeSetPtr nodes; 1539 char query[500]; 1540 int bus, dev, fn; 1541 char rcpath[255]; 1542 1543 if (bdf != (uint16_t)-1) { 1544 bus = (bdf & PCIE_REQ_ID_BUS_MASK) >> PCIE_REQ_ID_BUS_SHIFT; 1545 dev = (bdf & PCIE_REQ_ID_DEV_MASK) >> PCIE_REQ_ID_DEV_SHIFT; 1546 fn = (bdf & PCIE_REQ_ID_FUNC_MASK) >> PCIE_REQ_ID_FUNC_SHIFT; 1547 } 1548 1549 fab_get_rcpath(hdl, nvl, rcpath); 1550 1551 /* 1552 * Explanation of the XSL XPATH Query 1553 * Line 1: Look at all nodes with the node name "propval" 1554 * Line 2-3: See if the "value" of the node ends with correct PCIEx BDF 1555 * Line 4-5: See if the "value" of the node ends with correct PCI BDF 1556 * Line 6: Go up one level to the parent of the current node 1557 * Line 7: See if child node contains "ASRU" with the same PCIe Root 1558 * Line 8: Traverse up the parent and the other siblings and look for 1559 * the io "propgroup" and get the value of the dev "propval" 1560 */ 1561 (void) snprintf(query, sizeof (query), "//propval[" 1562 "contains(substring(@value, string-length(@value) - 34), " 1563 "'pciexbus=%d/pciexdev=%d/pciexfn=%d') or " 1564 "contains(substring(@value, string-length(@value) - 28), " 1565 "'pcibus=%d/pcidev=%d/pcifn=%d')" 1566 "]/parent::" 1567 "*/propval[@name='ASRU' and contains(@value, '%s')]" 1568 "/parent::*/following-sibling::*[@name='io']/propval[@name='dev']/" 1569 "@value", bus, dev, fn, bus, dev, fn, rcpath); 1570 1571 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); 1572 1573 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); 1574 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1575 nodes = xpathObj->nodesetval; 1576 if (nodes) { 1577 fmd_hdl_debug(hdl, "BDF Dev Path: %s\n", 1578 xmlNodeGetContent(nodes->nodeTab[0])); 1579 return ((char *)xmlNodeGetContent(nodes->nodeTab[0])); 1580 } 1581 return (NULL); 1582 } 1583 1584 static char * 1585 fab_find_addr(fmd_hdl_t *hdl, nvlist_t *nvl, uint64_t addr) { 1586 xmlXPathObjectPtr xpathObj; 1587 xmlNodeSetPtr nodes; 1588 xmlNodePtr devNode; 1589 char query[500]; 1590 int size, i, j; 1591 uint32_t prop[50]; 1592 char *token; 1593 pci_regspec_t *assign_p; 1594 uint64_t low, hi; 1595 char rcpath[255]; 1596 1597 fab_get_rcpath(hdl, nvl, rcpath); 1598 1599 (void) snprintf(query, sizeof (query), "//propval[" 1600 "@name='ASRU' and contains(@value, '%s')]/" 1601 "parent::*/following-sibling::*[@name='pci']/" 1602 "propval[@name='assigned-addresses']", rcpath); 1603 1604 xpathObj = xmlXPathEvalExpression((const xmlChar *)query, fab_xpathCtx); 1605 1606 fmd_hdl_debug(hdl, "xpathObj 0x%p type %d\n", xpathObj, xpathObj->type); 1607 fmd_hdl_debug(hdl, "xpathObj query %s\n", query); 1608 nodes = xpathObj->nodesetval; 1609 size = (nodes) ? nodes->nodeNr : 0; 1610 1611 /* Decode the list of assigned addresses xml nodes for each device */ 1612 for (i = 0; i < size; i++) { 1613 devNode = nodes->nodeTab[i]; 1614 if (!HAS_PROP(devNode, "value")) 1615 continue; 1616 1617 /* Convert "string" assigned-addresses to pci_regspec_t */ 1618 j = 0; 1619 for (token = strtok(GET_PROP(devNode, "value"), " "); token; 1620 token = strtok(NULL, " ")) { 1621 prop[j++] = strtoul(token, (char **)NULL, 16); 1622 } 1623 prop[j] = (uint32_t)-1; 1624 1625 /* Check if address belongs to this device */ 1626 for (assign_p = (pci_regspec_t *)prop; 1627 assign_p->pci_phys_hi != (uint_t)-1; assign_p++) { 1628 low = assign_p->pci_phys_low; 1629 hi = low + assign_p->pci_size_low; 1630 if ((addr < hi) && (addr >= low)) { 1631 fmd_hdl_debug(hdl, "Found Address\n"); 1632 goto found; 1633 } 1634 } 1635 } 1636 return (NULL); 1637 1638 found: 1639 /* Traverse up the xml tree and back down to find the right propgroup */ 1640 for (devNode = devNode->parent->parent->children; 1641 devNode; devNode = devNode->next) { 1642 if (STRCMP(devNode->name, "propgroup") && 1643 STRCMP(GET_PROP(devNode, "name"), "io")) 1644 goto propgroup; 1645 } 1646 return (NULL); 1647 1648 propgroup: 1649 /* Retrive the "dev" propval and return */ 1650 for (devNode = devNode->children; devNode; devNode = devNode->next) { 1651 if (STRCMP(devNode->name, "propval") && 1652 STRCMP(GET_PROP(devNode, "name"), "dev")) { 1653 fmd_hdl_debug(hdl, "Addr Dev Path: %s\n", 1654 GET_PROP(devNode, "value")); 1655 return (GET_PROP(devNode, "value")); 1656 } 1657 } 1658 return (NULL); 1659 } 1660 1661 static void 1662 fab_pr(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl) { 1663 nvpair_t *nvp; 1664 1665 for (nvp = nvlist_next_nvpair(nvl, NULL); 1666 nvp != NULL; 1667 nvp = nvlist_next_nvpair(nvl, nvp)) { 1668 1669 data_type_t type = nvpair_type(nvp); 1670 const char *name = nvpair_name(nvp); 1671 1672 boolean_t b; 1673 uint8_t i8; 1674 uint16_t i16; 1675 uint32_t i32; 1676 uint64_t i64; 1677 char *str; 1678 nvlist_t *cnv; 1679 1680 nvlist_t **nvlarr; 1681 uint_t arrsize; 1682 int arri; 1683 1684 1685 if (strcmp(name, FM_CLASS) == 0) 1686 continue; /* already printed by caller */ 1687 1688 fmd_hdl_debug(hdl, " %s=", name); 1689 1690 switch (type) { 1691 case DATA_TYPE_BOOLEAN: 1692 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN 1"); 1693 break; 1694 1695 case DATA_TYPE_BOOLEAN_VALUE: 1696 (void) nvpair_value_boolean_value(nvp, &b); 1697 fmd_hdl_debug(hdl, "DATA_TYPE_BOOLEAN_VALUE %d", 1698 b ? "1" : "0"); 1699 break; 1700 1701 case DATA_TYPE_BYTE: 1702 (void) nvpair_value_byte(nvp, &i8); 1703 fmd_hdl_debug(hdl, "DATA_TYPE_BYTE 0x%x", i8); 1704 break; 1705 1706 case DATA_TYPE_INT8: 1707 (void) nvpair_value_int8(nvp, (void *)&i8); 1708 fmd_hdl_debug(hdl, "DATA_TYPE_INT8 0x%x", i8); 1709 break; 1710 1711 case DATA_TYPE_UINT8: 1712 (void) nvpair_value_uint8(nvp, &i8); 1713 fmd_hdl_debug(hdl, "DATA_TYPE_UINT8 0x%x", i8); 1714 break; 1715 1716 case DATA_TYPE_INT16: 1717 (void) nvpair_value_int16(nvp, (void *)&i16); 1718 fmd_hdl_debug(hdl, "DATA_TYPE_INT16 0x%x", i16); 1719 break; 1720 1721 case DATA_TYPE_UINT16: 1722 (void) nvpair_value_uint16(nvp, &i16); 1723 fmd_hdl_debug(hdl, "DATA_TYPE_UINT16 0x%x", i16); 1724 break; 1725 1726 case DATA_TYPE_INT32: 1727 (void) nvpair_value_int32(nvp, (void *)&i32); 1728 fmd_hdl_debug(hdl, "DATA_TYPE_INT32 0x%x", i32); 1729 break; 1730 1731 case DATA_TYPE_UINT32: 1732 (void) nvpair_value_uint32(nvp, &i32); 1733 fmd_hdl_debug(hdl, "DATA_TYPE_UINT32 0x%x", i32); 1734 break; 1735 1736 case DATA_TYPE_INT64: 1737 (void) nvpair_value_int64(nvp, (void *)&i64); 1738 fmd_hdl_debug(hdl, "DATA_TYPE_INT64 0x%llx", 1739 (u_longlong_t)i64); 1740 break; 1741 1742 case DATA_TYPE_UINT64: 1743 (void) nvpair_value_uint64(nvp, &i64); 1744 fmd_hdl_debug(hdl, "DATA_TYPE_UINT64 0x%llx", 1745 (u_longlong_t)i64); 1746 break; 1747 1748 case DATA_TYPE_HRTIME: 1749 (void) nvpair_value_hrtime(nvp, (void *)&i64); 1750 fmd_hdl_debug(hdl, "DATA_TYPE_HRTIME 0x%llx", 1751 (u_longlong_t)i64); 1752 break; 1753 1754 case DATA_TYPE_STRING: 1755 (void) nvpair_value_string(nvp, &str); 1756 fmd_hdl_debug(hdl, "DATA_TYPE_STRING \"%s\"", 1757 str ? str : "<NULL>"); 1758 break; 1759 1760 case DATA_TYPE_NVLIST: 1761 fmd_hdl_debug(hdl, "["); 1762 (void) nvpair_value_nvlist(nvp, &cnv); 1763 fab_pr(hdl, NULL, cnv); 1764 fmd_hdl_debug(hdl, " ]"); 1765 break; 1766 1767 case DATA_TYPE_BOOLEAN_ARRAY: 1768 case DATA_TYPE_BYTE_ARRAY: 1769 case DATA_TYPE_INT8_ARRAY: 1770 case DATA_TYPE_UINT8_ARRAY: 1771 case DATA_TYPE_INT16_ARRAY: 1772 case DATA_TYPE_UINT16_ARRAY: 1773 case DATA_TYPE_INT32_ARRAY: 1774 case DATA_TYPE_UINT32_ARRAY: 1775 case DATA_TYPE_INT64_ARRAY: 1776 case DATA_TYPE_UINT64_ARRAY: 1777 case DATA_TYPE_STRING_ARRAY: 1778 fmd_hdl_debug(hdl, "[...]"); 1779 break; 1780 case DATA_TYPE_NVLIST_ARRAY: 1781 arrsize = 0; 1782 (void) nvpair_value_nvlist_array(nvp, &nvlarr, 1783 &arrsize); 1784 1785 for (arri = 0; arri < arrsize; arri++) { 1786 fab_pr(hdl, ep, nvlarr[arri]); 1787 } 1788 1789 break; 1790 case DATA_TYPE_UNKNOWN: 1791 fmd_hdl_debug(hdl, "<unknown>"); 1792 break; 1793 } 1794 } 1795 } 1796 1797 /*ARGSUSED*/ 1798 static void 1799 fab_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class) 1800 { 1801 fab_data_t fab_data = {0}; 1802 1803 if (!fab_valid_topo) 1804 fab_update_topo(hdl); 1805 1806 if (fmd_nvl_class_match(hdl, nvl, "ereport.io.pci.fabric")) { 1807 fmd_hdl_debug(hdl, "PCI ereport received: %s\n", class); 1808 fab_pci_fabric_to_data(hdl, nvl, &fab_data); 1809 fab_xlate_pcie_erpts(hdl, &fab_data); 1810 } else { 1811 fab_pr(hdl, ep, nvl); 1812 fmd_hdl_debug(hdl, "Fire RC ereport received: %s\n", class); 1813 fab_fire_to_data(hdl, nvl, &fab_data); 1814 fab_xlate_fire_erpts(hdl, &fab_data, nvl, class); 1815 fab_xlate_pcie_erpts(hdl, &fab_data); 1816 } 1817 } 1818 1819 /* ARGSUSED */ 1820 static void 1821 fab_topo(fmd_hdl_t *hdl, topo_hdl_t *topo) 1822 { 1823 fab_valid_topo = 0; 1824 } 1825 1826 static const fmd_hdl_ops_t fmd_ops = { 1827 fab_recv, /* fmdo_recv */ 1828 NULL, /* fmdo_timeout */ 1829 NULL, /* fmdo_close */ 1830 NULL, /* fmdo_stats */ 1831 NULL, /* fmdo_gc */ 1832 NULL, /* fmdo_send */ 1833 fab_topo, /* fmdo_topo */ 1834 }; 1835 1836 static const fmd_hdl_info_t fmd_info = { 1837 "Fabric Ereport Translater", "1.0", &fmd_ops, NULL 1838 }; 1839 1840 #define REG_OFF(reg) ((uint32_t)(uint32_t)&fab_data.reg - (uint32_t)&fab_data) 1841 #define SET_TBL(n, err, reg, sz) \ 1842 fab_master_err_tbl[n].erpt_tbl = fab_ ## err ## _erpt_tbl; \ 1843 fab_master_err_tbl[n].reg_offset = REG_OFF(reg); \ 1844 fab_master_err_tbl[n].reg_size = sz; \ 1845 fab_master_err_tbl[n].fab_prep = fab_prep_ ## err ## _erpt; 1846 1847 void 1848 _fmd_init(fmd_hdl_t *hdl) 1849 { 1850 fab_data_t fab_data; 1851 1852 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 1853 return; 1854 1855 /* Init libxml */ 1856 xmlInitParser(); 1857 1858 fab_fmd_xprt = fmd_xprt_open(hdl, FMD_XPRT_RDONLY, NULL, NULL); 1859 fmd_hdl_debug(hdl, "Fabric Translater Started\n"); 1860 1861 /* Setup the master error table */ 1862 fab_master_err_tbl = (fab_err_tbl_t *)calloc(13, 1863 sizeof (fab_err_tbl_t)); 1864 1865 SET_TBL(0, pci, pci_err_status, 16); 1866 SET_TBL(1, pci_bdg, pci_bdg_sec_stat, 16); 1867 SET_TBL(2, pci_bdg_ctl, pci_bdg_ctrl, 16); 1868 SET_TBL(3, pcie_ce, pcie_ce_status, 32); 1869 SET_TBL(4, pcie_ue, pcie_ue_status, 32); 1870 SET_TBL(5, pcie_sue, pcie_sue_status, 32); 1871 SET_TBL(6, pcix, pcix_status, 32); 1872 SET_TBL(7, pcix_bdg_sec, pcix_bdg_sec_stat, 16); 1873 SET_TBL(8, pcix_bdg, pcix_bdg_stat, 32); 1874 SET_TBL(9, pcie_nadv, pcie_err_status, 16); 1875 SET_TBL(10, pcie_rc, pcie_rp_err_status, 32); 1876 SET_TBL(11, pcie_fake_rc, pcie_err_status, 16); 1877 } 1878 1879 void 1880 _fmd_fini(fmd_hdl_t *hdl) 1881 { 1882 /* Fini xpath */ 1883 if (fab_xpathCtx) 1884 xmlXPathFreeContext(fab_xpathCtx); 1885 /* Free xml document */ 1886 if (fab_doc) 1887 xmlFreeDoc(fab_doc); 1888 /* Fini libxml */ 1889 xmlCleanupParser(); 1890 1891 fmd_xprt_close(hdl, fab_fmd_xprt); 1892 } 1893