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