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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/fm/io/sun4_fire.h>
29 #include "fabric-xlate.h"
31 typedef struct fab_fire_tbl
{
32 const char *err_class
;
33 uint32_t fire_bit
; /* Fire error bit */
34 uint16_t pci_err_sts
; /* Equivalent PCI Error Status */
35 uint16_t pci_bdg_sts
; /* Equivalent PCI Bridge Status */
39 * Translation tables for converting fire error bits into "pci" ereports.
42 * <pci error status reg>
43 * <pci bridge status reg>
46 #define FAB_FIRE_PEC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_PEC_ ## fb
47 #define FAB_FIRE_DMC_BIT(fb) "ereport.io." PCIEX_FIRE "." FIRE_DMC_ ## fb
48 #define FAB_N2_DMU_BIT(fb) "ereport.io.n2.dmu." fb
49 #define FAB_OB_PEC_BIT(fb) "ereport.io." PCIEX_OBERON "." FIRE_PEC_ ## fb
51 #define FAB_FIRE_UE(fb, bit, sts, bdg) \
52 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
53 #define FAB_OB_UE(fb, bit, sts, bdg) \
54 FAB_OB_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, sts, bdg
55 static fab_fire_tbl_t fab_fire_pec_ue_tbl
[] = {
56 FAB_FIRE_UE(UR
, UR
, PCI_STAT_S_SYSERR
, 0),
57 FAB_FIRE_UE(UC
, UC
, PCI_STAT_S_SYSERR
, 0),
58 FAB_OB_UE(ECRC
, ECRC
, PCI_STAT_S_SYSERR
, 0),
59 FAB_FIRE_UE(CTO
, TO
, PCI_STAT_S_SYSERR
, 0),
60 FAB_FIRE_UE(ROF
, RO
, PCI_STAT_S_SYSERR
, 0),
61 FAB_FIRE_UE(MFP
, MTLP
, PCI_STAT_S_SYSERR
, 0),
62 FAB_FIRE_UE(PP
, PTLP
, PCI_STAT_S_PERROR
,
63 (PCI_STAT_S_SYSERR
| PCI_STAT_PERROR
)),
64 FAB_FIRE_UE(FCP
, FCP
, PCI_STAT_S_SYSERR
, 0),
65 FAB_FIRE_UE(DLP
, DLP
, PCI_STAT_S_SYSERR
, 0),
66 FAB_FIRE_UE(TE
, TRAINING
, PCI_STAT_S_SYSERR
, 0),
67 FAB_FIRE_UE(CA
, CA
, PCI_STAT_S_TARG_AB
,
72 #define FAB_FIRE_CE(fb, bit) \
73 FAB_FIRE_PEC_BIT(fb), PCIE_AER_CE_ ## bit, 0, 0
74 static fab_fire_tbl_t fab_fire_pec_ce_tbl
[] = {
75 FAB_FIRE_CE(RTO
, REPLAY_TO
),
76 FAB_FIRE_CE(RNR
, REPLAY_ROLLOVER
),
77 FAB_FIRE_CE(BDP
, BAD_DLLP
),
78 FAB_FIRE_CE(BTP
, BAD_TLP
),
79 FAB_FIRE_CE(RE
, RECEIVER_ERR
),
84 * WUC/RUC will need to be special cased for the target ereports, because you
85 * need to decode the tlp log.
87 #define FAB_FIRE_WUCRUC(fb) \
88 FAB_FIRE_PEC_BIT(fb), 0, 0, (PCI_STAT_R_MAST_AB | PCI_STAT_S_SYSERR)
89 #define FAB_FIRE_OE(fb, bit) \
90 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
91 #define FAB_OB_OE(fb, bit) \
92 FAB_FIRE_PEC_BIT(fb), PCIE_AER_UCE_ ## bit, PCI_STAT_S_SYSERR, 0
93 static fab_fire_tbl_t fab_fire_pec_oe_tbl
[] = {
96 FAB_FIRE_OE(ERU
, DLP
),
97 FAB_FIRE_OE(ERO
, DLP
),
98 FAB_FIRE_OE(EMP
, DLP
),
99 FAB_FIRE_OE(EPE
, DLP
),
103 #define FAB_FIRE_DMC(fb) \
104 FAB_FIRE_DMC_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
105 #define FAB_N2_DMU(fb) \
106 FAB_N2_DMU_BIT(fb), PCIE_AER_UCE_CA, 0, PCI_STAT_S_TARG_AB
107 static fab_fire_tbl_t fab_fire_dmc_tbl
[] = {
108 FAB_FIRE_DMC(BYP_ERR
),
109 FAB_FIRE_DMC(BYP_OOR
),
110 FAB_FIRE_DMC(TRN_OOR
),
111 FAB_FIRE_DMC(TTE_INV
),
112 FAB_FIRE_DMC(TTE_PRT
),
113 FAB_N2_DMU("iotsbdesc_inv"),
114 FAB_N2_DMU("sun4v_adj_va_uf"),
115 FAB_N2_DMU("sun4v_inv_pg_sz"),
116 FAB_N2_DMU("sun4v_key_err"),
117 FAB_N2_DMU("sun4v_va_oor"),
123 fab_fire_to_data(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, fab_data_t
*data
)
127 /* Always Root Complex */
128 data
->dev_type
= PCIE_PCIECAP_DEV_TYPE_ROOT
;
130 data
->pcie_ue_sev
= (PCIE_AER_UCE_DLP
| PCIE_AER_UCE_SD
|
131 PCIE_AER_UCE_FCP
| PCIE_AER_UCE_RO
| PCIE_AER_UCE_MTLP
);
135 fab_xlate_fire_ce(fmd_hdl_t
*hdl
, fab_data_t
*data
, nvlist_t
*erpt
,
138 fab_fire_tbl_t
*entry
;
141 for (entry
= fab_fire_pec_ce_tbl
; entry
->err_class
; entry
++) {
142 if (STRCMP(class, entry
->err_class
))
149 fmd_hdl_debug(hdl
, "Translate Fire CE %s\n", class);
151 /* Fill in the device status register */
152 data
->pcie_err_status
= PCIE_DEVSTS_CE_DETECTED
;
154 /* Fill in the AER CE register */
155 if (nvlist_lookup_uint64(erpt
, "tlu-cess", ®
) == 0) {
156 data
->pcie_ce_status
= (uint32_t)reg
| (uint32_t)(reg
>> 32);
163 fab_xlate_fire_ue(fmd_hdl_t
*hdl
, fab_data_t
*data
, nvlist_t
*erpt
,
166 fab_fire_tbl_t
*entry
;
171 for (entry
= fab_fire_pec_ue_tbl
; entry
->err_class
; entry
++) {
172 if (STRCMP(class, entry
->err_class
))
179 fmd_hdl_debug(hdl
, "Translate Fire UE %s\n", class);
181 /* Fill in PCI Status Register */
182 data
->pci_err_status
= entry
->pci_err_sts
;
183 data
->pci_bdg_sec_stat
= entry
->pci_bdg_sts
;
185 /* Fill in the device status register */
186 if (entry
->fire_bit
& data
->pcie_ue_sev
)
187 data
->pcie_err_status
= PCIE_DEVSTS_FE_DETECTED
;
189 data
->pcie_err_status
= PCIE_DEVSTS_NFE_DETECTED
;
191 if (entry
->fire_bit
== PCIE_AER_UCE_UR
)
192 data
->pcie_err_status
|= PCIE_DEVSTS_UR_DETECTED
;
194 /* Fill in the AER UE register */
195 if (nvlist_lookup_uint64(erpt
, "tlu-uess", ®
) == 0) {
196 data
->pcie_ue_status
= (uint32_t)reg
| (uint32_t)(reg
>> 32);
199 /* Fill in the AER Control register */
200 if ((reg
& (uint64_t)entry
->fire_bit
) &&
201 nvlist_lookup_boolean(erpt
, "primary")) {
202 temp
= entry
->fire_bit
;
203 for (data
->pcie_adv_ctl
= (uint32_t)-1; temp
;
204 data
->pcie_adv_ctl
++)
208 /* If CTO create target information */
209 if (entry
->fire_bit
== PCIE_AER_UCE_TO
&&
210 nvlist_lookup_boolean(erpt
, "primary")) {
211 if (nvlist_lookup_uint64(erpt
, "tlu-tueh1l", ®
) == 0) {
212 data
->pcie_ue_hdr
[0] = (uint32_t)(reg
>> 32);
213 data
->pcie_ue_hdr
[1] = (uint32_t)(reg
);
215 if (nvlist_lookup_uint64(erpt
, "tlu-tueh2l", ®
) == 0) {
216 data
->pcie_ue_hdr
[2] = (uint32_t)(reg
>> 32);
217 data
->pcie_ue_hdr
[3] = (uint32_t)(reg
);
220 hdr
= (pcie_tlp_hdr_t
*)(&data
->pcie_ue_hdr
[0]);
222 case PCIE_TLP_TYPE_IO
:
223 case PCIE_TLP_TYPE_MEM
:
224 case PCIE_TLP_TYPE_MEMLK
:
225 data
->pcie_ue_tgt_trans
= PF_ADDR_PIO
;
226 if (hdr
->fmt
& 0x1) {
227 data
->pcie_ue_tgt_addr
= reg
;
229 data
->pcie_ue_tgt_addr
= data
->pcie_ue_hdr
[2];
232 case PCIE_TLP_TYPE_CFG0
:
233 case PCIE_TLP_TYPE_CFG1
:
234 data
->pcie_ue_tgt_trans
= PF_ADDR_CFG
;
235 data
->pcie_ue_tgt_bdf
= data
->pcie_ue_hdr
[2] >> 16;
240 /* Fill in the AER Header registers */
241 if (nvlist_lookup_uint64(erpt
, "tlu-rueh1l", ®
) == 0) {
242 data
->pcie_ue_hdr
[0] = (uint32_t)(reg
>> 32);
243 data
->pcie_ue_hdr
[1] = (uint32_t)(reg
);
245 if (nvlist_lookup_uint64(erpt
, "tlu-rueh2l", ®
) == 0) {
246 data
->pcie_ue_hdr
[2] = (uint32_t)(reg
>> 32);
247 data
->pcie_ue_hdr
[3] = (uint32_t)(reg
);
254 fab_xlate_fire_oe(fmd_hdl_t
*hdl
, fab_data_t
*data
, nvlist_t
*erpt
,
257 fab_fire_tbl_t
*entry
;
260 for (entry
= fab_fire_pec_oe_tbl
; entry
->err_class
; entry
++) {
261 if (STRCMP(class, entry
->err_class
))
268 fmd_hdl_debug(hdl
, "Translate Fire OE %s\n", class);
270 /* Fill in PCI Status Register */
271 if (entry
->fire_bit
) {
272 data
->pci_err_status
= entry
->pci_err_sts
;
273 data
->pci_bdg_sec_stat
= entry
->pci_bdg_sts
;
275 if (nvlist_lookup_uint64(erpt
, "tlu-roeeh1l", ®
) == 0) {
276 data
->pcie_ue_hdr
[0] = (uint32_t)(reg
>> 32);
277 data
->pcie_ue_hdr
[1] = (uint32_t)(reg
);
279 if (nvlist_lookup_uint64(erpt
, "tlu-roeeh2l", ®
) == 0) {
280 data
->pcie_ue_hdr
[2] = (uint32_t)(reg
>> 32);
281 data
->pcie_ue_hdr
[3] = (uint32_t)(reg
);
284 if (((pcie_tlp_hdr_t
*)(&data
->pcie_ue_hdr
[0]))->type
==
286 pcie_cpl_t
*cpl
= (pcie_cpl_t
*)&data
->pcie_ue_hdr
[1];
287 switch (cpl
->status
) {
288 case PCIE_CPL_STS_UR
:
289 data
->pci_err_status
= 0;
290 data
->pci_bdg_sec_stat
= PCI_STAT_R_MAST_AB
|
293 case PCIE_CPL_STS_CA
:
294 data
->pci_err_status
= 0;
295 data
->pci_bdg_sec_stat
= PCI_STAT_R_TARG_AB
|
302 /* Fill in the device status register */
303 if (entry
->fire_bit
& data
->pcie_ue_sev
)
304 data
->pcie_err_status
= PCIE_DEVSTS_FE_DETECTED
;
306 data
->pcie_err_status
= PCIE_DEVSTS_NFE_DETECTED
;
308 /* Fill in the AER UE register */
309 data
->pcie_ue_status
= entry
->fire_bit
;
315 fab_xlate_fire_dmc(fmd_hdl_t
*hdl
, fab_data_t
*data
, nvlist_t
*erpt
,
318 fab_fire_tbl_t
*entry
;
322 for (entry
= fab_fire_dmc_tbl
; entry
->err_class
; entry
++) {
323 fmd_hdl_debug(hdl
, "Matching %s\n", entry
->err_class
);
324 if (STRCMP(class, entry
->err_class
) &&
325 nvlist_lookup_boolean(erpt
, "primary"))
332 fmd_hdl_debug(hdl
, "Translate Fire DMC %s\n", class);
334 /* Fill in PCI Status Register */
335 data
->pci_err_status
= entry
->pci_err_sts
;
336 data
->pci_bdg_sec_stat
= entry
->pci_bdg_sts
;
338 /* Fill in the device status register */
339 data
->pcie_err_status
= PCIE_DEVSTS_NFE_DETECTED
;
341 /* Fill in the AER UE register */
342 data
->pcie_ue_status
= entry
->fire_bit
;
344 /* Fill in the AER Control register */
345 temp
= entry
->fire_bit
;
346 for (data
->pcie_adv_ctl
= (uint32_t)-1; temp
; data
->pcie_adv_ctl
++)
349 /* Fill in the AER Header registers */
350 if (nvlist_lookup_uint64(erpt
, "mmu-tfsr", ®
) == 0) {
351 fmd_hdl_debug(hdl
, "tfsr 0x%llx\n", reg
);
352 /* Get the trans type */
353 temp
= (reg
& 0x3F0000) >> 16;
354 data
->pcie_ue_hdr
[0] = (uint32_t)(temp
<< 24);
355 data
->pcie_ue_tgt_trans
= PF_ADDR_DMA
;
357 temp
= (reg
& 0xFFFF);
358 data
->pcie_ue_hdr
[1] = (uint32_t)(temp
<< 16);
359 data
->pcie_ue_tgt_bdf
= temp
;
362 if (nvlist_lookup_uint64(erpt
, "mmu-tfar", ®
) == 0) {
363 fmd_hdl_debug(hdl
, "tfar 0x%llx\n", reg
);
364 /* Get the address */
365 data
->pcie_ue_hdr
[2] = reg
;
366 data
->pcie_ue_hdr
[3] = 0;
367 data
->pcie_ue_tgt_addr
= reg
;
370 fmd_hdl_debug(hdl
, "HEADER 0 0x%x\n", data
->pcie_ue_hdr
[0]);
371 fmd_hdl_debug(hdl
, "HEADER 1 0x%x\n", data
->pcie_ue_hdr
[1]);
372 fmd_hdl_debug(hdl
, "HEADER 2 0x%x\n", data
->pcie_ue_hdr
[2]);
373 fmd_hdl_debug(hdl
, "HEADER 3 0x%x\n", data
->pcie_ue_hdr
[3]);
379 fab_xlate_fire_erpts(fmd_hdl_t
*hdl
, nvlist_t
*nvl
, const char *class)
381 fab_data_t data
= {0};
383 fmd_hdl_debug(hdl
, "Fire RC ereport received: %s\n", class);
385 fab_fire_to_data(hdl
, nvl
, &data
);
387 if (fmd_nvl_class_match(hdl
, nvl
, "ereport.io.fire.pec.*")) {
388 if (! fab_xlate_fire_ce(hdl
, &data
, nvl
, class) &&
389 ! fab_xlate_fire_ue(hdl
, &data
, nvl
, class))
390 (void) fab_xlate_fire_oe(hdl
, &data
, nvl
, class);
391 } else if (fmd_nvl_class_match(hdl
, nvl
, "ereport.io.fire.dmc.*") ||
392 fmd_nvl_class_match(hdl
, nvl
, "ereport.io.n2.dmu.*"))
393 (void) fab_xlate_fire_dmc(hdl
, &data
, nvl
, class);
395 fab_xlate_pcie_erpts(hdl
, &data
);