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