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 2007 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.rp_bdf = px_p->px_bdf; 158 pf_data.aer_h0 = (uint32_t)(pec_p->hdr[0]); 159 pf_data.aer_h1 = (uint32_t)(pec_p->hdr[0] >> 32); 160 pf_data.aer_h2 = (uint32_t)(pec_p->hdr[1]); 161 pf_data.aer_h3 = (uint32_t)(pec_p->hdr[1] >> 32); 162 163 /* translate RC UR/CA to legacy secondary errors */ 164 if ((dir == DIR_READ || dir == DIR_WRITE) && 165 pec_p->pec_descr.U) { 166 if (pec_p->ue_reg_status & PCIE_AER_UCE_UR) 167 s_status |= PCI_STAT_R_MAST_AB; 168 if (pec_p->ue_reg_status | PCIE_AER_UCE_CA) 169 s_status |= PCI_STAT_R_TARG_AB; 170 } 171 172 if (pec_p->ue_reg_status & PCIE_AER_UCE_PTLP) 173 s_status |= PCI_STAT_PERROR; 174 175 if (pec_p->ue_reg_status & PCIE_AER_UCE_CA) 176 s_status |= PCI_STAT_S_TARG_AB; 177 178 sts = pf_tlp_decode(dip, &pf_data, &fault_bdf, &fault_addr, 179 &trans_type); 180 } 181 182 if (sts == DDI_SUCCESS) 183 px_rp_en_q(px_p, fault_bdf, fault_addr, s_status); 184 } 185 186 /* 187 * px_err_intr: 188 * Interrupt handler for the JBC/DMC/PEC block. 189 * o lock 190 * o create derr 191 * o check safe access 192 * o px_err_check_severity(epkt) 193 * o pcie_scan_fabric 194 * o Idle intr state 195 * o unlock 196 * o handle error: fatal? fm_panic() : return INTR_CLAIMED) 197 */ 198 static uint_t 199 px_err_intr(px_fault_t *fault_p, px_rc_err_t *epkt) 200 { 201 px_t *px_p = DIP_TO_STATE(fault_p->px_fh_dip); 202 dev_info_t *rpdip = px_p->px_dip; 203 int rc_err, fab_err = PF_NO_PANIC, msg; 204 ddi_fm_error_t derr; 205 206 mutex_enter(&px_p->px_fm_mutex); 207 208 /* Create the derr */ 209 bzero(&derr, sizeof (ddi_fm_error_t)); 210 derr.fme_version = DDI_FME_VERSION; 211 derr.fme_ena = fm_ena_generate(epkt->stick, FM_ENA_FMT1); 212 derr.fme_flag = DDI_FM_ERR_UNEXPECTED; 213 214 /* Basically check for safe access */ 215 (void) px_err_cmn_intr(px_p, &derr, PX_INTR_CALL, PX_FM_BLOCK_ALL); 216 217 /* Check the severity of this error */ 218 rc_err = px_err_epkt_severity(px_p, &derr, epkt, PX_INTR_CALL); 219 220 /* Scan the fabric if the root port is not in drain state. */ 221 if (!px_lib_is_in_drain_state(px_p)) 222 fab_err = pf_scan_fabric(rpdip, &derr, px_p->px_dq_p, 223 &px_p->px_dq_tail); 224 225 /* Set the intr state to idle for the leaf that received the mondo */ 226 if (px_lib_intr_setstate(rpdip, fault_p->px_fh_sysino, 227 INTR_IDLE_STATE) != DDI_SUCCESS) { 228 mutex_exit(&px_p->px_fm_mutex); 229 return (DDI_INTR_UNCLAIMED); 230 } 231 232 mutex_exit(&px_p->px_fm_mutex); 233 234 switch (epkt->rc_descr.block) { 235 case BLOCK_MMU: /* FALLTHROUGH */ 236 case BLOCK_INTR: 237 msg = PX_RC; 238 break; 239 case BLOCK_PCIE: 240 msg = PX_RP; 241 break; 242 case BLOCK_HOSTBUS: /* FALLTHROUGH */ 243 default: 244 msg = PX_HB; 245 break; 246 } 247 248 px_err_panic(rc_err, msg, fab_err); 249 250 return (DDI_INTR_CLAIMED); 251 } 252 253 /* 254 * px_err_epkt_severity: 255 * Check the severity of the fire error based the epkt received 256 * 257 * @param px_p leaf in which to take the snap shot. 258 * @param derr fm err in which the ereport is to be based on 259 * @param epkt epkt recevied from HV 260 */ 261 static int 262 px_err_epkt_severity(px_t *px_p, ddi_fm_error_t *derr, px_rc_err_t *epkt, 263 int caller) 264 { 265 px_pec_t *pec_p = px_p->px_pec_p; 266 dev_info_t *dip = px_p->px_dip; 267 boolean_t is_safeacc = B_FALSE; 268 boolean_t is_block_pci = B_FALSE; 269 char buf[FM_MAX_CLASS], descr_buf[1024]; 270 int err = 0; 271 272 /* Cautious access error handling */ 273 switch (derr->fme_flag) { 274 case DDI_FM_ERR_EXPECTED: 275 if (caller == PX_TRAP_CALL) { 276 /* 277 * for ddi_caut_get treat all events as nonfatal 278 * The trampoline will set err_ena = 0, 279 * err_status = NONFATAL. 280 */ 281 derr->fme_status = DDI_FM_NONFATAL; 282 is_safeacc = B_TRUE; 283 } else { 284 /* 285 * For ddi_caut_put treat all events as nonfatal. Here 286 * we have the handle and can call ndi_fm_acc_err_set(). 287 */ 288 derr->fme_status = DDI_FM_NONFATAL; 289 ndi_fm_acc_err_set(pec_p->pec_acc_hdl, derr); 290 is_safeacc = B_TRUE; 291 } 292 break; 293 case DDI_FM_ERR_PEEK: 294 case DDI_FM_ERR_POKE: 295 /* 296 * For ddi_peek/poke treat all events as nonfatal. 297 */ 298 is_safeacc = B_TRUE; 299 break; 300 default: 301 is_safeacc = B_FALSE; 302 } 303 304 /* 305 * Older hypervisors in some cases send epkts with incorrect fields. 306 * We have to handle these "special" epkts correctly. 307 */ 308 if (px_legacy_epkt) 309 px_fix_legacy_epkt(dip, derr, epkt); 310 311 switch (epkt->rc_descr.block) { 312 case BLOCK_HOSTBUS: 313 err = px_cb_epkt_severity(dip, derr, epkt); 314 break; 315 case BLOCK_MMU: 316 err = px_mmu_epkt_severity(dip, derr, epkt); 317 px_err_fill_pfd(dip, px_p, epkt); 318 break; 319 case BLOCK_INTR: 320 err = px_intr_epkt_severity(dip, derr, epkt); 321 break; 322 case BLOCK_PCIE: 323 is_block_pci = B_TRUE; 324 err = px_pcie_epkt_severity(dip, derr, epkt); 325 px_err_fill_pfd(dip, px_p, epkt); 326 break; 327 default: 328 err = 0; 329 } 330 331 if ((err & PX_HW_RESET) || (err & PX_PANIC)) { 332 if (px_log & PX_PANIC) 333 px_err_log_handle(dip, epkt, is_block_pci, "PANIC"); 334 } else if (err & PX_PROTECTED) { 335 if (px_log & PX_PROTECTED) 336 px_err_log_handle(dip, epkt, is_block_pci, "PROTECTED"); 337 } else if (err & PX_NO_PANIC) { 338 if (px_log & PX_NO_PANIC) 339 px_err_log_handle(dip, epkt, is_block_pci, "NO PANIC"); 340 } else if (err & PX_NO_ERROR) { 341 if (px_log & PX_NO_ERROR) 342 px_err_log_handle(dip, epkt, is_block_pci, "NO ERROR"); 343 } else if (err == 0) { 344 px_err_log_handle(dip, epkt, is_block_pci, "UNRECOGNIZED"); 345 346 /* Unrecognized epkt. send ereport */ 347 (void) snprintf(buf, FM_MAX_CLASS, "%s", PX_FM_RC_UNRECOG); 348 349 if (is_block_pci) { 350 px_pec_err_t *pec = (px_pec_err_t *)epkt; 351 352 (void) snprintf(descr_buf, sizeof (descr_buf), 353 "Epkt contents:\n" 354 "Block: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d\n" 355 "I=%d, H=%d, C=%d, U=%d, E=%d, P=%d\n" 356 "PCI Err Status: 0x%x, PCIe Err Status: 0x%x\n" 357 "CE Status Reg: 0x%x, UE Status Reg: 0x%x\n" 358 "HDR1: 0x%lx, HDR2: 0x%lx\n" 359 "Err Src Reg: 0x%x, Root Err Status: 0x%x\n", 360 pec->pec_descr.block, pec->pec_descr.dir, 361 pec->pec_descr.Z, pec->pec_descr.S, 362 pec->pec_descr.R, pec->pec_descr.I, 363 pec->pec_descr.H, pec->pec_descr.C, 364 pec->pec_descr.U, pec->pec_descr.E, 365 pec->pec_descr.P, pec->pci_err_status, 366 pec->pcie_err_status, pec->ce_reg_status, 367 pec->ue_reg_status, pec->hdr[0], 368 pec->hdr[1], pec->err_src_reg, 369 pec->root_err_status); 370 371 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 372 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 373 EPKT_SYSINO, DATA_TYPE_UINT64, pec->sysino, 374 EPKT_EHDL, DATA_TYPE_UINT64, pec->ehdl, 375 EPKT_STICK, DATA_TYPE_UINT64, pec->stick, 376 EPKT_PEC_DESCR, DATA_TYPE_STRING, descr_buf); 377 } else { 378 (void) snprintf(descr_buf, sizeof (descr_buf), 379 "Epkt contents:\n" 380 "Block: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 381 "Dir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d\n" 382 "M=%d, S=%d, Size: 0x%x, Addr: 0x%lx\n" 383 "Hdr1: 0x%lx, Hdr2: 0x%lx, Res: 0x%lx\n", 384 epkt->rc_descr.block, epkt->rc_descr.op, 385 epkt->rc_descr.phase, epkt->rc_descr.cond, 386 epkt->rc_descr.dir, epkt->rc_descr.STOP, 387 epkt->rc_descr.H, epkt->rc_descr.R, 388 epkt->rc_descr.D, epkt->rc_descr.M, 389 epkt->rc_descr.S, epkt->size, epkt->addr, 390 epkt->hdr[0], epkt->hdr[1], epkt->reserved); 391 392 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 393 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 394 EPKT_SYSINO, DATA_TYPE_UINT64, epkt->sysino, 395 EPKT_EHDL, DATA_TYPE_UINT64, epkt->ehdl, 396 EPKT_STICK, DATA_TYPE_UINT64, epkt->stick, 397 EPKT_RC_DESCR, DATA_TYPE_STRING, descr_buf); 398 } 399 400 err = PX_PANIC; 401 } 402 403 /* Readjust the severity as a result of safe access */ 404 if (is_safeacc && !(err & PX_PANIC) && !(px_die & PX_PROTECTED)) 405 err = PX_NO_PANIC; 406 407 return (err); 408 } 409 410 static void 411 px_err_log_handle(dev_info_t *dip, px_rc_err_t *epkt, boolean_t is_block_pci, 412 char *msg) 413 { 414 if (is_block_pci) { 415 px_pec_err_t *pec = (px_pec_err_t *)epkt; 416 DBG(DBG_ERR_INTR, dip, 417 "A PCIe root port error has occured with a severity" 418 " \"%s\"\n" 419 "\tBlock: 0x%x, Dir: 0x%x, Flags: Z=%d, S=%d, R=%d, I=%d\n" 420 "\tH=%d, C=%d, U=%d, E=%d, P=%d\n" 421 "\tpci_err: 0x%x, pcie_err=0x%x, ce_reg: 0x%x\n" 422 "\tue_reg: 0x%x, Hdr1: 0x%p, Hdr2: 0x%p\n" 423 "\terr_src: 0x%x, root_err: 0x%x\n", 424 msg, pec->pec_descr.block, pec->pec_descr.dir, 425 pec->pec_descr.Z, pec->pec_descr.S, pec->pec_descr.R, 426 pec->pec_descr.I, pec->pec_descr.H, pec->pec_descr.C, 427 pec->pec_descr.U, pec->pec_descr.E, pec->pec_descr.P, 428 pec->pci_err_status, pec->pcie_err_status, 429 pec->ce_reg_status, pec->ue_reg_status, pec->hdr[0], 430 pec->hdr[1], pec->err_src_reg, pec->root_err_status); 431 } else { 432 DBG(DBG_ERR_INTR, dip, 433 "A PCIe root complex error has occured with a severity" 434 " \"%s\"\n" 435 "\tBlock: 0x%x, Op: 0x%x, Phase: 0x%x, Cond: 0x%x\n" 436 "\tDir: 0x%x, Flags: STOP=%d, H=%d, R=%d, D=%d, M=%d\n" 437 "\tS=%d, Size: 0x%x, Addr: 0x%p\n" 438 "\tHdr1: 0x%p, Hdr2: 0x%p, Res: 0x%p\n", 439 msg, epkt->rc_descr.block, epkt->rc_descr.op, 440 epkt->rc_descr.phase, epkt->rc_descr.cond, 441 epkt->rc_descr.dir, epkt->rc_descr.STOP, epkt->rc_descr.H, 442 epkt->rc_descr.R, epkt->rc_descr.D, epkt->rc_descr.M, 443 epkt->rc_descr.S, epkt->size, epkt->addr, epkt->hdr[0], 444 epkt->hdr[1], epkt->reserved); 445 } 446 } 447 448 /* ARGSUSED */ 449 static void 450 px_fix_legacy_epkt(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 451 { 452 /* 453 * We don't have a default case for any of the below switch statements 454 * since we are ok with the code falling through. 455 */ 456 switch (epkt->rc_descr.block) { 457 case BLOCK_HOSTBUS: 458 switch (epkt->rc_descr.op) { 459 case OP_DMA: 460 switch (epkt->rc_descr.phase) { 461 case PH_UNKNOWN: 462 switch (epkt->rc_descr.cond) { 463 case CND_UNKNOWN: 464 switch (epkt->rc_descr.dir) { 465 case DIR_RESERVED: 466 epkt->rc_descr.dir = DIR_READ; 467 break; 468 } /* DIR */ 469 } /* CND */ 470 } /* PH */ 471 } /* OP */ 472 break; 473 case BLOCK_MMU: 474 switch (epkt->rc_descr.op) { 475 case OP_XLAT: 476 switch (epkt->rc_descr.phase) { 477 case PH_DATA: 478 switch (epkt->rc_descr.cond) { 479 case CND_PROT: 480 switch (epkt->rc_descr.dir) { 481 case DIR_UNKNOWN: 482 epkt->rc_descr.dir = DIR_WRITE; 483 break; 484 } /* DIR */ 485 } /* CND */ 486 break; 487 case PH_IRR: 488 switch (epkt->rc_descr.cond) { 489 case CND_RESERVED: 490 switch (epkt->rc_descr.dir) { 491 case DIR_IRR: 492 epkt->rc_descr.phase = PH_ADDR; 493 epkt->rc_descr.cond = CND_IRR; 494 } /* DIR */ 495 } /* CND */ 496 } /* PH */ 497 } /* OP */ 498 break; 499 case BLOCK_INTR: 500 switch (epkt->rc_descr.op) { 501 case OP_MSIQ: 502 switch (epkt->rc_descr.phase) { 503 case PH_UNKNOWN: 504 switch (epkt->rc_descr.cond) { 505 case CND_ILL: 506 switch (epkt->rc_descr.dir) { 507 case DIR_RESERVED: 508 epkt->rc_descr.dir = DIR_IRR; 509 break; 510 } /* DIR */ 511 break; 512 case CND_IRR: 513 switch (epkt->rc_descr.dir) { 514 case DIR_IRR: 515 epkt->rc_descr.cond = CND_OV; 516 break; 517 } /* DIR */ 518 } /* CND */ 519 } /* PH */ 520 break; 521 case OP_RESERVED: 522 switch (epkt->rc_descr.phase) { 523 case PH_UNKNOWN: 524 switch (epkt->rc_descr.cond) { 525 case CND_ILL: 526 switch (epkt->rc_descr.dir) { 527 case DIR_IRR: 528 epkt->rc_descr.op = OP_MSI32; 529 epkt->rc_descr.phase = PH_DATA; 530 break; 531 } /* DIR */ 532 } /* CND */ 533 break; 534 case PH_DATA: 535 switch (epkt->rc_descr.cond) { 536 case CND_INT: 537 switch (epkt->rc_descr.dir) { 538 case DIR_UNKNOWN: 539 epkt->rc_descr.op = OP_MSI32; 540 break; 541 } /* DIR */ 542 } /* CND */ 543 } /* PH */ 544 } /* OP */ 545 } /* BLOCK */ 546 } 547 548 /* ARGSUSED */ 549 static int 550 px_intr_handle_errors(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 551 { 552 return (px_err_check_eq(dip)); 553 } 554 555 /* ARGSUSED */ 556 static int 557 px_pcie_epkt_severity(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 558 { 559 px_t *px_p = DIP_TO_STATE(dip); 560 px_pec_err_t *pec = (px_pec_err_t *)epkt; 561 px_err_pcie_t *pcie = (px_err_pcie_t *)epkt; 562 pf_data_t pf_data; 563 int x; 564 uint32_t temp; 565 566 /* 567 * Check for failed PIO Read/Writes, which are errors that are not 568 * defined in the PCIe spec. 569 */ 570 pf_data.rp_bdf = px_p->px_bdf; 571 temp = PCIE_AER_UCE_UR | PCIE_AER_UCE_CA; 572 if (((pec->pec_descr.dir == DIR_READ) || (pec->pec_descr.dir == 573 DIR_WRITE)) && pec->pec_descr.U && (pec->ue_reg_status == temp)) { 574 pf_data.aer_h0 = (uint32_t)(pec->hdr[0]); 575 pf_data.aer_h1 = (uint32_t)(pec->hdr[0] >> 32); 576 pf_data.aer_h2 = (uint32_t)(pec->hdr[1]); 577 pf_data.aer_h3 = (uint32_t)(pec->hdr[1] >> 32); 578 579 if (pf_tlp_hdl_lookup(dip, derr, &pf_data) != DDI_FM_UNKNOWN) 580 return (PX_NO_PANIC); 581 else 582 return (PX_PANIC); 583 } 584 585 if (!pec->pec_descr.C) 586 pec->ce_reg_status = 0; 587 if (!pec->pec_descr.U) 588 pec->ue_reg_status = 0; 589 if (!pec->pec_descr.H) 590 pec->hdr[0] = 0; 591 if (!pec->pec_descr.I) 592 pec->hdr[1] = 0; 593 594 /* 595 * According to the PCIe spec, there is a first error pointer. If there 596 * are header logs recorded and there are more than one error, the log 597 * will belong to the error that the first error pointer points to. 598 * 599 * The regs.primary_ue expects a bit number, go through the ue register 600 * and find the first error that occured. Because the sun4v epkt spec 601 * does not define this value, the algorithm below gives the lower bit 602 * priority. 603 */ 604 temp = pcie->ue_reg; 605 if (temp) { 606 for (x = 0; !(temp & 0x1); x++) { 607 temp = temp >> 1; 608 } 609 pcie->primary_ue = 1 << x; 610 } else { 611 pcie->primary_ue = 0; 612 } 613 614 /* Sun4v doesn't log the TX hdr except for CTOs */ 615 if (pcie->primary_ue == PCIE_AER_UCE_TO) { 616 pcie->tx_hdr1 = pcie->rx_hdr1; 617 pcie->tx_hdr2 = pcie->rx_hdr2; 618 pcie->tx_hdr3 = pcie->rx_hdr3; 619 pcie->tx_hdr4 = pcie->rx_hdr4; 620 pcie->rx_hdr1 = 0; 621 pcie->rx_hdr2 = 0; 622 pcie->rx_hdr3 = 0; 623 pcie->rx_hdr4 = 0; 624 } else { 625 pcie->tx_hdr1 = 0; 626 pcie->tx_hdr2 = 0; 627 pcie->tx_hdr3 = 0; 628 pcie->tx_hdr4 = 0; 629 } 630 631 return (px_err_check_pcie(dip, derr, pcie)); 632 } 633 634 static int 635 px_mmu_handle_lookup(dev_info_t *dip, ddi_fm_error_t *derr, px_rc_err_t *epkt) 636 { 637 uint32_t addr = (uint32_t)epkt->addr; 638 pcie_req_id_t bdf = NULL; 639 640 if (epkt->rc_descr.H) { 641 bdf = (uint32_t)((epkt->hdr[0] >> 16) && 0xFFFF); 642 } 643 644 return (pf_hdl_lookup(dip, derr->fme_ena, PF_DMA_ADDR, addr, 645 bdf)); 646 } 647