1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/sunndi.h> 29 #include <sys/sysmacros.h> 30 #include <sys/ddifm_impl.h> 31 #include <sys/fm/util.h> 32 #include <sys/fm/protocol.h> 33 #include <sys/fm/io/pci.h> 34 #include <sys/fm/io/ddi.h> 35 #include <sys/pci.h> 36 #include <sys/pci_cap.h> 37 #include <sys/pci_impl.h> 38 #include <sys/epm.h> 39 #include <sys/pcifm.h> 40 41 #define PCIX_ECC_VER_CHECK(x) (((x) == PCI_PCIX_VER_1) ||\ 42 ((x) == PCI_PCIX_VER_2)) 43 44 errorq_t *pci_target_queue = NULL; 45 46 pci_fm_err_t pci_err_tbl[] = { 47 PCI_DET_PERR, PCI_STAT_PERROR, NULL, DDI_FM_UNKNOWN, 48 PCI_MDPE, PCI_STAT_S_PERROR, PCI_TARG_MDPE, DDI_FM_UNKNOWN, 49 PCI_SIG_SERR, PCI_STAT_S_SYSERR, NULL, DDI_FM_FATAL, 50 PCI_MA, PCI_STAT_R_MAST_AB, PCI_TARG_MA, DDI_FM_UNKNOWN, 51 PCI_REC_TA, PCI_STAT_R_TARG_AB, PCI_TARG_REC_TA, DDI_FM_UNKNOWN, 52 PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, DDI_FM_UNKNOWN, 53 NULL, NULL, NULL, NULL, 54 }; 55 56 pci_fm_err_t pci_bdg_err_tbl[] = { 57 PCI_DET_PERR, PCI_STAT_PERROR, NULL, DDI_FM_UNKNOWN, 58 PCI_MDPE, PCI_STAT_S_PERROR, PCI_TARG_MDPE, DDI_FM_UNKNOWN, 59 PCI_REC_SERR, PCI_STAT_S_SYSERR, NULL, DDI_FM_UNKNOWN, 60 #if defined(__sparc) 61 PCI_MA, PCI_STAT_R_MAST_AB, PCI_TARG_MA, DDI_FM_UNKNOWN, 62 #endif 63 PCI_REC_TA, PCI_STAT_R_TARG_AB, PCI_TARG_REC_TA, DDI_FM_UNKNOWN, 64 PCI_SIG_TA, PCI_STAT_S_TARG_AB, NULL, DDI_FM_UNKNOWN, 65 NULL, NULL, NULL, NULL, 66 }; 67 68 static pci_fm_err_t pcix_err_tbl[] = { 69 PCIX_SPL_DIS, PCI_PCIX_SPL_DSCD, NULL, DDI_FM_UNKNOWN, 70 PCIX_UNEX_SPL, PCI_PCIX_UNEX_SPL, NULL, DDI_FM_UNKNOWN, 71 PCIX_RX_SPL_MSG, PCI_PCIX_RX_SPL_MSG, NULL, DDI_FM_UNKNOWN, 72 NULL, NULL, NULL, NULL, 73 }; 74 75 static pci_fm_err_t pcix_sec_err_tbl[] = { 76 PCIX_SPL_DIS, PCI_PCIX_BSS_SPL_DSCD, NULL, DDI_FM_UNKNOWN, 77 PCIX_UNEX_SPL, PCI_PCIX_BSS_UNEX_SPL, NULL, DDI_FM_UNKNOWN, 78 PCIX_BSS_SPL_OR, PCI_PCIX_BSS_SPL_OR, NULL, DDI_FM_OK, 79 PCIX_BSS_SPL_DLY, PCI_PCIX_BSS_SPL_DLY, NULL, DDI_FM_OK, 80 NULL, NULL, NULL, NULL, 81 }; 82 83 static int 84 pci_config_check(ddi_acc_handle_t handle, int fme_flag) 85 { 86 ddi_acc_hdl_t *hp = impl_acc_hdl_get(handle); 87 ddi_fm_error_t de; 88 89 if (!(DDI_FM_ACC_ERR_CAP(ddi_fm_capable(hp->ah_dip)))) 90 return (DDI_FM_OK); 91 92 de.fme_version = DDI_FME_VERSION; 93 94 ddi_fm_acc_err_get(handle, &de, de.fme_version); 95 if (de.fme_status != DDI_FM_OK) { 96 if (fme_flag == DDI_FM_ERR_UNEXPECTED) { 97 char buf[FM_MAX_CLASS]; 98 99 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", 100 PCI_ERROR_SUBCLASS, PCI_NR); 101 ddi_fm_ereport_post(hp->ah_dip, buf, de.fme_ena, 102 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, NULL); 103 } 104 ddi_fm_acc_err_clear(handle, de.fme_version); 105 } 106 return (de.fme_status); 107 } 108 109 static void 110 pcix_ecc_regs_gather(pci_erpt_t *erpt_p, pcix_ecc_regs_t *pcix_ecc_regs, 111 uint8_t pcix_cap_ptr, int fme_flag) 112 { 113 int bdg = erpt_p->pe_dflags & PCI_BRIDGE_DEV; 114 115 pcix_ecc_regs->pcix_ecc_ctlstat = pci_config_get32(erpt_p->pe_hdl, 116 (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_STATUS : 117 PCI_PCIX_ECC_STATUS))); 118 if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK) 119 pcix_ecc_regs->pcix_ecc_vflags |= PCIX_ERR_ECC_STS_VALID; 120 else 121 return; 122 pcix_ecc_regs->pcix_ecc_fstaddr = pci_config_get32(erpt_p->pe_hdl, 123 (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_FST_AD : 124 PCI_PCIX_ECC_FST_AD))); 125 pcix_ecc_regs->pcix_ecc_secaddr = pci_config_get32(erpt_p->pe_hdl, 126 (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_SEC_AD : 127 PCI_PCIX_ECC_SEC_AD))); 128 pcix_ecc_regs->pcix_ecc_attr = pci_config_get32(( 129 ddi_acc_handle_t)erpt_p->pe_hdl, 130 (pcix_cap_ptr + (bdg ? PCI_PCIX_BDG_ECC_ATTR : PCI_PCIX_ECC_ATTR))); 131 } 132 133 static void 134 pcix_regs_gather(pci_erpt_t *erpt_p, void *pe_regs, int fme_flag) 135 { 136 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 137 pcix_bdg_error_regs_t *pcix_bdg_regs = 138 (pcix_bdg_error_regs_t *)pe_regs; 139 uint8_t pcix_bdg_cap_ptr; 140 int i; 141 142 pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr; 143 pcix_bdg_regs->pcix_bdg_sec_stat = pci_config_get16( 144 erpt_p->pe_hdl, (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS)); 145 if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK) 146 pcix_bdg_regs->pcix_bdg_vflags |= 147 PCIX_BDG_SEC_STATUS_VALID; 148 else 149 return; 150 pcix_bdg_regs->pcix_bdg_stat = pci_config_get32(erpt_p->pe_hdl, 151 (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS)); 152 if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK) 153 pcix_bdg_regs->pcix_bdg_vflags |= PCIX_BDG_STATUS_VALID; 154 else 155 return; 156 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) { 157 pcix_ecc_regs_t *pcix_bdg_ecc_regs; 158 159 for (i = 0; i < 2; i++) { 160 pcix_bdg_ecc_regs = 161 pcix_bdg_regs->pcix_bdg_ecc_regs[i]; 162 pci_config_put32(erpt_p->pe_hdl, 163 (pcix_bdg_cap_ptr + 164 PCI_PCIX_BDG_ECC_STATUS), i); 165 pcix_ecc_regs_gather(erpt_p, 166 pcix_bdg_ecc_regs, 167 pcix_bdg_cap_ptr, fme_flag); 168 } 169 } 170 } else { 171 pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs; 172 uint8_t pcix_cap_ptr; 173 174 pcix_cap_ptr = pcix_regs->pcix_cap_ptr; 175 176 pcix_regs->pcix_command = pci_config_get16(erpt_p->pe_hdl, 177 (pcix_cap_ptr + PCI_PCIX_COMMAND)); 178 pcix_regs->pcix_status = pci_config_get32(erpt_p->pe_hdl, 179 (pcix_cap_ptr + PCI_PCIX_STATUS)); 180 if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK) 181 pcix_regs->pcix_vflags |= PCIX_ERR_STATUS_VALID; 182 else 183 return; 184 if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) { 185 pcix_ecc_regs_t *pcix_ecc_regs = 186 pcix_regs->pcix_ecc_regs; 187 188 pcix_ecc_regs_gather(erpt_p, pcix_ecc_regs, 189 pcix_cap_ptr, fme_flag); 190 } 191 } 192 } 193 194 /*ARGSUSED*/ 195 static void 196 pci_regs_gather(dev_info_t *dip, pci_erpt_t *erpt_p, int fme_flag) 197 { 198 pci_error_regs_t *pci_regs = erpt_p->pe_pci_regs; 199 200 /* 201 * Start by reading all the error registers that are available for 202 * pci and pci express and for leaf devices and bridges/switches 203 */ 204 pci_regs->pci_err_status = pci_config_get16(erpt_p->pe_hdl, 205 PCI_CONF_STAT); 206 if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK) 207 return; 208 pci_regs->pci_vflags |= PCI_ERR_STATUS_VALID; 209 pci_regs->pci_cfg_comm = pci_config_get16(erpt_p->pe_hdl, 210 PCI_CONF_COMM); 211 if (pci_config_check(erpt_p->pe_hdl, fme_flag) != DDI_FM_OK) 212 return; 213 214 /* 215 * If pci-pci bridge grab PCI bridge specific error registers. 216 */ 217 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 218 pci_regs->pci_bdg_regs->pci_bdg_sec_stat = 219 pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS); 220 if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK) 221 pci_regs->pci_bdg_regs->pci_bdg_vflags |= 222 PCI_BDG_SEC_STAT_VALID; 223 pci_regs->pci_bdg_regs->pci_bdg_ctrl = 224 pci_config_get16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL); 225 if (pci_config_check(erpt_p->pe_hdl, fme_flag) == DDI_FM_OK) 226 pci_regs->pci_bdg_regs->pci_bdg_vflags |= 227 PCI_BDG_CTRL_VALID; 228 } 229 230 /* If pci-x device grab error registers */ 231 if (erpt_p->pe_dflags & PCIX_DEV) 232 pcix_regs_gather(erpt_p, erpt_p->pe_regs, fme_flag); 233 234 } 235 236 static void 237 pcix_regs_clear(pci_erpt_t *erpt_p, void *pe_regs) 238 { 239 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 240 pcix_bdg_error_regs_t *pcix_bdg_regs = 241 (pcix_bdg_error_regs_t *)pe_regs; 242 uint8_t pcix_bdg_cap_ptr; 243 int i; 244 245 pcix_bdg_cap_ptr = pcix_bdg_regs->pcix_bdg_cap_ptr; 246 247 if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID) 248 pci_config_put16(erpt_p->pe_hdl, 249 (pcix_bdg_cap_ptr + PCI_PCIX_SEC_STATUS), 250 pcix_bdg_regs->pcix_bdg_sec_stat); 251 252 if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID) 253 pci_config_put32(erpt_p->pe_hdl, 254 (pcix_bdg_cap_ptr + PCI_PCIX_BDG_STATUS), 255 pcix_bdg_regs->pcix_bdg_stat); 256 257 pcix_bdg_regs->pcix_bdg_vflags = 0x0; 258 259 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) { 260 pcix_ecc_regs_t *pcix_bdg_ecc_regs; 261 for (i = 0; i < 2; i++) { 262 pcix_bdg_ecc_regs = 263 pcix_bdg_regs->pcix_bdg_ecc_regs[i]; 264 265 if (pcix_bdg_ecc_regs->pcix_ecc_vflags & 266 PCIX_ERR_ECC_STS_VALID) { 267 pci_config_put32(erpt_p->pe_hdl, 268 (pcix_bdg_cap_ptr + 269 PCI_PCIX_BDG_ECC_STATUS), 270 i); 271 272 pci_config_put32(erpt_p->pe_hdl, 273 (pcix_bdg_cap_ptr + 274 PCI_PCIX_BDG_ECC_STATUS), 275 pcix_bdg_ecc_regs-> 276 pcix_ecc_ctlstat); 277 } 278 pcix_bdg_ecc_regs->pcix_ecc_vflags = 279 0x0; 280 } 281 } 282 } else { 283 pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)pe_regs; 284 uint8_t pcix_cap_ptr; 285 286 pcix_cap_ptr = pcix_regs->pcix_cap_ptr; 287 288 if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID) 289 pci_config_put32(erpt_p->pe_hdl, 290 (pcix_cap_ptr + PCI_PCIX_STATUS), 291 pcix_regs->pcix_status); 292 293 pcix_regs->pcix_vflags = 0x0; 294 295 if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) { 296 pcix_ecc_regs_t *pcix_ecc_regs = 297 pcix_regs->pcix_ecc_regs; 298 299 if (pcix_ecc_regs->pcix_ecc_vflags & 300 PCIX_ERR_ECC_STS_VALID) 301 pci_config_put32(erpt_p->pe_hdl, 302 (pcix_cap_ptr + PCI_PCIX_ECC_STATUS), 303 pcix_ecc_regs->pcix_ecc_ctlstat); 304 305 pcix_ecc_regs->pcix_ecc_vflags = 0x0; 306 } 307 } 308 } 309 310 static void 311 pci_regs_clear(pci_erpt_t *erpt_p) 312 { 313 /* 314 * Finally clear the error bits 315 */ 316 if (erpt_p->pe_dflags & PCIX_DEV) 317 pcix_regs_clear(erpt_p, erpt_p->pe_regs); 318 319 if (erpt_p->pe_pci_regs->pci_vflags & PCI_ERR_STATUS_VALID) 320 pci_config_put16(erpt_p->pe_hdl, PCI_CONF_STAT, 321 erpt_p->pe_pci_regs->pci_err_status); 322 323 erpt_p->pe_pci_regs->pci_vflags = 0x0; 324 325 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 326 if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags & 327 PCI_BDG_SEC_STAT_VALID) 328 pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_SEC_STATUS, 329 erpt_p->pe_pci_regs->pci_bdg_regs-> 330 pci_bdg_sec_stat); 331 if (erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags & 332 PCI_BDG_CTRL_VALID) 333 pci_config_put16(erpt_p->pe_hdl, PCI_BCNF_BCNTRL, 334 erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_ctrl); 335 336 erpt_p->pe_pci_regs->pci_bdg_regs->pci_bdg_vflags = 0x0; 337 } 338 } 339 340 /* 341 * pcix_ereport_setup: Allocate structures for PCI-X error handling and ereport 342 * generation. 343 */ 344 /* ARGSUSED */ 345 static void 346 pcix_ereport_setup(dev_info_t *dip, pci_erpt_t *erpt_p) 347 { 348 uint16_t pcix_cap_ptr = PCI_CAP_NEXT_PTR_NULL; 349 ddi_acc_handle_t eh; 350 int i; 351 352 if (pci_config_setup(dip, &eh) == DDI_SUCCESS) { 353 (void) PCI_CAP_LOCATE(eh, PCI_CAP_ID_PCIX, &pcix_cap_ptr); 354 pci_config_teardown(&eh); 355 } 356 357 if (pcix_cap_ptr != PCI_CAP_NEXT_PTR_NULL) 358 erpt_p->pe_dflags |= PCIX_DEV; 359 else 360 return; 361 362 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 363 pcix_bdg_error_regs_t *pcix_bdg_regs; 364 365 erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_bdg_error_regs_t), 366 KM_SLEEP); 367 pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs; 368 pcix_bdg_regs->pcix_bdg_cap_ptr = pcix_cap_ptr; 369 pcix_bdg_regs->pcix_bdg_ver = pci_config_get16(erpt_p->pe_hdl, 370 pcix_cap_ptr + PCI_PCIX_SEC_STATUS) & PCI_PCIX_VER_MASK; 371 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) { 372 for (i = 0; i < 2; i++) { 373 pcix_bdg_regs->pcix_bdg_ecc_regs[i] = 374 kmem_zalloc(sizeof (pcix_ecc_regs_t), 375 KM_SLEEP); 376 } 377 } 378 } else { 379 pcix_error_regs_t *pcix_regs; 380 381 erpt_p->pe_regs = kmem_zalloc(sizeof (pcix_error_regs_t), 382 KM_SLEEP); 383 pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs; 384 pcix_regs->pcix_cap_ptr = pcix_cap_ptr; 385 pcix_regs->pcix_ver = pci_config_get16(erpt_p->pe_hdl, 386 pcix_cap_ptr + PCI_PCIX_COMMAND) & PCI_PCIX_VER_MASK; 387 if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) { 388 pcix_regs->pcix_ecc_regs = kmem_zalloc( 389 sizeof (pcix_ecc_regs_t), KM_SLEEP); 390 } 391 } 392 } 393 394 /* 395 * pci_ereport_setup: Detect PCI device type and initialize structures to be 396 * used to generate ereports based on detected generic device errors. 397 */ 398 void 399 pci_ereport_setup(dev_info_t *dip) 400 { 401 struct dev_info *devi = DEVI(dip); 402 struct i_ddi_fmhdl *fmhdl = devi->devi_fmhdl; 403 pci_erpt_t *erpt_p; 404 uint8_t pci_hdr_type; 405 uint16_t pci_status; 406 pci_regspec_t *pci_rp; 407 int32_t len; 408 uint32_t phys_hi; 409 410 /* 411 * If device is not ereport capbable then report an error against the 412 * driver for using this interface, 413 */ 414 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) && 415 !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) { 416 i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP); 417 return; 418 } 419 420 /* 421 * ASSERT fmhdl exists and fh_bus_specific is NULL. 422 */ 423 ASSERT(fmhdl && (fmhdl->fh_bus_specific == NULL)); 424 425 erpt_p = kmem_zalloc(sizeof (pci_erpt_t), KM_SLEEP); 426 427 if (pci_config_setup(dip, &erpt_p->pe_hdl) != DDI_SUCCESS) 428 goto error; 429 430 erpt_p->pe_pci_regs = kmem_zalloc(sizeof (pci_error_regs_t), KM_SLEEP); 431 432 pci_status = pci_config_get16(erpt_p->pe_hdl, PCI_CONF_STAT); 433 if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) != 434 DDI_FM_OK) 435 goto error; 436 437 /* 438 * Get header type and record if device is a bridge. 439 */ 440 pci_hdr_type = pci_config_get8(erpt_p->pe_hdl, PCI_CONF_HEADER); 441 if (pci_config_check(erpt_p->pe_hdl, DDI_FM_ERR_UNEXPECTED) != 442 DDI_FM_OK) 443 goto error; 444 445 /* 446 * Check to see if PCI device is a bridge, if so allocate pci bridge 447 * error register structure. 448 */ 449 if ((pci_hdr_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) { 450 erpt_p->pe_dflags |= PCI_BRIDGE_DEV; 451 erpt_p->pe_pci_regs->pci_bdg_regs = kmem_zalloc( 452 sizeof (pci_bdg_error_regs_t), KM_SLEEP); 453 } 454 455 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", 456 (caddr_t)&pci_rp, &len) == DDI_SUCCESS) { 457 phys_hi = pci_rp->pci_phys_hi; 458 kmem_free(pci_rp, len); 459 460 erpt_p->pe_bdf = (uint16_t)(PCI_REG_BDFR_G(phys_hi) >> 461 PCI_REG_FUNC_SHIFT); 462 } 463 464 if (!(pci_status & PCI_STAT_CAP)) { 465 goto done; 466 } 467 468 /* Initialize structures for PCI-X devices. */ 469 pcix_ereport_setup(dip, erpt_p); 470 471 done: 472 pci_regs_gather(dip, erpt_p, DDI_FM_ERR_UNEXPECTED); 473 pci_regs_clear(erpt_p); 474 475 /* 476 * Before returning set fh_bus_specific to completed pci_erpt_t 477 * structure 478 */ 479 fmhdl->fh_bus_specific = (void *)erpt_p; 480 481 return; 482 error: 483 if (erpt_p->pe_pci_regs) 484 kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t)); 485 kmem_free(erpt_p, sizeof (pci_erpt_t)); 486 erpt_p = NULL; 487 } 488 489 static void 490 pcix_ereport_teardown(pci_erpt_t *erpt_p) 491 { 492 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 493 pcix_bdg_error_regs_t *pcix_bdg_regs; 494 uint16_t pcix_ver; 495 496 pcix_bdg_regs = (pcix_bdg_error_regs_t *)erpt_p->pe_regs; 497 pcix_ver = pcix_bdg_regs->pcix_bdg_ver; 498 if (PCIX_ECC_VER_CHECK(pcix_ver)) { 499 int i; 500 for (i = 0; i < 2; i++) 501 kmem_free(pcix_bdg_regs->pcix_bdg_ecc_regs[i], 502 sizeof (pcix_ecc_regs_t)); 503 } 504 kmem_free(erpt_p->pe_regs, sizeof (pcix_bdg_error_regs_t)); 505 } else { 506 pcix_error_regs_t *pcix_regs; 507 uint16_t pcix_ver; 508 509 pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs; 510 pcix_ver = pcix_regs->pcix_ver; 511 if (PCIX_ECC_VER_CHECK(pcix_ver)) { 512 kmem_free(pcix_regs->pcix_ecc_regs, 513 sizeof (pcix_ecc_regs_t)); 514 } 515 kmem_free(erpt_p->pe_regs, sizeof (pcix_error_regs_t)); 516 } 517 } 518 519 void 520 pci_ereport_teardown(dev_info_t *dip) 521 { 522 struct i_ddi_fmhdl *fmhdl = DEVI(dip)->devi_fmhdl; 523 pci_erpt_t *erpt_p; 524 525 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) && 526 !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) { 527 i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_SLEEP); 528 } 529 530 ASSERT(fmhdl); 531 532 erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific; 533 if (erpt_p == NULL) 534 return; 535 536 if (erpt_p->pe_dflags & PCIX_DEV) 537 pcix_ereport_teardown(erpt_p); 538 pci_config_teardown((ddi_acc_handle_t *)&erpt_p->pe_hdl); 539 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) 540 kmem_free(erpt_p->pe_pci_regs->pci_bdg_regs, 541 sizeof (pci_bdg_error_regs_t)); 542 kmem_free(erpt_p->pe_pci_regs, sizeof (pci_error_regs_t)); 543 kmem_free(erpt_p, sizeof (pci_erpt_t)); 544 fmhdl->fh_bus_specific = NULL; 545 546 /* 547 * The following sparc specific code should be removed once the pci_cap 548 * interfaces create the necessary properties for us. 549 */ 550 } 551 552 /*ARGSUSED*/ 553 static int 554 pcix_check_addr(dev_info_t *dip, ddi_fm_error_t *derr, 555 pcix_ecc_regs_t *pcix_ecc_regs, int type) 556 { 557 int cmd = (pcix_ecc_regs->pcix_ecc_ctlstat >> 16) & 0xf; 558 uint64_t addr; 559 pci_fme_bus_specific_t *pci_fme_bsp = 560 (pci_fme_bus_specific_t *)derr->fme_bus_specific; 561 562 addr = pcix_ecc_regs->pcix_ecc_secaddr; 563 addr = addr << 32; 564 addr |= pcix_ecc_regs->pcix_ecc_fstaddr; 565 566 switch (cmd) { 567 case PCI_PCIX_CMD_INTR: 568 case PCI_PCIX_CMD_SPEC: 569 return (DDI_FM_FATAL); 570 case PCI_PCIX_CMD_IORD: 571 case PCI_PCIX_CMD_IOWR: 572 pci_fme_bsp->pci_bs_addr = addr; 573 pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID; 574 pci_fme_bsp->pci_bs_type = type; 575 return (DDI_FM_UNKNOWN); 576 case PCI_PCIX_CMD_DEVID: 577 return (DDI_FM_FATAL); 578 case PCI_PCIX_CMD_MEMRD_DW: 579 case PCI_PCIX_CMD_MEMWR: 580 case PCI_PCIX_CMD_MEMRD_BL: 581 case PCI_PCIX_CMD_MEMWR_BL: 582 pci_fme_bsp->pci_bs_addr = addr; 583 pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID; 584 pci_fme_bsp->pci_bs_type = type; 585 return (DDI_FM_UNKNOWN); 586 case PCI_PCIX_CMD_CFRD: 587 case PCI_PCIX_CMD_CFWR: 588 /* 589 * for type 1 config transaction we can find bdf from address 590 */ 591 if ((addr & 3) == 1) { 592 pci_fme_bsp->pci_bs_bdf = (addr >> 8) & 0xffffffff; 593 pci_fme_bsp->pci_bs_flags |= PCI_BS_BDF_VALID; 594 pci_fme_bsp->pci_bs_type = type; 595 } 596 return (DDI_FM_UNKNOWN); 597 case PCI_PCIX_CMD_SPL: 598 case PCI_PCIX_CMD_DADR: 599 return (DDI_FM_UNKNOWN); 600 case PCI_PCIX_CMD_MEMRDBL: 601 case PCI_PCIX_CMD_MEMWRBL: 602 pci_fme_bsp->pci_bs_addr = addr; 603 pci_fme_bsp->pci_bs_flags |= PCI_BS_ADDR_VALID; 604 pci_fme_bsp->pci_bs_type = type; 605 return (DDI_FM_UNKNOWN); 606 default: 607 return (DDI_FM_FATAL); 608 } 609 } 610 611 /*ARGSUSED*/ 612 static int 613 pci_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p) 614 { 615 pci_bdg_error_regs_t *pci_bdg_regs = erpt_p->pe_pci_regs->pci_bdg_regs; 616 int fatal = 0; 617 int nonfatal = 0; 618 int unknown = 0; 619 int ok = 0; 620 int ret = DDI_FM_OK; 621 char buf[FM_MAX_CLASS]; 622 int i; 623 pci_fme_bus_specific_t *pci_fme_bsp = 624 (pci_fme_bus_specific_t *)derr->fme_bus_specific; 625 626 if (derr->fme_flag != DDI_FM_ERR_UNEXPECTED) 627 goto done; 628 629 if ((pci_bdg_regs->pci_bdg_vflags & PCI_BDG_CTRL_VALID) && 630 (pci_bdg_regs->pci_bdg_ctrl & PCI_BCNF_BCNTRL_DTO_STAT)) { 631 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", 632 PCI_ERROR_SUBCLASS, PCI_DTO); 633 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 634 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 635 PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16, 636 pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL, 637 DATA_TYPE_UINT16, pci_bdg_regs->pci_bdg_ctrl, NULL); 638 unknown++; 639 } 640 641 if (pci_bdg_regs->pci_bdg_vflags & PCI_BDG_SEC_STAT_VALID) { 642 for (i = 0; pci_bdg_err_tbl[i].err_class != NULL; i++) { 643 if (pci_bdg_regs->pci_bdg_sec_stat & 644 pci_bdg_err_tbl[i].reg_bit) { 645 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s", 646 PCI_ERROR_SUBCLASS, PCI_SEC_ERROR_SUBCLASS, 647 pci_bdg_err_tbl[i].err_class); 648 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 649 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 650 PCI_SEC_CONFIG_STATUS, DATA_TYPE_UINT16, 651 pci_bdg_regs->pci_bdg_sec_stat, PCI_BCNTRL, 652 DATA_TYPE_UINT16, 653 pci_bdg_regs->pci_bdg_ctrl, NULL); 654 PCI_FM_SEV_INC(pci_bdg_err_tbl[i].flags); 655 if (pci_fme_bsp && (pci_fme_bsp->pci_bs_flags & 656 PCI_BS_ADDR_VALID) && 657 pci_fme_bsp->pci_bs_type == ACC_HANDLE && 658 pci_bdg_err_tbl[i].terr_class) 659 pci_target_enqueue(derr->fme_ena, 660 pci_bdg_err_tbl[i].terr_class, 661 PCI_ERROR_SUBCLASS, 662 pci_fme_bsp->pci_bs_addr); 663 } 664 } 665 } 666 667 done: 668 /* 669 * Need to check for poke and cautious put. We already know peek 670 * and cautious get errors occurred (as we got a trap) and we know 671 * they are nonfatal. 672 */ 673 if (derr->fme_flag == DDI_FM_ERR_EXPECTED) { 674 /* 675 * for cautious puts we treat all errors as nonfatal. Actually 676 * we set nonfatal for cautious gets as well - doesn't do any 677 * harm 678 */ 679 if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB | 680 PCI_STAT_R_MAST_AB | PCI_STAT_S_PERROR | PCI_STAT_S_SYSERR)) 681 nonfatal++; 682 } 683 if (derr->fme_flag == DDI_FM_ERR_POKE) { 684 /* 685 * special case for pokes - we only consider master abort 686 * and target abort as nonfatal. Sserr with no master abort is 687 * fatal, but master/target abort can come in on separate 688 * instance, so return unknown and parent will determine if 689 * nonfatal (if another child returned nonfatal - ie master 690 * or target abort) or fatal otherwise 691 */ 692 if (pci_bdg_regs->pci_bdg_sec_stat & (PCI_STAT_R_TARG_AB | 693 PCI_STAT_R_MAST_AB)) 694 nonfatal++; 695 if (erpt_p->pe_pci_regs->pci_err_status & PCI_STAT_S_SYSERR) 696 unknown++; 697 } 698 699 /* 700 * now check children below the bridge 701 */ 702 ret = ndi_fm_handler_dispatch(dip, NULL, derr); 703 PCI_FM_SEV_INC(ret); 704 return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL : 705 (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK))); 706 } 707 708 static int 709 pcix_ecc_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p, 710 void *pe_regs) 711 { 712 pcix_error_regs_t *pcix_regs; 713 pcix_bdg_error_regs_t *pcix_bdg_regs; 714 pcix_ecc_regs_t *pcix_ecc_regs; 715 int bridge; 716 int i; 717 int ecc_phase; 718 int ecc_corr; 719 int sec_ue; 720 int sec_ce; 721 int fatal = 0; 722 int nonfatal = 0; 723 int unknown = 0; 724 int ok = 0; 725 char buf[FM_MAX_CLASS]; 726 727 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 728 pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs; 729 bridge = 1; 730 } else { 731 pcix_regs = (pcix_error_regs_t *)pe_regs; 732 bridge = 0; 733 } 734 735 for (i = 0; i < (bridge ? 2 : 1); i++) { 736 int ret = DDI_FM_OK; 737 pcix_ecc_regs = bridge ? pcix_bdg_regs->pcix_bdg_ecc_regs[i] : 738 pcix_regs->pcix_ecc_regs; 739 if (pcix_ecc_regs->pcix_ecc_vflags & PCIX_ERR_ECC_STS_VALID) { 740 ecc_phase = (pcix_ecc_regs->pcix_ecc_ctlstat & 741 PCI_PCIX_ECC_PHASE) >> 0x4; 742 ecc_corr = (pcix_ecc_regs->pcix_ecc_ctlstat & 743 PCI_PCIX_ECC_CORR); 744 sec_ue = (pcix_ecc_regs->pcix_ecc_ctlstat & 745 PCI_PCIX_ECC_S_UE); 746 sec_ce = (pcix_ecc_regs->pcix_ecc_ctlstat & 747 PCI_PCIX_ECC_S_CE); 748 749 switch (ecc_phase) { 750 case PCI_PCIX_ECC_PHASE_NOERR: 751 break; 752 case PCI_PCIX_ECC_PHASE_FADDR: 753 case PCI_PCIX_ECC_PHASE_SADDR: 754 PCI_FM_SEV_INC(ecc_corr ? DDI_FM_OK : 755 DDI_FM_FATAL); 756 (void) snprintf(buf, FM_MAX_CLASS, 757 "%s.%s%s", PCIX_ERROR_SUBCLASS, 758 i ? PCIX_SEC_ERROR_SUBCLASS : "", 759 ecc_corr ? PCIX_ECC_CE_ADDR : 760 PCIX_ECC_UE_ADDR); 761 break; 762 case PCI_PCIX_ECC_PHASE_ATTR: 763 PCI_FM_SEV_INC(ecc_corr ? 764 DDI_FM_OK : DDI_FM_FATAL); 765 (void) snprintf(buf, FM_MAX_CLASS, 766 "%s.%s%s", PCIX_ERROR_SUBCLASS, 767 i ? PCIX_SEC_ERROR_SUBCLASS : "", 768 ecc_corr ? PCIX_ECC_CE_ATTR : 769 PCIX_ECC_UE_ATTR); 770 break; 771 case PCI_PCIX_ECC_PHASE_DATA32: 772 case PCI_PCIX_ECC_PHASE_DATA64: 773 if (ecc_corr) 774 ret = DDI_FM_OK; 775 else { 776 int type; 777 pci_error_regs_t *pci_regs = 778 erpt_p->pe_pci_regs; 779 780 if (i) { 781 if (pci_regs->pci_bdg_regs-> 782 pci_bdg_sec_stat & 783 PCI_STAT_S_PERROR) 784 type = ACC_HANDLE; 785 else 786 type = DMA_HANDLE; 787 } else { 788 if (pci_regs->pci_err_status & 789 PCI_STAT_S_PERROR) 790 type = DMA_HANDLE; 791 else 792 type = ACC_HANDLE; 793 } 794 ret = pcix_check_addr(dip, derr, 795 pcix_ecc_regs, type); 796 } 797 PCI_FM_SEV_INC(ret); 798 799 (void) snprintf(buf, FM_MAX_CLASS, 800 "%s.%s%s", PCIX_ERROR_SUBCLASS, 801 i ? PCIX_SEC_ERROR_SUBCLASS : "", 802 ecc_corr ? PCIX_ECC_CE_DATA : 803 PCIX_ECC_UE_DATA); 804 break; 805 } 806 if (ecc_phase) 807 if (bridge) 808 ddi_fm_ereport_post(dip, buf, 809 derr->fme_ena, 810 DDI_NOSLEEP, FM_VERSION, 811 DATA_TYPE_UINT8, 0, 812 PCIX_SEC_STATUS, DATA_TYPE_UINT16, 813 pcix_bdg_regs->pcix_bdg_sec_stat, 814 PCIX_BDG_STAT, DATA_TYPE_UINT32, 815 pcix_bdg_regs->pcix_bdg_stat, 816 PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32, 817 pcix_ecc_regs->pcix_ecc_ctlstat, 818 PCIX_ECC_ATTR, DATA_TYPE_UINT32, 819 pcix_ecc_regs->pcix_ecc_attr, NULL); 820 else 821 ddi_fm_ereport_post(dip, buf, 822 derr->fme_ena, 823 DDI_NOSLEEP, FM_VERSION, 824 DATA_TYPE_UINT8, 0, 825 PCIX_COMMAND, DATA_TYPE_UINT16, 826 pcix_regs->pcix_command, 827 PCIX_STATUS, DATA_TYPE_UINT32, 828 pcix_regs->pcix_status, 829 PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32, 830 pcix_ecc_regs->pcix_ecc_ctlstat, 831 PCIX_ECC_ATTR, DATA_TYPE_UINT32, 832 pcix_ecc_regs->pcix_ecc_attr, NULL); 833 if (sec_ce || sec_ue) { 834 (void) snprintf(buf, FM_MAX_CLASS, 835 "%s.%s%s", PCIX_ERROR_SUBCLASS, 836 i ? PCIX_SEC_ERROR_SUBCLASS : "", 837 sec_ce ? PCIX_ECC_S_CE : PCIX_ECC_S_UE); 838 if (bridge) 839 ddi_fm_ereport_post(dip, buf, 840 derr->fme_ena, 841 DDI_NOSLEEP, FM_VERSION, 842 DATA_TYPE_UINT8, 0, 843 PCIX_SEC_STATUS, DATA_TYPE_UINT16, 844 pcix_bdg_regs->pcix_bdg_sec_stat, 845 PCIX_BDG_STAT, DATA_TYPE_UINT32, 846 pcix_bdg_regs->pcix_bdg_stat, 847 PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32, 848 pcix_ecc_regs->pcix_ecc_ctlstat, 849 PCIX_ECC_ATTR, DATA_TYPE_UINT32, 850 pcix_ecc_regs->pcix_ecc_attr, NULL); 851 else 852 ddi_fm_ereport_post(dip, buf, 853 derr->fme_ena, 854 DDI_NOSLEEP, FM_VERSION, 855 DATA_TYPE_UINT8, 0, 856 PCIX_COMMAND, DATA_TYPE_UINT16, 857 pcix_regs->pcix_command, 858 PCIX_STATUS, DATA_TYPE_UINT32, 859 pcix_regs->pcix_status, 860 PCIX_ECC_CTLSTAT, DATA_TYPE_UINT32, 861 pcix_ecc_regs->pcix_ecc_ctlstat, 862 PCIX_ECC_ATTR, DATA_TYPE_UINT32, 863 pcix_ecc_regs->pcix_ecc_attr, NULL); 864 PCI_FM_SEV_INC(sec_ue ? DDI_FM_FATAL : 865 DDI_FM_OK); 866 } 867 } 868 } 869 return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL : 870 (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK))); 871 } 872 873 static int 874 pcix_bdg_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p, 875 void *pe_regs) 876 { 877 pcix_bdg_error_regs_t *pcix_bdg_regs = (pcix_bdg_error_regs_t *)pe_regs; 878 int fatal = 0; 879 int nonfatal = 0; 880 int unknown = 0; 881 int ok = 0; 882 char buf[FM_MAX_CLASS]; 883 int i; 884 885 if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_STATUS_VALID) { 886 for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) { 887 if ((pcix_bdg_regs->pcix_bdg_stat & 888 pcix_err_tbl[i].reg_bit)) { 889 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", 890 PCIX_ERROR_SUBCLASS, 891 pcix_err_tbl[i].err_class); 892 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 893 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 894 PCIX_SEC_STATUS, DATA_TYPE_UINT16, 895 pcix_bdg_regs->pcix_bdg_sec_stat, 896 PCIX_BDG_STAT, DATA_TYPE_UINT32, 897 pcix_bdg_regs->pcix_bdg_stat, NULL); 898 PCI_FM_SEV_INC(pcix_err_tbl[i].flags); 899 } 900 } 901 } 902 903 if (pcix_bdg_regs->pcix_bdg_vflags & PCIX_BDG_SEC_STATUS_VALID) { 904 for (i = 0; pcix_sec_err_tbl[i].err_class != NULL; i++) { 905 if ((pcix_bdg_regs->pcix_bdg_sec_stat & 906 pcix_sec_err_tbl[i].reg_bit)) { 907 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s%s", 908 PCIX_ERROR_SUBCLASS, 909 PCIX_SEC_ERROR_SUBCLASS, 910 pcix_sec_err_tbl[i].err_class); 911 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 912 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 913 PCIX_SEC_STATUS, DATA_TYPE_UINT16, 914 pcix_bdg_regs->pcix_bdg_sec_stat, 915 PCIX_BDG_STAT, DATA_TYPE_UINT32, 916 pcix_bdg_regs->pcix_bdg_stat, NULL); 917 PCI_FM_SEV_INC(pcix_sec_err_tbl[i].flags); 918 } 919 } 920 } 921 922 /* Log/Handle ECC errors */ 923 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs->pcix_bdg_ver)) { 924 int ret; 925 926 ret = pcix_ecc_error_report(dip, derr, erpt_p, 927 (void *)pcix_bdg_regs); 928 PCI_FM_SEV_INC(ret); 929 } 930 return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL : 931 (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK))); 932 } 933 934 static int 935 pcix_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p) 936 { 937 pcix_error_regs_t *pcix_regs = (pcix_error_regs_t *)erpt_p->pe_regs; 938 int fatal = 0; 939 int nonfatal = 0; 940 int unknown = 0; 941 int ok = 0; 942 char buf[FM_MAX_CLASS]; 943 int i; 944 945 if (pcix_regs->pcix_vflags & PCIX_ERR_STATUS_VALID) { 946 for (i = 0; pcix_err_tbl[i].err_class != NULL; i++) { 947 if (!(pcix_regs->pcix_status & pcix_err_tbl[i].reg_bit)) 948 continue; 949 950 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", 951 PCIX_ERROR_SUBCLASS, pcix_err_tbl[i].err_class); 952 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 953 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 954 PCIX_COMMAND, DATA_TYPE_UINT16, 955 pcix_regs->pcix_command, PCIX_STATUS, 956 DATA_TYPE_UINT32, pcix_regs->pcix_status, 957 NULL); 958 PCI_FM_SEV_INC(pcix_err_tbl[i].flags); 959 } 960 } 961 /* Log/Handle ECC errors */ 962 if (PCIX_ECC_VER_CHECK(pcix_regs->pcix_ver)) { 963 int ret = pcix_ecc_error_report(dip, derr, erpt_p, 964 (void *)pcix_regs); 965 PCI_FM_SEV_INC(ret); 966 } 967 968 return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL : 969 (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK))); 970 } 971 972 static void 973 pci_error_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_erpt_t *erpt_p) 974 { 975 int fatal = 0; 976 int nonfatal = 0; 977 int unknown = 0; 978 int ok = 0; 979 char buf[FM_MAX_CLASS]; 980 int i; 981 982 if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) { 983 /* 984 * Log generic PCI errors. 985 */ 986 for (i = 0; pci_err_tbl[i].err_class != NULL; i++) { 987 if (!(erpt_p->pe_pci_regs->pci_err_status & 988 pci_err_tbl[i].reg_bit) || 989 !(erpt_p->pe_pci_regs->pci_vflags & 990 PCI_ERR_STATUS_VALID)) 991 continue; 992 /* 993 * Generate an ereport for this error bit. 994 */ 995 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", 996 PCI_ERROR_SUBCLASS, pci_err_tbl[i].err_class); 997 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 998 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 999 PCI_CONFIG_STATUS, DATA_TYPE_UINT16, 1000 erpt_p->pe_pci_regs->pci_err_status, 1001 PCI_CONFIG_COMMAND, DATA_TYPE_UINT16, 1002 erpt_p->pe_pci_regs->pci_cfg_comm, NULL); 1003 1004 PCI_FM_SEV_INC(pci_err_tbl[i].flags); 1005 } 1006 if (erpt_p->pe_dflags & PCIX_DEV) { 1007 if (erpt_p->pe_dflags & PCI_BRIDGE_DEV) { 1008 int ret = pcix_bdg_error_report(dip, derr, 1009 erpt_p, erpt_p->pe_regs); 1010 PCI_FM_SEV_INC(ret); 1011 } else { 1012 int ret = pcix_error_report(dip, derr, erpt_p); 1013 PCI_FM_SEV_INC(ret); 1014 } 1015 } 1016 } 1017 1018 if ((erpt_p->pe_dflags & PCI_BRIDGE_DEV)) { 1019 int ret = pci_bdg_error_report(dip, derr, erpt_p); 1020 PCI_FM_SEV_INC(ret); 1021 } 1022 1023 if (derr->fme_flag == DDI_FM_ERR_UNEXPECTED) { 1024 pci_fme_bus_specific_t *pci_fme_bsp; 1025 int ret = DDI_FM_UNKNOWN; 1026 1027 pci_fme_bsp = (pci_fme_bus_specific_t *)derr->fme_bus_specific; 1028 if (pci_fme_bsp->pci_bs_flags & PCI_BS_ADDR_VALID) { 1029 ret = ndi_fmc_entry_error(dip, 1030 pci_fme_bsp->pci_bs_type, derr, 1031 (void *)&pci_fme_bsp->pci_bs_addr); 1032 PCI_FM_SEV_INC(ret); 1033 } 1034 /* 1035 * If we didn't find the handle using an addr, try using bdf. 1036 * Note we don't do this where the bdf is for a 1037 * device behind a pciex/pci bridge as the bridge may have 1038 * fabricated the bdf. 1039 */ 1040 if (ret == DDI_FM_UNKNOWN && 1041 (pci_fme_bsp->pci_bs_flags & PCI_BS_BDF_VALID) && 1042 pci_fme_bsp->pci_bs_bdf == erpt_p->pe_bdf) { 1043 ret = ndi_fmc_entry_error_all(dip, 1044 pci_fme_bsp->pci_bs_type, derr); 1045 PCI_FM_SEV_INC(ret); 1046 } 1047 } 1048 1049 derr->fme_status = (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL : 1050 (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK))); 1051 } 1052 1053 void 1054 pci_ereport_post(dev_info_t *dip, ddi_fm_error_t *derr, uint16_t *xx_status) 1055 { 1056 struct i_ddi_fmhdl *fmhdl; 1057 pci_erpt_t *erpt_p; 1058 ddi_fm_error_t de; 1059 pci_fme_bus_specific_t pci_fme_bs; 1060 1061 /* 1062 * On PCI Express systems, all error handling and ereport are done via 1063 * the PCIe misc module. This function is a no-op for PCIe Systems. In 1064 * order to tell if a system is a PCI or PCIe system, check that the 1065 * bus_private_data exists. If it exists, this is a PCIe system. 1066 */ 1067 if (ndi_get_bus_private(dip, B_TRUE)) { 1068 derr->fme_status = DDI_FM_OK; 1069 if (xx_status != NULL) 1070 *xx_status = 0x0; 1071 1072 return; 1073 } 1074 1075 fmhdl = DEVI(dip)->devi_fmhdl; 1076 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip)) && 1077 !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip))) { 1078 i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, DDI_NOSLEEP); 1079 return; 1080 } 1081 1082 /* 1083 * copy in the ddi_fm_error_t structure in case it's VER0 1084 */ 1085 de.fme_version = derr->fme_version; 1086 de.fme_status = derr->fme_status; 1087 de.fme_flag = derr->fme_flag; 1088 de.fme_ena = derr->fme_ena; 1089 de.fme_acc_handle = derr->fme_acc_handle; 1090 de.fme_dma_handle = derr->fme_dma_handle; 1091 de.fme_bus_specific = derr->fme_bus_specific; 1092 if (derr->fme_version >= DDI_FME_VER1) 1093 de.fme_bus_type = derr->fme_bus_type; 1094 else 1095 de.fme_bus_type = DDI_FME_BUS_TYPE_DFLT; 1096 if (de.fme_bus_type == DDI_FME_BUS_TYPE_DFLT) { 1097 /* 1098 * if this is the first pci device we've found convert 1099 * fme_bus_specific to DDI_FME_BUS_TYPE_PCI 1100 */ 1101 bzero(&pci_fme_bs, sizeof (pci_fme_bs)); 1102 if (de.fme_bus_specific) { 1103 /* 1104 * the cpu passed us an addr - this can be used to look 1105 * up an access handle 1106 */ 1107 pci_fme_bs.pci_bs_addr = (uintptr_t)de.fme_bus_specific; 1108 pci_fme_bs.pci_bs_type = ACC_HANDLE; 1109 pci_fme_bs.pci_bs_flags |= PCI_BS_ADDR_VALID; 1110 } 1111 de.fme_bus_specific = (void *)&pci_fme_bs; 1112 de.fme_bus_type = DDI_FME_BUS_TYPE_PCI; 1113 } 1114 1115 ASSERT(fmhdl); 1116 1117 if (de.fme_ena == NULL) 1118 de.fme_ena = fm_ena_generate(0, FM_ENA_FMT1); 1119 1120 erpt_p = (pci_erpt_t *)fmhdl->fh_bus_specific; 1121 if (erpt_p == NULL) 1122 return; 1123 1124 pci_regs_gather(dip, erpt_p, de.fme_flag); 1125 pci_error_report(dip, &de, erpt_p); 1126 pci_regs_clear(erpt_p); 1127 1128 derr->fme_status = de.fme_status; 1129 derr->fme_ena = de.fme_ena; 1130 derr->fme_acc_handle = de.fme_acc_handle; 1131 derr->fme_dma_handle = de.fme_dma_handle; 1132 if (xx_status != NULL) 1133 *xx_status = erpt_p->pe_pci_regs->pci_err_status; 1134 } 1135 1136 /* 1137 * private version of walk_devs() that can be used during panic. No 1138 * sleeping or locking required. 1139 */ 1140 static int 1141 pci_fm_walk_devs(dev_info_t *dip, int (*f)(dev_info_t *, void *), void *arg) 1142 { 1143 while (dip) { 1144 switch ((*f)(dip, arg)) { 1145 case DDI_WALK_TERMINATE: 1146 return (DDI_WALK_TERMINATE); 1147 case DDI_WALK_CONTINUE: 1148 if (pci_fm_walk_devs(ddi_get_child(dip), f, 1149 arg) == DDI_WALK_TERMINATE) 1150 return (DDI_WALK_TERMINATE); 1151 break; 1152 case DDI_WALK_PRUNECHILD: 1153 break; 1154 } 1155 dip = ddi_get_next_sibling(dip); 1156 } 1157 return (DDI_WALK_CONTINUE); 1158 } 1159 1160 /* 1161 * need special version of ddi_fm_ereport_post() as the leaf driver may 1162 * not be hardened. 1163 */ 1164 static void 1165 pci_fm_ereport_post(dev_info_t *dip, const char *error_class, uint64_t ena, 1166 uint8_t version, ...) 1167 { 1168 char *name; 1169 char device_path[MAXPATHLEN]; 1170 char ddi_error_class[FM_MAX_CLASS]; 1171 nvlist_t *ereport, *detector; 1172 nv_alloc_t *nva; 1173 errorq_elem_t *eqep; 1174 va_list ap; 1175 1176 if (panicstr) { 1177 eqep = errorq_reserve(ereport_errorq); 1178 if (eqep == NULL) 1179 return; 1180 ereport = errorq_elem_nvl(ereport_errorq, eqep); 1181 nva = errorq_elem_nva(ereport_errorq, eqep); 1182 detector = fm_nvlist_create(nva); 1183 } else { 1184 ereport = fm_nvlist_create(NULL); 1185 detector = fm_nvlist_create(NULL); 1186 } 1187 1188 (void) ddi_pathname(dip, device_path); 1189 fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, 1190 device_path, NULL); 1191 (void) snprintf(ddi_error_class, FM_MAX_CLASS, "%s.%s", 1192 DDI_IO_CLASS, error_class); 1193 fm_ereport_set(ereport, version, ddi_error_class, ena, detector, NULL); 1194 1195 va_start(ap, version); 1196 name = va_arg(ap, char *); 1197 (void) i_fm_payload_set(ereport, name, ap); 1198 va_end(ap); 1199 1200 if (panicstr) { 1201 errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC); 1202 } else { 1203 (void) fm_ereport_post(ereport, EVCH_TRYHARD); 1204 fm_nvlist_destroy(ereport, FM_NVA_FREE); 1205 fm_nvlist_destroy(detector, FM_NVA_FREE); 1206 } 1207 } 1208 1209 static int 1210 pci_check_regs(dev_info_t *dip, void *arg) 1211 { 1212 int reglen; 1213 int rn; 1214 int totreg; 1215 pci_regspec_t *drv_regp; 1216 pci_target_err_t *tgt_err = (pci_target_err_t *)arg; 1217 1218 if (tgt_err->tgt_pci_space == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) { 1219 /* 1220 * for config space, we need to check if the given address 1221 * is a valid config space address for this device - based 1222 * on pci_phys_hi of the config space entry in reg property. 1223 */ 1224 if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 1225 "reg", (caddr_t)&drv_regp, ®len) != DDI_SUCCESS) 1226 return (DDI_WALK_CONTINUE); 1227 1228 totreg = reglen / sizeof (pci_regspec_t); 1229 for (rn = 0; rn < totreg; rn++) { 1230 if (tgt_err->tgt_pci_space == 1231 PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi) && 1232 (tgt_err->tgt_pci_addr & (PCI_REG_BUS_M | 1233 PCI_REG_DEV_M | PCI_REG_FUNC_M)) == 1234 (drv_regp[rn].pci_phys_hi & (PCI_REG_BUS_M | 1235 PCI_REG_DEV_M | PCI_REG_FUNC_M))) { 1236 tgt_err->tgt_dip = dip; 1237 kmem_free(drv_regp, reglen); 1238 return (DDI_WALK_TERMINATE); 1239 } 1240 } 1241 kmem_free(drv_regp, reglen); 1242 } else { 1243 /* 1244 * for non config space, need to check reg to look 1245 * for any non-relocable mapping, otherwise check 1246 * assigned-addresses. 1247 */ 1248 if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 1249 "reg", (caddr_t)&drv_regp, ®len) != DDI_SUCCESS) 1250 return (DDI_WALK_CONTINUE); 1251 1252 totreg = reglen / sizeof (pci_regspec_t); 1253 for (rn = 0; rn < totreg; rn++) { 1254 if ((drv_regp[rn].pci_phys_hi & PCI_RELOCAT_B) && 1255 (tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN || 1256 tgt_err->tgt_pci_space == 1257 PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) && 1258 (tgt_err->tgt_pci_addr >= 1259 (uint64_t)drv_regp[rn].pci_phys_low + 1260 ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) && 1261 (tgt_err->tgt_pci_addr < 1262 (uint64_t)drv_regp[rn].pci_phys_low + 1263 ((uint64_t)drv_regp[rn].pci_phys_mid << 32) + 1264 (uint64_t)drv_regp[rn].pci_size_low + 1265 ((uint64_t)drv_regp[rn].pci_size_hi << 32))) { 1266 tgt_err->tgt_dip = dip; 1267 kmem_free(drv_regp, reglen); 1268 return (DDI_WALK_TERMINATE); 1269 } 1270 } 1271 kmem_free(drv_regp, reglen); 1272 1273 if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 1274 "assigned-addresses", (caddr_t)&drv_regp, ®len) != 1275 DDI_SUCCESS) 1276 return (DDI_WALK_CONTINUE); 1277 1278 totreg = reglen / sizeof (pci_regspec_t); 1279 for (rn = 0; rn < totreg; rn++) { 1280 if ((tgt_err->tgt_pci_space == TGT_PCI_SPACE_UNKNOWN || 1281 tgt_err->tgt_pci_space == 1282 PCI_REG_ADDR_G(drv_regp[rn].pci_phys_hi)) && 1283 (tgt_err->tgt_pci_addr >= 1284 (uint64_t)drv_regp[rn].pci_phys_low + 1285 ((uint64_t)drv_regp[rn].pci_phys_mid << 32)) && 1286 (tgt_err->tgt_pci_addr < 1287 (uint64_t)drv_regp[rn].pci_phys_low + 1288 ((uint64_t)drv_regp[rn].pci_phys_mid << 32) + 1289 (uint64_t)drv_regp[rn].pci_size_low + 1290 ((uint64_t)drv_regp[rn].pci_size_hi << 32))) { 1291 tgt_err->tgt_dip = dip; 1292 kmem_free(drv_regp, reglen); 1293 return (DDI_WALK_TERMINATE); 1294 } 1295 } 1296 kmem_free(drv_regp, reglen); 1297 } 1298 return (DDI_WALK_CONTINUE); 1299 } 1300 1301 /* 1302 * impl_fix_ranges - fixes the config space entry of the "ranges" 1303 * property on psycho+ platforms. (if changing this function please make sure 1304 * to change the pci_fix_ranges function in pcipsy.c) 1305 */ 1306 /*ARGSUSED*/ 1307 static void 1308 pci_fix_ranges(dev_info_t *dip, pci_ranges_t *pci_ranges, int nrange) 1309 { 1310 #if defined(__sparc) 1311 char *name = ddi_binding_name(dip); 1312 1313 if ((strcmp(name, "pci108e,8000") == 0) || 1314 (strcmp(name, "pci108e,a000") == 0) || 1315 (strcmp(name, "pci108e,a001") == 0)) { 1316 int i; 1317 for (i = 0; i < nrange; i++, pci_ranges++) 1318 if ((pci_ranges->child_high & PCI_REG_ADDR_M) == 1319 PCI_ADDR_CONFIG) 1320 pci_ranges->parent_low |= 1321 pci_ranges->child_high; 1322 } 1323 #endif 1324 } 1325 1326 static int 1327 pci_check_ranges(dev_info_t *dip, void *arg) 1328 { 1329 uint64_t range_parent_begin; 1330 uint64_t range_parent_size; 1331 uint64_t range_parent_end; 1332 uint32_t space_type; 1333 uint32_t bus_num; 1334 uint32_t range_offset; 1335 pci_ranges_t *pci_ranges, *rangep; 1336 pci_bus_range_t *pci_bus_rangep; 1337 int pci_ranges_length; 1338 int nrange; 1339 pci_target_err_t *tgt_err = (pci_target_err_t *)arg; 1340 int i, size; 1341 if (strcmp(ddi_node_name(dip), "pci") != 0 && 1342 strcmp(ddi_node_name(dip), "pciex") != 0) 1343 return (DDI_WALK_CONTINUE); 1344 1345 /* 1346 * Get the ranges property. Note we only look at the top level pci 1347 * node (hostbridge) which has a ranges property of type pci_ranges_t 1348 * not at pci-pci bridges. 1349 */ 1350 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges", 1351 (caddr_t)&pci_ranges, &pci_ranges_length) != DDI_SUCCESS) { 1352 /* 1353 * no ranges property - no translation needed 1354 */ 1355 tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr; 1356 tgt_err->tgt_pci_space = TGT_PCI_SPACE_UNKNOWN; 1357 if (panicstr) 1358 (void) pci_fm_walk_devs(ddi_get_child(dip), 1359 pci_check_regs, (void *)tgt_err); 1360 else { 1361 int circ = 0; 1362 ndi_devi_enter(dip, &circ); 1363 ddi_walk_devs(ddi_get_child(dip), pci_check_regs, 1364 (void *)tgt_err); 1365 ndi_devi_exit(dip, circ); 1366 } 1367 if (tgt_err->tgt_dip != NULL) 1368 return (DDI_WALK_TERMINATE); 1369 return (DDI_WALK_PRUNECHILD); 1370 } 1371 nrange = pci_ranges_length / sizeof (pci_ranges_t); 1372 rangep = pci_ranges; 1373 1374 /* Need to fix the pci ranges property for psycho based systems */ 1375 pci_fix_ranges(dip, pci_ranges, nrange); 1376 1377 for (i = 0; i < nrange; i++, rangep++) { 1378 range_parent_begin = ((uint64_t)rangep->parent_high << 32) + 1379 rangep->parent_low; 1380 range_parent_size = ((uint64_t)rangep->size_high << 32) + 1381 rangep->size_low; 1382 range_parent_end = range_parent_begin + range_parent_size - 1; 1383 1384 if ((tgt_err->tgt_err_addr < range_parent_begin) || 1385 (tgt_err->tgt_err_addr > range_parent_end)) { 1386 /* Not in range */ 1387 continue; 1388 } 1389 space_type = PCI_REG_ADDR_G(rangep->child_high); 1390 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) { 1391 /* Config space address - check bus range */ 1392 range_offset = tgt_err->tgt_err_addr - 1393 range_parent_begin; 1394 bus_num = PCI_REG_BUS_G(range_offset); 1395 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 1396 DDI_PROP_DONTPASS, "bus-range", 1397 (caddr_t)&pci_bus_rangep, &size) != DDI_SUCCESS) { 1398 continue; 1399 } 1400 if ((bus_num < pci_bus_rangep->lo) || 1401 (bus_num > pci_bus_rangep->hi)) { 1402 /* 1403 * Bus number not appropriate for this 1404 * pci nexus. 1405 */ 1406 kmem_free(pci_bus_rangep, size); 1407 continue; 1408 } 1409 kmem_free(pci_bus_rangep, size); 1410 } 1411 1412 /* We have a match if we get here - compute pci address */ 1413 tgt_err->tgt_pci_addr = tgt_err->tgt_err_addr - 1414 range_parent_begin; 1415 tgt_err->tgt_pci_addr += (((uint64_t)rangep->child_mid << 32) + 1416 rangep->child_low); 1417 tgt_err->tgt_pci_space = space_type; 1418 if (panicstr) 1419 (void) pci_fm_walk_devs(ddi_get_child(dip), 1420 pci_check_regs, (void *)tgt_err); 1421 else { 1422 int circ = 0; 1423 ndi_devi_enter(dip, &circ); 1424 ddi_walk_devs(ddi_get_child(dip), pci_check_regs, 1425 (void *)tgt_err); 1426 ndi_devi_exit(dip, circ); 1427 } 1428 if (tgt_err->tgt_dip != NULL) { 1429 kmem_free(pci_ranges, pci_ranges_length); 1430 return (DDI_WALK_TERMINATE); 1431 } 1432 } 1433 kmem_free(pci_ranges, pci_ranges_length); 1434 return (DDI_WALK_PRUNECHILD); 1435 } 1436 1437 /* 1438 * Function used to drain pci_target_queue, either during panic or after softint 1439 * is generated, to generate target device ereports based on captured physical 1440 * addresses 1441 */ 1442 /*ARGSUSED*/ 1443 static void 1444 pci_target_drain(void *private_p, pci_target_err_t *tgt_err) 1445 { 1446 char buf[FM_MAX_CLASS]; 1447 1448 /* 1449 * The following assumes that all pci_pci bridge devices 1450 * are configured as transparant. Find the top-level pci 1451 * nexus which has tgt_err_addr in one of its ranges, converting this 1452 * to a pci address in the process. Then starting at this node do 1453 * another tree walk to find a device with the pci address we've 1454 * found within range of one of it's assigned-addresses properties. 1455 */ 1456 tgt_err->tgt_dip = NULL; 1457 if (panicstr) 1458 (void) pci_fm_walk_devs(ddi_root_node(), pci_check_ranges, 1459 (void *)tgt_err); 1460 else 1461 ddi_walk_devs(ddi_root_node(), pci_check_ranges, 1462 (void *)tgt_err); 1463 if (tgt_err->tgt_dip == NULL) 1464 return; 1465 1466 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", tgt_err->tgt_bridge_type, 1467 tgt_err->tgt_err_class); 1468 pci_fm_ereport_post(tgt_err->tgt_dip, buf, tgt_err->tgt_err_ena, 0, 1469 PCI_PA, DATA_TYPE_UINT64, tgt_err->tgt_err_addr, NULL); 1470 } 1471 1472 void 1473 pci_target_enqueue(uint64_t ena, char *class, char *bridge_type, uint64_t addr) 1474 { 1475 pci_target_err_t tgt_err; 1476 1477 tgt_err.tgt_err_ena = ena; 1478 tgt_err.tgt_err_class = class; 1479 tgt_err.tgt_bridge_type = bridge_type; 1480 tgt_err.tgt_err_addr = addr; 1481 errorq_dispatch(pci_target_queue, (void *)&tgt_err, 1482 sizeof (pci_target_err_t), ERRORQ_ASYNC); 1483 } 1484 1485 void 1486 pci_targetq_init(void) 1487 { 1488 /* 1489 * PCI target errorq, to schedule async handling of generation of 1490 * target device ereports based on captured physical address. 1491 * The errorq is created here but destroyed when _fini is called 1492 * for the pci module. 1493 */ 1494 if (pci_target_queue == NULL) { 1495 pci_target_queue = errorq_create("pci_target_queue", 1496 (errorq_func_t)pci_target_drain, (void *)NULL, 1497 TARGET_MAX_ERRS, sizeof (pci_target_err_t), FM_ERR_PIL, 1498 ERRORQ_VITAL); 1499 if (pci_target_queue == NULL) 1500 panic("failed to create required system error queue"); 1501 } 1502 } 1503