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.
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.
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]
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
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>
35 #include <sys/pci_cap.h>
36 #include <sys/pci_impl.h>
38 #include <sys/pcifm.h>
40 #define PCIX_ECC_VER_CHECK(x) (((x) == PCI_PCIX_VER_1) ||\
41 ((x) == PCI_PCIX_VER_2))
43 errorq_t
*pci_target_queue
= NULL
;
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
,
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 PCI_REC_TA
, PCI_STAT_R_TARG_AB
, PCI_TARG_REC_TA
, DDI_FM_UNKNOWN
,
60 PCI_SIG_TA
, PCI_STAT_S_TARG_AB
, NULL
, DDI_FM_UNKNOWN
,
64 static pci_fm_err_t pcix_err_tbl
[] = {
65 PCIX_SPL_DIS
, PCI_PCIX_SPL_DSCD
, NULL
, DDI_FM_UNKNOWN
,
66 PCIX_UNEX_SPL
, PCI_PCIX_UNEX_SPL
, NULL
, DDI_FM_UNKNOWN
,
67 PCIX_RX_SPL_MSG
, PCI_PCIX_RX_SPL_MSG
, NULL
, DDI_FM_UNKNOWN
,
71 static pci_fm_err_t pcix_sec_err_tbl
[] = {
72 PCIX_SPL_DIS
, PCI_PCIX_BSS_SPL_DSCD
, NULL
, DDI_FM_UNKNOWN
,
73 PCIX_UNEX_SPL
, PCI_PCIX_BSS_UNEX_SPL
, NULL
, DDI_FM_UNKNOWN
,
74 PCIX_BSS_SPL_OR
, PCI_PCIX_BSS_SPL_OR
, NULL
, DDI_FM_OK
,
75 PCIX_BSS_SPL_DLY
, PCI_PCIX_BSS_SPL_DLY
, NULL
, DDI_FM_OK
,
80 pci_config_check(ddi_acc_handle_t handle
, int fme_flag
)
82 ddi_acc_hdl_t
*hp
= impl_acc_hdl_get(handle
);
85 if (!(DDI_FM_ACC_ERR_CAP(ddi_fm_capable(hp
->ah_dip
))))
88 de
.fme_version
= DDI_FME_VERSION
;
90 ddi_fm_acc_err_get(handle
, &de
, de
.fme_version
);
91 if (de
.fme_status
!= DDI_FM_OK
) {
92 if (fme_flag
== DDI_FM_ERR_UNEXPECTED
) {
93 char buf
[FM_MAX_CLASS
];
95 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s",
96 PCI_ERROR_SUBCLASS
, PCI_NR
);
97 ddi_fm_ereport_post(hp
->ah_dip
, buf
, de
.fme_ena
,
98 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0, NULL
);
100 ddi_fm_acc_err_clear(handle
, de
.fme_version
);
102 return (de
.fme_status
);
106 pcix_ecc_regs_gather(pci_erpt_t
*erpt_p
, pcix_ecc_regs_t
*pcix_ecc_regs
,
107 uint8_t pcix_cap_ptr
, int fme_flag
)
109 int bdg
= erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
;
111 pcix_ecc_regs
->pcix_ecc_ctlstat
= pci_config_get32(erpt_p
->pe_hdl
,
112 (pcix_cap_ptr
+ (bdg
? PCI_PCIX_BDG_ECC_STATUS
:
113 PCI_PCIX_ECC_STATUS
)));
114 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) == DDI_FM_OK
)
115 pcix_ecc_regs
->pcix_ecc_vflags
|= PCIX_ERR_ECC_STS_VALID
;
118 pcix_ecc_regs
->pcix_ecc_fstaddr
= pci_config_get32(erpt_p
->pe_hdl
,
119 (pcix_cap_ptr
+ (bdg
? PCI_PCIX_BDG_ECC_FST_AD
:
120 PCI_PCIX_ECC_FST_AD
)));
121 pcix_ecc_regs
->pcix_ecc_secaddr
= pci_config_get32(erpt_p
->pe_hdl
,
122 (pcix_cap_ptr
+ (bdg
? PCI_PCIX_BDG_ECC_SEC_AD
:
123 PCI_PCIX_ECC_SEC_AD
)));
124 pcix_ecc_regs
->pcix_ecc_attr
= pci_config_get32((
125 ddi_acc_handle_t
)erpt_p
->pe_hdl
,
126 (pcix_cap_ptr
+ (bdg
? PCI_PCIX_BDG_ECC_ATTR
: PCI_PCIX_ECC_ATTR
)));
130 pcix_regs_gather(pci_erpt_t
*erpt_p
, void *pe_regs
, int fme_flag
)
132 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
133 pcix_bdg_error_regs_t
*pcix_bdg_regs
=
134 (pcix_bdg_error_regs_t
*)pe_regs
;
135 uint8_t pcix_bdg_cap_ptr
;
138 pcix_bdg_cap_ptr
= pcix_bdg_regs
->pcix_bdg_cap_ptr
;
139 pcix_bdg_regs
->pcix_bdg_sec_stat
= pci_config_get16(
140 erpt_p
->pe_hdl
, (pcix_bdg_cap_ptr
+ PCI_PCIX_SEC_STATUS
));
141 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) == DDI_FM_OK
)
142 pcix_bdg_regs
->pcix_bdg_vflags
|=
143 PCIX_BDG_SEC_STATUS_VALID
;
146 pcix_bdg_regs
->pcix_bdg_stat
= pci_config_get32(erpt_p
->pe_hdl
,
147 (pcix_bdg_cap_ptr
+ PCI_PCIX_BDG_STATUS
));
148 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) == DDI_FM_OK
)
149 pcix_bdg_regs
->pcix_bdg_vflags
|= PCIX_BDG_STATUS_VALID
;
152 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs
->pcix_bdg_ver
)) {
153 pcix_ecc_regs_t
*pcix_bdg_ecc_regs
;
155 for (i
= 0; i
< 2; i
++) {
157 pcix_bdg_regs
->pcix_bdg_ecc_regs
[i
];
158 pci_config_put32(erpt_p
->pe_hdl
,
160 PCI_PCIX_BDG_ECC_STATUS
), i
);
161 pcix_ecc_regs_gather(erpt_p
,
163 pcix_bdg_cap_ptr
, fme_flag
);
167 pcix_error_regs_t
*pcix_regs
= (pcix_error_regs_t
*)pe_regs
;
168 uint8_t pcix_cap_ptr
;
170 pcix_cap_ptr
= pcix_regs
->pcix_cap_ptr
;
172 pcix_regs
->pcix_command
= pci_config_get16(erpt_p
->pe_hdl
,
173 (pcix_cap_ptr
+ PCI_PCIX_COMMAND
));
174 pcix_regs
->pcix_status
= pci_config_get32(erpt_p
->pe_hdl
,
175 (pcix_cap_ptr
+ PCI_PCIX_STATUS
));
176 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) == DDI_FM_OK
)
177 pcix_regs
->pcix_vflags
|= PCIX_ERR_STATUS_VALID
;
180 if (PCIX_ECC_VER_CHECK(pcix_regs
->pcix_ver
)) {
181 pcix_ecc_regs_t
*pcix_ecc_regs
=
182 pcix_regs
->pcix_ecc_regs
;
184 pcix_ecc_regs_gather(erpt_p
, pcix_ecc_regs
,
185 pcix_cap_ptr
, fme_flag
);
192 pci_regs_gather(dev_info_t
*dip
, pci_erpt_t
*erpt_p
, int fme_flag
)
194 pci_error_regs_t
*pci_regs
= erpt_p
->pe_pci_regs
;
197 * Start by reading all the error registers that are available for
198 * pci and pci express and for leaf devices and bridges/switches
200 pci_regs
->pci_err_status
= pci_config_get16(erpt_p
->pe_hdl
,
202 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) != DDI_FM_OK
)
204 pci_regs
->pci_vflags
|= PCI_ERR_STATUS_VALID
;
205 pci_regs
->pci_cfg_comm
= pci_config_get16(erpt_p
->pe_hdl
,
207 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) != DDI_FM_OK
)
211 * If pci-pci bridge grab PCI bridge specific error registers.
213 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
214 pci_regs
->pci_bdg_regs
->pci_bdg_sec_stat
=
215 pci_config_get16(erpt_p
->pe_hdl
, PCI_BCNF_SEC_STATUS
);
216 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) == DDI_FM_OK
)
217 pci_regs
->pci_bdg_regs
->pci_bdg_vflags
|=
218 PCI_BDG_SEC_STAT_VALID
;
219 pci_regs
->pci_bdg_regs
->pci_bdg_ctrl
=
220 pci_config_get16(erpt_p
->pe_hdl
, PCI_BCNF_BCNTRL
);
221 if (pci_config_check(erpt_p
->pe_hdl
, fme_flag
) == DDI_FM_OK
)
222 pci_regs
->pci_bdg_regs
->pci_bdg_vflags
|=
226 /* If pci-x device grab error registers */
227 if (erpt_p
->pe_dflags
& PCIX_DEV
)
228 pcix_regs_gather(erpt_p
, erpt_p
->pe_regs
, fme_flag
);
233 pcix_regs_clear(pci_erpt_t
*erpt_p
, void *pe_regs
)
235 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
236 pcix_bdg_error_regs_t
*pcix_bdg_regs
=
237 (pcix_bdg_error_regs_t
*)pe_regs
;
238 uint8_t pcix_bdg_cap_ptr
;
241 pcix_bdg_cap_ptr
= pcix_bdg_regs
->pcix_bdg_cap_ptr
;
243 if (pcix_bdg_regs
->pcix_bdg_vflags
& PCIX_BDG_SEC_STATUS_VALID
)
244 pci_config_put16(erpt_p
->pe_hdl
,
245 (pcix_bdg_cap_ptr
+ PCI_PCIX_SEC_STATUS
),
246 pcix_bdg_regs
->pcix_bdg_sec_stat
);
248 if (pcix_bdg_regs
->pcix_bdg_vflags
& PCIX_BDG_STATUS_VALID
)
249 pci_config_put32(erpt_p
->pe_hdl
,
250 (pcix_bdg_cap_ptr
+ PCI_PCIX_BDG_STATUS
),
251 pcix_bdg_regs
->pcix_bdg_stat
);
253 pcix_bdg_regs
->pcix_bdg_vflags
= 0x0;
255 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs
->pcix_bdg_ver
)) {
256 pcix_ecc_regs_t
*pcix_bdg_ecc_regs
;
257 for (i
= 0; i
< 2; i
++) {
259 pcix_bdg_regs
->pcix_bdg_ecc_regs
[i
];
261 if (pcix_bdg_ecc_regs
->pcix_ecc_vflags
&
262 PCIX_ERR_ECC_STS_VALID
) {
263 pci_config_put32(erpt_p
->pe_hdl
,
265 PCI_PCIX_BDG_ECC_STATUS
),
268 pci_config_put32(erpt_p
->pe_hdl
,
270 PCI_PCIX_BDG_ECC_STATUS
),
274 pcix_bdg_ecc_regs
->pcix_ecc_vflags
=
279 pcix_error_regs_t
*pcix_regs
= (pcix_error_regs_t
*)pe_regs
;
280 uint8_t pcix_cap_ptr
;
282 pcix_cap_ptr
= pcix_regs
->pcix_cap_ptr
;
284 if (pcix_regs
->pcix_vflags
& PCIX_ERR_STATUS_VALID
)
285 pci_config_put32(erpt_p
->pe_hdl
,
286 (pcix_cap_ptr
+ PCI_PCIX_STATUS
),
287 pcix_regs
->pcix_status
);
289 pcix_regs
->pcix_vflags
= 0x0;
291 if (PCIX_ECC_VER_CHECK(pcix_regs
->pcix_ver
)) {
292 pcix_ecc_regs_t
*pcix_ecc_regs
=
293 pcix_regs
->pcix_ecc_regs
;
295 if (pcix_ecc_regs
->pcix_ecc_vflags
&
296 PCIX_ERR_ECC_STS_VALID
)
297 pci_config_put32(erpt_p
->pe_hdl
,
298 (pcix_cap_ptr
+ PCI_PCIX_ECC_STATUS
),
299 pcix_ecc_regs
->pcix_ecc_ctlstat
);
301 pcix_ecc_regs
->pcix_ecc_vflags
= 0x0;
307 pci_regs_clear(pci_erpt_t
*erpt_p
)
310 * Finally clear the error bits
312 if (erpt_p
->pe_dflags
& PCIX_DEV
)
313 pcix_regs_clear(erpt_p
, erpt_p
->pe_regs
);
315 if (erpt_p
->pe_pci_regs
->pci_vflags
& PCI_ERR_STATUS_VALID
)
316 pci_config_put16(erpt_p
->pe_hdl
, PCI_CONF_STAT
,
317 erpt_p
->pe_pci_regs
->pci_err_status
);
319 erpt_p
->pe_pci_regs
->pci_vflags
= 0x0;
321 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
322 if (erpt_p
->pe_pci_regs
->pci_bdg_regs
->pci_bdg_vflags
&
323 PCI_BDG_SEC_STAT_VALID
)
324 pci_config_put16(erpt_p
->pe_hdl
, PCI_BCNF_SEC_STATUS
,
325 erpt_p
->pe_pci_regs
->pci_bdg_regs
->
327 if (erpt_p
->pe_pci_regs
->pci_bdg_regs
->pci_bdg_vflags
&
329 pci_config_put16(erpt_p
->pe_hdl
, PCI_BCNF_BCNTRL
,
330 erpt_p
->pe_pci_regs
->pci_bdg_regs
->pci_bdg_ctrl
);
332 erpt_p
->pe_pci_regs
->pci_bdg_regs
->pci_bdg_vflags
= 0x0;
337 * pcix_ereport_setup: Allocate structures for PCI-X error handling and ereport
342 pcix_ereport_setup(dev_info_t
*dip
, pci_erpt_t
*erpt_p
)
344 uint16_t pcix_cap_ptr
= PCI_CAP_NEXT_PTR_NULL
;
348 if (pci_config_setup(dip
, &eh
) == DDI_SUCCESS
) {
349 (void) PCI_CAP_LOCATE(eh
, PCI_CAP_ID_PCIX
, &pcix_cap_ptr
);
350 pci_config_teardown(&eh
);
353 if (pcix_cap_ptr
!= PCI_CAP_NEXT_PTR_NULL
)
354 erpt_p
->pe_dflags
|= PCIX_DEV
;
358 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
359 pcix_bdg_error_regs_t
*pcix_bdg_regs
;
361 erpt_p
->pe_regs
= kmem_zalloc(sizeof (pcix_bdg_error_regs_t
),
363 pcix_bdg_regs
= (pcix_bdg_error_regs_t
*)erpt_p
->pe_regs
;
364 pcix_bdg_regs
->pcix_bdg_cap_ptr
= pcix_cap_ptr
;
365 pcix_bdg_regs
->pcix_bdg_ver
= pci_config_get16(erpt_p
->pe_hdl
,
366 pcix_cap_ptr
+ PCI_PCIX_SEC_STATUS
) & PCI_PCIX_VER_MASK
;
367 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs
->pcix_bdg_ver
)) {
368 for (i
= 0; i
< 2; i
++) {
369 pcix_bdg_regs
->pcix_bdg_ecc_regs
[i
] =
370 kmem_zalloc(sizeof (pcix_ecc_regs_t
),
375 pcix_error_regs_t
*pcix_regs
;
377 erpt_p
->pe_regs
= kmem_zalloc(sizeof (pcix_error_regs_t
),
379 pcix_regs
= (pcix_error_regs_t
*)erpt_p
->pe_regs
;
380 pcix_regs
->pcix_cap_ptr
= pcix_cap_ptr
;
381 pcix_regs
->pcix_ver
= pci_config_get16(erpt_p
->pe_hdl
,
382 pcix_cap_ptr
+ PCI_PCIX_COMMAND
) & PCI_PCIX_VER_MASK
;
383 if (PCIX_ECC_VER_CHECK(pcix_regs
->pcix_ver
)) {
384 pcix_regs
->pcix_ecc_regs
= kmem_zalloc(
385 sizeof (pcix_ecc_regs_t
), KM_SLEEP
);
391 * pci_ereport_setup: Detect PCI device type and initialize structures to be
392 * used to generate ereports based on detected generic device errors.
395 pci_ereport_setup(dev_info_t
*dip
)
397 struct dev_info
*devi
= DEVI(dip
);
398 struct i_ddi_fmhdl
*fmhdl
= devi
->devi_fmhdl
;
400 uint8_t pci_hdr_type
;
402 pci_regspec_t
*pci_rp
;
407 * If device is not ereport capbable then report an error against the
408 * driver for using this interface,
410 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip
)) &&
411 !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip
))) {
412 i_ddi_drv_ereport_post(dip
, DVR_EFMCAP
, NULL
, DDI_SLEEP
);
417 * ASSERT fmhdl exists and fh_bus_specific is NULL.
419 ASSERT(fmhdl
&& (fmhdl
->fh_bus_specific
== NULL
));
421 erpt_p
= kmem_zalloc(sizeof (pci_erpt_t
), KM_SLEEP
);
423 if (pci_config_setup(dip
, &erpt_p
->pe_hdl
) != DDI_SUCCESS
)
426 erpt_p
->pe_pci_regs
= kmem_zalloc(sizeof (pci_error_regs_t
), KM_SLEEP
);
428 pci_status
= pci_config_get16(erpt_p
->pe_hdl
, PCI_CONF_STAT
);
429 if (pci_config_check(erpt_p
->pe_hdl
, DDI_FM_ERR_UNEXPECTED
) !=
434 * Get header type and record if device is a bridge.
436 pci_hdr_type
= pci_config_get8(erpt_p
->pe_hdl
, PCI_CONF_HEADER
);
437 if (pci_config_check(erpt_p
->pe_hdl
, DDI_FM_ERR_UNEXPECTED
) !=
442 * Check to see if PCI device is a bridge, if so allocate pci bridge
443 * error register structure.
445 if ((pci_hdr_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_PPB
) {
446 erpt_p
->pe_dflags
|= PCI_BRIDGE_DEV
;
447 erpt_p
->pe_pci_regs
->pci_bdg_regs
= kmem_zalloc(
448 sizeof (pci_bdg_error_regs_t
), KM_SLEEP
);
451 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
, "reg",
452 (caddr_t
)&pci_rp
, &len
) == DDI_SUCCESS
) {
453 phys_hi
= pci_rp
->pci_phys_hi
;
454 kmem_free(pci_rp
, len
);
456 erpt_p
->pe_bdf
= (uint16_t)(PCI_REG_BDFR_G(phys_hi
) >>
460 if (!(pci_status
& PCI_STAT_CAP
)) {
464 /* Initialize structures for PCI-X devices. */
465 pcix_ereport_setup(dip
, erpt_p
);
468 pci_regs_gather(dip
, erpt_p
, DDI_FM_ERR_UNEXPECTED
);
469 pci_regs_clear(erpt_p
);
472 * Before returning set fh_bus_specific to completed pci_erpt_t
475 fmhdl
->fh_bus_specific
= (void *)erpt_p
;
479 if (erpt_p
->pe_pci_regs
)
480 kmem_free(erpt_p
->pe_pci_regs
, sizeof (pci_error_regs_t
));
481 kmem_free(erpt_p
, sizeof (pci_erpt_t
));
486 pcix_ereport_teardown(pci_erpt_t
*erpt_p
)
488 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
489 pcix_bdg_error_regs_t
*pcix_bdg_regs
;
492 pcix_bdg_regs
= (pcix_bdg_error_regs_t
*)erpt_p
->pe_regs
;
493 pcix_ver
= pcix_bdg_regs
->pcix_bdg_ver
;
494 if (PCIX_ECC_VER_CHECK(pcix_ver
)) {
496 for (i
= 0; i
< 2; i
++)
497 kmem_free(pcix_bdg_regs
->pcix_bdg_ecc_regs
[i
],
498 sizeof (pcix_ecc_regs_t
));
500 kmem_free(erpt_p
->pe_regs
, sizeof (pcix_bdg_error_regs_t
));
502 pcix_error_regs_t
*pcix_regs
;
505 pcix_regs
= (pcix_error_regs_t
*)erpt_p
->pe_regs
;
506 pcix_ver
= pcix_regs
->pcix_ver
;
507 if (PCIX_ECC_VER_CHECK(pcix_ver
)) {
508 kmem_free(pcix_regs
->pcix_ecc_regs
,
509 sizeof (pcix_ecc_regs_t
));
511 kmem_free(erpt_p
->pe_regs
, sizeof (pcix_error_regs_t
));
516 pci_ereport_teardown(dev_info_t
*dip
)
518 struct i_ddi_fmhdl
*fmhdl
= DEVI(dip
)->devi_fmhdl
;
521 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip
)) &&
522 !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip
))) {
523 i_ddi_drv_ereport_post(dip
, DVR_EFMCAP
, NULL
, DDI_SLEEP
);
528 erpt_p
= (pci_erpt_t
*)fmhdl
->fh_bus_specific
;
532 if (erpt_p
->pe_dflags
& PCIX_DEV
)
533 pcix_ereport_teardown(erpt_p
);
534 pci_config_teardown((ddi_acc_handle_t
*)&erpt_p
->pe_hdl
);
535 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
)
536 kmem_free(erpt_p
->pe_pci_regs
->pci_bdg_regs
,
537 sizeof (pci_bdg_error_regs_t
));
538 kmem_free(erpt_p
->pe_pci_regs
, sizeof (pci_error_regs_t
));
539 kmem_free(erpt_p
, sizeof (pci_erpt_t
));
540 fmhdl
->fh_bus_specific
= NULL
;
543 * The following sparc specific code should be removed once the pci_cap
544 * interfaces create the necessary properties for us.
550 pcix_check_addr(dev_info_t
*dip
, ddi_fm_error_t
*derr
,
551 pcix_ecc_regs_t
*pcix_ecc_regs
, int type
)
553 int cmd
= (pcix_ecc_regs
->pcix_ecc_ctlstat
>> 16) & 0xf;
555 pci_fme_bus_specific_t
*pci_fme_bsp
=
556 (pci_fme_bus_specific_t
*)derr
->fme_bus_specific
;
558 addr
= pcix_ecc_regs
->pcix_ecc_secaddr
;
560 addr
|= pcix_ecc_regs
->pcix_ecc_fstaddr
;
563 case PCI_PCIX_CMD_INTR
:
564 case PCI_PCIX_CMD_SPEC
:
565 return (DDI_FM_FATAL
);
566 case PCI_PCIX_CMD_IORD
:
567 case PCI_PCIX_CMD_IOWR
:
568 pci_fme_bsp
->pci_bs_addr
= addr
;
569 pci_fme_bsp
->pci_bs_flags
|= PCI_BS_ADDR_VALID
;
570 pci_fme_bsp
->pci_bs_type
= type
;
571 return (DDI_FM_UNKNOWN
);
572 case PCI_PCIX_CMD_DEVID
:
573 return (DDI_FM_FATAL
);
574 case PCI_PCIX_CMD_MEMRD_DW
:
575 case PCI_PCIX_CMD_MEMWR
:
576 case PCI_PCIX_CMD_MEMRD_BL
:
577 case PCI_PCIX_CMD_MEMWR_BL
:
578 pci_fme_bsp
->pci_bs_addr
= addr
;
579 pci_fme_bsp
->pci_bs_flags
|= PCI_BS_ADDR_VALID
;
580 pci_fme_bsp
->pci_bs_type
= type
;
581 return (DDI_FM_UNKNOWN
);
582 case PCI_PCIX_CMD_CFRD
:
583 case PCI_PCIX_CMD_CFWR
:
585 * for type 1 config transaction we can find bdf from address
587 if ((addr
& 3) == 1) {
588 pci_fme_bsp
->pci_bs_bdf
= (addr
>> 8) & 0xffffffff;
589 pci_fme_bsp
->pci_bs_flags
|= PCI_BS_BDF_VALID
;
590 pci_fme_bsp
->pci_bs_type
= type
;
592 return (DDI_FM_UNKNOWN
);
593 case PCI_PCIX_CMD_SPL
:
594 case PCI_PCIX_CMD_DADR
:
595 return (DDI_FM_UNKNOWN
);
596 case PCI_PCIX_CMD_MEMRDBL
:
597 case PCI_PCIX_CMD_MEMWRBL
:
598 pci_fme_bsp
->pci_bs_addr
= addr
;
599 pci_fme_bsp
->pci_bs_flags
|= PCI_BS_ADDR_VALID
;
600 pci_fme_bsp
->pci_bs_type
= type
;
601 return (DDI_FM_UNKNOWN
);
603 return (DDI_FM_FATAL
);
609 pci_bdg_error_report(dev_info_t
*dip
, ddi_fm_error_t
*derr
, pci_erpt_t
*erpt_p
)
611 pci_bdg_error_regs_t
*pci_bdg_regs
= erpt_p
->pe_pci_regs
->pci_bdg_regs
;
617 char buf
[FM_MAX_CLASS
];
619 pci_fme_bus_specific_t
*pci_fme_bsp
=
620 (pci_fme_bus_specific_t
*)derr
->fme_bus_specific
;
622 if (derr
->fme_flag
!= DDI_FM_ERR_UNEXPECTED
)
625 if ((pci_bdg_regs
->pci_bdg_vflags
& PCI_BDG_CTRL_VALID
) &&
626 (pci_bdg_regs
->pci_bdg_ctrl
& PCI_BCNF_BCNTRL_DTO_STAT
)) {
627 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s",
628 PCI_ERROR_SUBCLASS
, PCI_DTO
);
629 ddi_fm_ereport_post(dip
, buf
, derr
->fme_ena
,
630 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0,
631 PCI_SEC_CONFIG_STATUS
, DATA_TYPE_UINT16
,
632 pci_bdg_regs
->pci_bdg_sec_stat
, PCI_BCNTRL
,
633 DATA_TYPE_UINT16
, pci_bdg_regs
->pci_bdg_ctrl
, NULL
);
637 if (pci_bdg_regs
->pci_bdg_vflags
& PCI_BDG_SEC_STAT_VALID
) {
638 for (i
= 0; pci_bdg_err_tbl
[i
].err_class
!= NULL
; i
++) {
639 if (pci_bdg_regs
->pci_bdg_sec_stat
&
640 pci_bdg_err_tbl
[i
].reg_bit
) {
641 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s-%s",
642 PCI_ERROR_SUBCLASS
, PCI_SEC_ERROR_SUBCLASS
,
643 pci_bdg_err_tbl
[i
].err_class
);
644 ddi_fm_ereport_post(dip
, buf
, derr
->fme_ena
,
645 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0,
646 PCI_SEC_CONFIG_STATUS
, DATA_TYPE_UINT16
,
647 pci_bdg_regs
->pci_bdg_sec_stat
, PCI_BCNTRL
,
649 pci_bdg_regs
->pci_bdg_ctrl
, NULL
);
650 PCI_FM_SEV_INC(pci_bdg_err_tbl
[i
].flags
);
651 if (pci_fme_bsp
&& (pci_fme_bsp
->pci_bs_flags
&
652 PCI_BS_ADDR_VALID
) &&
653 pci_fme_bsp
->pci_bs_type
== ACC_HANDLE
&&
654 pci_bdg_err_tbl
[i
].terr_class
)
655 pci_target_enqueue(derr
->fme_ena
,
656 pci_bdg_err_tbl
[i
].terr_class
,
658 pci_fme_bsp
->pci_bs_addr
);
665 * Need to check for poke and cautious put. We already know peek
666 * and cautious get errors occurred (as we got a trap) and we know
669 if (derr
->fme_flag
== DDI_FM_ERR_EXPECTED
) {
671 * for cautious puts we treat all errors as nonfatal. Actually
672 * we set nonfatal for cautious gets as well - doesn't do any
675 if (pci_bdg_regs
->pci_bdg_sec_stat
& (PCI_STAT_R_TARG_AB
|
676 PCI_STAT_R_MAST_AB
| PCI_STAT_S_PERROR
| PCI_STAT_S_SYSERR
))
679 if (derr
->fme_flag
== DDI_FM_ERR_POKE
) {
681 * special case for pokes - we only consider master abort
682 * and target abort as nonfatal. Sserr with no master abort is
683 * fatal, but master/target abort can come in on separate
684 * instance, so return unknown and parent will determine if
685 * nonfatal (if another child returned nonfatal - ie master
686 * or target abort) or fatal otherwise
688 if (pci_bdg_regs
->pci_bdg_sec_stat
& (PCI_STAT_R_TARG_AB
|
691 if (erpt_p
->pe_pci_regs
->pci_err_status
& PCI_STAT_S_SYSERR
)
696 * now check children below the bridge
698 ret
= ndi_fm_handler_dispatch(dip
, NULL
, derr
);
700 return (fatal
? DDI_FM_FATAL
: (nonfatal
? DDI_FM_NONFATAL
:
701 (unknown
? DDI_FM_UNKNOWN
: DDI_FM_OK
)));
705 pcix_ecc_error_report(dev_info_t
*dip
, ddi_fm_error_t
*derr
, pci_erpt_t
*erpt_p
,
708 pcix_error_regs_t
*pcix_regs
;
709 pcix_bdg_error_regs_t
*pcix_bdg_regs
;
710 pcix_ecc_regs_t
*pcix_ecc_regs
;
721 char buf
[FM_MAX_CLASS
];
723 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
724 pcix_bdg_regs
= (pcix_bdg_error_regs_t
*)pe_regs
;
727 pcix_regs
= (pcix_error_regs_t
*)pe_regs
;
731 for (i
= 0; i
< (bridge
? 2 : 1); i
++) {
733 pcix_ecc_regs
= bridge
? pcix_bdg_regs
->pcix_bdg_ecc_regs
[i
] :
734 pcix_regs
->pcix_ecc_regs
;
735 if (pcix_ecc_regs
->pcix_ecc_vflags
& PCIX_ERR_ECC_STS_VALID
) {
736 ecc_phase
= (pcix_ecc_regs
->pcix_ecc_ctlstat
&
737 PCI_PCIX_ECC_PHASE
) >> 0x4;
738 ecc_corr
= (pcix_ecc_regs
->pcix_ecc_ctlstat
&
740 sec_ue
= (pcix_ecc_regs
->pcix_ecc_ctlstat
&
742 sec_ce
= (pcix_ecc_regs
->pcix_ecc_ctlstat
&
746 case PCI_PCIX_ECC_PHASE_NOERR
:
748 case PCI_PCIX_ECC_PHASE_FADDR
:
749 case PCI_PCIX_ECC_PHASE_SADDR
:
750 PCI_FM_SEV_INC(ecc_corr
? DDI_FM_OK
:
752 (void) snprintf(buf
, FM_MAX_CLASS
,
753 "%s.%s%s", PCIX_ERROR_SUBCLASS
,
754 i
? PCIX_SEC_ERROR_SUBCLASS
: "",
755 ecc_corr
? PCIX_ECC_CE_ADDR
:
758 case PCI_PCIX_ECC_PHASE_ATTR
:
759 PCI_FM_SEV_INC(ecc_corr
?
760 DDI_FM_OK
: DDI_FM_FATAL
);
761 (void) snprintf(buf
, FM_MAX_CLASS
,
762 "%s.%s%s", PCIX_ERROR_SUBCLASS
,
763 i
? PCIX_SEC_ERROR_SUBCLASS
: "",
764 ecc_corr
? PCIX_ECC_CE_ATTR
:
767 case PCI_PCIX_ECC_PHASE_DATA32
:
768 case PCI_PCIX_ECC_PHASE_DATA64
:
773 pci_error_regs_t
*pci_regs
=
777 if (pci_regs
->pci_bdg_regs
->
784 if (pci_regs
->pci_err_status
&
790 ret
= pcix_check_addr(dip
, derr
,
791 pcix_ecc_regs
, type
);
795 (void) snprintf(buf
, FM_MAX_CLASS
,
796 "%s.%s%s", PCIX_ERROR_SUBCLASS
,
797 i
? PCIX_SEC_ERROR_SUBCLASS
: "",
798 ecc_corr
? PCIX_ECC_CE_DATA
:
804 ddi_fm_ereport_post(dip
, buf
,
806 DDI_NOSLEEP
, FM_VERSION
,
808 PCIX_SEC_STATUS
, DATA_TYPE_UINT16
,
809 pcix_bdg_regs
->pcix_bdg_sec_stat
,
810 PCIX_BDG_STAT
, DATA_TYPE_UINT32
,
811 pcix_bdg_regs
->pcix_bdg_stat
,
812 PCIX_ECC_CTLSTAT
, DATA_TYPE_UINT32
,
813 pcix_ecc_regs
->pcix_ecc_ctlstat
,
814 PCIX_ECC_ATTR
, DATA_TYPE_UINT32
,
815 pcix_ecc_regs
->pcix_ecc_attr
, NULL
);
817 ddi_fm_ereport_post(dip
, buf
,
819 DDI_NOSLEEP
, FM_VERSION
,
821 PCIX_COMMAND
, DATA_TYPE_UINT16
,
822 pcix_regs
->pcix_command
,
823 PCIX_STATUS
, DATA_TYPE_UINT32
,
824 pcix_regs
->pcix_status
,
825 PCIX_ECC_CTLSTAT
, DATA_TYPE_UINT32
,
826 pcix_ecc_regs
->pcix_ecc_ctlstat
,
827 PCIX_ECC_ATTR
, DATA_TYPE_UINT32
,
828 pcix_ecc_regs
->pcix_ecc_attr
, NULL
);
829 if (sec_ce
|| sec_ue
) {
830 (void) snprintf(buf
, FM_MAX_CLASS
,
831 "%s.%s%s", PCIX_ERROR_SUBCLASS
,
832 i
? PCIX_SEC_ERROR_SUBCLASS
: "",
833 sec_ce
? PCIX_ECC_S_CE
: PCIX_ECC_S_UE
);
835 ddi_fm_ereport_post(dip
, buf
,
837 DDI_NOSLEEP
, FM_VERSION
,
839 PCIX_SEC_STATUS
, DATA_TYPE_UINT16
,
840 pcix_bdg_regs
->pcix_bdg_sec_stat
,
841 PCIX_BDG_STAT
, DATA_TYPE_UINT32
,
842 pcix_bdg_regs
->pcix_bdg_stat
,
843 PCIX_ECC_CTLSTAT
, DATA_TYPE_UINT32
,
844 pcix_ecc_regs
->pcix_ecc_ctlstat
,
845 PCIX_ECC_ATTR
, DATA_TYPE_UINT32
,
846 pcix_ecc_regs
->pcix_ecc_attr
, NULL
);
848 ddi_fm_ereport_post(dip
, buf
,
850 DDI_NOSLEEP
, FM_VERSION
,
852 PCIX_COMMAND
, DATA_TYPE_UINT16
,
853 pcix_regs
->pcix_command
,
854 PCIX_STATUS
, DATA_TYPE_UINT32
,
855 pcix_regs
->pcix_status
,
856 PCIX_ECC_CTLSTAT
, DATA_TYPE_UINT32
,
857 pcix_ecc_regs
->pcix_ecc_ctlstat
,
858 PCIX_ECC_ATTR
, DATA_TYPE_UINT32
,
859 pcix_ecc_regs
->pcix_ecc_attr
, NULL
);
860 PCI_FM_SEV_INC(sec_ue
? DDI_FM_FATAL
:
865 return (fatal
? DDI_FM_FATAL
: (nonfatal
? DDI_FM_NONFATAL
:
866 (unknown
? DDI_FM_UNKNOWN
: DDI_FM_OK
)));
870 pcix_bdg_error_report(dev_info_t
*dip
, ddi_fm_error_t
*derr
, pci_erpt_t
*erpt_p
,
873 pcix_bdg_error_regs_t
*pcix_bdg_regs
= (pcix_bdg_error_regs_t
*)pe_regs
;
878 char buf
[FM_MAX_CLASS
];
881 if (pcix_bdg_regs
->pcix_bdg_vflags
& PCIX_BDG_STATUS_VALID
) {
882 for (i
= 0; pcix_err_tbl
[i
].err_class
!= NULL
; i
++) {
883 if ((pcix_bdg_regs
->pcix_bdg_stat
&
884 pcix_err_tbl
[i
].reg_bit
)) {
885 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s",
887 pcix_err_tbl
[i
].err_class
);
888 ddi_fm_ereport_post(dip
, buf
, derr
->fme_ena
,
889 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0,
890 PCIX_SEC_STATUS
, DATA_TYPE_UINT16
,
891 pcix_bdg_regs
->pcix_bdg_sec_stat
,
892 PCIX_BDG_STAT
, DATA_TYPE_UINT32
,
893 pcix_bdg_regs
->pcix_bdg_stat
, NULL
);
894 PCI_FM_SEV_INC(pcix_err_tbl
[i
].flags
);
899 if (pcix_bdg_regs
->pcix_bdg_vflags
& PCIX_BDG_SEC_STATUS_VALID
) {
900 for (i
= 0; pcix_sec_err_tbl
[i
].err_class
!= NULL
; i
++) {
901 if ((pcix_bdg_regs
->pcix_bdg_sec_stat
&
902 pcix_sec_err_tbl
[i
].reg_bit
)) {
903 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s%s",
905 PCIX_SEC_ERROR_SUBCLASS
,
906 pcix_sec_err_tbl
[i
].err_class
);
907 ddi_fm_ereport_post(dip
, buf
, derr
->fme_ena
,
908 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0,
909 PCIX_SEC_STATUS
, DATA_TYPE_UINT16
,
910 pcix_bdg_regs
->pcix_bdg_sec_stat
,
911 PCIX_BDG_STAT
, DATA_TYPE_UINT32
,
912 pcix_bdg_regs
->pcix_bdg_stat
, NULL
);
913 PCI_FM_SEV_INC(pcix_sec_err_tbl
[i
].flags
);
918 /* Log/Handle ECC errors */
919 if (PCIX_ECC_VER_CHECK(pcix_bdg_regs
->pcix_bdg_ver
)) {
922 ret
= pcix_ecc_error_report(dip
, derr
, erpt_p
,
923 (void *)pcix_bdg_regs
);
926 return (fatal
? DDI_FM_FATAL
: (nonfatal
? DDI_FM_NONFATAL
:
927 (unknown
? DDI_FM_UNKNOWN
: DDI_FM_OK
)));
931 pcix_error_report(dev_info_t
*dip
, ddi_fm_error_t
*derr
, pci_erpt_t
*erpt_p
)
933 pcix_error_regs_t
*pcix_regs
= (pcix_error_regs_t
*)erpt_p
->pe_regs
;
938 char buf
[FM_MAX_CLASS
];
941 if (pcix_regs
->pcix_vflags
& PCIX_ERR_STATUS_VALID
) {
942 for (i
= 0; pcix_err_tbl
[i
].err_class
!= NULL
; i
++) {
943 if (!(pcix_regs
->pcix_status
& pcix_err_tbl
[i
].reg_bit
))
946 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s",
947 PCIX_ERROR_SUBCLASS
, pcix_err_tbl
[i
].err_class
);
948 ddi_fm_ereport_post(dip
, buf
, derr
->fme_ena
,
949 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0,
950 PCIX_COMMAND
, DATA_TYPE_UINT16
,
951 pcix_regs
->pcix_command
, PCIX_STATUS
,
952 DATA_TYPE_UINT32
, pcix_regs
->pcix_status
,
954 PCI_FM_SEV_INC(pcix_err_tbl
[i
].flags
);
957 /* Log/Handle ECC errors */
958 if (PCIX_ECC_VER_CHECK(pcix_regs
->pcix_ver
)) {
959 int ret
= pcix_ecc_error_report(dip
, derr
, erpt_p
,
964 return (fatal
? DDI_FM_FATAL
: (nonfatal
? DDI_FM_NONFATAL
:
965 (unknown
? DDI_FM_UNKNOWN
: DDI_FM_OK
)));
969 pci_error_report(dev_info_t
*dip
, ddi_fm_error_t
*derr
, pci_erpt_t
*erpt_p
)
975 char buf
[FM_MAX_CLASS
];
978 if (derr
->fme_flag
== DDI_FM_ERR_UNEXPECTED
) {
980 * Log generic PCI errors.
982 for (i
= 0; pci_err_tbl
[i
].err_class
!= NULL
; i
++) {
983 if (!(erpt_p
->pe_pci_regs
->pci_err_status
&
984 pci_err_tbl
[i
].reg_bit
) ||
985 !(erpt_p
->pe_pci_regs
->pci_vflags
&
986 PCI_ERR_STATUS_VALID
))
989 * Generate an ereport for this error bit.
991 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s",
992 PCI_ERROR_SUBCLASS
, pci_err_tbl
[i
].err_class
);
993 ddi_fm_ereport_post(dip
, buf
, derr
->fme_ena
,
994 DDI_NOSLEEP
, FM_VERSION
, DATA_TYPE_UINT8
, 0,
995 PCI_CONFIG_STATUS
, DATA_TYPE_UINT16
,
996 erpt_p
->pe_pci_regs
->pci_err_status
,
997 PCI_CONFIG_COMMAND
, DATA_TYPE_UINT16
,
998 erpt_p
->pe_pci_regs
->pci_cfg_comm
, NULL
);
1000 PCI_FM_SEV_INC(pci_err_tbl
[i
].flags
);
1002 if (erpt_p
->pe_dflags
& PCIX_DEV
) {
1003 if (erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
) {
1004 int ret
= pcix_bdg_error_report(dip
, derr
,
1005 erpt_p
, erpt_p
->pe_regs
);
1006 PCI_FM_SEV_INC(ret
);
1008 int ret
= pcix_error_report(dip
, derr
, erpt_p
);
1009 PCI_FM_SEV_INC(ret
);
1014 if ((erpt_p
->pe_dflags
& PCI_BRIDGE_DEV
)) {
1015 int ret
= pci_bdg_error_report(dip
, derr
, erpt_p
);
1016 PCI_FM_SEV_INC(ret
);
1019 if (derr
->fme_flag
== DDI_FM_ERR_UNEXPECTED
) {
1020 pci_fme_bus_specific_t
*pci_fme_bsp
;
1021 int ret
= DDI_FM_UNKNOWN
;
1023 pci_fme_bsp
= (pci_fme_bus_specific_t
*)derr
->fme_bus_specific
;
1024 if (pci_fme_bsp
->pci_bs_flags
& PCI_BS_ADDR_VALID
) {
1025 ret
= ndi_fmc_entry_error(dip
,
1026 pci_fme_bsp
->pci_bs_type
, derr
,
1027 (void *)&pci_fme_bsp
->pci_bs_addr
);
1028 PCI_FM_SEV_INC(ret
);
1031 * If we didn't find the handle using an addr, try using bdf.
1032 * Note we don't do this where the bdf is for a
1033 * device behind a pciex/pci bridge as the bridge may have
1034 * fabricated the bdf.
1036 if (ret
== DDI_FM_UNKNOWN
&&
1037 (pci_fme_bsp
->pci_bs_flags
& PCI_BS_BDF_VALID
) &&
1038 pci_fme_bsp
->pci_bs_bdf
== erpt_p
->pe_bdf
) {
1039 ret
= ndi_fmc_entry_error_all(dip
,
1040 pci_fme_bsp
->pci_bs_type
, derr
);
1041 PCI_FM_SEV_INC(ret
);
1045 derr
->fme_status
= (fatal
? DDI_FM_FATAL
: (nonfatal
? DDI_FM_NONFATAL
:
1046 (unknown
? DDI_FM_UNKNOWN
: DDI_FM_OK
)));
1050 pci_ereport_post(dev_info_t
*dip
, ddi_fm_error_t
*derr
, uint16_t *xx_status
)
1052 struct i_ddi_fmhdl
*fmhdl
;
1055 pci_fme_bus_specific_t pci_fme_bs
;
1058 * On PCI Express systems, all error handling and ereport are done via
1059 * the PCIe misc module. This function is a no-op for PCIe Systems. In
1060 * order to tell if a system is a PCI or PCIe system, check that the
1061 * bus_private_data exists. If it exists, this is a PCIe system.
1063 if (ndi_get_bus_private(dip
, B_TRUE
)) {
1064 derr
->fme_status
= DDI_FM_OK
;
1065 if (xx_status
!= NULL
)
1071 fmhdl
= DEVI(dip
)->devi_fmhdl
;
1072 if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip
)) &&
1073 !DDI_FM_ERRCB_CAP(ddi_fm_capable(dip
))) {
1074 i_ddi_drv_ereport_post(dip
, DVR_EFMCAP
, NULL
, DDI_NOSLEEP
);
1079 * copy in the ddi_fm_error_t structure in case it's VER0
1081 de
.fme_version
= derr
->fme_version
;
1082 de
.fme_status
= derr
->fme_status
;
1083 de
.fme_flag
= derr
->fme_flag
;
1084 de
.fme_ena
= derr
->fme_ena
;
1085 de
.fme_acc_handle
= derr
->fme_acc_handle
;
1086 de
.fme_dma_handle
= derr
->fme_dma_handle
;
1087 de
.fme_bus_specific
= derr
->fme_bus_specific
;
1088 if (derr
->fme_version
>= DDI_FME_VER1
)
1089 de
.fme_bus_type
= derr
->fme_bus_type
;
1091 de
.fme_bus_type
= DDI_FME_BUS_TYPE_DFLT
;
1092 if (de
.fme_bus_type
== DDI_FME_BUS_TYPE_DFLT
) {
1094 * if this is the first pci device we've found convert
1095 * fme_bus_specific to DDI_FME_BUS_TYPE_PCI
1097 bzero(&pci_fme_bs
, sizeof (pci_fme_bs
));
1098 if (de
.fme_bus_specific
) {
1100 * the cpu passed us an addr - this can be used to look
1101 * up an access handle
1103 pci_fme_bs
.pci_bs_addr
= (uintptr_t)de
.fme_bus_specific
;
1104 pci_fme_bs
.pci_bs_type
= ACC_HANDLE
;
1105 pci_fme_bs
.pci_bs_flags
|= PCI_BS_ADDR_VALID
;
1107 de
.fme_bus_specific
= (void *)&pci_fme_bs
;
1108 de
.fme_bus_type
= DDI_FME_BUS_TYPE_PCI
;
1113 if (de
.fme_ena
== 0)
1114 de
.fme_ena
= fm_ena_generate(0, FM_ENA_FMT1
);
1116 erpt_p
= (pci_erpt_t
*)fmhdl
->fh_bus_specific
;
1120 pci_regs_gather(dip
, erpt_p
, de
.fme_flag
);
1121 pci_error_report(dip
, &de
, erpt_p
);
1122 pci_regs_clear(erpt_p
);
1124 derr
->fme_status
= de
.fme_status
;
1125 derr
->fme_ena
= de
.fme_ena
;
1126 derr
->fme_acc_handle
= de
.fme_acc_handle
;
1127 derr
->fme_dma_handle
= de
.fme_dma_handle
;
1128 if (xx_status
!= NULL
)
1129 *xx_status
= erpt_p
->pe_pci_regs
->pci_err_status
;
1133 * private version of walk_devs() that can be used during panic. No
1134 * sleeping or locking required.
1137 pci_fm_walk_devs(dev_info_t
*dip
, int (*f
)(dev_info_t
*, void *), void *arg
)
1140 switch ((*f
)(dip
, arg
)) {
1141 case DDI_WALK_TERMINATE
:
1142 return (DDI_WALK_TERMINATE
);
1143 case DDI_WALK_CONTINUE
:
1144 if (pci_fm_walk_devs(ddi_get_child(dip
), f
,
1145 arg
) == DDI_WALK_TERMINATE
)
1146 return (DDI_WALK_TERMINATE
);
1148 case DDI_WALK_PRUNECHILD
:
1151 dip
= ddi_get_next_sibling(dip
);
1153 return (DDI_WALK_CONTINUE
);
1157 * need special version of ddi_fm_ereport_post() as the leaf driver may
1161 pci_fm_ereport_post(dev_info_t
*dip
, const char *error_class
, uint64_t ena
,
1162 uint8_t version
, ...)
1165 char device_path
[MAXPATHLEN
];
1166 char ddi_error_class
[FM_MAX_CLASS
];
1167 nvlist_t
*ereport
, *detector
;
1169 errorq_elem_t
*eqep
;
1173 eqep
= errorq_reserve(ereport_errorq
);
1176 ereport
= errorq_elem_nvl(ereport_errorq
, eqep
);
1177 nva
= errorq_elem_nva(ereport_errorq
, eqep
);
1178 detector
= fm_nvlist_create(nva
);
1180 ereport
= fm_nvlist_create(NULL
);
1181 detector
= fm_nvlist_create(NULL
);
1184 (void) ddi_pathname(dip
, device_path
);
1185 fm_fmri_dev_set(detector
, FM_DEV_SCHEME_VERSION
, NULL
,
1186 device_path
, NULL
, NULL
);
1187 (void) snprintf(ddi_error_class
, FM_MAX_CLASS
, "%s.%s",
1188 DDI_IO_CLASS
, error_class
);
1189 fm_ereport_set(ereport
, version
, ddi_error_class
, ena
, detector
, NULL
);
1191 va_start(ap
, version
);
1192 name
= va_arg(ap
, char *);
1193 (void) i_fm_payload_set(ereport
, name
, ap
);
1197 errorq_commit(ereport_errorq
, eqep
, ERRORQ_SYNC
);
1199 (void) fm_ereport_post(ereport
, EVCH_TRYHARD
);
1200 fm_nvlist_destroy(ereport
, FM_NVA_FREE
);
1201 fm_nvlist_destroy(detector
, FM_NVA_FREE
);
1206 pci_check_regs(dev_info_t
*dip
, void *arg
)
1211 pci_regspec_t
*drv_regp
;
1212 pci_target_err_t
*tgt_err
= (pci_target_err_t
*)arg
;
1214 if (tgt_err
->tgt_pci_space
== PCI_REG_ADDR_G(PCI_ADDR_CONFIG
)) {
1216 * for config space, we need to check if the given address
1217 * is a valid config space address for this device - based
1218 * on pci_phys_hi of the config space entry in reg property.
1220 if (ddi_getlongprop(DDI_DEV_T_NONE
, dip
, DDI_PROP_DONTPASS
,
1221 "reg", (caddr_t
)&drv_regp
, ®len
) != DDI_SUCCESS
)
1222 return (DDI_WALK_CONTINUE
);
1224 totreg
= reglen
/ sizeof (pci_regspec_t
);
1225 for (rn
= 0; rn
< totreg
; rn
++) {
1226 if (tgt_err
->tgt_pci_space
==
1227 PCI_REG_ADDR_G(drv_regp
[rn
].pci_phys_hi
) &&
1228 (tgt_err
->tgt_pci_addr
& (PCI_REG_BUS_M
|
1229 PCI_REG_DEV_M
| PCI_REG_FUNC_M
)) ==
1230 (drv_regp
[rn
].pci_phys_hi
& (PCI_REG_BUS_M
|
1231 PCI_REG_DEV_M
| PCI_REG_FUNC_M
))) {
1232 tgt_err
->tgt_dip
= dip
;
1233 kmem_free(drv_regp
, reglen
);
1234 return (DDI_WALK_TERMINATE
);
1237 kmem_free(drv_regp
, reglen
);
1240 * for non config space, need to check reg to look
1241 * for any non-relocable mapping, otherwise check
1242 * assigned-addresses.
1244 if (ddi_getlongprop(DDI_DEV_T_NONE
, dip
, DDI_PROP_DONTPASS
,
1245 "reg", (caddr_t
)&drv_regp
, ®len
) != DDI_SUCCESS
)
1246 return (DDI_WALK_CONTINUE
);
1248 totreg
= reglen
/ sizeof (pci_regspec_t
);
1249 for (rn
= 0; rn
< totreg
; rn
++) {
1250 if ((drv_regp
[rn
].pci_phys_hi
& PCI_RELOCAT_B
) &&
1251 (tgt_err
->tgt_pci_space
== TGT_PCI_SPACE_UNKNOWN
||
1252 tgt_err
->tgt_pci_space
==
1253 PCI_REG_ADDR_G(drv_regp
[rn
].pci_phys_hi
)) &&
1254 (tgt_err
->tgt_pci_addr
>=
1255 (uint64_t)drv_regp
[rn
].pci_phys_low
+
1256 ((uint64_t)drv_regp
[rn
].pci_phys_mid
<< 32)) &&
1257 (tgt_err
->tgt_pci_addr
<
1258 (uint64_t)drv_regp
[rn
].pci_phys_low
+
1259 ((uint64_t)drv_regp
[rn
].pci_phys_mid
<< 32) +
1260 (uint64_t)drv_regp
[rn
].pci_size_low
+
1261 ((uint64_t)drv_regp
[rn
].pci_size_hi
<< 32))) {
1262 tgt_err
->tgt_dip
= dip
;
1263 kmem_free(drv_regp
, reglen
);
1264 return (DDI_WALK_TERMINATE
);
1267 kmem_free(drv_regp
, reglen
);
1269 if (ddi_getlongprop(DDI_DEV_T_NONE
, dip
, DDI_PROP_DONTPASS
,
1270 "assigned-addresses", (caddr_t
)&drv_regp
, ®len
) !=
1272 return (DDI_WALK_CONTINUE
);
1274 totreg
= reglen
/ sizeof (pci_regspec_t
);
1275 for (rn
= 0; rn
< totreg
; rn
++) {
1276 if ((tgt_err
->tgt_pci_space
== TGT_PCI_SPACE_UNKNOWN
||
1277 tgt_err
->tgt_pci_space
==
1278 PCI_REG_ADDR_G(drv_regp
[rn
].pci_phys_hi
)) &&
1279 (tgt_err
->tgt_pci_addr
>=
1280 (uint64_t)drv_regp
[rn
].pci_phys_low
+
1281 ((uint64_t)drv_regp
[rn
].pci_phys_mid
<< 32)) &&
1282 (tgt_err
->tgt_pci_addr
<
1283 (uint64_t)drv_regp
[rn
].pci_phys_low
+
1284 ((uint64_t)drv_regp
[rn
].pci_phys_mid
<< 32) +
1285 (uint64_t)drv_regp
[rn
].pci_size_low
+
1286 ((uint64_t)drv_regp
[rn
].pci_size_hi
<< 32))) {
1287 tgt_err
->tgt_dip
= dip
;
1288 kmem_free(drv_regp
, reglen
);
1289 return (DDI_WALK_TERMINATE
);
1292 kmem_free(drv_regp
, reglen
);
1294 return (DDI_WALK_CONTINUE
);
1298 * impl_fix_ranges - fixes the config space entry of the "ranges"
1299 * property on psycho+ platforms. (if changing this function please make sure
1300 * to change the pci_fix_ranges function in pcipsy.c)
1304 pci_fix_ranges(dev_info_t
*dip
, pci_ranges_t
*pci_ranges
, int nrange
)
1309 pci_check_ranges(dev_info_t
*dip
, void *arg
)
1311 uint64_t range_parent_begin
;
1312 uint64_t range_parent_size
;
1313 uint64_t range_parent_end
;
1314 uint32_t space_type
;
1316 uint32_t range_offset
;
1317 pci_ranges_t
*pci_ranges
, *rangep
;
1318 pci_bus_range_t
*pci_bus_rangep
;
1319 int pci_ranges_length
;
1321 pci_target_err_t
*tgt_err
= (pci_target_err_t
*)arg
;
1323 if (strcmp(ddi_node_name(dip
), "pci") != 0 &&
1324 strcmp(ddi_node_name(dip
), "pciex") != 0)
1325 return (DDI_WALK_CONTINUE
);
1328 * Get the ranges property. Note we only look at the top level pci
1329 * node (hostbridge) which has a ranges property of type pci_ranges_t
1330 * not at pci-pci bridges.
1332 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
, "ranges",
1333 (caddr_t
)&pci_ranges
, &pci_ranges_length
) != DDI_SUCCESS
) {
1335 * no ranges property - no translation needed
1337 tgt_err
->tgt_pci_addr
= tgt_err
->tgt_err_addr
;
1338 tgt_err
->tgt_pci_space
= TGT_PCI_SPACE_UNKNOWN
;
1340 (void) pci_fm_walk_devs(ddi_get_child(dip
),
1341 pci_check_regs
, (void *)tgt_err
);
1344 ndi_devi_enter(dip
, &circ
);
1345 ddi_walk_devs(ddi_get_child(dip
), pci_check_regs
,
1347 ndi_devi_exit(dip
, circ
);
1349 if (tgt_err
->tgt_dip
!= NULL
)
1350 return (DDI_WALK_TERMINATE
);
1351 return (DDI_WALK_PRUNECHILD
);
1353 nrange
= pci_ranges_length
/ sizeof (pci_ranges_t
);
1354 rangep
= pci_ranges
;
1356 /* Need to fix the pci ranges property for psycho based systems */
1357 pci_fix_ranges(dip
, pci_ranges
, nrange
);
1359 for (i
= 0; i
< nrange
; i
++, rangep
++) {
1360 range_parent_begin
= ((uint64_t)rangep
->parent_high
<< 32) +
1362 range_parent_size
= ((uint64_t)rangep
->size_high
<< 32) +
1364 range_parent_end
= range_parent_begin
+ range_parent_size
- 1;
1366 if ((tgt_err
->tgt_err_addr
< range_parent_begin
) ||
1367 (tgt_err
->tgt_err_addr
> range_parent_end
)) {
1371 space_type
= PCI_REG_ADDR_G(rangep
->child_high
);
1372 if (space_type
== PCI_REG_ADDR_G(PCI_ADDR_CONFIG
)) {
1373 /* Config space address - check bus range */
1374 range_offset
= tgt_err
->tgt_err_addr
-
1376 bus_num
= PCI_REG_BUS_G(range_offset
);
1377 if (ddi_getlongprop(DDI_DEV_T_ANY
, dip
,
1378 DDI_PROP_DONTPASS
, "bus-range",
1379 (caddr_t
)&pci_bus_rangep
, &size
) != DDI_SUCCESS
) {
1382 if ((bus_num
< pci_bus_rangep
->lo
) ||
1383 (bus_num
> pci_bus_rangep
->hi
)) {
1385 * Bus number not appropriate for this
1388 kmem_free(pci_bus_rangep
, size
);
1391 kmem_free(pci_bus_rangep
, size
);
1394 /* We have a match if we get here - compute pci address */
1395 tgt_err
->tgt_pci_addr
= tgt_err
->tgt_err_addr
-
1397 tgt_err
->tgt_pci_addr
+= (((uint64_t)rangep
->child_mid
<< 32) +
1399 tgt_err
->tgt_pci_space
= space_type
;
1401 (void) pci_fm_walk_devs(ddi_get_child(dip
),
1402 pci_check_regs
, (void *)tgt_err
);
1405 ndi_devi_enter(dip
, &circ
);
1406 ddi_walk_devs(ddi_get_child(dip
), pci_check_regs
,
1408 ndi_devi_exit(dip
, circ
);
1410 if (tgt_err
->tgt_dip
!= NULL
) {
1411 kmem_free(pci_ranges
, pci_ranges_length
);
1412 return (DDI_WALK_TERMINATE
);
1415 kmem_free(pci_ranges
, pci_ranges_length
);
1416 return (DDI_WALK_PRUNECHILD
);
1420 * Function used to drain pci_target_queue, either during panic or after softint
1421 * is generated, to generate target device ereports based on captured physical
1426 pci_target_drain(void *private_p
, pci_target_err_t
*tgt_err
)
1428 char buf
[FM_MAX_CLASS
];
1431 * The following assumes that all pci_pci bridge devices
1432 * are configured as transparant. Find the top-level pci
1433 * nexus which has tgt_err_addr in one of its ranges, converting this
1434 * to a pci address in the process. Then starting at this node do
1435 * another tree walk to find a device with the pci address we've
1436 * found within range of one of it's assigned-addresses properties.
1438 tgt_err
->tgt_dip
= NULL
;
1440 (void) pci_fm_walk_devs(ddi_root_node(), pci_check_ranges
,
1443 ddi_walk_devs(ddi_root_node(), pci_check_ranges
,
1445 if (tgt_err
->tgt_dip
== NULL
)
1448 (void) snprintf(buf
, FM_MAX_CLASS
, "%s.%s", tgt_err
->tgt_bridge_type
,
1449 tgt_err
->tgt_err_class
);
1450 pci_fm_ereport_post(tgt_err
->tgt_dip
, buf
, tgt_err
->tgt_err_ena
, 0,
1451 PCI_PA
, DATA_TYPE_UINT64
, tgt_err
->tgt_err_addr
, NULL
);
1455 pci_target_enqueue(uint64_t ena
, char *class, char *bridge_type
, uint64_t addr
)
1457 pci_target_err_t tgt_err
;
1459 tgt_err
.tgt_err_ena
= ena
;
1460 tgt_err
.tgt_err_class
= class;
1461 tgt_err
.tgt_bridge_type
= bridge_type
;
1462 tgt_err
.tgt_err_addr
= addr
;
1463 errorq_dispatch(pci_target_queue
, (void *)&tgt_err
,
1464 sizeof (pci_target_err_t
), ERRORQ_ASYNC
);
1468 pci_targetq_init(void)
1471 * PCI target errorq, to schedule async handling of generation of
1472 * target device ereports based on captured physical address.
1473 * The errorq is created here but destroyed when _fini is called
1474 * for the pci module.
1476 if (pci_target_queue
== NULL
) {
1477 pci_target_queue
= errorq_create("pci_target_queue",
1478 (errorq_func_t
)pci_target_drain
, NULL
,
1479 TARGET_MAX_ERRS
, sizeof (pci_target_err_t
), FM_ERR_PIL
,
1481 if (pci_target_queue
== NULL
)
1482 panic("failed to create required system error queue");