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*d0f40dc6SKrishna Elango * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23f8d2de6bSjchu */ 24f8d2de6bSjchu 25f8d2de6bSjchu /* 26f8d2de6bSjchu * sun4v Fire Error Handling 27f8d2de6bSjchu */ 28f8d2de6bSjchu 29f8d2de6bSjchu #include <sys/types.h> 30f8d2de6bSjchu #include <sys/ddi.h> 31f8d2de6bSjchu #include <sys/sunddi.h> 32eae2e508Skrishnae #include <sys/sunndi.h> 33f8d2de6bSjchu #include <sys/fm/protocol.h> 34f8d2de6bSjchu #include <sys/fm/util.h> 35f8d2de6bSjchu #include <sys/membar.h> 36f8d2de6bSjchu #include "px_obj.h" 37f8d2de6bSjchu #include "px_err.h" 38f8d2de6bSjchu 39fc256490SJason Beloro static void px_err_fill_pfd(dev_info_t *dip, pf_data_t *pfd_p, 40fc256490SJason Beloro px_rc_err_t *epkt); 41bf8fc234Set142600 static uint_t px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt); 42bf8fc234Set142600 static int px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, 43fc256490SJason Beloro px_rc_err_t *epkt, pf_data_t *pfd_p); 44f8d2de6bSjchu 45bf8fc234Set142600 static void px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, 46bf8fc234Set142600 boolean_t is_block_pci, char *msg); 47eae2e508Skrishnae static void px_err_send_epkt_erpt(dev_info_t *dip, px_rc_err_t *epkt, 48eae2e508Skrishnae boolean_t is_block_pci, int err, ddi_fm_error_t *derr, 49eae2e508Skrishnae boolean_t is_valid_epkt); 50bf8fc234Set142600 static int px_cb_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 51*d0f40dc6SKrishna Elango px_rc_err_t *epkt, pf_data_t *pfd_p); 52bf8fc234Set142600 static int px_mmu_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 53*d0f40dc6SKrishna Elango px_rc_err_t *epkt, pf_data_t *pfd_p); 54bf8fc234Set142600 static int px_intr_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 55*d0f40dc6SKrishna Elango px_rc_err_t *epkt, pf_data_t *pfd_p); 564df55fdeSJanie Lu static int px_port_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 57fc256490SJason Beloro px_rc_err_t *epkt, pf_data_t *pfd_p); 58bf8fc234Set142600 static int px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 59*d0f40dc6SKrishna Elango px_rc_err_t *epkt, pf_data_t *pfd_p); 60bf8fc234Set142600 static int px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, 61*d0f40dc6SKrishna Elango px_rc_err_t *epkt, pf_data_t *pfd_p); 624df55fdeSJanie Lu static int px_port_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, 63fc256490SJason Beloro px_rc_err_t *epkt, pf_data_t *pfd_p); 64bf8fc234Set142600 static void px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, 65bf8fc234Set142600 px_rc_err_t *epkt); 66bf8fc234Set142600 static int px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, 67bf8fc234Set142600 px_rc_err_t *epkt); 68bf8fc234Set142600 69bf8fc234Set142600 /* Include the code generated sun4v epkt checking code */ 70bf8fc234Set142600 #include "px_err_gen.c" 71bf8fc234Set142600 72bf8fc234Set142600 /* 73bf8fc234Set142600 * This variable indicates if we have a hypervisor that could potentially send 74bf8fc234Set142600 * incorrect epkts. We always set this to TRUE for now until we find a way to 75bf8fc234Set142600 * tell if this HV bug has been fixed. 76bf8fc234Set142600 */ 77bf8fc234Set142600 boolean_t px_legacy_epkt = B_TRUE; 78f8d2de6bSjchu 79f8d2de6bSjchu /* 80f8d2de6bSjchu * px_err_cb_intr: 81f8d2de6bSjchu * Interrupt handler for the Host Bus Block. 82f8d2de6bSjchu */ 83f8d2de6bSjchu uint_t 84f8d2de6bSjchu px_err_cb_intr(caddr_t arg) 85f8d2de6bSjchu { 86f8d2de6bSjchu px_fault_t *fault_p = (px_fault_t *)arg; 87f8d2de6bSjchu px_rc_err_t *epkt = (px_rc_err_t *)fault_p->px_intr_payload; 88f8d2de6bSjchu 89f8d2de6bSjchu if (epkt != NULL) { 90bf8fc234Set142600 return (px_err_intr(fault_p, epkt)); 91f8d2de6bSjchu } 92f8d2de6bSjchu 93f8d2de6bSjchu return (DDI_INTR_UNCLAIMED); 94f8d2de6bSjchu } 95f8d2de6bSjchu 96f8d2de6bSjchu /* 97f8d2de6bSjchu * px_err_dmc_pec_intr: 98f8d2de6bSjchu * Interrupt handler for the DMC/PEC block. 99f8d2de6bSjchu */ 100f8d2de6bSjchu uint_t 101f8d2de6bSjchu px_err_dmc_pec_intr(caddr_t arg) 102f8d2de6bSjchu { 103f8d2de6bSjchu px_fault_t *fault_p = (px_fault_t *)arg; 104f8d2de6bSjchu px_rc_err_t *epkt = (px_rc_err_t *)fault_p->px_intr_payload; 105f8d2de6bSjchu 106f8d2de6bSjchu if (epkt != NULL) { 107bf8fc234Set142600 return (px_err_intr(fault_p, epkt)); 108f8d2de6bSjchu } 109f8d2de6bSjchu 110f8d2de6bSjchu return (DDI_INTR_UNCLAIMED); 111f8d2de6bSjchu } 112f8d2de6bSjchu 113f8d2de6bSjchu /* 114bf8fc234Set142600 * px_err_cmn_intr: 115f8d2de6bSjchu * Common function called by trap, mondo and fabric intr. 116f8d2de6bSjchu * This function is more meaningful in sun4u implementation. Kept 117f8d2de6bSjchu * to mirror sun4u call stack. 118f8d2de6bSjchu * o check for safe access 119bf8fc234Set142600 * o create and queue RC info for later use in fabric scan. 120bf8fc234Set142600 * o RUC/WUC, PTLP, MMU Errors(CA), UR 121f8d2de6bSjchu * 122f8d2de6bSjchu * @param px_p leaf in which to check access 123f8d2de6bSjchu * @param derr fm err data structure to be updated 124f8d2de6bSjchu * @param caller PX_TRAP_CALL | PX_INTR_CALL 125f8d2de6bSjchu * @param chkjbc whether to handle hostbus registers (ignored) 126bf8fc234Set142600 * @return err PX_NO_PANIC | PX_PROTECTED | 127bf8fc234Set142600 * PX_PANIC | PX_HW_RESET | PX_EXPECTED 128f8d2de6bSjchu */ 129f8d2de6bSjchu /* ARGSUSED */ 130f8d2de6bSjchu int 131bf8fc234Set142600 px_err_cmn_intr(px_t *px_p, ddi_fm_error_t *derr, int caller, int block) 132f8d2de6bSjchu { 133f8d2de6bSjchu px_err_safeacc_check(px_p, derr); 1345613d828SKrishna Elango return (PX_NO_ERROR); 135f8d2de6bSjchu } 136f8d2de6bSjchu 137f8d2de6bSjchu /* 138bf8fc234Set142600 * fills RC specific fault data 139bf8fc234Set142600 */ 140bf8fc234Set142600 static void 141fc256490SJason Beloro px_err_fill_pfd(dev_info_t *dip, pf_data_t *pfd_p, px_rc_err_t *epkt) { 142eae2e508Skrishnae pf_pcie_adv_err_regs_t adv_reg; 143c85864d8SKrishna Elango pcie_req_id_t fault_bdf = PCIE_INVALID_BDF; 144eae2e508Skrishnae uint64_t fault_addr = 0; 145bf8fc234Set142600 uint16_t s_status = 0; 146*d0f40dc6SKrishna Elango px_pec_err_t *pec_p; 147*d0f40dc6SKrishna Elango uint32_t dir; 148bf8fc234Set142600 149bf8fc234Set142600 /* Add an PCIE PF_DATA Entry */ 150*d0f40dc6SKrishna Elango switch (epkt->rc_descr.block) { 151*d0f40dc6SKrishna Elango case BLOCK_MMU: 152bf8fc234Set142600 /* Only PIO Fault Addresses are valid, this is DMA */ 153bf8fc234Set142600 s_status = PCI_STAT_S_TARG_AB; 154bf8fc234Set142600 fault_addr = NULL; 155bf8fc234Set142600 156fc256490SJason Beloro if (epkt->rc_descr.H) { 157bf8fc234Set142600 fault_bdf = (pcie_req_id_t)(epkt->hdr[0] >> 16); 158fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = 159fc256490SJason Beloro PF_AFFECTED_BDF; 160fc256490SJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_bdf = 161fc256490SJason Beloro fault_bdf; 1625613d828SKrishna Elango } 163*d0f40dc6SKrishna Elango break; 164*d0f40dc6SKrishna Elango case BLOCK_PCIE: 165*d0f40dc6SKrishna Elango pec_p = (px_pec_err_t *)epkt; 166*d0f40dc6SKrishna Elango dir = pec_p->pec_descr.dir; 167bf8fc234Set142600 168bf8fc234Set142600 /* translate RC UR/CA to legacy secondary errors */ 169bf8fc234Set142600 if ((dir == DIR_READ || dir == DIR_WRITE) && 170bf8fc234Set142600 pec_p->pec_descr.U) { 171bf8fc234Set142600 if (pec_p->ue_reg_status & PCIE_AER_UCE_UR) 172bf8fc234Set142600 s_status |= PCI_STAT_R_MAST_AB; 1731ff65112Segillett if (pec_p->ue_reg_status & PCIE_AER_UCE_CA) 174bf8fc234Set142600 s_status |= PCI_STAT_R_TARG_AB; 175bf8fc234Set142600 } 176bf8fc234Set142600 177bf8fc234Set142600 if (pec_p->ue_reg_status & PCIE_AER_UCE_PTLP) 178bf8fc234Set142600 s_status |= PCI_STAT_PERROR; 179bf8fc234Set142600 180bf8fc234Set142600 if (pec_p->ue_reg_status & PCIE_AER_UCE_CA) 181bf8fc234Set142600 s_status |= PCI_STAT_S_TARG_AB; 182bf8fc234Set142600 1835613d828SKrishna Elango if (pec_p->pec_descr.H) { 1845613d828SKrishna Elango adv_reg.pcie_ue_hdr[0] = (uint32_t)(pec_p->hdr[0] >>32); 1855613d828SKrishna Elango adv_reg.pcie_ue_hdr[1] = (uint32_t)(pec_p->hdr[0]); 1865613d828SKrishna Elango adv_reg.pcie_ue_hdr[2] = (uint32_t)(pec_p->hdr[1] >>32); 1875613d828SKrishna Elango adv_reg.pcie_ue_hdr[3] = (uint32_t)(pec_p->hdr[1]); 1885613d828SKrishna Elango 1895613d828SKrishna Elango if (pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg) == 1905613d828SKrishna Elango DDI_SUCCESS) { 191eae2e508Skrishnae fault_bdf = adv_reg.pcie_ue_tgt_bdf; 192c85864d8SKrishna Elango fault_addr = adv_reg.pcie_ue_tgt_addr; 1935613d828SKrishna Elango /* 1945613d828SKrishna Elango * affected BDF is to be filled in by 1955613d828SKrishna Elango * px_scan_fabric 1965613d828SKrishna Elango */ 1975613d828SKrishna Elango } 1985613d828SKrishna Elango } 199*d0f40dc6SKrishna Elango break; 200*d0f40dc6SKrishna Elango case BLOCK_HOSTBUS: 201*d0f40dc6SKrishna Elango case BLOCK_INTR: 202*d0f40dc6SKrishna Elango case BLOCK_PORT: 203*d0f40dc6SKrishna Elango /* 204*d0f40dc6SKrishna Elango * If the affected device information is available then we 205*d0f40dc6SKrishna Elango * add the affected_bdf to the pfd, so the affected device 206*d0f40dc6SKrishna Elango * will be scanned and added to the error q. This will then 207*d0f40dc6SKrishna Elango * go through the pciev_eh code path and forgive the error 208*d0f40dc6SKrishna Elango * as needed. 209*d0f40dc6SKrishna Elango */ 210*d0f40dc6SKrishna Elango if (PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags == 211*d0f40dc6SKrishna Elango PF_AFFECTED_BDF) 212*d0f40dc6SKrishna Elango fault_bdf = PFD_AFFECTED_DEV(pfd_p)->pe_affected_bdf; 213*d0f40dc6SKrishna Elango 214*d0f40dc6SKrishna Elango break; 215*d0f40dc6SKrishna Elango default: 216*d0f40dc6SKrishna Elango break; 217bf8fc234Set142600 } 218bf8fc234Set142600 219fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_bdf = fault_bdf; 220fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_addr = (uint64_t)fault_addr; 221fc256490SJason Beloro PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = s_status; 222fc256490SJason Beloro } 223fc256490SJason Beloro 224fc256490SJason Beloro /* 225fc256490SJason Beloro * Convert error severity from PX internal values to PCIe Fabric values. Most 226fc256490SJason Beloro * are self explanitory, except PX_PROTECTED. PX_PROTECTED will never be 227fc256490SJason Beloro * returned as is if forgivable. 228fc256490SJason Beloro */ 229*d0f40dc6SKrishna Elango static int 230*d0f40dc6SKrishna Elango px_err_to_fab_sev(int *rc_err) { 231fc256490SJason Beloro int fab_err = 0; 232fc256490SJason Beloro 233*d0f40dc6SKrishna Elango if (*rc_err & px_die) { 234*d0f40dc6SKrishna Elango /* 235*d0f40dc6SKrishna Elango * Let fabric scan decide the final severity of the error. 236*d0f40dc6SKrishna Elango * This is needed incase IOV code needs to forgive the error. 237*d0f40dc6SKrishna Elango */ 238*d0f40dc6SKrishna Elango *rc_err = PX_FABRIC_SCAN; 239*d0f40dc6SKrishna Elango fab_err |= PF_ERR_PANIC; 240*d0f40dc6SKrishna Elango } 241*d0f40dc6SKrishna Elango 242*d0f40dc6SKrishna Elango if (*rc_err & (PX_EXPECTED | PX_NO_PANIC)) 243fc256490SJason Beloro fab_err |= PF_ERR_NO_PANIC; 244fc256490SJason Beloro 245*d0f40dc6SKrishna Elango if (*rc_err & PX_NO_ERROR) 246fc256490SJason Beloro fab_err |= PF_ERR_NO_ERROR; 247fc256490SJason Beloro 248fc256490SJason Beloro return (fab_err); 249bf8fc234Set142600 } 250bf8fc234Set142600 251bf8fc234Set142600 /* 252bf8fc234Set142600 * px_err_intr: 253f8d2de6bSjchu * Interrupt handler for the JBC/DMC/PEC block. 254f8d2de6bSjchu * o lock 255f8d2de6bSjchu * o create derr 256f8d2de6bSjchu * o check safe access 257bf8fc234Set142600 * o px_err_check_severity(epkt) 258bf8fc234Set142600 * o pcie_scan_fabric 259f8d2de6bSjchu * o Idle intr state 260f8d2de6bSjchu * o unlock 261f8d2de6bSjchu * o handle error: fatal? fm_panic() : return INTR_CLAIMED) 262f8d2de6bSjchu */ 263f8d2de6bSjchu static uint_t 264bf8fc234Set142600 px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt) 265f8d2de6bSjchu { 266f8d2de6bSjchu px_t *px_p = DIP_TO_STATE(fault_p->px_fh_dip); 267f8d2de6bSjchu dev_info_t *rpdip = px_p->px_dip; 268*d0f40dc6SKrishna Elango int rc_err, tmp_rc_err, fab_err, msg; 269f8d2de6bSjchu ddi_fm_error_t derr; 270fc256490SJason Beloro pf_data_t *pfd_p; 271f8d2de6bSjchu 272eae2e508Skrishnae if (px_fm_enter(px_p) != DDI_SUCCESS) 273eae2e508Skrishnae goto done; 274f8d2de6bSjchu 275fc256490SJason Beloro pfd_p = px_get_pfd(px_p); 276fc256490SJason Beloro PCIE_ROOT_EH_SRC(pfd_p)->intr_type = PF_INTR_TYPE_INTERNAL; 277fc256490SJason Beloro PCIE_ROOT_EH_SRC(pfd_p)->intr_data = epkt; 278fc256490SJason Beloro 279f8d2de6bSjchu /* Create the derr */ 280f8d2de6bSjchu bzero(&derr, sizeof (ddi_fm_error_t)); 281f8d2de6bSjchu derr.fme_version = DDI_FME_VERSION; 282f8d2de6bSjchu derr.fme_ena = fm_ena_generate(epkt->stick, FM_ENA_FMT1); 283f8d2de6bSjchu derr.fme_flag = DDI_FM_ERR_UNEXPECTED; 284f8d2de6bSjchu 285f8d2de6bSjchu /* Basically check for safe access */ 286bf8fc234Set142600 (void) px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_ALL); 287f8d2de6bSjchu 288f8d2de6bSjchu /* Check the severity of this error */ 289fc256490SJason Beloro rc_err = px_err_epkt_severity(px_p, &derr, epkt, pfd_p); 290fc256490SJason Beloro 291*d0f40dc6SKrishna Elango /* Pass the 'rc_err' severity to the fabric scan code. */ 292*d0f40dc6SKrishna Elango tmp_rc_err = rc_err; 293*d0f40dc6SKrishna Elango pfd_p->pe_severity_flags = px_err_to_fab_sev(&rc_err); 294f8d2de6bSjchu 295*d0f40dc6SKrishna Elango /* Scan the fabric */ 296*d0f40dc6SKrishna Elango if (!(fab_err = px_scan_fabric(px_p, rpdip, &derr))) { 297*d0f40dc6SKrishna Elango /* 298*d0f40dc6SKrishna Elango * Fabric scan didn't occur because of some error condition 299*d0f40dc6SKrishna Elango * such as Root Port being in drain state, so reset rc_err. 300*d0f40dc6SKrishna Elango */ 301*d0f40dc6SKrishna Elango rc_err = tmp_rc_err; 302*d0f40dc6SKrishna Elango } 303f8d2de6bSjchu 304f8d2de6bSjchu /* Set the intr state to idle for the leaf that received the mondo */ 305f8d2de6bSjchu if (px_lib_intr_setstate(rpdip, fault_p->px_fh_sysino, 306f8d2de6bSjchu INTR_IDLE_STATE) != DDI_SUCCESS) { 307eae2e508Skrishnae px_fm_exit(px_p); 308f8d2de6bSjchu return (DDI_INTR_UNCLAIMED); 309f8d2de6bSjchu } 310f8d2de6bSjchu 311bf8fc234Set142600 switch (epkt->rc_descr.block) { 312bf8fc234Set142600 case BLOCK_MMU: /* FALLTHROUGH */ 313bf8fc234Set142600 case BLOCK_INTR: 314bf8fc234Set142600 msg = PX_RC; 315bf8fc234Set142600 break; 316bf8fc234Set142600 case BLOCK_PCIE: 317bf8fc234Set142600 msg = PX_RP; 318bf8fc234Set142600 break; 319bf8fc234Set142600 case BLOCK_HOSTBUS: /* FALLTHROUGH */ 320bf8fc234Set142600 default: 321bf8fc234Set142600 msg = PX_HB; 322bf8fc234Set142600 break; 323bf8fc234Set142600 } 324bf8fc234Set142600 325eae2e508Skrishnae px_err_panic(rc_err, msg, fab_err, B_TRUE); 326eae2e508Skrishnae px_fm_exit(px_p); 327eae2e508Skrishnae px_err_panic(rc_err, msg, fab_err, B_FALSE); 328f8d2de6bSjchu 329eae2e508Skrishnae done: 330f8d2de6bSjchu return (DDI_INTR_CLAIMED); 331f8d2de6bSjchu } 332f8d2de6bSjchu 333f8d2de6bSjchu /* 334bf8fc234Set142600 * px_err_epkt_severity: 335f8d2de6bSjchu * Check the severity of the fire error based the epkt received 336f8d2de6bSjchu * 337f8d2de6bSjchu * @param px_p leaf in which to take the snap shot. 338f8d2de6bSjchu * @param derr fm err in which the ereport is to be based on 339f8d2de6bSjchu * @param epkt epkt recevied from HV 340f8d2de6bSjchu */ 341f8d2de6bSjchu static int 342bf8fc234Set142600 px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, px_rc_err_t *epkt, 343fc256490SJason Beloro pf_data_t *pfd_p) 344f8d2de6bSjchu { 345f8d2de6bSjchu px_pec_t *pec_p = px_p->px_pec_p; 346f8d2de6bSjchu dev_info_t *dip = px_p->px_dip; 347bf8fc234Set142600 boolean_t is_safeacc = B_FALSE; 348bf8fc234Set142600 boolean_t is_block_pci = B_FALSE; 349eae2e508Skrishnae boolean_t is_valid_epkt = B_FALSE; 350f8d2de6bSjchu int err = 0; 351f8d2de6bSjchu 352f8d2de6bSjchu /* Cautious access error handling */ 353bf8fc234Set142600 switch (derr->fme_flag) { 354bf8fc234Set142600 case DDI_FM_ERR_EXPECTED: 355f8d2de6bSjchu /* 356f8d2de6bSjchu * For ddi_caut_put treat all events as nonfatal. Here 357f8d2de6bSjchu * we have the handle and can call ndi_fm_acc_err_set(). 358f8d2de6bSjchu */ 359f8d2de6bSjchu derr->fme_status = DDI_FM_NONFATAL; 360f8d2de6bSjchu ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr); 361bf8fc234Set142600 is_safeacc = B_TRUE; 3623d9c56a1Set142600 break; 363bf8fc234Set142600 case DDI_FM_ERR_PEEK: 364bf8fc234Set142600 case DDI_FM_ERR_POKE: 365bf8fc234Set142600 /* 366bf8fc234Set142600 * For ddi_peek/poke treat all events as nonfatal. 367bf8fc234Set142600 */ 368bf8fc234Set142600 is_safeacc = B_TRUE; 369f8d2de6bSjchu break; 370f8d2de6bSjchu default: 371bf8fc234Set142600 is_safeacc = B_FALSE; 3723d9c56a1Set142600 } 3733d9c56a1Set142600 3743d9c56a1Set142600 /* 375bf8fc234Set142600 * Older hypervisors in some cases send epkts with incorrect fields. 376bf8fc234Set142600 * We have to handle these "special" epkts correctly. 3773d9c56a1Set142600 */ 378bf8fc234Set142600 if (px_legacy_epkt) 379bf8fc234Set142600 px_fix_legacy_epkt(dip, derr, epkt); 3803d9c56a1Set142600 381*d0f40dc6SKrishna Elango /* 382*d0f40dc6SKrishna Elango * The affected device by default is set to 'SELF'. The 'block' 383*d0f40dc6SKrishna Elango * specific error handling below will update this as needed. 384*d0f40dc6SKrishna Elango */ 385*d0f40dc6SKrishna Elango PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = PF_AFFECTED_SELF; 386*d0f40dc6SKrishna Elango 387bf8fc234Set142600 switch (epkt->rc_descr.block) { 388bf8fc234Set142600 case BLOCK_HOSTBUS: 389*d0f40dc6SKrishna Elango err = px_cb_epkt_severity(dip, derr, epkt, pfd_p); 390bf8fc234Set142600 break; 391bf8fc234Set142600 case BLOCK_MMU: 392*d0f40dc6SKrishna Elango err = px_mmu_epkt_severity(dip, derr, epkt, pfd_p); 393bf8fc234Set142600 break; 394bf8fc234Set142600 case BLOCK_INTR: 395*d0f40dc6SKrishna Elango err = px_intr_epkt_severity(dip, derr, epkt, pfd_p); 396bf8fc234Set142600 break; 3974df55fdeSJanie Lu case BLOCK_PORT: 398fc256490SJason Beloro err = px_port_epkt_severity(dip, derr, epkt, pfd_p); 3994df55fdeSJanie Lu break; 400bf8fc234Set142600 case BLOCK_PCIE: 401bf8fc234Set142600 is_block_pci = B_TRUE; 402*d0f40dc6SKrishna Elango err = px_pcie_epkt_severity(dip, derr, epkt, pfd_p); 403e51949e6Sdduvall break; 404e51949e6Sdduvall default: 405bf8fc234Set142600 err = 0; 4063d9c56a1Set142600 } 4073d9c56a1Set142600 408*d0f40dc6SKrishna Elango px_err_fill_pfd(dip, pfd_p, epkt); 409*d0f40dc6SKrishna Elango 410bf8fc234Set142600 if ((err & PX_HW_RESET) || (err & PX_PANIC)) { 411bf8fc234Set142600 if (px_log & PX_PANIC) 412bf8fc234Set142600 px_err_log_handle(dip, epkt, is_block_pci, "PANIC"); 413eae2e508Skrishnae is_valid_epkt = B_TRUE; 414bf8fc234Set142600 } else if (err & PX_PROTECTED) { 415bf8fc234Set142600 if (px_log & PX_PROTECTED) 416bf8fc234Set142600 px_err_log_handle(dip, epkt, is_block_pci, "PROTECTED"); 417eae2e508Skrishnae is_valid_epkt = B_TRUE; 418bf8fc234Set142600 } else if (err & PX_NO_PANIC) { 419bf8fc234Set142600 if (px_log & PX_NO_PANIC) 420bf8fc234Set142600 px_err_log_handle(dip, epkt, is_block_pci, "NO PANIC"); 421eae2e508Skrishnae is_valid_epkt = B_TRUE; 422bf8fc234Set142600 } else if (err & PX_NO_ERROR) { 423bf8fc234Set142600 if (px_log & PX_NO_ERROR) 424bf8fc234Set142600 px_err_log_handle(dip, epkt, is_block_pci, "NO ERROR"); 425eae2e508Skrishnae is_valid_epkt = B_TRUE; 426bf8fc234Set142600 } else if (err == 0) { 427bf8fc234Set142600 px_err_log_handle(dip, epkt, is_block_pci, "UNRECOGNIZED"); 428eae2e508Skrishnae is_valid_epkt = B_FALSE; 429e51949e6Sdduvall 430eae2e508Skrishnae /* Panic on a unrecognized epkt */ 431eae2e508Skrishnae err = PX_PANIC; 432eae2e508Skrishnae } 433eae2e508Skrishnae 434eae2e508Skrishnae px_err_send_epkt_erpt(dip, epkt, is_block_pci, err, derr, 435eae2e508Skrishnae is_valid_epkt); 436eae2e508Skrishnae 437eae2e508Skrishnae /* Readjust the severity as a result of safe access */ 438eae2e508Skrishnae if (is_safeacc && !(err & PX_PANIC) && !(px_die & PX_PROTECTED)) 439eae2e508Skrishnae err = PX_NO_PANIC; 440eae2e508Skrishnae 441eae2e508Skrishnae return (err); 442eae2e508Skrishnae } 443eae2e508Skrishnae 444eae2e508Skrishnae static void 445eae2e508Skrishnae px_err_send_epkt_erpt(dev_info_t *dip, px_rc_err_t *epkt, 446eae2e508Skrishnae boolean_t is_block_pci, int err, ddi_fm_error_t *derr, 447eae2e508Skrishnae boolean_t is_valid_epkt) 448eae2e508Skrishnae { 449eae2e508Skrishnae char buf[FM_MAX_CLASS], descr_buf[1024]; 450eae2e508Skrishnae 451eae2e508Skrishnae /* send ereport for debug purposes */ 452bf8fc234Set142600 (void) snprintf(buf, FM_MAX_CLASS, "%s", PX_FM_RC_UNRECOG); 453e51949e6Sdduvall 454bf8fc234Set142600 if (is_block_pci) { 455e51949e6Sdduvall px_pec_err_t *pec = (px_pec_err_t *)epkt; 456bf8fc234Set142600 (void) snprintf(descr_buf, sizeof (descr_buf), 457eae2e508Skrishnae "%s Epkt contents:\n" 458bf8fc234Set142600 "Block: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d\n" 459bf8fc234Set142600 "I=%d, H=%d, C=%d, U=%d, E=%d, P=%d\n" 460bf8fc234Set142600 "PCI Err Status: 0x%x, PCIe Err Status: 0x%x\n" 461bf8fc234Set142600 "CE Status Reg: 0x%x, UE Status Reg: 0x%x\n" 462bf8fc234Set142600 "HDR1: 0x%lx, HDR2: 0x%lx\n" 463eae2e508Skrishnae "Err Src Reg: 0x%x, Root Err Status: 0x%x\n" 464eae2e508Skrishnae "Err Severity: 0x%x\n", 465eae2e508Skrishnae is_valid_epkt ? "Valid" : "Invalid", 466bf8fc234Set142600 pec->pec_descr.block, pec->pec_descr.dir, 467bf8fc234Set142600 pec->pec_descr.Z, pec->pec_descr.S, 468bf8fc234Set142600 pec->pec_descr.R, pec->pec_descr.I, 469bf8fc234Set142600 pec->pec_descr.H, pec->pec_descr.C, 470bf8fc234Set142600 pec->pec_descr.U, pec->pec_descr.E, 471bf8fc234Set142600 pec->pec_descr.P, pec->pci_err_status, 472bf8fc234Set142600 pec->pcie_err_status, pec->ce_reg_status, 473bf8fc234Set142600 pec->ue_reg_status, pec->hdr[0], 474bf8fc234Set142600 pec->hdr[1], pec->err_src_reg, 475eae2e508Skrishnae pec->root_err_status, err); 476bf8fc234Set142600 477bf8fc234Set142600 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 478bf8fc234Set142600 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 479eae2e508Skrishnae EPKT_SYSINO, DATA_TYPE_UINT64, 480eae2e508Skrishnae is_valid_epkt ? pec->sysino : 0, 481eae2e508Skrishnae EPKT_EHDL, DATA_TYPE_UINT64, 482eae2e508Skrishnae is_valid_epkt ? pec->ehdl : 0, 483eae2e508Skrishnae EPKT_STICK, DATA_TYPE_UINT64, 484eae2e508Skrishnae is_valid_epkt ? pec->stick : 0, 4854df55fdeSJanie Lu EPKT_DW0, DATA_TYPE_UINT64, ((uint64_t *)pec)[3], 4864df55fdeSJanie Lu EPKT_DW1, DATA_TYPE_UINT64, ((uint64_t *)pec)[4], 4874df55fdeSJanie Lu EPKT_DW2, DATA_TYPE_UINT64, ((uint64_t *)pec)[5], 4884df55fdeSJanie Lu EPKT_DW3, DATA_TYPE_UINT64, ((uint64_t *)pec)[6], 4894df55fdeSJanie Lu EPKT_DW4, DATA_TYPE_UINT64, ((uint64_t *)pec)[7], 490bf8fc234Set142600 EPKT_PEC_DESCR, DATA_TYPE_STRING, descr_buf); 491bf8fc234Set142600 } else { 492bf8fc234Set142600 (void) snprintf(descr_buf, sizeof (descr_buf), 493eae2e508Skrishnae "%s Epkt contents:\n" 494bf8fc234Set142600 "Block: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 495bf8fc234Set142600 "Dir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d\n" 496bf8fc234Set142600 "M=%d, S=%d, Size: 0x%x, Addr: 0x%lx\n" 497eae2e508Skrishnae "Hdr1: 0x%lx, Hdr2: 0x%lx, Res: 0x%lx\n" 498eae2e508Skrishnae "Err Severity: 0x%x\n", 499eae2e508Skrishnae is_valid_epkt ? "Valid" : "Invalid", 500bf8fc234Set142600 epkt->rc_descr.block, epkt->rc_descr.op, 501bf8fc234Set142600 epkt->rc_descr.phase, epkt->rc_descr.cond, 502bf8fc234Set142600 epkt->rc_descr.dir, epkt->rc_descr.STOP, 503bf8fc234Set142600 epkt->rc_descr.H, epkt->rc_descr.R, 504bf8fc234Set142600 epkt->rc_descr.D, epkt->rc_descr.M, 505bf8fc234Set142600 epkt->rc_descr.S, epkt->size, epkt->addr, 506eae2e508Skrishnae epkt->hdr[0], epkt->hdr[1], epkt->reserved, 507eae2e508Skrishnae err); 508bf8fc234Set142600 509bf8fc234Set142600 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 510bf8fc234Set142600 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 511eae2e508Skrishnae EPKT_SYSINO, DATA_TYPE_UINT64, 512eae2e508Skrishnae is_valid_epkt ? epkt->sysino : 0, 513eae2e508Skrishnae EPKT_EHDL, DATA_TYPE_UINT64, 514eae2e508Skrishnae is_valid_epkt ? epkt->ehdl : 0, 515eae2e508Skrishnae EPKT_STICK, DATA_TYPE_UINT64, 516eae2e508Skrishnae is_valid_epkt ? epkt->stick : 0, 5174df55fdeSJanie Lu EPKT_DW0, DATA_TYPE_UINT64, ((uint64_t *)epkt)[3], 5184df55fdeSJanie Lu EPKT_DW1, DATA_TYPE_UINT64, ((uint64_t *)epkt)[4], 5194df55fdeSJanie Lu EPKT_DW2, DATA_TYPE_UINT64, ((uint64_t *)epkt)[5], 5204df55fdeSJanie Lu EPKT_DW3, DATA_TYPE_UINT64, ((uint64_t *)epkt)[6], 5214df55fdeSJanie Lu EPKT_DW4, DATA_TYPE_UINT64, ((uint64_t *)epkt)[7], 522bf8fc234Set142600 EPKT_RC_DESCR, DATA_TYPE_STRING, descr_buf); 523e51949e6Sdduvall } 524bf8fc234Set142600 } 525bf8fc234Set142600 526bf8fc234Set142600 static void 527bf8fc234Set142600 px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, boolean_t is_block_pci, 528bf8fc234Set142600 char *msg) 529bf8fc234Set142600 { 530bf8fc234Set142600 if (is_block_pci) { 531bf8fc234Set142600 px_pec_err_t *pec = (px_pec_err_t *)epkt; 532bf8fc234Set142600 DBG(DBG_ERR_INTR, dip, 533bf8fc234Set142600 "A PCIe root port error has occured with a severity" 534bf8fc234Set142600 " \"%s\"\n" 535bf8fc234Set142600 "\tBlock: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d, I=%d\n" 536bf8fc234Set142600 "\tH=%d, C=%d, U=%d, E=%d, P=%d\n" 537bf8fc234Set142600 "\tpci_err: 0x%x, pcie_err=0x%x, ce_reg: 0x%x\n" 538bf8fc234Set142600 "\tue_reg: 0x%x, Hdr1: 0x%p, Hdr2: 0x%p\n" 539bf8fc234Set142600 "\terr_src: 0x%x, root_err: 0x%x\n", 540bf8fc234Set142600 msg, pec->pec_descr.block, pec->pec_descr.dir, 541bf8fc234Set142600 pec->pec_descr.Z, pec->pec_descr.S, pec->pec_descr.R, 542bf8fc234Set142600 pec->pec_descr.I, pec->pec_descr.H, pec->pec_descr.C, 543bf8fc234Set142600 pec->pec_descr.U, pec->pec_descr.E, pec->pec_descr.P, 544bf8fc234Set142600 pec->pci_err_status, pec->pcie_err_status, 545bf8fc234Set142600 pec->ce_reg_status, pec->ue_reg_status, pec->hdr[0], 546bf8fc234Set142600 pec->hdr[1], pec->err_src_reg, pec->root_err_status); 547bf8fc234Set142600 } else { 548bf8fc234Set142600 DBG(DBG_ERR_INTR, dip, 549bf8fc234Set142600 "A PCIe root complex error has occured with a severity" 550bf8fc234Set142600 " \"%s\"\n" 551bf8fc234Set142600 "\tBlock: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 552bf8fc234Set142600 "\tDir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d, M=%d\n" 553bf8fc234Set142600 "\tS=%d, Size: 0x%x, Addr: 0x%p\n" 554bf8fc234Set142600 "\tHdr1: 0x%p, Hdr2: 0x%p, Res: 0x%p\n", 555bf8fc234Set142600 msg, epkt->rc_descr.block, epkt->rc_descr.op, 556bf8fc234Set142600 epkt->rc_descr.phase, epkt->rc_descr.cond, 557bf8fc234Set142600 epkt->rc_descr.dir, epkt->rc_descr.STOP, epkt->rc_descr.H, 558bf8fc234Set142600 epkt->rc_descr.R, epkt->rc_descr.D, epkt->rc_descr.M, 559bf8fc234Set142600 epkt->rc_descr.S, epkt->size, epkt->addr, epkt->hdr[0], 560bf8fc234Set142600 epkt->hdr[1], epkt->reserved); 561bf8fc234Set142600 } 562bf8fc234Set142600 } 563bf8fc234Set142600 564bf8fc234Set142600 /* ARGSUSED */ 565bf8fc234Set142600 static void 566bf8fc234Set142600 px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 567bf8fc234Set142600 { 568bf8fc234Set142600 /* 569bf8fc234Set142600 * We don't have a default case for any of the below switch statements 570bf8fc234Set142600 * since we are ok with the code falling through. 571bf8fc234Set142600 */ 572bf8fc234Set142600 switch (epkt->rc_descr.block) { 573bf8fc234Set142600 case BLOCK_HOSTBUS: 574bf8fc234Set142600 switch (epkt->rc_descr.op) { 575bf8fc234Set142600 case OP_DMA: 576bf8fc234Set142600 switch (epkt->rc_descr.phase) { 577bf8fc234Set142600 case PH_UNKNOWN: 578bf8fc234Set142600 switch (epkt->rc_descr.cond) { 579bf8fc234Set142600 case CND_UNKNOWN: 580bf8fc234Set142600 switch (epkt->rc_descr.dir) { 581bf8fc234Set142600 case DIR_RESERVED: 582bf8fc234Set142600 epkt->rc_descr.dir = DIR_READ; 583bf8fc234Set142600 break; 584bf8fc234Set142600 } /* DIR */ 585bf8fc234Set142600 } /* CND */ 586bf8fc234Set142600 } /* PH */ 587bf8fc234Set142600 } /* OP */ 588bf8fc234Set142600 break; 589bf8fc234Set142600 case BLOCK_MMU: 590bf8fc234Set142600 switch (epkt->rc_descr.op) { 591bf8fc234Set142600 case OP_XLAT: 592bf8fc234Set142600 switch (epkt->rc_descr.phase) { 593bf8fc234Set142600 case PH_DATA: 594bf8fc234Set142600 switch (epkt->rc_descr.cond) { 595bf8fc234Set142600 case CND_PROT: 596bf8fc234Set142600 switch (epkt->rc_descr.dir) { 597bf8fc234Set142600 case DIR_UNKNOWN: 598bf8fc234Set142600 epkt->rc_descr.dir = DIR_WRITE; 599bf8fc234Set142600 break; 600bf8fc234Set142600 } /* DIR */ 601bf8fc234Set142600 } /* CND */ 602bf8fc234Set142600 break; 603bf8fc234Set142600 case PH_IRR: 604bf8fc234Set142600 switch (epkt->rc_descr.cond) { 605bf8fc234Set142600 case CND_RESERVED: 606bf8fc234Set142600 switch (epkt->rc_descr.dir) { 607bf8fc234Set142600 case DIR_IRR: 608bf8fc234Set142600 epkt->rc_descr.phase = PH_ADDR; 609bf8fc234Set142600 epkt->rc_descr.cond = CND_IRR; 610bf8fc234Set142600 } /* DIR */ 611bf8fc234Set142600 } /* CND */ 612bf8fc234Set142600 } /* PH */ 613bf8fc234Set142600 } /* OP */ 614bf8fc234Set142600 break; 615bf8fc234Set142600 case BLOCK_INTR: 616bf8fc234Set142600 switch (epkt->rc_descr.op) { 617bf8fc234Set142600 case OP_MSIQ: 618bf8fc234Set142600 switch (epkt->rc_descr.phase) { 619bf8fc234Set142600 case PH_UNKNOWN: 620bf8fc234Set142600 switch (epkt->rc_descr.cond) { 621bf8fc234Set142600 case CND_ILL: 622bf8fc234Set142600 switch (epkt->rc_descr.dir) { 623bf8fc234Set142600 case DIR_RESERVED: 624bf8fc234Set142600 epkt->rc_descr.dir = DIR_IRR; 625bf8fc234Set142600 break; 626bf8fc234Set142600 } /* DIR */ 627bf8fc234Set142600 break; 628bf8fc234Set142600 case CND_IRR: 629bf8fc234Set142600 switch (epkt->rc_descr.dir) { 630bf8fc234Set142600 case DIR_IRR: 631bf8fc234Set142600 epkt->rc_descr.cond = CND_OV; 632bf8fc234Set142600 break; 633bf8fc234Set142600 } /* DIR */ 634bf8fc234Set142600 } /* CND */ 635bf8fc234Set142600 } /* PH */ 636bf8fc234Set142600 break; 637bf8fc234Set142600 case OP_RESERVED: 638bf8fc234Set142600 switch (epkt->rc_descr.phase) { 639bf8fc234Set142600 case PH_UNKNOWN: 640bf8fc234Set142600 switch (epkt->rc_descr.cond) { 641bf8fc234Set142600 case CND_ILL: 642bf8fc234Set142600 switch (epkt->rc_descr.dir) { 643bf8fc234Set142600 case DIR_IRR: 644bf8fc234Set142600 epkt->rc_descr.op = OP_MSI32; 645bf8fc234Set142600 epkt->rc_descr.phase = PH_DATA; 646bf8fc234Set142600 break; 647bf8fc234Set142600 } /* DIR */ 648bf8fc234Set142600 } /* CND */ 649bf8fc234Set142600 break; 650bf8fc234Set142600 case PH_DATA: 651bf8fc234Set142600 switch (epkt->rc_descr.cond) { 652bf8fc234Set142600 case CND_INT: 653bf8fc234Set142600 switch (epkt->rc_descr.dir) { 654bf8fc234Set142600 case DIR_UNKNOWN: 655bf8fc234Set142600 epkt->rc_descr.op = OP_MSI32; 656bf8fc234Set142600 break; 657bf8fc234Set142600 } /* DIR */ 658bf8fc234Set142600 } /* CND */ 659bf8fc234Set142600 } /* PH */ 660bf8fc234Set142600 } /* OP */ 661bf8fc234Set142600 } /* BLOCK */ 662bf8fc234Set142600 } 663bf8fc234Set142600 664bf8fc234Set142600 /* ARGSUSED */ 665bf8fc234Set142600 static int 666*d0f40dc6SKrishna Elango px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt, 667*d0f40dc6SKrishna Elango pf_data_t *pfd_p) 668bf8fc234Set142600 { 669bf8fc234Set142600 return (px_err_check_eq(dip)); 670bf8fc234Set142600 } 671bf8fc234Set142600 672bf8fc234Set142600 /* ARGSUSED */ 673bf8fc234Set142600 static int 674fc256490SJason Beloro px_port_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt, 675fc256490SJason Beloro pf_data_t *pfd_p) 6764df55fdeSJanie Lu { 6774df55fdeSJanie Lu pf_pcie_adv_err_regs_t adv_reg; 6784df55fdeSJanie Lu uint16_t s_status; 6794df55fdeSJanie Lu int sts = PX_PANIC; 6804df55fdeSJanie Lu 6814df55fdeSJanie Lu /* 6824df55fdeSJanie Lu * Check for failed non-posted writes, which are errors that are not 6834df55fdeSJanie Lu * defined in the PCIe spec. If not return panic. 6844df55fdeSJanie Lu */ 6854df55fdeSJanie Lu if (!((epkt->rc_descr.op == OP_PIO) && 6864df55fdeSJanie Lu (epkt->rc_descr.phase == PH_IRR))) { 6874df55fdeSJanie Lu sts = (PX_PANIC); 6884df55fdeSJanie Lu goto done; 6894df55fdeSJanie Lu } 6904df55fdeSJanie Lu 6914df55fdeSJanie Lu /* 6924df55fdeSJanie Lu * Gather the error logs, if they do not exist just return with no panic 6934df55fdeSJanie Lu * and let the fabric message take care of the error. 6944df55fdeSJanie Lu */ 6954df55fdeSJanie Lu if (!epkt->rc_descr.H) { 6964df55fdeSJanie Lu sts = (PX_NO_PANIC); 6974df55fdeSJanie Lu goto done; 6984df55fdeSJanie Lu } 6994df55fdeSJanie Lu 7005613d828SKrishna Elango adv_reg.pcie_ue_hdr[0] = (uint32_t)(epkt->hdr[0] >> 32); 7015613d828SKrishna Elango adv_reg.pcie_ue_hdr[1] = (uint32_t)(epkt->hdr[0]); 7025613d828SKrishna Elango adv_reg.pcie_ue_hdr[2] = (uint32_t)(epkt->hdr[1] >> 32); 7035613d828SKrishna Elango adv_reg.pcie_ue_hdr[3] = (uint32_t)(epkt->hdr[1]); 7044df55fdeSJanie Lu 7054df55fdeSJanie Lu sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg); 7064df55fdeSJanie Lu 7074df55fdeSJanie Lu if (epkt->rc_descr.M) 7084df55fdeSJanie Lu adv_reg.pcie_ue_tgt_addr = epkt->addr; 7094df55fdeSJanie Lu 7104df55fdeSJanie Lu if (!((sts == DDI_SUCCESS) || (epkt->rc_descr.M))) { 7114df55fdeSJanie Lu /* Let the fabric message take care of error */ 7124df55fdeSJanie Lu sts = PX_NO_PANIC; 7134df55fdeSJanie Lu goto done; 7144df55fdeSJanie Lu } 7154df55fdeSJanie Lu 7164df55fdeSJanie Lu /* See if the failed transaction belonged to a hardened driver */ 7174df55fdeSJanie Lu if (pf_hdl_lookup(dip, derr->fme_ena, 7184df55fdeSJanie Lu adv_reg.pcie_ue_tgt_trans, adv_reg.pcie_ue_tgt_addr, 7194df55fdeSJanie Lu adv_reg.pcie_ue_tgt_bdf) == PF_HDL_FOUND) 7204df55fdeSJanie Lu sts = (PX_NO_PANIC); 7214df55fdeSJanie Lu else 7224df55fdeSJanie Lu sts = (PX_PANIC); 7234df55fdeSJanie Lu 7244df55fdeSJanie Lu /* Add pfd to cause a fabric scan */ 7254df55fdeSJanie Lu switch (epkt->rc_descr.cond) { 7264df55fdeSJanie Lu case CND_RCA: 7274df55fdeSJanie Lu s_status = PCI_STAT_R_TARG_AB; 7284df55fdeSJanie Lu break; 7294df55fdeSJanie Lu case CND_RUR: 7304df55fdeSJanie Lu s_status = PCI_STAT_R_MAST_AB; 7314df55fdeSJanie Lu break; 7324df55fdeSJanie Lu } 733fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_bdf = adv_reg.pcie_ue_tgt_bdf; 734fc256490SJason Beloro PCIE_ROOT_FAULT(pfd_p)->scan_addr = adv_reg.pcie_ue_tgt_addr; 735fc256490SJason Beloro PCI_BDG_ERR_REG(pfd_p)->pci_bdg_sec_stat = s_status; 7364df55fdeSJanie Lu 737*d0f40dc6SKrishna Elango PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags = PF_AFFECTED_BDF; 738*d0f40dc6SKrishna Elango PFD_AFFECTED_DEV(pfd_p)->pe_affected_bdf = adv_reg.pcie_ue_tgt_bdf; 739*d0f40dc6SKrishna Elango 7404df55fdeSJanie Lu done: 7414df55fdeSJanie Lu return (sts); 7424df55fdeSJanie Lu } 7434df55fdeSJanie Lu 7444df55fdeSJanie Lu /* ARGSUSED */ 7454df55fdeSJanie Lu static int 746*d0f40dc6SKrishna Elango px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt, 747*d0f40dc6SKrishna Elango pf_data_t *pfd_p) 748bf8fc234Set142600 { 749eae2e508Skrishnae px_pec_err_t *pec_p = (px_pec_err_t *)epkt; 750bf8fc234Set142600 px_err_pcie_t *pcie = (px_err_pcie_t *)epkt; 751eae2e508Skrishnae pf_pcie_adv_err_regs_t adv_reg; 752eae2e508Skrishnae int sts; 753bf8fc234Set142600 uint32_t temp; 754bf8fc234Set142600 755bf8fc234Set142600 /* 756bf8fc234Set142600 * Check for failed PIO Read/Writes, which are errors that are not 757bf8fc234Set142600 * defined in the PCIe spec. 758bf8fc234Set142600 */ 7595613d828SKrishna Elango 760bf8fc234Set142600 temp = PCIE_AER_UCE_UR | PCIE_AER_UCE_CA; 761eae2e508Skrishnae if (((pec_p->pec_descr.dir == DIR_READ) || 762eae2e508Skrishnae (pec_p->pec_descr.dir == DIR_WRITE)) && 763eae2e508Skrishnae pec_p->pec_descr.U && (pec_p->ue_reg_status & temp)) { 7645613d828SKrishna Elango 7655613d828SKrishna Elango adv_reg.pcie_ue_hdr[0] = (uint32_t)(pec_p->hdr[0] >> 32); 7665613d828SKrishna Elango adv_reg.pcie_ue_hdr[1] = (uint32_t)(pec_p->hdr[0]); 7675613d828SKrishna Elango adv_reg.pcie_ue_hdr[2] = (uint32_t)(pec_p->hdr[1] >> 32); 7685613d828SKrishna Elango adv_reg.pcie_ue_hdr[3] = (uint32_t)(pec_p->hdr[1]); 769bf8fc234Set142600 770eae2e508Skrishnae sts = pf_tlp_decode(PCIE_DIP2BUS(dip), &adv_reg); 771eae2e508Skrishnae 772eae2e508Skrishnae if (sts == DDI_SUCCESS && 773eae2e508Skrishnae pf_hdl_lookup(dip, derr->fme_ena, 774eae2e508Skrishnae adv_reg.pcie_ue_tgt_trans, 775eae2e508Skrishnae adv_reg.pcie_ue_tgt_addr, 776eae2e508Skrishnae adv_reg.pcie_ue_tgt_bdf) == PF_HDL_FOUND) 777bf8fc234Set142600 return (PX_NO_PANIC); 778bf8fc234Set142600 else 779bf8fc234Set142600 return (PX_PANIC); 780bf8fc234Set142600 } 781bf8fc234Set142600 782eae2e508Skrishnae if (!pec_p->pec_descr.C) 783eae2e508Skrishnae pec_p->ce_reg_status = 0; 784eae2e508Skrishnae if (!pec_p->pec_descr.U) 785eae2e508Skrishnae pec_p->ue_reg_status = 0; 786eae2e508Skrishnae if (!pec_p->pec_descr.H) 787eae2e508Skrishnae pec_p->hdr[0] = 0; 788eae2e508Skrishnae if (!pec_p->pec_descr.I) 789eae2e508Skrishnae pec_p->hdr[1] = 0; 790bf8fc234Set142600 791bf8fc234Set142600 /* 792bf8fc234Set142600 * According to the PCIe spec, there is a first error pointer. If there 793bf8fc234Set142600 * are header logs recorded and there are more than one error, the log 794bf8fc234Set142600 * will belong to the error that the first error pointer points to. 795bf8fc234Set142600 * 796bf8fc234Set142600 * The regs.primary_ue expects a bit number, go through the ue register 797bf8fc234Set142600 * and find the first error that occured. Because the sun4v epkt spec 798bf8fc234Set142600 * does not define this value, the algorithm below gives the lower bit 799bf8fc234Set142600 * priority. 800bf8fc234Set142600 */ 801bf8fc234Set142600 temp = pcie->ue_reg; 802bf8fc234Set142600 if (temp) { 803eae2e508Skrishnae int x; 804bf8fc234Set142600 for (x = 0; !(temp & 0x1); x++) { 805bf8fc234Set142600 temp = temp >> 1; 806bf8fc234Set142600 } 807bf8fc234Set142600 pcie->primary_ue = 1 << x; 808bf8fc234Set142600 } else { 809bf8fc234Set142600 pcie->primary_ue = 0; 810bf8fc234Set142600 } 811bf8fc234Set142600 812bf8fc234Set142600 /* Sun4v doesn't log the TX hdr except for CTOs */ 813bf8fc234Set142600 if (pcie->primary_ue == PCIE_AER_UCE_TO) { 814bf8fc234Set142600 pcie->tx_hdr1 = pcie->rx_hdr1; 815bf8fc234Set142600 pcie->tx_hdr2 = pcie->rx_hdr2; 816bf8fc234Set142600 pcie->tx_hdr3 = pcie->rx_hdr3; 817bf8fc234Set142600 pcie->tx_hdr4 = pcie->rx_hdr4; 818bf8fc234Set142600 pcie->rx_hdr1 = 0; 819bf8fc234Set142600 pcie->rx_hdr2 = 0; 820bf8fc234Set142600 pcie->rx_hdr3 = 0; 821bf8fc234Set142600 pcie->rx_hdr4 = 0; 822bf8fc234Set142600 } else { 823bf8fc234Set142600 pcie->tx_hdr1 = 0; 824bf8fc234Set142600 pcie->tx_hdr2 = 0; 825bf8fc234Set142600 pcie->tx_hdr3 = 0; 826bf8fc234Set142600 pcie->tx_hdr4 = 0; 827bf8fc234Set142600 } 828bf8fc234Set142600 8295613d828SKrishna Elango return (px_err_check_pcie(dip, derr, pcie, PF_INTR_TYPE_INTERNAL)); 830bf8fc234Set142600 } 831bf8fc234Set142600 832bf8fc234Set142600 static int 833bf8fc234Set142600 px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 834bf8fc234Set142600 { 835eae2e508Skrishnae uint64_t addr = (uint64_t)epkt->addr; 836c85864d8SKrishna Elango pcie_req_id_t bdf = PCIE_INVALID_BDF; 837bf8fc234Set142600 838bf8fc234Set142600 if (epkt->rc_descr.H) { 839bf8fc234Set142600 bdf = (uint32_t)((epkt->hdr[0] >> 16) && 0xFFFF); 840bf8fc234Set142600 } 841bf8fc234Set142600 842eae2e508Skrishnae return (pf_hdl_lookup(dip, derr->fme_ena, PF_ADDR_DMA, addr, 843bf8fc234Set142600 bdf)); 844f8d2de6bSjchu } 845