1f8d2de6bSjchu /* 2f8d2de6bSjchu * CDDL HEADER START 3f8d2de6bSjchu * 4f8d2de6bSjchu * The contents of this file are subject to the terms of the 501689544Sjchu * Common Development and Distribution License (the "License"). 601689544Sjchu * You may not use this file except in compliance with the License. 7f8d2de6bSjchu * 8f8d2de6bSjchu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f8d2de6bSjchu * or http://www.opensolaris.org/os/licensing. 10f8d2de6bSjchu * See the License for the specific language governing permissions 11f8d2de6bSjchu * and limitations under the License. 12f8d2de6bSjchu * 13f8d2de6bSjchu * When distributing Covered Code, include this CDDL HEADER in each 14f8d2de6bSjchu * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f8d2de6bSjchu * If applicable, add the following below this CDDL HEADER, with the 16f8d2de6bSjchu * fields enclosed by brackets "[]" replaced with your own identifying 17f8d2de6bSjchu * information: Portions Copyright [yyyy] [name of copyright owner] 18f8d2de6bSjchu * 19f8d2de6bSjchu * CDDL HEADER END 20f8d2de6bSjchu */ 21f8d2de6bSjchu /* 22*fc256490SJason Beloro * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23f8d2de6bSjchu * Use is subject to license terms. 24f8d2de6bSjchu */ 25f8d2de6bSjchu 26f8d2de6bSjchu /* 27f8d2de6bSjchu * sun4v Fire Error Handling 28f8d2de6bSjchu */ 29f8d2de6bSjchu 30f8d2de6bSjchu #include <sys/types.h> 31f8d2de6bSjchu #include <sys/ddi.h> 32f8d2de6bSjchu #include <sys/sunddi.h> 33eae2e508Skrishnae #include <sys/sunndi.h> 34f8d2de6bSjchu #include <sys/fm/protocol.h> 35f8d2de6bSjchu #include <sys/fm/util.h> 36f8d2de6bSjchu #include <sys/membar.h> 37f8d2de6bSjchu #include "px_obj.h" 38f8d2de6bSjchu #include "px_err.h" 39f8d2de6bSjchu 40*fc256490SJason Beloro static void px_err_fill_pfd(dev_info_t *dip, pf_data_t *pfd_p, 41*fc256490SJason Beloro px_rc_err_t *epkt); 42bf8fc234Set static uint_t px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt); 43bf8fc234Set static int px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, 44*fc256490SJason Beloro px_rc_err_t *epkt, pf_data_t *pfd_p); 45f8d2de6bSjchu 46bf8fc234Set static void px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, 47bf8fc234Set boolean_t is_block_pci, char *msg); 48eae2e508Skrishnae static void px_err_send_epkt_erpt(dev_info_t *dip, px_rc_err_t *epkt, 49eae2e508Skrishnae boolean_t is_block_pci, int err, ddi_fm_error_t *derr, 50eae2e508Skrishnae boolean_t is_valid_epkt); 51bf8fc234Set static int px_cb_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 52bf8fc234Set px_rc_err_t *epkt); 53bf8fc234Set static int px_mmu_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 54bf8fc234Set px_rc_err_t *epkt); 55bf8fc234Set static int px_intr_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 56bf8fc234Set px_rc_err_t *epkt); 574df55fdeSJanie Lu static int px_port_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 58*fc256490SJason Beloro px_rc_err_t *epkt, pf_data_t *pfd_p); 59bf8fc234Set static int px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 60bf8fc234Set px_rc_err_t *epkt); 61bf8fc234Set static int px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, 62bf8fc234Set px_rc_err_t *epkt); 634df55fdeSJanie Lu static int px_port_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, 64*fc256490SJason Beloro px_rc_err_t *epkt, pf_data_t *pfd_p); 65bf8fc234Set static void px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, 66bf8fc234Set px_rc_err_t *epkt); 67bf8fc234Set static int px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, 68bf8fc234Set px_rc_err_t *epkt); 69bf8fc234Set 70bf8fc234Set /* Include the code generated sun4v epkt checking code */ 71bf8fc234Set #include "px_err_gen.c" 72bf8fc234Set 73bf8fc234Set /* 74bf8fc234Set * This variable indicates if we have a hypervisor that could potentially send 75bf8fc234Set * incorrect epkts. We always set this to TRUE for now until we find a way to 76bf8fc234Set * tell if this HV bug has been fixed. 77bf8fc234Set */ 78bf8fc234Set boolean_t px_legacy_epkt = B_TRUE; 79f8d2de6bSjchu 80f8d2de6bSjchu /* 81f8d2de6bSjchu * px_err_cb_intr: 82f8d2de6bSjchu * Interrupt handler for the Host Bus Block. 83f8d2de6bSjchu */ 84f8d2de6bSjchu uint_t 85f8d2de6bSjchu px_err_cb_intr(caddr_t arg) 86f8d2de6bSjchu { 87f8d2de6bSjchu px_fault_t *fault_p = (px_fault_t *)arg; 88f8d2de6bSjchu px_rc_err_t *epkt = (px_rc_err_t *)fault_p->px_intr_payload; 89f8d2de6bSjchu 90f8d2de6bSjchu if (epkt != NULL) { 91bf8fc234Set return (px_err_intr(fault_p, epkt)); 92f8d2de6bSjchu } 93f8d2de6bSjchu 94f8d2de6bSjchu return (DDI_INTR_UNCLAIMED); 95f8d2de6bSjchu } 96f8d2de6bSjchu 97f8d2de6bSjchu /* 98f8d2de6bSjchu * px_err_dmc_pec_intr: 99f8d2de6bSjchu * Interrupt handler for the DMC/PEC block. 100f8d2de6bSjchu */ 101f8d2de6bSjchu uint_t 102f8d2de6bSjchu px_err_dmc_pec_intr(caddr_t arg) 103f8d2de6bSjchu { 104f8d2de6bSjchu px_fault_t *fault_p = (px_fault_t *)arg; 105f8d2de6bSjchu px_rc_err_t *epkt = (px_rc_err_t *)fault_p->px_intr_payload; 106f8d2de6bSjchu 107f8d2de6bSjchu if (epkt != NULL) { 108bf8fc234Set return (px_err_intr(fault_p, epkt)); 109f8d2de6bSjchu } 110f8d2de6bSjchu 111f8d2de6bSjchu return (DDI_INTR_UNCLAIMED); 112f8d2de6bSjchu } 113f8d2de6bSjchu 114f8d2de6bSjchu /* 115bf8fc234Set * px_err_cmn_intr: 116f8d2de6bSjchu * Common function called by trap, mondo and fabric intr. 117f8d2de6bSjchu * This function is more meaningful in sun4u implementation. Kept 118f8d2de6bSjchu * to mirror sun4u call stack. 119f8d2de6bSjchu * o check for safe access 120bf8fc234Set * o create and queue RC info for later use in fabric scan. 121bf8fc234Set * o RUC/WUC, PTLP, MMU Errors(CA), UR 122f8d2de6bSjchu * 123f8d2de6bSjchu * @param px_p leaf in which to check access 124f8d2de6bSjchu * @param derr fm err data structure to be updated 125f8d2de6bSjchu * @param caller PX_TRAP_CALL | PX_INTR_CALL 126f8d2de6bSjchu * @param chkjbc whether to handle hostbus registers (ignored) 127bf8fc234Set * @return err PX_NO_PANIC | PX_PROTECTED | 128bf8fc234Set * PX_PANIC | PX_HW_RESET | PX_EXPECTED 129f8d2de6bSjchu */ 130f8d2de6bSjchu /* ARGSUSED */ 131f8d2de6bSjchu int 132bf8fc234Set px_err_cmn_intr(px_t *px_p, ddi_fm_error_t *derr, int caller, int block) 133f8d2de6bSjchu { 134f8d2de6bSjchu px_err_safeacc_check(px_p, derr); 135e51949e6Sdduvall return (DDI_FM_OK); 1363d9c56a1Set } 1373d9c56a1Set 1383d9c56a1Set /* 139bf8fc234Set * fills RC specific fault data 140bf8fc234Set */ 141bf8fc234Set static void 142*fc256490SJason Beloro px_err_fill_pfd(dev_info_t *dip, pf_data_t *pfd_p, px_rc_err_t *epkt) { 143eae2e508Skrishnae pf_pcie_adv_err_regs_t adv_reg; 144bf8fc234Set int sts = DDI_SUCCESS; 145c85864d8SKrishna Elango pcie_req_id_t fault_bdf = PCIE_INVALID_BDF; 146eae2e508Skrishnae uint64_t fault_addr = 0; 147bf8fc234Set uint16_t s_status = 0; 148bf8fc234Set 149bf8fc234Set /* Add an PCIE PF_DATA Entry */ 150bf8fc234Set if (epkt->rc_descr.block == BLOCK_MMU) { 151bf8fc234Set /* Only PIO Fault Addresses are valid, this is DMA */ 152bf8fc234Set s_status = PCI_STAT_S_TARG_AB; 153bf8fc234Set fault_addr = NULL; 154bf8fc234Set 155*fc256490SJason Beloro if (epkt->rc_descr.H) { 156bf8fc234Set fault_bdf = (pcie_req_id_t)(epkt->hdr[0] >> 16); 157*fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = 158*fc256490SJason Beloro PF_AFFECTED_BDF; 159*fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_bdf = 160*fc256490SJason Beloro fault_bdf; 161*fc256490SJason Beloro } else 162bf8fc234Set sts = DDI_FAILURE; 163bf8fc234Set } else { 164bf8fc234Set px_pec_err_t *pec_p = (px_pec_err_t *)epkt; 165bf8fc234Set uint32_t dir = pec_p->pec_descr.dir; 166bf8fc234Set 167eae2e508Skrishnae adv_reg.pcie_ue_hdr[0] = (uint32_t)(pec_p->hdr[0]); 168eae2e508Skrishnae adv_reg.pcie_ue_hdr[1] = (uint32_t)(pec_p->hdr[0] >> 32); 169eae2e508Skrishnae adv_reg.pcie_ue_hdr[2] = (uint32_t)(pec_p->hdr[1]); 170eae2e508Skrishnae adv_reg.pcie_ue_hdr[3] = (uint32_t)(pec_p->hdr[1] >> 32); 171bf8fc234Set 172bf8fc234Set /* translate RC UR/CA to legacy secondary errors */ 173bf8fc234Set if ((dir == DIR_READ || dir == DIR_WRITE) && 174bf8fc234Set pec_p->pec_descr.U) { 175bf8fc234Set if (pec_p->ue_reg_status & PCIE_AER_UCE_UR) 176bf8fc234Set s_status |= PCI_STAT_R_MAST_AB; 1771ff65112Segillett if (pec_p->ue_reg_status & PCIE_AER_UCE_CA) 178bf8fc234Set s_status |= PCI_STAT_R_TARG_AB; 179bf8fc234Set } 180bf8fc234Set 181bf8fc234Set if (pec_p->ue_reg_status & PCIE_AER_UCE_PTLP) 182bf8fc234Set s_status |= PCI_STAT_PERROR; 183bf8fc234Set 184bf8fc234Set if (pec_p->ue_reg_status & PCIE_AER_UCE_CA) 185bf8fc234Set s_status |= PCI_STAT_S_TARG_AB; 186bf8fc234Set 187eae2e508Skrishnae sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg); 188eae2e508Skrishnae fault_bdf = adv_reg.pcie_ue_tgt_bdf; 189c85864d8SKrishna Elango fault_addr = adv_reg.pcie_ue_tgt_addr; 190*fc256490SJason Beloro /* affected BDF is to be filled in by px_scan_fabric */ 191*fc256490SJason Beloro } 192*fc256490SJason Beloro 193*fc256490SJason Beloro if (sts == DDI_SUCCESS) { 194*fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_bdf = fault_bdf; 195*fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_addr = (uint64_t)fault_addr; 196*fc256490SJason Beloro PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = s_status; 197bf8fc234Set } 198*fc256490SJason Beloro } 199*fc256490SJason Beloro 200*fc256490SJason Beloro /* 201*fc256490SJason Beloro * Convert error severity from PX internal values to PCIe Fabric values. Most 202*fc256490SJason Beloro * are self explanitory, except PX_PROTECTED. PX_PROTECTED will never be 203*fc256490SJason Beloro * returned as is if forgivable. 204*fc256490SJason Beloro */ 205*fc256490SJason Beloro static int px_err_to_fab_sev(int rc_err) { 206*fc256490SJason Beloro int fab_err = 0; 207*fc256490SJason Beloro 208*fc256490SJason Beloro if (rc_err & (PX_HW_RESET | PX_EXPECTED | PX_NO_PANIC)) 209*fc256490SJason Beloro fab_err |= PF_ERR_NO_PANIC; 210bf8fc234Set 211*fc256490SJason Beloro if (rc_err & (PX_PANIC | PX_PROTECTED)) 212*fc256490SJason Beloro fab_err |= PF_ERR_PANIC; 213*fc256490SJason Beloro 214*fc256490SJason Beloro if (rc_err & PX_NO_ERROR) 215*fc256490SJason Beloro fab_err |= PF_ERR_NO_ERROR; 216*fc256490SJason Beloro 217*fc256490SJason Beloro return (fab_err); 218bf8fc234Set } 219bf8fc234Set 220bf8fc234Set /* 221bf8fc234Set * px_err_intr: 222f8d2de6bSjchu * Interrupt handler for the JBC/DMC/PEC block. 223f8d2de6bSjchu * o lock 224f8d2de6bSjchu * o create derr 225f8d2de6bSjchu * o check safe access 226bf8fc234Set * o px_err_check_severity(epkt) 227bf8fc234Set * o pcie_scan_fabric 228f8d2de6bSjchu * o Idle intr state 229f8d2de6bSjchu * o unlock 230f8d2de6bSjchu * o handle error: fatal? fm_panic() : return INTR_CLAIMED) 231f8d2de6bSjchu */ 232f8d2de6bSjchu static uint_t 233bf8fc234Set px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt) 234f8d2de6bSjchu { 235f8d2de6bSjchu px_t *px_p = DIP_TO_STATE(fault_p->px_fh_dip); 236f8d2de6bSjchu dev_info_t *rpdip = px_p->px_dip; 237eae2e508Skrishnae int rc_err, fab_err, msg; 238f8d2de6bSjchu ddi_fm_error_t derr; 239*fc256490SJason Beloro pf_data_t *pfd_p; 240f8d2de6bSjchu 241eae2e508Skrishnae if (px_fm_enter(px_p) != DDI_SUCCESS) 242eae2e508Skrishnae goto done; 243f8d2de6bSjchu 244*fc256490SJason Beloro pfd_p = px_get_pfd(px_p); 245*fc256490SJason Beloro PCIE_ROOT_EH_SRC(pfd_p)->intr_type = PF_INTR_TYPE_INTERNAL; 246*fc256490SJason Beloro PCIE_ROOT_EH_SRC(pfd_p)->intr_data = epkt; 247*fc256490SJason Beloro 248f8d2de6bSjchu /* Create the derr */ 249f8d2de6bSjchu bzero(&derr, sizeof (ddi_fm_error_t)); 250f8d2de6bSjchu derr.fme_version = DDI_FME_VERSION; 251f8d2de6bSjchu derr.fme_ena = fm_ena_generate(epkt->stick, FM_ENA_FMT1); 252f8d2de6bSjchu derr.fme_flag = DDI_FM_ERR_UNEXPECTED; 253f8d2de6bSjchu 254f8d2de6bSjchu /* Basically check for safe access */ 255bf8fc234Set (void) px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_ALL); 256f8d2de6bSjchu 257f8d2de6bSjchu /* Check the severity of this error */ 258*fc256490SJason Beloro rc_err = px_err_epkt_severity(px_p, &derr, epkt, pfd_p); 259*fc256490SJason Beloro 260*fc256490SJason Beloro pfd_p->pe_severity_flags = px_err_to_fab_sev(rc_err); 261*fc256490SJason Beloro /* 262*fc256490SJason Beloro * px_err_epkt_severity needs to populate affected dev 263*fc256490SJason Beloro * Only MMU errors and PCIe errors need this. 264*fc256490SJason Beloro * For MMU we will call pf_handle_lookup, using fault bdf 265*fc256490SJason Beloro * - need to call bdf look up.. 266*fc256490SJason Beloro * For PCIe do not fill in affected.. 267*fc256490SJason Beloro */ 268f8d2de6bSjchu 269bf8fc234Set /* Scan the fabric if the root port is not in drain state. */ 270eae2e508Skrishnae fab_err = px_scan_fabric(px_p, rpdip, &derr); 271f8d2de6bSjchu 272f8d2de6bSjchu /* Set the intr state to idle for the leaf that received the mondo */ 273f8d2de6bSjchu if (px_lib_intr_setstate(rpdip, fault_p->px_fh_sysino, 2741ff65112Segillett INTR_IDLE_STATE) != DDI_SUCCESS) { 275eae2e508Skrishnae px_fm_exit(px_p); 276f8d2de6bSjchu return (DDI_INTR_UNCLAIMED); 277f8d2de6bSjchu } 278f8d2de6bSjchu 279bf8fc234Set switch (epkt->rc_descr.block) { 280bf8fc234Set case BLOCK_MMU: /* FALLTHROUGH */ 281bf8fc234Set case BLOCK_INTR: 282bf8fc234Set msg = PX_RC; 283bf8fc234Set break; 284bf8fc234Set case BLOCK_PCIE: 285bf8fc234Set msg = PX_RP; 286bf8fc234Set break; 287bf8fc234Set case BLOCK_HOSTBUS: /* FALLTHROUGH */ 288bf8fc234Set default: 289bf8fc234Set msg = PX_HB; 290bf8fc234Set break; 291bf8fc234Set } 292bf8fc234Set 293eae2e508Skrishnae px_err_panic(rc_err, msg, fab_err, B_TRUE); 294eae2e508Skrishnae px_fm_exit(px_p); 295eae2e508Skrishnae px_err_panic(rc_err, msg, fab_err, B_FALSE); 296f8d2de6bSjchu 297eae2e508Skrishnae done: 298f8d2de6bSjchu return (DDI_INTR_CLAIMED); 299f8d2de6bSjchu } 300f8d2de6bSjchu 301f8d2de6bSjchu /* 302bf8fc234Set * px_err_epkt_severity: 303f8d2de6bSjchu * Check the severity of the fire error based the epkt received 304f8d2de6bSjchu * 305f8d2de6bSjchu * @param px_p leaf in which to take the snap shot. 306f8d2de6bSjchu * @param derr fm err in which the ereport is to be based on 307f8d2de6bSjchu * @param epkt epkt recevied from HV 308f8d2de6bSjchu */ 309f8d2de6bSjchu static int 310bf8fc234Set px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, px_rc_err_t *epkt, 311*fc256490SJason Beloro pf_data_t *pfd_p) 312f8d2de6bSjchu { 313f8d2de6bSjchu px_pec_t *pec_p = px_p->px_pec_p; 314f8d2de6bSjchu dev_info_t *dip = px_p->px_dip; 315bf8fc234Set boolean_t is_safeacc = B_FALSE; 316bf8fc234Set boolean_t is_block_pci = B_FALSE; 317eae2e508Skrishnae boolean_t is_valid_epkt = B_FALSE; 318f8d2de6bSjchu int err = 0; 319f8d2de6bSjchu 320f8d2de6bSjchu /* Cautious access error handling */ 321bf8fc234Set switch (derr->fme_flag) { 322bf8fc234Set case DDI_FM_ERR_EXPECTED: 323*fc256490SJason Beloro /* 324*fc256490SJason Beloro * For ddi_caut_put treat all events as nonfatal. Here 325*fc256490SJason Beloro * we have the handle and can call ndi_fm_acc_err_set(). 326*fc256490SJason Beloro */ 327*fc256490SJason Beloro derr->fme_status = DDI_FM_NONFATAL; 328*fc256490SJason Beloro ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr); 329*fc256490SJason Beloro is_safeacc = B_TRUE; 330bf8fc234Set break; 331bf8fc234Set case DDI_FM_ERR_PEEK: 332bf8fc234Set case DDI_FM_ERR_POKE: 333bf8fc234Set /* 334bf8fc234Set * For ddi_peek/poke treat all events as nonfatal. 335bf8fc234Set */ 336bf8fc234Set is_safeacc = B_TRUE; 337bf8fc234Set break; 338bf8fc234Set default: 339bf8fc234Set is_safeacc = B_FALSE; 340f8d2de6bSjchu } 341f8d2de6bSjchu 342bf8fc234Set /* 343bf8fc234Set * Older hypervisors in some cases send epkts with incorrect fields. 344bf8fc234Set * We have to handle these "special" epkts correctly. 345bf8fc234Set */ 346bf8fc234Set if (px_legacy_epkt) 347bf8fc234Set px_fix_legacy_epkt(dip, derr, epkt); 348bf8fc234Set 349f8d2de6bSjchu switch (epkt->rc_descr.block) { 350f8d2de6bSjchu case BLOCK_HOSTBUS: 351bf8fc234Set err = px_cb_epkt_severity(dip, derr, epkt); 352*fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = PF_AFFECTED_SELF; 353f8d2de6bSjchu break; 354f8d2de6bSjchu case BLOCK_MMU: 355bf8fc234Set err = px_mmu_epkt_severity(dip, derr, epkt); 356*fc256490SJason Beloro px_err_fill_pfd(dip, pfd_p, epkt); 357f8d2de6bSjchu break; 358f8d2de6bSjchu case BLOCK_INTR: 359bf8fc234Set err = px_intr_epkt_severity(dip, derr, epkt); 360*fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = PF_AFFECTED_SELF; 361f8d2de6bSjchu break; 3624df55fdeSJanie Lu case BLOCK_PORT: 363*fc256490SJason Beloro err = px_port_epkt_severity(dip, derr, epkt, pfd_p); 3644df55fdeSJanie Lu break; 365f8d2de6bSjchu case BLOCK_PCIE: 366bf8fc234Set is_block_pci = B_TRUE; 367bf8fc234Set err = px_pcie_epkt_severity(dip, derr, epkt); 368*fc256490SJason Beloro px_err_fill_pfd(dip, pfd_p, epkt); 369f8d2de6bSjchu break; 370f8d2de6bSjchu default: 371bf8fc234Set err = 0; 372f8d2de6bSjchu } 373f8d2de6bSjchu 374bf8fc234Set if ((err & PX_HW_RESET) || (err & PX_PANIC)) { 375bf8fc234Set if (px_log & PX_PANIC) 376bf8fc234Set px_err_log_handle(dip, epkt, is_block_pci, "PANIC"); 377eae2e508Skrishnae is_valid_epkt = B_TRUE; 378bf8fc234Set } else if (err & PX_PROTECTED) { 379bf8fc234Set if (px_log & PX_PROTECTED) 380bf8fc234Set px_err_log_handle(dip, epkt, is_block_pci, "PROTECTED"); 381eae2e508Skrishnae is_valid_epkt = B_TRUE; 382bf8fc234Set } else if (err & PX_NO_PANIC) { 383bf8fc234Set if (px_log & PX_NO_PANIC) 384bf8fc234Set px_err_log_handle(dip, epkt, is_block_pci, "NO PANIC"); 385eae2e508Skrishnae is_valid_epkt = B_TRUE; 386bf8fc234Set } else if (err & PX_NO_ERROR) { 387bf8fc234Set if (px_log & PX_NO_ERROR) 388bf8fc234Set px_err_log_handle(dip, epkt, is_block_pci, "NO ERROR"); 389eae2e508Skrishnae is_valid_epkt = B_TRUE; 390bf8fc234Set } else if (err == 0) { 391bf8fc234Set px_err_log_handle(dip, epkt, is_block_pci, "UNRECOGNIZED"); 392eae2e508Skrishnae is_valid_epkt = B_FALSE; 393bf8fc234Set 394eae2e508Skrishnae /* Panic on a unrecognized epkt */ 395bf8fc234Set err = PX_PANIC; 396bf8fc234Set } 397bf8fc234Set 398eae2e508Skrishnae px_err_send_epkt_erpt(dip, epkt, is_block_pci, err, derr, 399eae2e508Skrishnae is_valid_epkt); 400eae2e508Skrishnae 401bf8fc234Set /* Readjust the severity as a result of safe access */ 402bf8fc234Set if (is_safeacc && !(err & PX_PANIC) && !(px_die & PX_PROTECTED)) 403bf8fc234Set err = PX_NO_PANIC; 404bf8fc234Set 405f8d2de6bSjchu return (err); 406f8d2de6bSjchu } 407f8d2de6bSjchu 408eae2e508Skrishnae static void 409eae2e508Skrishnae px_err_send_epkt_erpt(dev_info_t *dip, px_rc_err_t *epkt, 410eae2e508Skrishnae boolean_t is_block_pci, int err, ddi_fm_error_t *derr, 411eae2e508Skrishnae boolean_t is_valid_epkt) 412eae2e508Skrishnae { 413eae2e508Skrishnae char buf[FM_MAX_CLASS], descr_buf[1024]; 414eae2e508Skrishnae 415eae2e508Skrishnae /* send ereport for debug purposes */ 416eae2e508Skrishnae (void) snprintf(buf, FM_MAX_CLASS, "%s", PX_FM_RC_UNRECOG); 417eae2e508Skrishnae 418eae2e508Skrishnae if (is_block_pci) { 419eae2e508Skrishnae px_pec_err_t *pec = (px_pec_err_t *)epkt; 420eae2e508Skrishnae (void) snprintf(descr_buf, sizeof (descr_buf), 421eae2e508Skrishnae "%s Epkt contents:\n" 422eae2e508Skrishnae "Block: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d\n" 423eae2e508Skrishnae "I=%d, H=%d, C=%d, U=%d, E=%d, P=%d\n" 424eae2e508Skrishnae "PCI Err Status: 0x%x, PCIe Err Status: 0x%x\n" 425eae2e508Skrishnae "CE Status Reg: 0x%x, UE Status Reg: 0x%x\n" 426eae2e508Skrishnae "HDR1: 0x%lx, HDR2: 0x%lx\n" 427eae2e508Skrishnae "Err Src Reg: 0x%x, Root Err Status: 0x%x\n" 428eae2e508Skrishnae "Err Severity: 0x%x\n", 429eae2e508Skrishnae is_valid_epkt ? "Valid" : "Invalid", 430eae2e508Skrishnae pec->pec_descr.block, pec->pec_descr.dir, 431eae2e508Skrishnae pec->pec_descr.Z, pec->pec_descr.S, 432eae2e508Skrishnae pec->pec_descr.R, pec->pec_descr.I, 433eae2e508Skrishnae pec->pec_descr.H, pec->pec_descr.C, 434eae2e508Skrishnae pec->pec_descr.U, pec->pec_descr.E, 435eae2e508Skrishnae pec->pec_descr.P, pec->pci_err_status, 436eae2e508Skrishnae pec->pcie_err_status, pec->ce_reg_status, 437eae2e508Skrishnae pec->ue_reg_status, pec->hdr[0], 438eae2e508Skrishnae pec->hdr[1], pec->err_src_reg, 439eae2e508Skrishnae pec->root_err_status, err); 440eae2e508Skrishnae 441eae2e508Skrishnae ddi_fm_ereport_post(dip, buf, derr->fme_ena, 442eae2e508Skrishnae DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 443eae2e508Skrishnae EPKT_SYSINO, DATA_TYPE_UINT64, 444eae2e508Skrishnae is_valid_epkt ? pec->sysino : 0, 445eae2e508Skrishnae EPKT_EHDL, DATA_TYPE_UINT64, 446eae2e508Skrishnae is_valid_epkt ? pec->ehdl : 0, 447eae2e508Skrishnae EPKT_STICK, DATA_TYPE_UINT64, 448eae2e508Skrishnae is_valid_epkt ? pec->stick : 0, 4494df55fdeSJanie Lu EPKT_DW0, DATA_TYPE_UINT64, ((uint64_t *)pec)[3], 4504df55fdeSJanie Lu EPKT_DW1, DATA_TYPE_UINT64, ((uint64_t *)pec)[4], 4514df55fdeSJanie Lu EPKT_DW2, DATA_TYPE_UINT64, ((uint64_t *)pec)[5], 4524df55fdeSJanie Lu EPKT_DW3, DATA_TYPE_UINT64, ((uint64_t *)pec)[6], 4534df55fdeSJanie Lu EPKT_DW4, DATA_TYPE_UINT64, ((uint64_t *)pec)[7], 454eae2e508Skrishnae EPKT_PEC_DESCR, DATA_TYPE_STRING, descr_buf); 455eae2e508Skrishnae } else { 456eae2e508Skrishnae (void) snprintf(descr_buf, sizeof (descr_buf), 457eae2e508Skrishnae "%s Epkt contents:\n" 458eae2e508Skrishnae "Block: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 459eae2e508Skrishnae "Dir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d\n" 460eae2e508Skrishnae "M=%d, S=%d, Size: 0x%x, Addr: 0x%lx\n" 461eae2e508Skrishnae "Hdr1: 0x%lx, Hdr2: 0x%lx, Res: 0x%lx\n" 462eae2e508Skrishnae "Err Severity: 0x%x\n", 463eae2e508Skrishnae is_valid_epkt ? "Valid" : "Invalid", 464eae2e508Skrishnae epkt->rc_descr.block, epkt->rc_descr.op, 465eae2e508Skrishnae epkt->rc_descr.phase, epkt->rc_descr.cond, 466eae2e508Skrishnae epkt->rc_descr.dir, epkt->rc_descr.STOP, 467eae2e508Skrishnae epkt->rc_descr.H, epkt->rc_descr.R, 468eae2e508Skrishnae epkt->rc_descr.D, epkt->rc_descr.M, 469eae2e508Skrishnae epkt->rc_descr.S, epkt->size, epkt->addr, 470eae2e508Skrishnae epkt->hdr[0], epkt->hdr[1], epkt->reserved, 471eae2e508Skrishnae err); 472eae2e508Skrishnae 473eae2e508Skrishnae ddi_fm_ereport_post(dip, buf, derr->fme_ena, 474eae2e508Skrishnae DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 475eae2e508Skrishnae EPKT_SYSINO, DATA_TYPE_UINT64, 476eae2e508Skrishnae is_valid_epkt ? epkt->sysino : 0, 477eae2e508Skrishnae EPKT_EHDL, DATA_TYPE_UINT64, 478eae2e508Skrishnae is_valid_epkt ? epkt->ehdl : 0, 479eae2e508Skrishnae EPKT_STICK, DATA_TYPE_UINT64, 480eae2e508Skrishnae is_valid_epkt ? epkt->stick : 0, 4814df55fdeSJanie Lu EPKT_DW0, DATA_TYPE_UINT64, ((uint64_t *)epkt)[3], 4824df55fdeSJanie Lu EPKT_DW1, DATA_TYPE_UINT64, ((uint64_t *)epkt)[4], 4834df55fdeSJanie Lu EPKT_DW2, DATA_TYPE_UINT64, ((uint64_t *)epkt)[5], 4844df55fdeSJanie Lu EPKT_DW3, DATA_TYPE_UINT64, ((uint64_t *)epkt)[6], 4854df55fdeSJanie Lu EPKT_DW4, DATA_TYPE_UINT64, ((uint64_t *)epkt)[7], 486eae2e508Skrishnae EPKT_RC_DESCR, DATA_TYPE_STRING, descr_buf); 487eae2e508Skrishnae } 488eae2e508Skrishnae } 489eae2e508Skrishnae 490bf8fc234Set static void 491bf8fc234Set px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, boolean_t is_block_pci, 492bf8fc234Set char *msg) 493bf8fc234Set { 494bf8fc234Set if (is_block_pci) { 495bf8fc234Set px_pec_err_t *pec = (px_pec_err_t *)epkt; 496bf8fc234Set DBG(DBG_ERR_INTR, dip, 497bf8fc234Set "A PCIe root port error has occured with a severity" 498bf8fc234Set " \"%s\"\n" 499bf8fc234Set "\tBlock: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d, I=%d\n" 500bf8fc234Set "\tH=%d, C=%d, U=%d, E=%d, P=%d\n" 501bf8fc234Set "\tpci_err: 0x%x, pcie_err=0x%x, ce_reg: 0x%x\n" 502bf8fc234Set "\tue_reg: 0x%x, Hdr1: 0x%p, Hdr2: 0x%p\n" 503bf8fc234Set "\terr_src: 0x%x, root_err: 0x%x\n", 504bf8fc234Set msg, pec->pec_descr.block, pec->pec_descr.dir, 505bf8fc234Set pec->pec_descr.Z, pec->pec_descr.S, pec->pec_descr.R, 506bf8fc234Set pec->pec_descr.I, pec->pec_descr.H, pec->pec_descr.C, 507bf8fc234Set pec->pec_descr.U, pec->pec_descr.E, pec->pec_descr.P, 508bf8fc234Set pec->pci_err_status, pec->pcie_err_status, 509bf8fc234Set pec->ce_reg_status, pec->ue_reg_status, pec->hdr[0], 510bf8fc234Set pec->hdr[1], pec->err_src_reg, pec->root_err_status); 511bf8fc234Set } else { 512bf8fc234Set DBG(DBG_ERR_INTR, dip, 513bf8fc234Set "A PCIe root complex error has occured with a severity" 514bf8fc234Set " \"%s\"\n" 515bf8fc234Set "\tBlock: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 516bf8fc234Set "\tDir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d, M=%d\n" 517bf8fc234Set "\tS=%d, Size: 0x%x, Addr: 0x%p\n" 518bf8fc234Set "\tHdr1: 0x%p, Hdr2: 0x%p, Res: 0x%p\n", 519bf8fc234Set msg, epkt->rc_descr.block, epkt->rc_descr.op, 520bf8fc234Set epkt->rc_descr.phase, epkt->rc_descr.cond, 521bf8fc234Set epkt->rc_descr.dir, epkt->rc_descr.STOP, epkt->rc_descr.H, 522bf8fc234Set epkt->rc_descr.R, epkt->rc_descr.D, epkt->rc_descr.M, 523bf8fc234Set epkt->rc_descr.S, epkt->size, epkt->addr, epkt->hdr[0], 524bf8fc234Set epkt->hdr[1], epkt->reserved); 525bf8fc234Set } 526bf8fc234Set } 527bf8fc234Set 528f8d2de6bSjchu /* ARGSUSED */ 529bf8fc234Set static void 530bf8fc234Set px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 531f8d2de6bSjchu { 532bf8fc234Set /* 533bf8fc234Set * We don't have a default case for any of the below switch statements 534bf8fc234Set * since we are ok with the code falling through. 535bf8fc234Set */ 536bf8fc234Set switch (epkt->rc_descr.block) { 537bf8fc234Set case BLOCK_HOSTBUS: 538bf8fc234Set switch (epkt->rc_descr.op) { 539bf8fc234Set case OP_DMA: 540bf8fc234Set switch (epkt->rc_descr.phase) { 541bf8fc234Set case PH_UNKNOWN: 542bf8fc234Set switch (epkt->rc_descr.cond) { 543bf8fc234Set case CND_UNKNOWN: 544bf8fc234Set switch (epkt->rc_descr.dir) { 545bf8fc234Set case DIR_RESERVED: 546bf8fc234Set epkt->rc_descr.dir = DIR_READ; 547bf8fc234Set break; 548bf8fc234Set } /* DIR */ 549bf8fc234Set } /* CND */ 550bf8fc234Set } /* PH */ 551bf8fc234Set } /* OP */ 552f8d2de6bSjchu break; 553bf8fc234Set case BLOCK_MMU: 554bf8fc234Set switch (epkt->rc_descr.op) { 555bf8fc234Set case OP_XLAT: 556bf8fc234Set switch (epkt->rc_descr.phase) { 557bf8fc234Set case PH_DATA: 558bf8fc234Set switch (epkt->rc_descr.cond) { 559bf8fc234Set case CND_PROT: 560bf8fc234Set switch (epkt->rc_descr.dir) { 561bf8fc234Set case DIR_UNKNOWN: 562bf8fc234Set epkt->rc_descr.dir = DIR_WRITE; 563bf8fc234Set break; 564bf8fc234Set } /* DIR */ 565bf8fc234Set } /* CND */ 5663d9c56a1Set break; 567bf8fc234Set case PH_IRR: 568bf8fc234Set switch (epkt->rc_descr.cond) { 569bf8fc234Set case CND_RESERVED: 570bf8fc234Set switch (epkt->rc_descr.dir) { 571bf8fc234Set case DIR_IRR: 572bf8fc234Set epkt->rc_descr.phase = PH_ADDR; 573bf8fc234Set epkt->rc_descr.cond = CND_IRR; 574bf8fc234Set } /* DIR */ 575bf8fc234Set } /* CND */ 576bf8fc234Set } /* PH */ 577bf8fc234Set } /* OP */ 578e51949e6Sdduvall break; 579bf8fc234Set case BLOCK_INTR: 580bf8fc234Set switch (epkt->rc_descr.op) { 581bf8fc234Set case OP_MSIQ: 582bf8fc234Set switch (epkt->rc_descr.phase) { 583bf8fc234Set case PH_UNKNOWN: 584bf8fc234Set switch (epkt->rc_descr.cond) { 585bf8fc234Set case CND_ILL: 586bf8fc234Set switch (epkt->rc_descr.dir) { 587bf8fc234Set case DIR_RESERVED: 588bf8fc234Set epkt->rc_descr.dir = DIR_IRR; 589bf8fc234Set break; 590bf8fc234Set } /* DIR */ 591bf8fc234Set break; 592bf8fc234Set case CND_IRR: 593bf8fc234Set switch (epkt->rc_descr.dir) { 594bf8fc234Set case DIR_IRR: 595bf8fc234Set epkt->rc_descr.cond = CND_OV; 596bf8fc234Set break; 597bf8fc234Set } /* DIR */ 598bf8fc234Set } /* CND */ 599bf8fc234Set } /* PH */ 600bf8fc234Set break; 601bf8fc234Set case OP_RESERVED: 602bf8fc234Set switch (epkt->rc_descr.phase) { 603bf8fc234Set case PH_UNKNOWN: 604bf8fc234Set switch (epkt->rc_descr.cond) { 605bf8fc234Set case CND_ILL: 606bf8fc234Set switch (epkt->rc_descr.dir) { 607bf8fc234Set case DIR_IRR: 608bf8fc234Set epkt->rc_descr.op = OP_MSI32; 609bf8fc234Set epkt->rc_descr.phase = PH_DATA; 610bf8fc234Set break; 611bf8fc234Set } /* DIR */ 612bf8fc234Set } /* CND */ 613bf8fc234Set break; 614bf8fc234Set case PH_DATA: 615bf8fc234Set switch (epkt->rc_descr.cond) { 616bf8fc234Set case CND_INT: 617bf8fc234Set switch (epkt->rc_descr.dir) { 618bf8fc234Set case DIR_UNKNOWN: 619bf8fc234Set epkt->rc_descr.op = OP_MSI32; 620bf8fc234Set break; 621bf8fc234Set } /* DIR */ 622bf8fc234Set } /* CND */ 623bf8fc234Set } /* PH */ 624bf8fc234Set } /* OP */ 625bf8fc234Set } /* BLOCK */ 626bf8fc234Set } 6273d9c56a1Set 628bf8fc234Set /* ARGSUSED */ 629bf8fc234Set static int 630bf8fc234Set px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 631bf8fc234Set { 632bf8fc234Set return (px_err_check_eq(dip)); 633bf8fc234Set } 634bf8fc234Set 6354df55fdeSJanie Lu /* ARGSUSED */ 6364df55fdeSJanie Lu static int 637*fc256490SJason Beloro px_port_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt, 638*fc256490SJason Beloro pf_data_t *pfd_p) 6394df55fdeSJanie Lu { 6404df55fdeSJanie Lu pf_pcie_adv_err_regs_t adv_reg; 6414df55fdeSJanie Lu uint16_t s_status; 6424df55fdeSJanie Lu int sts = PX_PANIC; 6434df55fdeSJanie Lu 6444df55fdeSJanie Lu /* 6454df55fdeSJanie Lu * Check for failed non-posted writes, which are errors that are not 6464df55fdeSJanie Lu * defined in the PCIe spec. If not return panic. 6474df55fdeSJanie Lu */ 6484df55fdeSJanie Lu if (!((epkt->rc_descr.op == OP_PIO) && 6494df55fdeSJanie Lu (epkt->rc_descr.phase == PH_IRR))) { 6504df55fdeSJanie Lu sts = (PX_PANIC); 651*fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = PF_AFFECTED_SELF; 6524df55fdeSJanie Lu goto done; 6534df55fdeSJanie Lu } 6544df55fdeSJanie Lu 6554df55fdeSJanie Lu /* 6564df55fdeSJanie Lu * Gather the error logs, if they do not exist just return with no panic 6574df55fdeSJanie Lu * and let the fabric message take care of the error. 6584df55fdeSJanie Lu */ 6594df55fdeSJanie Lu if (!epkt->rc_descr.H) { 6604df55fdeSJanie Lu sts = (PX_NO_PANIC); 6614df55fdeSJanie Lu goto done; 6624df55fdeSJanie Lu } 6634df55fdeSJanie Lu 6644df55fdeSJanie Lu adv_reg.pcie_ue_hdr[0] = (uint32_t)(epkt->hdr[0]); 6654df55fdeSJanie Lu adv_reg.pcie_ue_hdr[1] = (uint32_t)(epkt->hdr[0] >> 32); 6664df55fdeSJanie Lu adv_reg.pcie_ue_hdr[2] = (uint32_t)(epkt->hdr[1]); 6674df55fdeSJanie Lu adv_reg.pcie_ue_hdr[3] = (uint32_t)(epkt->hdr[1] >> 32); 6684df55fdeSJanie Lu 6694df55fdeSJanie Lu sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg); 6704df55fdeSJanie Lu 6714df55fdeSJanie Lu if (epkt->rc_descr.M) 6724df55fdeSJanie Lu adv_reg.pcie_ue_tgt_addr = epkt->addr; 6734df55fdeSJanie Lu 6744df55fdeSJanie Lu if (!((sts == DDI_SUCCESS) || (epkt->rc_descr.M))) { 6754df55fdeSJanie Lu /* Let the fabric message take care of error */ 6764df55fdeSJanie Lu sts = PX_NO_PANIC; 6774df55fdeSJanie Lu goto done; 6784df55fdeSJanie Lu } 6794df55fdeSJanie Lu 6804df55fdeSJanie Lu /* See if the failed transaction belonged to a hardened driver */ 6814df55fdeSJanie Lu if (pf_hdl_lookup(dip, derr->fme_ena, 6824df55fdeSJanie Lu adv_reg.pcie_ue_tgt_trans, adv_reg.pcie_ue_tgt_addr, 6834df55fdeSJanie Lu adv_reg.pcie_ue_tgt_bdf) == PF_HDL_FOUND) 6844df55fdeSJanie Lu sts = (PX_NO_PANIC); 6854df55fdeSJanie Lu else 6864df55fdeSJanie Lu sts = (PX_PANIC); 6874df55fdeSJanie Lu 6884df55fdeSJanie Lu /* Add pfd to cause a fabric scan */ 6894df55fdeSJanie Lu switch (epkt->rc_descr.cond) { 6904df55fdeSJanie Lu case CND_RCA: 6914df55fdeSJanie Lu s_status = PCI_STAT_R_TARG_AB; 6924df55fdeSJanie Lu break; 6934df55fdeSJanie Lu case CND_RUR: 6944df55fdeSJanie Lu s_status = PCI_STAT_R_MAST_AB; 6954df55fdeSJanie Lu break; 6964df55fdeSJanie Lu } 697*fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_bdf = adv_reg.pcie_ue_tgt_bdf; 698*fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_addr = adv_reg.pcie_ue_tgt_addr; 699*fc256490SJason Beloro PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = s_status; 7004df55fdeSJanie Lu 7014df55fdeSJanie Lu done: 7024df55fdeSJanie Lu return (sts); 7034df55fdeSJanie Lu } 7044df55fdeSJanie Lu 705bf8fc234Set /* ARGSUSED */ 706bf8fc234Set static int 707bf8fc234Set px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 708bf8fc234Set { 709eae2e508Skrishnae px_pec_err_t *pec_p = (px_pec_err_t *)epkt; 710bf8fc234Set px_err_pcie_t *pcie = (px_err_pcie_t *)epkt; 711eae2e508Skrishnae pf_pcie_adv_err_regs_t adv_reg; 712eae2e508Skrishnae int sts; 713bf8fc234Set uint32_t temp; 714f8d2de6bSjchu 715f8d2de6bSjchu /* 716bf8fc234Set * Check for failed PIO Read/Writes, which are errors that are not 717bf8fc234Set * defined in the PCIe spec. 718f8d2de6bSjchu */ 719bf8fc234Set temp = PCIE_AER_UCE_UR | PCIE_AER_UCE_CA; 720eae2e508Skrishnae if (((pec_p->pec_descr.dir == DIR_READ) || 721eae2e508Skrishnae (pec_p->pec_descr.dir == DIR_WRITE)) && 722eae2e508Skrishnae pec_p->pec_descr.U && (pec_p->ue_reg_status & temp)) { 723eae2e508Skrishnae adv_reg.pcie_ue_hdr[0] = (uint32_t)(pec_p->hdr[0]); 724eae2e508Skrishnae adv_reg.pcie_ue_hdr[1] = (uint32_t)(pec_p->hdr[0] >> 32); 725eae2e508Skrishnae adv_reg.pcie_ue_hdr[2] = (uint32_t)(pec_p->hdr[1]); 726eae2e508Skrishnae adv_reg.pcie_ue_hdr[3] = (uint32_t)(pec_p->hdr[1] >> 32); 727eae2e508Skrishnae 728eae2e508Skrishnae sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg); 729eae2e508Skrishnae 730eae2e508Skrishnae if (sts == DDI_SUCCESS && 731eae2e508Skrishnae pf_hdl_lookup(dip, derr->fme_ena, 732eae2e508Skrishnae adv_reg.pcie_ue_tgt_trans, 733eae2e508Skrishnae adv_reg.pcie_ue_tgt_addr, 734eae2e508Skrishnae adv_reg.pcie_ue_tgt_bdf) == PF_HDL_FOUND) 735bf8fc234Set return (PX_NO_PANIC); 736f8d2de6bSjchu else 737bf8fc234Set return (PX_PANIC); 738f8d2de6bSjchu } 739f8d2de6bSjchu 740eae2e508Skrishnae if (!pec_p->pec_descr.C) 741eae2e508Skrishnae pec_p->ce_reg_status = 0; 742eae2e508Skrishnae if (!pec_p->pec_descr.U) 743eae2e508Skrishnae pec_p->ue_reg_status = 0; 744eae2e508Skrishnae if (!pec_p->pec_descr.H) 745eae2e508Skrishnae pec_p->hdr[0] = 0; 746eae2e508Skrishnae if (!pec_p->pec_descr.I) 747eae2e508Skrishnae pec_p->hdr[1] = 0; 748f8d2de6bSjchu 749bf8fc234Set /* 750bf8fc234Set * According to the PCIe spec, there is a first error pointer. If there 751bf8fc234Set * are header logs recorded and there are more than one error, the log 752bf8fc234Set * will belong to the error that the first error pointer points to. 753bf8fc234Set * 754bf8fc234Set * The regs.primary_ue expects a bit number, go through the ue register 755bf8fc234Set * and find the first error that occured. Because the sun4v epkt spec 756bf8fc234Set * does not define this value, the algorithm below gives the lower bit 757bf8fc234Set * priority. 758bf8fc234Set */ 759bf8fc234Set temp = pcie->ue_reg; 760bf8fc234Set if (temp) { 761eae2e508Skrishnae int x; 762bf8fc234Set for (x = 0; !(temp & 0x1); x++) { 763bf8fc234Set temp = temp >> 1; 764bf8fc234Set } 765bf8fc234Set pcie->primary_ue = 1 << x; 766bf8fc234Set } else { 767bf8fc234Set pcie->primary_ue = 0; 7683d9c56a1Set } 769f8d2de6bSjchu 770bf8fc234Set /* Sun4v doesn't log the TX hdr except for CTOs */ 771bf8fc234Set if (pcie->primary_ue == PCIE_AER_UCE_TO) { 772bf8fc234Set pcie->tx_hdr1 = pcie->rx_hdr1; 773bf8fc234Set pcie->tx_hdr2 = pcie->rx_hdr2; 774bf8fc234Set pcie->tx_hdr3 = pcie->rx_hdr3; 775bf8fc234Set pcie->tx_hdr4 = pcie->rx_hdr4; 776bf8fc234Set pcie->rx_hdr1 = 0; 777bf8fc234Set pcie->rx_hdr2 = 0; 778bf8fc234Set pcie->rx_hdr3 = 0; 779bf8fc234Set pcie->rx_hdr4 = 0; 780bf8fc234Set } else { 781bf8fc234Set pcie->tx_hdr1 = 0; 782bf8fc234Set pcie->tx_hdr2 = 0; 783bf8fc234Set pcie->tx_hdr3 = 0; 784bf8fc234Set pcie->tx_hdr4 = 0; 785bf8fc234Set } 786e51949e6Sdduvall 787bf8fc234Set return (px_err_check_pcie(dip, derr, pcie)); 788f8d2de6bSjchu } 789f8d2de6bSjchu 790f8d2de6bSjchu static int 791bf8fc234Set px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 792f8d2de6bSjchu { 793eae2e508Skrishnae uint64_t addr = (uint64_t)epkt->addr; 794c85864d8SKrishna Elango pcie_req_id_t bdf = PCIE_INVALID_BDF; 795f8d2de6bSjchu 796bf8fc234Set if (epkt->rc_descr.H) { 797bf8fc234Set bdf = (uint32_t)((epkt->hdr[0] >> 16) && 0xFFFF); 798f8d2de6bSjchu } 799f8d2de6bSjchu 800eae2e508Skrishnae return (pf_hdl_lookup(dip, derr->fme_ena, PF_ADDR_DMA, addr, 8011ff65112Segillett bdf)); 802f8d2de6bSjchu } 803