xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_fm.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/nxge/nxge_impl.h>
29 #include <sys/nxge/nxge_hio.h>
30 #include <sys/ddifm.h>
31 #include <sys/fm/protocol.h>
32 #include <sys/fm/util.h>
33 #include <sys/fm/io/ddi.h>
34 
35 static nxge_fm_ereport_attr_t
36 *nxge_fm_get_ereport_attr(nxge_fm_ereport_id_t);
37 
38 static int
39 nxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data);
40 
41 nxge_fm_ereport_attr_t	nxge_fm_ereport_pcs[] = {
42 	{NXGE_FM_EREPORT_XPCS_LINK_DOWN,	"10g_link_down",
43 						DDI_FM_DEVICE_INVAL_STATE,
44 						DDI_SERVICE_LOST},
45 	{NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT,	"10g_tx_link_fault",
46 						DDI_FM_DEVICE_INVAL_STATE,
47 						DDI_SERVICE_DEGRADED},
48 	{NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT,	"10g_rx_link_fault",
49 						DDI_FM_DEVICE_INVAL_STATE,
50 						DDI_SERVICE_DEGRADED},
51 	{NXGE_FM_EREPORT_PCS_LINK_DOWN,		"1g_link_down",
52 						DDI_FM_DEVICE_INVAL_STATE,
53 						DDI_SERVICE_LOST},
54 	{NXGE_FM_EREPORT_PCS_REMOTE_FAULT,	"1g_remote_fault",
55 						DDI_FM_DEVICE_INVAL_STATE,
56 						DDI_SERVICE_DEGRADED},
57 };
58 
59 nxge_fm_ereport_attr_t	nxge_fm_ereport_mif[] = {
60 	{NXGE_FM_EREPORT_MIF_ACCESS_FAIL,	"transceiver_access_fail"}
61 };
62 
63 nxge_fm_ereport_attr_t nxge_fm_ereport_fflp[] = {
64 	{NXGE_FM_EREPORT_FFLP_TCAM_ERR,		"classifier_tcam_err",
65 						DDI_FM_DEVICE_INTERN_UNCORR,
66 						DDI_SERVICE_UNAFFECTED},
67 	{NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR,	"classifier_vlan_par_err",
68 						DDI_FM_DEVICE_INTERN_UNCORR,
69 						DDI_SERVICE_UNAFFECTED},
70 	{NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR,	"classifier_hasht_data_err",
71 						DDI_FM_DEVICE_INTERN_UNCORR,
72 						DDI_SERVICE_UNAFFECTED},
73 	{NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR,	"classifier_hasht_lookup_err",
74 						DDI_FM_DEVICE_INTERN_UNCORR,
75 						DDI_SERVICE_UNAFFECTED},
76 	{NXGE_FM_EREPORT_FFLP_ACCESS_FAIL,	"classifier_access_fail",
77 						DDI_FM_DEVICE_NO_RESPONSE,
78 						DDI_SERVICE_DEGRADED}
79 };
80 
81 nxge_fm_ereport_attr_t nxge_fm_ereport_ipp[] = {
82 	{NXGE_FM_EREPORT_IPP_EOP_MISS,		"rx_eop_miss",
83 						DDI_FM_DEVICE_INVAL_STATE,
84 						DDI_SERVICE_LOST},
85 	{NXGE_FM_EREPORT_IPP_SOP_MISS,		"rx_sop_miss",
86 						DDI_FM_DEVICE_INVAL_STATE,
87 						DDI_SERVICE_LOST},
88 	{NXGE_FM_EREPORT_IPP_DFIFO_UE,		"rx_dfifo_ucorr_err",
89 						DDI_FM_DEVICE_INTERN_UNCORR,
90 						DDI_SERVICE_LOST},
91 	{NXGE_FM_EREPORT_IPP_DFIFO_CE,		"rx_dfifo_corr_err",
92 						DDI_FM_DEVICE_INTERN_CORR,
93 						DDI_SERVICE_UNAFFECTED},
94 	{NXGE_FM_EREPORT_IPP_PFIFO_PERR,	"rx_dfifo_parity_err",
95 						DDI_FM_DEVICE_INTERN_UNCORR,
96 						DDI_SERVICE_LOST},
97 	{NXGE_FM_EREPORT_IPP_ECC_ERR_MAX,	"rx_ecc_err_max",
98 						DDI_FM_DEVICE_INTERN_UNCORR,
99 						DDI_SERVICE_UNAFFECTED},
100 	{NXGE_FM_EREPORT_IPP_PFIFO_OVER,	"rx_pfifo_overflow",
101 						DDI_FM_DEVICE_INVAL_STATE,
102 						DDI_SERVICE_LOST},
103 	{NXGE_FM_EREPORT_IPP_PFIFO_UND,		"rx_pfifo_underrun",
104 						DDI_FM_DEVICE_INVAL_STATE,
105 						DDI_SERVICE_LOST},
106 	{NXGE_FM_EREPORT_IPP_BAD_CS_MX,		"rx_bad_cksum_max",
107 						DDI_FM_DEVICE_INTERN_UNCORR,
108 						DDI_SERVICE_UNAFFECTED},
109 	{NXGE_FM_EREPORT_IPP_PKT_DIS_MX,	"rx_pkt_discard_max",
110 						DDI_FM_DEVICE_INTERN_UNCORR,
111 						DDI_SERVICE_UNAFFECTED},
112 	{NXGE_FM_EREPORT_IPP_RESET_FAIL,	"rx_reset_fail",
113 						DDI_FM_DEVICE_NO_RESPONSE,
114 						DDI_SERVICE_LOST}
115 };
116 
117 nxge_fm_ereport_attr_t nxge_fm_ereport_rdmc[] = {
118 	{NXGE_FM_EREPORT_RDMC_DCF_ERR,		"rxdma_dcf_err",
119 						DDI_FM_DEVICE_INTERN_UNCORR,
120 						DDI_SERVICE_LOST},
121 	{NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR,	"rxdma_rcr_ack_err",
122 						DDI_FM_DEVICE_INTERN_UNCORR,
123 						DDI_SERVICE_DEGRADED},
124 	{NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR,	"rxdma_dc_fifo_err",
125 						DDI_FM_DEVICE_INTERN_UNCORR,
126 						DDI_SERVICE_LOST},
127 	{NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR,	"rxdma_rcr_sha_par_err",
128 						DDI_FM_DEVICE_INTERN_UNCORR,
129 						DDI_SERVICE_DEGRADED},
130 	{NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR,	"rxdma_rbr_pre_par_err",
131 						DDI_FM_DEVICE_INTERN_UNCORR,
132 						DDI_SERVICE_DEGRADED},
133 	{NXGE_FM_EREPORT_RDMC_RBR_TMOUT,	"rxdma_rbr_tmout",
134 						DDI_FM_DEVICE_NO_RESPONSE,
135 						DDI_SERVICE_DEGRADED},
136 	{NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR,	"rxdma_rsp_cnt_err",
137 						DDI_FM_DEVICE_INVAL_STATE,
138 						DDI_SERVICE_DEGRADED},
139 	{NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS,	"rxdma_byte_en_bus",
140 						DDI_FM_DEVICE_INVAL_STATE,
141 						DDI_SERVICE_DEGRADED},
142 	{NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR,	"rxdma_rsp_dat_err",
143 						DDI_FM_DEVICE_INTERN_UNCORR,
144 						DDI_SERVICE_DEGRADED},
145 	{NXGE_FM_EREPORT_RDMC_ID_MISMATCH,	"rxdma_id_mismatch",
146 						DDI_FM_DEVICE_INVAL_STATE,
147 						DDI_SERVICE_LOST},
148 	{NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR,	"rxdma_zcp_eop_err",
149 						DDI_FM_DEVICE_INVAL_STATE,
150 						DDI_SERVICE_LOST},
151 	{NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR,	"rxdma_ipp_eop_err",
152 						DDI_FM_DEVICE_INVAL_STATE,
153 						DDI_SERVICE_LOST},
154 	{NXGE_FM_EREPORT_RDMC_RCR_ERR,		"rxdma_completion_err",
155 						DDI_FM_DEVICE_INTERN_UNCORR,
156 						DDI_SERVICE_UNAFFECTED},
157 	{NXGE_FM_EREPORT_RDMC_CONFIG_ERR,	"rxdma_config_err",
158 						DDI_FM_DEVICE_INVAL_STATE,
159 						DDI_SERVICE_DEGRADED},
160 	{NXGE_FM_EREPORT_RDMC_RCRINCON,		"rxdma_rcrincon",
161 						DDI_FM_DEVICE_INVAL_STATE,
162 						DDI_SERVICE_DEGRADED},
163 	{NXGE_FM_EREPORT_RDMC_RCRFULL,		"rxdma_rcrfull",
164 						DDI_FM_DEVICE_INVAL_STATE,
165 						DDI_SERVICE_DEGRADED},
166 	{NXGE_FM_EREPORT_RDMC_RBRFULL,		"rxdma_rbrfull",
167 						DDI_FM_DEVICE_INVAL_STATE,
168 						DDI_SERVICE_DEGRADED},
169 	{NXGE_FM_EREPORT_RDMC_RBRLOGPAGE,	"rxdma_rbrlogpage",
170 						DDI_FM_DEVICE_INVAL_STATE,
171 						DDI_SERVICE_DEGRADED},
172 	{NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE,	"rxdma_cfiglogpage",
173 						DDI_FM_DEVICE_INVAL_STATE,
174 						DDI_SERVICE_DEGRADED}
175 };
176 
177 nxge_fm_ereport_attr_t nxge_fm_ereport_zcp[] = {
178 	{NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN,	"rxzcopy_rrfifo_underrun",
179 						DDI_FM_DEVICE_INVAL_STATE,
180 						DDI_SERVICE_UNAFFECTED},
181 	{NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR,
182 						"rxzcopy_rspfifo_uncorr_err",
183 						DDI_FM_DEVICE_INTERN_UNCORR,
184 						DDI_SERVICE_UNAFFECTED},
185 	{NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR,	"rxzcopy_stat_tbl_perr",
186 						DDI_FM_DEVICE_INTERN_UNCORR,
187 						DDI_SERVICE_UNAFFECTED},
188 	{NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR,	"rxzcopy_dyn_tbl_perr",
189 						DDI_FM_DEVICE_INTERN_UNCORR,
190 						DDI_SERVICE_UNAFFECTED},
191 	{NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR,	"rxzcopy_buf_tbl_perr",
192 						DDI_FM_DEVICE_INTERN_UNCORR,
193 						DDI_SERVICE_UNAFFECTED},
194 	{NXGE_FM_EREPORT_ZCP_CFIFO_ECC,		"rxzcopy_cfifo_ecc",
195 						DDI_FM_DEVICE_INTERN_CORR,
196 						DDI_SERVICE_UNAFFECTED},
197 	{NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN,	"rxzcopy_rrfifo_overrun",
198 						DDI_FM_DEVICE_INVAL_STATE,
199 						DDI_SERVICE_UNAFFECTED},
200 	{NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW,	"rxzcopy_buffer_overflow",
201 						DDI_FM_DEVICE_INVAL_STATE,
202 						DDI_SERVICE_LOST},
203 	{NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR,	"rxzcopy_tt_program_err",
204 						DDI_FM_DEVICE_INVAL_STATE,
205 						DDI_SERVICE_UNAFFECTED},
206 	{NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR,	"rxzcopy_rsp_tt_index_err",
207 						DDI_FM_DEVICE_INVAL_STATE,
208 						DDI_SERVICE_UNAFFECTED},
209 	{NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR,	"rxzcopy_slv_tt_index_err",
210 						DDI_FM_DEVICE_INVAL_STATE,
211 						DDI_SERVICE_UNAFFECTED},
212 	{NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR,	"rxzcopy_tt_index_err",
213 						DDI_FM_DEVICE_INVAL_STATE,
214 						DDI_SERVICE_UNAFFECTED},
215 	{NXGE_FM_EREPORT_ZCP_ACCESS_FAIL,	"rxzcopy_access_fail",
216 						DDI_FM_DEVICE_NO_RESPONSE,
217 						DDI_SERVICE_LOST},
218 };
219 
220 nxge_fm_ereport_attr_t nxge_fm_ereport_rxmac[] = {
221 	{NXGE_FM_EREPORT_RXMAC_UNDERFLOW,	"rxmac_underflow",
222 						DDI_FM_DEVICE_INVAL_STATE,
223 						DDI_SERVICE_UNAFFECTED},
224 	{NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP,	"rxmac_crc_errcnt_exp",
225 						DDI_FM_DEVICE_INTERN_UNCORR,
226 						DDI_SERVICE_UNAFFECTED},
227 	{NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP,
228 						"rxmac_length_errcnt_exp",
229 						DDI_FM_DEVICE_INTERN_UNCORR,
230 						DDI_SERVICE_UNAFFECTED},
231 	{NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP,	"rxmac_viol_errcnt_exp",
232 						DDI_FM_DEVICE_INTERN_UNCORR,
233 						DDI_SERVICE_UNAFFECTED},
234 	{NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP,	"rxmac_rxfrag_cnt_exp",
235 						DDI_FM_DEVICE_INTERN_UNCORR,
236 						DDI_SERVICE_UNAFFECTED},
237 	{NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP,	"rxmac_align_ecnt_exp",
238 						DDI_FM_DEVICE_INTERN_UNCORR,
239 						DDI_SERVICE_UNAFFECTED},
240 	{NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP,
241 						"rxmac_linkfault_cnt_exp",
242 						DDI_FM_DEVICE_INTERN_UNCORR,
243 						DDI_SERVICE_UNAFFECTED},
244 	{NXGE_FM_EREPORT_RXMAC_RESET_FAIL,	"rxmac_reset_fail",
245 						DDI_FM_DEVICE_NO_RESPONSE,
246 						DDI_SERVICE_UNAFFECTED},
247 };
248 
249 nxge_fm_ereport_attr_t nxge_fm_ereport_tdmc[] = {
250 	{NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR,	"txdma_pref_buf_par_err",
251 						DDI_FM_DEVICE_INTERN_UNCORR,
252 						DDI_SERVICE_DEGRADED},
253 	{NXGE_FM_EREPORT_TDMC_MBOX_ERR,		"txdma_mbox_err",
254 						DDI_FM_DEVICE_NO_RESPONSE,
255 						DDI_SERVICE_DEGRADED},
256 	{NXGE_FM_EREPORT_TDMC_NACK_PREF,	"txdma_nack_pref",
257 						DDI_FM_DEVICE_NO_RESPONSE,
258 						DDI_SERVICE_DEGRADED},
259 	{NXGE_FM_EREPORT_TDMC_NACK_PKT_RD,	"txdma_nack_pkt_rd",
260 						DDI_FM_DEVICE_NO_RESPONSE,
261 						DDI_SERVICE_DEGRADED},
262 	{NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR,	"txdma_pkt_size_err",
263 						DDI_FM_DEVICE_INVAL_STATE,
264 						DDI_SERVICE_DEGRADED},
265 	{NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW,	"txdma_tx_ring_oflow",
266 						DDI_FM_DEVICE_INVAL_STATE,
267 						DDI_SERVICE_DEGRADED},
268 	{NXGE_FM_EREPORT_TDMC_CONF_PART_ERR,	"txdma_conf_part_err",
269 						DDI_FM_DEVICE_INVAL_STATE,
270 						DDI_SERVICE_DEGRADED},
271 	{NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR,	"txdma_pkt_prt_err",
272 						DDI_FM_DEVICE_INTERN_UNCORR,
273 						DDI_SERVICE_DEGRADED},
274 	{NXGE_FM_EREPORT_TDMC_RESET_FAIL,	"txdma_reset_fail",
275 						DDI_FM_DEVICE_NO_RESPONSE,
276 						DDI_SERVICE_LOST},
277 };
278 
279 nxge_fm_ereport_attr_t nxge_fm_ereport_txc[] = {
280 	{NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR,	"tx_ro_correct_err",
281 						DDI_FM_DEVICE_INTERN_CORR,
282 						DDI_SERVICE_UNAFFECTED},
283 	{NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR,	"tx_ro_uncorrect_err",
284 						DDI_FM_DEVICE_INTERN_UNCORR,
285 						DDI_SERVICE_UNAFFECTED},
286 	{NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR,	"tx_sf_correct_err",
287 						DDI_FM_DEVICE_INTERN_CORR,
288 						DDI_SERVICE_UNAFFECTED},
289 	{NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR,	"tx_sf_uncorrect_err",
290 						DDI_FM_DEVICE_INTERN_UNCORR,
291 						DDI_SERVICE_UNAFFECTED},
292 	{NXGE_FM_EREPORT_TXC_ASSY_DEAD,		"tx_assembly_uncorrect_err",
293 						DDI_FM_DEVICE_INTERN_UNCORR,
294 						DDI_SERVICE_UNAFFECTED},
295 	{NXGE_FM_EREPORT_TXC_REORDER_ERR,	"tx_reorder_err",
296 						DDI_FM_DEVICE_INVAL_STATE,
297 						DDI_SERVICE_LOST},
298 };
299 
300 nxge_fm_ereport_attr_t nxge_fm_ereport_txmac[] = {
301 	{NXGE_FM_EREPORT_TXMAC_UNDERFLOW,	"txmac_underflow",
302 						DDI_FM_DEVICE_INVAL_STATE,
303 						DDI_SERVICE_UNAFFECTED},
304 	{NXGE_FM_EREPORT_TXMAC_OVERFLOW,	"txmac_overflow",
305 						DDI_FM_DEVICE_INVAL_STATE,
306 						DDI_SERVICE_UNAFFECTED},
307 	{NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR,	"txmac_txfifo_xfr_err",
308 						DDI_FM_DEVICE_INVAL_STATE,
309 						DDI_SERVICE_UNAFFECTED},
310 	{NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR,	"txmac_max_pkt_err",
311 						DDI_FM_DEVICE_INTERN_UNCORR,
312 						DDI_SERVICE_UNAFFECTED},
313 	{NXGE_FM_EREPORT_TXMAC_RESET_FAIL,	"txmac_reset_fail",
314 						DDI_FM_DEVICE_NO_RESPONSE,
315 						DDI_SERVICE_UNAFFECTED},
316 };
317 
318 nxge_fm_ereport_attr_t nxge_fm_ereport_espc[] = {
319 	{NXGE_FM_EREPORT_ESPC_ACCESS_FAIL,	"eprom_access_fail",
320 						DDI_FM_DEVICE_NO_RESPONSE,
321 						DDI_SERVICE_LOST},
322 };
323 
324 nxge_fm_ereport_attr_t nxge_fm_ereport_xaui[] = {
325 	{NXGE_FM_EREPORT_XAUI_ERR,		"xaui_bad_or_missing",
326 						NXGE_FM_DEVICE_XAUI_ERR,
327 						DDI_SERVICE_LOST},
328 };
329 
330 nxge_fm_ereport_attr_t nxge_fm_ereport_xfp[] = {
331 	{NXGE_FM_EREPORT_XFP_ERR,		"xfp_bad_or_missing",
332 						NXGE_FM_DEVICE_XFP_ERR,
333 						DDI_SERVICE_LOST},
334 };
335 
336 nxge_fm_ereport_attr_t nxge_fm_ereport_sw[] = {
337 	{NXGE_FM_EREPORT_SW_INVALID_PORT_NUM,	"invalid_port_num",
338 						DDI_FM_DEVICE_INVAL_STATE,
339 						DDI_SERVICE_LOST},
340 	{NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM,	"invalid_chan_num",
341 						DDI_FM_DEVICE_INVAL_STATE,
342 						DDI_SERVICE_LOST},
343 	{NXGE_FM_EREPORT_SW_INVALID_PARAM,	"invalid_param",
344 						DDI_FM_DEVICE_INVAL_STATE,
345 						DDI_SERVICE_LOST},
346 };
347 
348 void
349 nxge_fm_init(p_nxge_t nxgep, ddi_device_acc_attr_t *reg_attr,
350 	ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr)
351 {
352 	ddi_iblock_cookie_t iblk;
353 
354 	/*
355 	 * fm-capable in nxge.conf can be used to set fm_capabilities.
356 	 * If fm-capable is not defined, then the last argument passed to
357 	 * ddi_prop_get_int will be returned as the capabilities.
358 	 */
359 	nxgep->fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, nxgep->dip,
360 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "fm-capable",
361 	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE);
362 
363 	NXGE_ERROR_MSG((nxgep, DDI_CTL,
364 	    "FM capable = %d\n", nxgep->fm_capabilities));
365 
366 	if (isLDOMguest(nxgep)) {
367 		nxgep->fm_capabilities = DDI_FM_NOT_CAPABLE;
368 		return;
369 	}
370 
371 	/*
372 	 * Register capabilities with IO Fault Services. The capabilities
373 	 * set above may not be supported by the parent nexus, in that case
374 	 * some capability bits may be cleared.
375 	 */
376 	if (nxgep->fm_capabilities)
377 		ddi_fm_init(nxgep->dip, &nxgep->fm_capabilities, &iblk);
378 
379 	/*
380 	 * Initialize pci ereport capabilities if ereport capable
381 	 */
382 	if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities) ||
383 	    DDI_FM_ERRCB_CAP(nxgep->fm_capabilities)) {
384 		pci_ereport_setup(nxgep->dip);
385 	}
386 
387 	/* Register error callback if error callback capable */
388 	if (DDI_FM_ERRCB_CAP(nxgep->fm_capabilities)) {
389 		ddi_fm_handler_register(nxgep->dip,
390 		    nxge_fm_error_cb, (void*) nxgep);
391 	}
392 
393 	/*
394 	 * DDI_FLGERR_ACC indicates:
395 	 * o Driver will check its access handle(s) for faults on
396 	 *   a regular basis by calling ddi_fm_acc_err_get
397 	 * o Driver is able to cope with incorrect results of I/O
398 	 *   operations resulted from an I/O fault
399 	 */
400 	if (DDI_FM_ACC_ERR_CAP(nxgep->fm_capabilities)) {
401 		reg_attr->devacc_attr_access  = DDI_FLAGERR_ACC;
402 		desc_attr->devacc_attr_access = DDI_FLAGERR_ACC;
403 	} else {
404 		reg_attr->devacc_attr_access  = DDI_DEFAULT_ACC;
405 		desc_attr->devacc_attr_access = DDI_DEFAULT_ACC;
406 	}
407 
408 	/*
409 	 * DDI_DMA_FLAGERR indicates:
410 	 * o Driver will check its DMA handle(s) for faults on a
411 	 *   regular basis using ddi_fm_dma_err_get
412 	 * o Driver is able to cope with incorrect results of DMA
413 	 *   operations resulted from an I/O fault
414 	 */
415 	if (DDI_FM_DMA_ERR_CAP(nxgep->fm_capabilities))
416 		dma_attr->dma_attr_flags |= DDI_DMA_FLAGERR;
417 	else
418 		dma_attr->dma_attr_flags &= ~DDI_DMA_FLAGERR;
419 
420 }
421 
422 void
423 nxge_fm_fini(p_nxge_t nxgep)
424 {
425 	/* Only unregister FMA capabilities if we registered some */
426 	if (nxgep->fm_capabilities) {
427 
428 		/*
429 		 * Release any resources allocated by pci_ereport_setup()
430 		 */
431 		if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities) ||
432 		    DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
433 			pci_ereport_teardown(nxgep->dip);
434 
435 		/*
436 		 * Un-register error callback if error callback capable
437 		 */
438 		if (DDI_FM_ERRCB_CAP(nxgep->fm_capabilities))
439 			ddi_fm_handler_unregister(nxgep->dip);
440 
441 		/* Unregister from IO Fault Services */
442 		ddi_fm_fini(nxgep->dip);
443 	}
444 }
445 
446 /*ARGSUSED*/
447 /*
448  * Simply call pci_ereport_post which generates ereports for errors
449  * that occur in the PCI local bus configuration status registers.
450  */
451 static int
452 nxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
453 	const void *impl_data)
454 {
455 	pci_ereport_post(dip, err, NULL);
456 	return (err->fme_status);
457 }
458 
459 
460 static nxge_fm_ereport_attr_t *
461 nxge_fm_get_ereport_attr(nxge_fm_ereport_id_t ereport_id)
462 {
463 	nxge_fm_ereport_attr_t *attr;
464 	uint8_t	blk_id = (ereport_id >> EREPORT_FM_ID_SHIFT) &
465 	    EREPORT_FM_ID_MASK;
466 	uint8_t index = ereport_id & EREPORT_INDEX_MASK;
467 
468 	switch (blk_id) {
469 	case FM_SW_ID:
470 		attr = &nxge_fm_ereport_sw[index];
471 		break;
472 	case FM_PCS_ID:
473 		attr = &nxge_fm_ereport_pcs[index];
474 		break;
475 	case FM_TXMAC_ID:
476 		attr = &nxge_fm_ereport_txmac[index];
477 		break;
478 	case FM_RXMAC_ID:
479 		attr = &nxge_fm_ereport_rxmac[index];
480 		break;
481 	case FM_MIF_ID:
482 		attr = &nxge_fm_ereport_mif[index];
483 		break;
484 	case FM_FFLP_ID:
485 		attr = &nxge_fm_ereport_fflp[index];
486 		break;
487 	case FM_ZCP_ID:
488 		attr = &nxge_fm_ereport_zcp[index];
489 		break;
490 	case FM_RXDMA_ID:
491 		attr = &nxge_fm_ereport_rdmc[index];
492 		break;
493 	case FM_TXDMA_ID:
494 		attr = &nxge_fm_ereport_tdmc[index];
495 		break;
496 	case FM_IPP_ID:
497 		attr = &nxge_fm_ereport_ipp[index];
498 		break;
499 	case FM_TXC_ID:
500 		attr = &nxge_fm_ereport_txc[index];
501 		break;
502 	case FM_ESPC_ID:
503 		attr = &nxge_fm_ereport_espc[index];
504 		break;
505 	case FM_XAUI_ID:
506 		attr = &nxge_fm_ereport_xaui[index];
507 		break;
508 	case FM_XFP_ID:
509 		attr = &nxge_fm_ereport_xfp[index];
510 		break;
511 	default:
512 		attr = NULL;
513 	}
514 
515 	return (attr);
516 }
517 
518 static void
519 nxge_fm_ereport(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
520 					nxge_fm_ereport_attr_t *ereport)
521 {
522 	uint64_t		ena;
523 	char			eclass[FM_MAX_CLASS];
524 	char			*err_str;
525 	p_nxge_stats_t		statsp;
526 
527 	(void) snprintf(eclass, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE,
528 	    ereport->eclass);
529 	err_str = ereport->str;
530 	ena = fm_ena_generate(0, FM_ENA_FMT1);
531 	statsp = nxgep->statsp;
532 
533 	switch (ereport->index) {
534 		case NXGE_FM_EREPORT_XPCS_LINK_DOWN:
535 		case NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT:
536 		case NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT:
537 		case NXGE_FM_EREPORT_PCS_LINK_DOWN:
538 		case NXGE_FM_EREPORT_PCS_REMOTE_FAULT:
539 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
540 			    DDI_NOSLEEP,
541 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
542 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
543 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
544 			    NULL);
545 			break;
546 		case NXGE_FM_EREPORT_IPP_EOP_MISS:
547 		case NXGE_FM_EREPORT_IPP_SOP_MISS:
548 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
549 			    DDI_NOSLEEP,
550 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
551 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
552 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
553 			    ERNAME_DFIFO_RD_PTR, DATA_TYPE_UINT16,
554 			    statsp->ipp_stats.errlog.dfifo_rd_ptr,
555 			    ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
556 			    statsp->ipp_stats.errlog.state_mach,
557 			    NULL);
558 			break;
559 		case NXGE_FM_EREPORT_IPP_DFIFO_UE:
560 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
561 			    DDI_NOSLEEP,
562 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
563 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
564 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
565 			    ERNAME_DFIFO_ENTRY, DATA_TYPE_UINT16,
566 			    nxgep->ipp.status.bits.w0.dfifo_ecc_err_idx,
567 			    ERNAME_DFIFO_SYNDROME, DATA_TYPE_UINT16,
568 			    statsp->ipp_stats.errlog.ecc_syndrome,
569 			    NULL);
570 			break;
571 		case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
572 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
573 			    DDI_NOSLEEP,
574 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
575 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
576 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
577 			    ERNAME_PFIFO_ENTRY, DATA_TYPE_UINT8,
578 			    nxgep->ipp.status.bits.w0.pre_fifo_perr_idx,
579 			    NULL);
580 			break;
581 		case NXGE_FM_EREPORT_IPP_DFIFO_CE:
582 		case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
583 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
584 			    DDI_NOSLEEP,
585 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
586 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
587 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
588 			    NULL);
589 			break;
590 		case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
591 		case NXGE_FM_EREPORT_IPP_PFIFO_UND:
592 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
593 			    DDI_NOSLEEP,
594 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
595 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
596 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
597 			    ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
598 			    statsp->ipp_stats.errlog.state_mach,
599 			    NULL);
600 			break;
601 		case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
602 		case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
603 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
604 			    DDI_NOSLEEP,
605 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
606 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
607 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
608 			    NULL);
609 			break;
610 		case NXGE_FM_EREPORT_FFLP_TCAM_ERR:
611 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
612 			    DDI_NOSLEEP,
613 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
614 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
615 			    ERNAME_TCAM_ERR_LOG, DATA_TYPE_UINT32,
616 			    statsp->fflp_stats.errlog.tcam,
617 			    NULL);
618 			break;
619 		case NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR:
620 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
621 			    DDI_NOSLEEP,
622 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
623 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
624 			    ERNAME_VLANTAB_ERR_LOG, DATA_TYPE_UINT32,
625 			    statsp->fflp_stats.errlog.vlan,
626 			    NULL);
627 			break;
628 		case NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR:
629 		{
630 			int rdc_grp;
631 			hash_tbl_data_log_t hash_log;
632 
633 			for (rdc_grp = 0; rdc_grp < MAX_PARTITION; rdc_grp++) {
634 				hash_log.value = nxgep->classifier.fflp_stats->
635 				    errlog.hash_pio[rdc_grp];
636 				if (hash_log.bits.ldw.pio_err) {
637 					ddi_fm_ereport_post(nxgep->dip, eclass,
638 					    ena, DDI_NOSLEEP,
639 					    FM_VERSION, DATA_TYPE_UINT8,
640 					    FM_EREPORT_VERS0,
641 					    ERNAME_DETAILED_ERR_TYPE,
642 					    DATA_TYPE_STRING, err_str,
643 					    ERNAME_HASHTAB_ERR_LOG,
644 					    DATA_TYPE_UINT32,
645 					    nxgep->classifier.fflp_stats->
646 					    errlog.hash_pio[rdc_grp], NULL);
647 				}
648 			}
649 		}
650 			break;
651 		case NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR:
652 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
653 			    DDI_NOSLEEP,
654 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
655 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
656 			    ERNAME_HASHT_LOOKUP_ERR_LOG0, DATA_TYPE_UINT32,
657 			    statsp->fflp_stats.errlog. hash_lookup1,
658 			    ERNAME_HASHT_LOOKUP_ERR_LOG1, DATA_TYPE_UINT32,
659 			    statsp->fflp_stats.errlog.hash_lookup2,
660 			    NULL);
661 			break;
662 		case NXGE_FM_EREPORT_RDMC_DCF_ERR:
663 		case NXGE_FM_EREPORT_RDMC_RBR_TMOUT:
664 		case NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR:
665 		case NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS:
666 		case NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR:
667 		case NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR:
668 		case NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR:
669 		case NXGE_FM_EREPORT_RDMC_CONFIG_ERR:
670 		case NXGE_FM_EREPORT_RDMC_RCRINCON:
671 		case NXGE_FM_EREPORT_RDMC_RCRFULL:
672 		case NXGE_FM_EREPORT_RDMC_RBRFULL:
673 		case NXGE_FM_EREPORT_RDMC_RBRLOGPAGE:
674 		case NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE:
675 		case NXGE_FM_EREPORT_RDMC_ID_MISMATCH:
676 		case NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR:
677 		case NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR:
678 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
679 			    DDI_NOSLEEP,
680 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
681 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
682 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
683 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
684 			    NULL);
685 			break;
686 		case NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
687 		case NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR:
688 			{
689 			uint32_t err_log;
690 			if (ereport->index == NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
691 				err_log = (uint32_t)statsp->
692 				    rdc_stats[err_chan].errlog.pre_par.value;
693 			else
694 				err_log = (uint32_t)statsp->
695 				    rdc_stats[err_chan].errlog.sha_par.value;
696 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
697 			    DDI_NOSLEEP,
698 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
699 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
700 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
701 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
702 			    ERNAME_RDMC_PAR_ERR_LOG, DATA_TYPE_UINT8, err_log,
703 			    NULL);
704 			}
705 			break;
706 		case NXGE_FM_EREPORT_RDMC_RCR_ERR:
707 			{
708 			uint8_t err_type;
709 			err_type = statsp->
710 			    rdc_stats[err_chan].errlog.compl_err_type;
711 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
712 			    DDI_NOSLEEP,
713 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
714 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
715 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
716 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
717 			    ERNAME_RDC_ERR_TYPE, DATA_TYPE_UINT8, err_type,
718 			    NULL);
719 			}
720 			break;
721 
722 		case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
723 		case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
724 		case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
725 			{
726 			uint32_t sm;
727 			sm = statsp->
728 			    zcp_stats.errlog.state_mach.bits.ldw.state;
729 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
730 			    DDI_NOSLEEP,
731 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
732 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
733 			    sm, DATA_TYPE_UINT32,
734 			    NULL);
735 			break;
736 			}
737 		case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
738 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
739 			    DDI_NOSLEEP,
740 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
741 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
742 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
743 			    NULL);
744 			break;
745 		case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
746 		case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
747 		case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
748 		case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
749 		case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
750 		case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
751 		case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
752 		case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
753 		case NXGE_FM_EREPORT_RXMAC_UNDERFLOW:
754 		case NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP:
755 		case NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP:
756 		case NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP:
757 		case NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP:
758 		case NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP:
759 		case NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP:
760 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
761 			    DDI_NOSLEEP,
762 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
763 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
764 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
765 			    NULL);
766 			break;
767 		case NXGE_FM_EREPORT_TDMC_MBOX_ERR:
768 		case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW:
769 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
770 			    DDI_NOSLEEP,
771 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
772 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
773 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
774 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
775 			    NULL);
776 			break;
777 		case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR:
778 		case NXGE_FM_EREPORT_TDMC_NACK_PREF:
779 		case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD:
780 		case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
781 		case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR:
782 		case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR:
783 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
784 			    DDI_NOSLEEP,
785 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
786 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
787 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
788 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
789 			    ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
790 			    statsp->tdc_stats[err_chan].errlog.logl.value,
791 			    ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
792 			    statsp->tdc_stats[err_chan].errlog.logh.value,
793 			    DATA_TYPE_UINT32,
794 			    NULL);
795 			break;
796 		case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
797 		case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
798 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
799 			    DDI_NOSLEEP,
800 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
801 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
802 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
803 			    ERNAME_TXC_ROECC_ADDR, DATA_TYPE_UINT16,
804 			    statsp->txc_stats.errlog.ro_st.roecc.
805 			    bits.ldw.ecc_address,
806 			    ERNAME_TXC_ROECC_DATA0, DATA_TYPE_UINT32,
807 			    statsp->txc_stats.errlog.ro_st.d0.
808 			    bits.ldw.ro_ecc_data0,
809 			    ERNAME_TXC_ROECC_DATA1, DATA_TYPE_UINT32,
810 			    statsp->txc_stats.errlog.ro_st.d1.
811 			    bits.ldw.ro_ecc_data1,
812 			    ERNAME_TXC_ROECC_DATA2, DATA_TYPE_UINT32,
813 			    statsp->txc_stats.errlog.ro_st.d2.
814 			    bits.ldw.ro_ecc_data2,
815 			    ERNAME_TXC_ROECC_DATA3, DATA_TYPE_UINT32,
816 			    statsp->txc_stats.errlog.ro_st.d3.
817 			    bits.ldw.ro_ecc_data3,
818 			    ERNAME_TXC_ROECC_DATA4, DATA_TYPE_UINT32,
819 			    statsp->txc_stats.errlog.ro_st.d4.
820 			    bits.ldw.ro_ecc_data4,
821 			    NULL);
822 			break;
823 		case NXGE_FM_EREPORT_TXC_REORDER_ERR:
824 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
825 			    DDI_NOSLEEP,
826 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
827 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
828 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
829 			    ERNAME_TXC_RO_STATE0, DATA_TYPE_UINT32,
830 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st0.value,
831 			    ERNAME_TXC_RO_STATE1, DATA_TYPE_UINT32,
832 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st1.value,
833 			    ERNAME_TXC_RO_STATE2, DATA_TYPE_UINT32,
834 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st2.value,
835 			    ERNAME_TXC_RO_STATE3, DATA_TYPE_UINT32,
836 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st3.value,
837 			    ERNAME_TXC_RO_STATE_CTL, DATA_TYPE_UINT32,
838 			    (uint32_t)statsp->txc_stats.errlog.ro_st.ctl.value,
839 			    ERNAME_TXC_RO_TIDS, DATA_TYPE_UINT32,
840 			    (uint32_t)statsp->txc_stats.errlog.ro_st.tids.value,
841 			    NULL);
842 			break;
843 		case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
844 		case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
845 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
846 			    DDI_NOSLEEP,
847 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
848 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
849 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
850 			    ERNAME_TXC_SFECC_ADDR, DATA_TYPE_UINT32,
851 			    statsp->txc_stats.errlog.sf_st.sfecc.
852 			    bits.ldw.ecc_address,
853 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
854 			    statsp->txc_stats.errlog.sf_st.d0.
855 			    bits.ldw.sf_ecc_data0,
856 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
857 			    statsp->txc_stats.errlog.sf_st.d1.
858 			    bits.ldw.sf_ecc_data1,
859 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
860 			    statsp->txc_stats.errlog.sf_st.d2.
861 			    bits.ldw.sf_ecc_data2,
862 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
863 			    statsp->txc_stats.errlog.sf_st.d3.
864 			    bits.ldw.sf_ecc_data3,
865 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
866 			    statsp->txc_stats.errlog.sf_st.d4.
867 			    bits.ldw.sf_ecc_data4,
868 			    NULL);
869 			break;
870 		case NXGE_FM_EREPORT_TXMAC_UNDERFLOW:
871 		case NXGE_FM_EREPORT_TXMAC_OVERFLOW:
872 		case NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR:
873 		case NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR:
874 		case NXGE_FM_EREPORT_XAUI_ERR:
875 		case NXGE_FM_EREPORT_XFP_ERR:
876 		case NXGE_FM_EREPORT_SW_INVALID_PORT_NUM:
877 		case NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM:
878 		case NXGE_FM_EREPORT_SW_INVALID_PARAM:
879 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
880 			    DDI_NOSLEEP,
881 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
882 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
883 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
884 			    NULL);
885 			break;
886 	}
887 }
888 
889 void
890 nxge_fm_report_error(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
891 					nxge_fm_ereport_id_t fm_ereport_id)
892 {
893 	nxge_fm_ereport_attr_t		*fm_ereport_attr;
894 
895 	fm_ereport_attr = nxge_fm_get_ereport_attr(fm_ereport_id);
896 	if (fm_ereport_attr != NULL &&
897 	    (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities))) {
898 		nxge_fm_ereport(nxgep, err_portn, err_chan, fm_ereport_attr);
899 		ddi_fm_service_impact(nxgep->dip, fm_ereport_attr->impact);
900 	}
901 }
902 
903 int
904 fm_check_acc_handle(ddi_acc_handle_t handle)
905 {
906 	ddi_fm_error_t err;
907 
908 	ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
909 #ifndef	NXGE_FM_S10
910 	ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
911 #endif
912 	return (err.fme_status);
913 }
914 
915 int
916 fm_check_dma_handle(ddi_dma_handle_t handle)
917 {
918 	ddi_fm_error_t err;
919 
920 	ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
921 	return (err.fme_status);
922 }
923