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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * sun4v Fire Error Handling 30 */ 31 32 #include <sys/types.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/fm/protocol.h> 36 #include <sys/fm/util.h> 37 #include <sys/membar.h> 38 #include "px_obj.h" 39 #include "px_err.h" 40 41 static void px_err_fill_pf_data(dev_info_t *dip, px_t *px_p, px_rc_err_t *epkt); 42 static uint_t px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt); 43 static int px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, 44 px_rc_err_t *epkt, int caller); 45 46 static void px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, 47 boolean_t is_block_pci, char *msg); 48 static int px_cb_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 49 px_rc_err_t *epkt); 50 static int px_mmu_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 51 px_rc_err_t *epkt); 52 static int px_intr_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 53 px_rc_err_t *epkt); 54 static int px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, 55 px_rc_err_t *epkt); 56 static int px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, 57 px_rc_err_t *epkt); 58 static void px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, 59 px_rc_err_t *epkt); 60 static int px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, 61 px_rc_err_t *epkt); 62 63 /* Include the code generated sun4v epkt checking code */ 64 #include "px_err_gen.c" 65 66 /* 67 * This variable indicates if we have a hypervisor that could potentially send 68 * incorrect epkts. We always set this to TRUE for now until we find a way to 69 * tell if this HV bug has been fixed. 70 */ 71 boolean_t px_legacy_epkt = B_TRUE; 72 73 /* 74 * px_err_cb_intr: 75 * Interrupt handler for the Host Bus Block. 76 */ 77 uint_t 78 px_err_cb_intr(caddr_t arg) 79 { 80 px_fault_t *fault_p = (px_fault_t *)arg; 81 px_rc_err_t *epkt = (px_rc_err_t *)fault_p->px_intr_payload; 82 83 if (epkt != NULL) { 84 return (px_err_intr(fault_p, epkt)); 85 } 86 87 return (DDI_INTR_UNCLAIMED); 88 } 89 90 /* 91 * px_err_dmc_pec_intr: 92 * Interrupt handler for the DMC/PEC block. 93 */ 94 uint_t 95 px_err_dmc_pec_intr(caddr_t arg) 96 { 97 px_fault_t *fault_p = (px_fault_t *)arg; 98 px_rc_err_t *epkt = (px_rc_err_t *)fault_p->px_intr_payload; 99 100 if (epkt != NULL) { 101 return (px_err_intr(fault_p, epkt)); 102 } 103 104 return (DDI_INTR_UNCLAIMED); 105 } 106 107 /* 108 * px_err_cmn_intr: 109 * Common function called by trap, mondo and fabric intr. 110 * This function is more meaningful in sun4u implementation. Kept 111 * to mirror sun4u call stack. 112 * o check for safe access 113 * o create and queue RC info for later use in fabric scan. 114 * o RUC/WUC, PTLP, MMU Errors(CA), UR 115 * 116 * @param px_p leaf in which to check access 117 * @param derr fm err data structure to be updated 118 * @param caller PX_TRAP_CALL | PX_INTR_CALL 119 * @param chkjbc whether to handle hostbus registers (ignored) 120 * @return err PX_NO_PANIC | PX_PROTECTED | 121 * PX_PANIC | PX_HW_RESET | PX_EXPECTED 122 */ 123 /* ARGSUSED */ 124 int 125 px_err_cmn_intr(px_t *px_p, ddi_fm_error_t *derr, int caller, int block) 126 { 127 px_err_safeacc_check(px_p, derr); 128 return (DDI_FM_OK); 129 } 130 131 /* 132 * fills RC specific fault data 133 */ 134 static void 135 px_err_fill_pfd(dev_info_t *dip, px_t *px_p, px_rc_err_t *epkt) { 136 pf_data_t pf_data = {0}; 137 int sts = DDI_SUCCESS; 138 pcie_req_id_t fault_bdf = 0; 139 uint32_t fault_addr = 0; 140 uint16_t s_status = 0; 141 142 /* Add an PCIE PF_DATA Entry */ 143 if (epkt->rc_descr.block == BLOCK_MMU) { 144 /* Only PIO Fault Addresses are valid, this is DMA */ 145 s_status = PCI_STAT_S_TARG_AB; 146 fault_addr = NULL; 147 148 if (epkt->rc_descr.H) 149 fault_bdf = (pcie_req_id_t)(epkt->hdr[0] >> 16); 150 else 151 sts = DDI_FAILURE; 152 } else { 153 px_pec_err_t *pec_p = (px_pec_err_t *)epkt; 154 uint32_t trans_type; 155 uint32_t dir = pec_p->pec_descr.dir; 156 157 pf_data.aer_h0 = (uint32_t)(pec_p->hdr[0]); 158 pf_data.aer_h1 = (uint32_t)(pec_p->hdr[0] >> 32); 159 pf_data.aer_h2 = (uint32_t)(pec_p->hdr[1]); 160 pf_data.aer_h3 = (uint32_t)(pec_p->hdr[1] >> 32); 161 162 /* translate RC UR/CA to legacy secondary errors */ 163 if ((dir == DIR_READ || dir == DIR_WRITE) && 164 pec_p->pec_descr.U) { 165 if (pec_p->ue_reg_status & PCIE_AER_UCE_UR) 166 s_status |= PCI_STAT_R_MAST_AB; 167 if (pec_p->ue_reg_status | PCIE_AER_UCE_CA) 168 s_status |= PCI_STAT_R_TARG_AB; 169 } 170 171 if (pec_p->ue_reg_status & PCIE_AER_UCE_PTLP) 172 s_status |= PCI_STAT_PERROR; 173 174 if (pec_p->ue_reg_status & PCIE_AER_UCE_CA) 175 s_status |= PCI_STAT_S_TARG_AB; 176 177 sts = pf_tlp_decode(dip, &pf_data, &fault_bdf, &fault_addr, 178 &trans_type); 179 } 180 181 if (sts == DDI_SUCCESS) 182 px_rp_en_q(px_p, fault_bdf, fault_addr, s_status); 183 } 184 185 /* 186 * px_err_intr: 187 * Interrupt handler for the JBC/DMC/PEC block. 188 * o lock 189 * o create derr 190 * o check safe access 191 * o px_err_check_severity(epkt) 192 * o pcie_scan_fabric 193 * o Idle intr state 194 * o unlock 195 * o handle error: fatal? fm_panic() : return INTR_CLAIMED) 196 */ 197 static uint_t 198 px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt) 199 { 200 px_t *px_p = DIP_TO_STATE(fault_p->px_fh_dip); 201 dev_info_t *rpdip = px_p->px_dip; 202 int rc_err, fab_err = PF_NO_PANIC, msg; 203 ddi_fm_error_t derr; 204 205 mutex_enter(&px_p->px_fm_mutex); 206 207 /* Create the derr */ 208 bzero(&derr, sizeof (ddi_fm_error_t)); 209 derr.fme_version = DDI_FME_VERSION; 210 derr.fme_ena = fm_ena_generate(epkt->stick, FM_ENA_FMT1); 211 derr.fme_flag = DDI_FM_ERR_UNEXPECTED; 212 213 /* Basically check for safe access */ 214 (void) px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_ALL); 215 216 /* Check the severity of this error */ 217 rc_err = px_err_epkt_severity(px_p, &derr, epkt, PX_INTR_CALL); 218 219 /* Scan the fabric if the root port is not in drain state. */ 220 if (!px_lib_is_in_drain_state(px_p)) 221 fab_err = pf_scan_fabric(rpdip, &derr, px_p->px_dq_p, 222 &px_p->px_dq_tail); 223 224 /* Set the intr state to idle for the leaf that received the mondo */ 225 if (px_lib_intr_setstate(rpdip, fault_p->px_fh_sysino, 226 INTR_IDLE_STATE) != DDI_SUCCESS) { 227 mutex_exit(&px_p->px_fm_mutex); 228 return (DDI_INTR_UNCLAIMED); 229 } 230 231 mutex_exit(&px_p->px_fm_mutex); 232 233 switch (epkt->rc_descr.block) { 234 case BLOCK_MMU: /* FALLTHROUGH */ 235 case BLOCK_INTR: 236 msg = PX_RC; 237 break; 238 case BLOCK_PCIE: 239 msg = PX_RP; 240 break; 241 case BLOCK_HOSTBUS: /* FALLTHROUGH */ 242 default: 243 msg = PX_HB; 244 break; 245 } 246 247 px_err_panic(rc_err, msg, fab_err); 248 249 return (DDI_INTR_CLAIMED); 250 } 251 252 /* 253 * px_err_epkt_severity: 254 * Check the severity of the fire error based the epkt received 255 * 256 * @param px_p leaf in which to take the snap shot. 257 * @param derr fm err in which the ereport is to be based on 258 * @param epkt epkt recevied from HV 259 */ 260 static int 261 px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, px_rc_err_t *epkt, 262 int caller) 263 { 264 px_pec_t *pec_p = px_p->px_pec_p; 265 dev_info_t *dip = px_p->px_dip; 266 boolean_t is_safeacc = B_FALSE; 267 boolean_t is_block_pci = B_FALSE; 268 char buf[FM_MAX_CLASS], descr_buf[1024]; 269 int err = 0; 270 271 /* Cautious access error handling */ 272 switch (derr->fme_flag) { 273 case DDI_FM_ERR_EXPECTED: 274 if (caller == PX_TRAP_CALL) { 275 /* 276 * for ddi_caut_get treat all events as nonfatal 277 * The trampoline will set err_ena = 0, 278 * err_status = NONFATAL. 279 */ 280 derr->fme_status = DDI_FM_NONFATAL; 281 is_safeacc = B_TRUE; 282 } else { 283 /* 284 * For ddi_caut_put treat all events as nonfatal. Here 285 * we have the handle and can call ndi_fm_acc_err_set(). 286 */ 287 derr->fme_status = DDI_FM_NONFATAL; 288 ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr); 289 is_safeacc = B_TRUE; 290 } 291 break; 292 case DDI_FM_ERR_PEEK: 293 case DDI_FM_ERR_POKE: 294 /* 295 * For ddi_peek/poke treat all events as nonfatal. 296 */ 297 is_safeacc = B_TRUE; 298 break; 299 default: 300 is_safeacc = B_FALSE; 301 } 302 303 /* 304 * Older hypervisors in some cases send epkts with incorrect fields. 305 * We have to handle these "special" epkts correctly. 306 */ 307 if (px_legacy_epkt) 308 px_fix_legacy_epkt(dip, derr, epkt); 309 310 switch (epkt->rc_descr.block) { 311 case BLOCK_HOSTBUS: 312 err = px_cb_epkt_severity(dip, derr, epkt); 313 break; 314 case BLOCK_MMU: 315 err = px_mmu_epkt_severity(dip, derr, epkt); 316 px_err_fill_pfd(dip, px_p, epkt); 317 break; 318 case BLOCK_INTR: 319 err = px_intr_epkt_severity(dip, derr, epkt); 320 break; 321 case BLOCK_PCIE: 322 is_block_pci = B_TRUE; 323 err = px_pcie_epkt_severity(dip, derr, epkt); 324 px_err_fill_pfd(dip, px_p, epkt); 325 break; 326 default: 327 err = 0; 328 } 329 330 if ((err & PX_HW_RESET) || (err & PX_PANIC)) { 331 if (px_log & PX_PANIC) 332 px_err_log_handle(dip, epkt, is_block_pci, "PANIC"); 333 } else if (err & PX_PROTECTED) { 334 if (px_log & PX_PROTECTED) 335 px_err_log_handle(dip, epkt, is_block_pci, "PROTECTED"); 336 } else if (err & PX_NO_PANIC) { 337 if (px_log & PX_NO_PANIC) 338 px_err_log_handle(dip, epkt, is_block_pci, "NO PANIC"); 339 } else if (err & PX_NO_ERROR) { 340 if (px_log & PX_NO_ERROR) 341 px_err_log_handle(dip, epkt, is_block_pci, "NO ERROR"); 342 } else if (err == 0) { 343 px_err_log_handle(dip, epkt, is_block_pci, "UNRECOGNIZED"); 344 345 /* Unrecognized epkt. send ereport */ 346 (void) snprintf(buf, FM_MAX_CLASS, "%s", PX_FM_RC_UNRECOG); 347 348 if (is_block_pci) { 349 px_pec_err_t *pec = (px_pec_err_t *)epkt; 350 351 (void) snprintf(descr_buf, sizeof (descr_buf), 352 "Epkt contents:\n" 353 "Block: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d\n" 354 "I=%d, H=%d, C=%d, U=%d, E=%d, P=%d\n" 355 "PCI Err Status: 0x%x, PCIe Err Status: 0x%x\n" 356 "CE Status Reg: 0x%x, UE Status Reg: 0x%x\n" 357 "HDR1: 0x%lx, HDR2: 0x%lx\n" 358 "Err Src Reg: 0x%x, Root Err Status: 0x%x\n", 359 pec->pec_descr.block, pec->pec_descr.dir, 360 pec->pec_descr.Z, pec->pec_descr.S, 361 pec->pec_descr.R, pec->pec_descr.I, 362 pec->pec_descr.H, pec->pec_descr.C, 363 pec->pec_descr.U, pec->pec_descr.E, 364 pec->pec_descr.P, pec->pci_err_status, 365 pec->pcie_err_status, pec->ce_reg_status, 366 pec->ue_reg_status, pec->hdr[0], 367 pec->hdr[1], pec->err_src_reg, 368 pec->root_err_status); 369 370 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 371 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 372 EPKT_SYSINO, DATA_TYPE_UINT64, pec->sysino, 373 EPKT_EHDL, DATA_TYPE_UINT64, pec->ehdl, 374 EPKT_STICK, DATA_TYPE_UINT64, pec->stick, 375 EPKT_PEC_DESCR, DATA_TYPE_STRING, descr_buf); 376 } else { 377 (void) snprintf(descr_buf, sizeof (descr_buf), 378 "Epkt contents:\n" 379 "Block: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 380 "Dir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d\n" 381 "M=%d, S=%d, Size: 0x%x, Addr: 0x%lx\n" 382 "Hdr1: 0x%lx, Hdr2: 0x%lx, Res: 0x%lx\n", 383 epkt->rc_descr.block, epkt->rc_descr.op, 384 epkt->rc_descr.phase, epkt->rc_descr.cond, 385 epkt->rc_descr.dir, epkt->rc_descr.STOP, 386 epkt->rc_descr.H, epkt->rc_descr.R, 387 epkt->rc_descr.D, epkt->rc_descr.M, 388 epkt->rc_descr.S, epkt->size, epkt->addr, 389 epkt->hdr[0], epkt->hdr[1], epkt->reserved); 390 391 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 392 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 393 EPKT_SYSINO, DATA_TYPE_UINT64, epkt->sysino, 394 EPKT_EHDL, DATA_TYPE_UINT64, epkt->ehdl, 395 EPKT_STICK, DATA_TYPE_UINT64, epkt->stick, 396 EPKT_RC_DESCR, DATA_TYPE_STRING, descr_buf); 397 } 398 399 err = PX_PANIC; 400 } 401 402 /* Readjust the severity as a result of safe access */ 403 if (is_safeacc && !(err & PX_PANIC) && !(px_die & PX_PROTECTED)) 404 err = PX_NO_PANIC; 405 406 return (err); 407 } 408 409 static void 410 px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, boolean_t is_block_pci, 411 char *msg) 412 { 413 if (is_block_pci) { 414 px_pec_err_t *pec = (px_pec_err_t *)epkt; 415 DBG(DBG_ERR_INTR, dip, 416 "A PCIe root port error has occured with a severity" 417 " \"%s\"\n" 418 "\tBlock: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d, I=%d\n" 419 "\tH=%d, C=%d, U=%d, E=%d, P=%d\n" 420 "\tpci_err: 0x%x, pcie_err=0x%x, ce_reg: 0x%x\n" 421 "\tue_reg: 0x%x, Hdr1: 0x%p, Hdr2: 0x%p\n" 422 "\terr_src: 0x%x, root_err: 0x%x\n", 423 msg, pec->pec_descr.block, pec->pec_descr.dir, 424 pec->pec_descr.Z, pec->pec_descr.S, pec->pec_descr.R, 425 pec->pec_descr.I, pec->pec_descr.H, pec->pec_descr.C, 426 pec->pec_descr.U, pec->pec_descr.E, pec->pec_descr.P, 427 pec->pci_err_status, pec->pcie_err_status, 428 pec->ce_reg_status, pec->ue_reg_status, pec->hdr[0], 429 pec->hdr[1], pec->err_src_reg, pec->root_err_status); 430 } else { 431 DBG(DBG_ERR_INTR, dip, 432 "A PCIe root complex error has occured with a severity" 433 " \"%s\"\n" 434 "\tBlock: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 435 "\tDir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d, M=%d\n" 436 "\tS=%d, Size: 0x%x, Addr: 0x%p\n" 437 "\tHdr1: 0x%p, Hdr2: 0x%p, Res: 0x%p\n", 438 msg, epkt->rc_descr.block, epkt->rc_descr.op, 439 epkt->rc_descr.phase, epkt->rc_descr.cond, 440 epkt->rc_descr.dir, epkt->rc_descr.STOP, epkt->rc_descr.H, 441 epkt->rc_descr.R, epkt->rc_descr.D, epkt->rc_descr.M, 442 epkt->rc_descr.S, epkt->size, epkt->addr, epkt->hdr[0], 443 epkt->hdr[1], epkt->reserved); 444 } 445 } 446 447 /* ARGSUSED */ 448 static void 449 px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 450 { 451 /* 452 * We don't have a default case for any of the below switch statements 453 * since we are ok with the code falling through. 454 */ 455 switch (epkt->rc_descr.block) { 456 case BLOCK_HOSTBUS: 457 switch (epkt->rc_descr.op) { 458 case OP_DMA: 459 switch (epkt->rc_descr.phase) { 460 case PH_UNKNOWN: 461 switch (epkt->rc_descr.cond) { 462 case CND_UNKNOWN: 463 switch (epkt->rc_descr.dir) { 464 case DIR_RESERVED: 465 epkt->rc_descr.dir = DIR_READ; 466 break; 467 } /* DIR */ 468 } /* CND */ 469 } /* PH */ 470 } /* OP */ 471 break; 472 case BLOCK_MMU: 473 switch (epkt->rc_descr.op) { 474 case OP_XLAT: 475 switch (epkt->rc_descr.phase) { 476 case PH_DATA: 477 switch (epkt->rc_descr.cond) { 478 case CND_PROT: 479 switch (epkt->rc_descr.dir) { 480 case DIR_UNKNOWN: 481 epkt->rc_descr.dir = DIR_WRITE; 482 break; 483 } /* DIR */ 484 } /* CND */ 485 break; 486 case PH_IRR: 487 switch (epkt->rc_descr.cond) { 488 case CND_RESERVED: 489 switch (epkt->rc_descr.dir) { 490 case DIR_IRR: 491 epkt->rc_descr.phase = PH_ADDR; 492 epkt->rc_descr.cond = CND_IRR; 493 } /* DIR */ 494 } /* CND */ 495 } /* PH */ 496 } /* OP */ 497 break; 498 case BLOCK_INTR: 499 switch (epkt->rc_descr.op) { 500 case OP_MSIQ: 501 switch (epkt->rc_descr.phase) { 502 case PH_UNKNOWN: 503 switch (epkt->rc_descr.cond) { 504 case CND_ILL: 505 switch (epkt->rc_descr.dir) { 506 case DIR_RESERVED: 507 epkt->rc_descr.dir = DIR_IRR; 508 break; 509 } /* DIR */ 510 break; 511 case CND_IRR: 512 switch (epkt->rc_descr.dir) { 513 case DIR_IRR: 514 epkt->rc_descr.cond = CND_OV; 515 break; 516 } /* DIR */ 517 } /* CND */ 518 } /* PH */ 519 break; 520 case OP_RESERVED: 521 switch (epkt->rc_descr.phase) { 522 case PH_UNKNOWN: 523 switch (epkt->rc_descr.cond) { 524 case CND_ILL: 525 switch (epkt->rc_descr.dir) { 526 case DIR_IRR: 527 epkt->rc_descr.op = OP_MSI32; 528 epkt->rc_descr.phase = PH_DATA; 529 break; 530 } /* DIR */ 531 } /* CND */ 532 break; 533 case PH_DATA: 534 switch (epkt->rc_descr.cond) { 535 case CND_INT: 536 switch (epkt->rc_descr.dir) { 537 case DIR_UNKNOWN: 538 epkt->rc_descr.op = OP_MSI32; 539 break; 540 } /* DIR */ 541 } /* CND */ 542 } /* PH */ 543 } /* OP */ 544 } /* BLOCK */ 545 } 546 547 /* ARGSUSED */ 548 static int 549 px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 550 { 551 return (px_err_check_eq(dip)); 552 } 553 554 /* ARGSUSED */ 555 static int 556 px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 557 { 558 px_pec_err_t *pec = (px_pec_err_t *)epkt; 559 px_err_pcie_t *pcie = (px_err_pcie_t *)epkt; 560 pf_data_t pf_data; 561 int x; 562 uint32_t temp; 563 564 /* 565 * Check for failed PIO Read/Writes, which are errors that are not 566 * defined in the PCIe spec. 567 */ 568 temp = PCIE_AER_UCE_UR | PCIE_AER_UCE_CA; 569 if (((pec->pec_descr.dir == DIR_READ) || (pec->pec_descr.dir == 570 DIR_WRITE)) && pec->pec_descr.U && (pec->ue_reg_status == temp)) { 571 pf_data.aer_h0 = (uint32_t)(pec->hdr[0]); 572 pf_data.aer_h1 = (uint32_t)(pec->hdr[0] >> 32); 573 pf_data.aer_h2 = (uint32_t)(pec->hdr[1]); 574 pf_data.aer_h3 = (uint32_t)(pec->hdr[1] >> 32); 575 576 if (pf_tlp_hdl_lookup(dip, derr, &pf_data) != DDI_FM_UNKNOWN) 577 return (PX_NO_PANIC); 578 else 579 return (PX_PANIC); 580 } 581 582 if (!pec->pec_descr.C) 583 pec->ce_reg_status = 0; 584 if (!pec->pec_descr.U) 585 pec->ue_reg_status = 0; 586 if (!pec->pec_descr.H) 587 pec->hdr[0] = 0; 588 if (!pec->pec_descr.I) 589 pec->hdr[1] = 0; 590 591 /* 592 * According to the PCIe spec, there is a first error pointer. If there 593 * are header logs recorded and there are more than one error, the log 594 * will belong to the error that the first error pointer points to. 595 * 596 * The regs.primary_ue expects a bit number, go through the ue register 597 * and find the first error that occured. Because the sun4v epkt spec 598 * does not define this value, the algorithm below gives the lower bit 599 * priority. 600 */ 601 temp = pcie->ue_reg; 602 if (temp) { 603 for (x = 0; !(temp & 0x1); x++) { 604 temp = temp >> 1; 605 } 606 pcie->primary_ue = 1 << x; 607 } else { 608 pcie->primary_ue = 0; 609 } 610 611 /* Sun4v doesn't log the TX hdr except for CTOs */ 612 if (pcie->primary_ue == PCIE_AER_UCE_TO) { 613 pcie->tx_hdr1 = pcie->rx_hdr1; 614 pcie->tx_hdr2 = pcie->rx_hdr2; 615 pcie->tx_hdr3 = pcie->rx_hdr3; 616 pcie->tx_hdr4 = pcie->rx_hdr4; 617 pcie->rx_hdr1 = 0; 618 pcie->rx_hdr2 = 0; 619 pcie->rx_hdr3 = 0; 620 pcie->rx_hdr4 = 0; 621 } else { 622 pcie->tx_hdr1 = 0; 623 pcie->tx_hdr2 = 0; 624 pcie->tx_hdr3 = 0; 625 pcie->tx_hdr4 = 0; 626 } 627 628 return (px_err_check_pcie(dip, derr, pcie)); 629 } 630 631 static int 632 px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 633 { 634 uint32_t addr = (uint32_t)epkt->addr; 635 pcie_req_id_t bdf = NULL; 636 637 if (epkt->rc_descr.H) { 638 bdf = (uint32_t)((epkt->hdr[0] >> 16) && 0xFFFF); 639 } 640 641 return (pf_hdl_lookup(dip, derr->fme_ena, PF_DMA_ADDR, addr, 642 bdf)); 643 } 644