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