xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_fm.c (revision f998c95e3b7029fe5f7542e115f7474ddb8024d7)
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 	switch (ereport->index) {
528 		case NXGE_FM_EREPORT_XPCS_LINK_DOWN:
529 		case NXGE_FM_EREPORT_XPCS_TX_LINK_FAULT:
530 		case NXGE_FM_EREPORT_XPCS_RX_LINK_FAULT:
531 		case NXGE_FM_EREPORT_PCS_LINK_DOWN:
532 		case NXGE_FM_EREPORT_PCS_REMOTE_FAULT:
533 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
534 			    DDI_NOSLEEP,
535 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
536 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
537 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
538 			    NULL);
539 			break;
540 		case NXGE_FM_EREPORT_IPP_EOP_MISS:
541 		case NXGE_FM_EREPORT_IPP_SOP_MISS:
542 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
543 			    DDI_NOSLEEP,
544 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
545 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
546 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
547 			    ERNAME_DFIFO_RD_PTR, DATA_TYPE_UINT16,
548 			    statsp->ipp_stats.errlog.dfifo_rd_ptr,
549 			    ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
550 			    statsp->ipp_stats.errlog.state_mach,
551 			    NULL);
552 			break;
553 		case NXGE_FM_EREPORT_IPP_DFIFO_UE:
554 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
555 			    DDI_NOSLEEP,
556 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
557 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
558 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
559 			    ERNAME_DFIFO_ENTRY, DATA_TYPE_UINT16,
560 			    nxgep->ipp.status.bits.w0.dfifo_ecc_err_idx,
561 			    ERNAME_DFIFO_SYNDROME, DATA_TYPE_UINT16,
562 			    statsp->ipp_stats.errlog.ecc_syndrome,
563 			    NULL);
564 			break;
565 		case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
566 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
567 			    DDI_NOSLEEP,
568 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
569 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
570 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
571 			    ERNAME_PFIFO_ENTRY, DATA_TYPE_UINT8,
572 			    nxgep->ipp.status.bits.w0.pre_fifo_perr_idx,
573 			    NULL);
574 			break;
575 		case NXGE_FM_EREPORT_IPP_DFIFO_CE:
576 		case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
577 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
578 			    DDI_NOSLEEP,
579 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
580 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
581 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
582 			    NULL);
583 			break;
584 		case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
585 		case NXGE_FM_EREPORT_IPP_PFIFO_UND:
586 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
587 			    DDI_NOSLEEP,
588 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
589 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
590 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
591 			    ERNAME_IPP_STATE_MACH, DATA_TYPE_UINT32,
592 			    statsp->ipp_stats.errlog.state_mach,
593 			    NULL);
594 			break;
595 		case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
596 		case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
597 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
598 			    DDI_NOSLEEP,
599 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
600 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
601 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
602 			    NULL);
603 			break;
604 		case NXGE_FM_EREPORT_FFLP_TCAM_ERR:
605 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
606 			    DDI_NOSLEEP,
607 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
608 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
609 			    ERNAME_TCAM_ERR_LOG, DATA_TYPE_UINT32,
610 			    statsp->fflp_stats.errlog.tcam,
611 			    NULL);
612 			break;
613 		case NXGE_FM_EREPORT_FFLP_VLAN_PAR_ERR:
614 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
615 			    DDI_NOSLEEP,
616 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
617 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
618 			    ERNAME_VLANTAB_ERR_LOG, DATA_TYPE_UINT32,
619 			    statsp->fflp_stats.errlog.vlan,
620 			    NULL);
621 			break;
622 		case NXGE_FM_EREPORT_FFLP_HASHT_DATA_ERR:
623 		{
624 			int rdc_grp;
625 			hash_tbl_data_log_t hash_log;
626 
627 			for (rdc_grp = 0; rdc_grp < MAX_PARTITION; rdc_grp++) {
628 				hash_log.value = nxgep->classifier.fflp_stats->
629 						errlog.hash_pio[rdc_grp];
630 				if (hash_log.bits.ldw.pio_err) {
631 					ddi_fm_ereport_post(nxgep->dip, eclass,
632 						ena, DDI_NOSLEEP,
633 						FM_VERSION, DATA_TYPE_UINT8,
634 						FM_EREPORT_VERS0,
635 						ERNAME_DETAILED_ERR_TYPE,
636 						DATA_TYPE_STRING, err_str,
637 						ERNAME_HASHTAB_ERR_LOG,
638 						DATA_TYPE_UINT32,
639 						nxgep->classifier.fflp_stats->
640 						errlog.hash_pio[rdc_grp], NULL);
641 				}
642 			}
643 		}
644 			break;
645 		case NXGE_FM_EREPORT_FFLP_HASHT_LOOKUP_ERR:
646 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
647 			    DDI_NOSLEEP,
648 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
649 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
650 			    ERNAME_HASHT_LOOKUP_ERR_LOG0, DATA_TYPE_UINT32,
651 			    statsp->fflp_stats.errlog. hash_lookup1,
652 			    ERNAME_HASHT_LOOKUP_ERR_LOG1, DATA_TYPE_UINT32,
653 			    statsp->fflp_stats.errlog.hash_lookup2,
654 			    NULL);
655 			break;
656 		case NXGE_FM_EREPORT_RDMC_DCF_ERR:
657 		case NXGE_FM_EREPORT_RDMC_RBR_TMOUT:
658 		case NXGE_FM_EREPORT_RDMC_RSP_CNT_ERR:
659 		case NXGE_FM_EREPORT_RDMC_BYTE_EN_BUS:
660 		case NXGE_FM_EREPORT_RDMC_RSP_DAT_ERR:
661 		case NXGE_FM_EREPORT_RDMC_RCR_ACK_ERR:
662 		case NXGE_FM_EREPORT_RDMC_DC_FIFO_ERR:
663 		case NXGE_FM_EREPORT_RDMC_CONFIG_ERR:
664 		case NXGE_FM_EREPORT_RDMC_RCRINCON:
665 		case NXGE_FM_EREPORT_RDMC_RCRFULL:
666 		case NXGE_FM_EREPORT_RDMC_RBRFULL:
667 		case NXGE_FM_EREPORT_RDMC_RBRLOGPAGE:
668 		case NXGE_FM_EREPORT_RDMC_CFIGLOGPAGE:
669 		case NXGE_FM_EREPORT_RDMC_ID_MISMATCH:
670 		case NXGE_FM_EREPORT_RDMC_ZCP_EOP_ERR:
671 		case NXGE_FM_EREPORT_RDMC_IPP_EOP_ERR:
672 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
673 			    DDI_NOSLEEP,
674 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
675 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
676 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
677 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
678 			    NULL);
679 			break;
680 		case NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
681 		case NXGE_FM_EREPORT_RDMC_RCR_SHA_PAR:
682 			{
683 			uint32_t err_log;
684 			if (ereport->index == NXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
685 				err_log = (uint32_t)statsp->
686 				rdc_stats[err_chan].errlog.pre_par.value;
687 			else
688 				err_log = (uint32_t)statsp->
689 				rdc_stats[err_chan].errlog.sha_par.value;
690 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
691 			    DDI_NOSLEEP,
692 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
693 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
694 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
695 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
696 			    ERNAME_RDMC_PAR_ERR_LOG, DATA_TYPE_UINT8, err_log,
697 			    NULL);
698 			}
699 			break;
700 		case NXGE_FM_EREPORT_RDMC_RCR_ERR:
701 			{
702 			uint8_t err_type;
703 			err_type = statsp->
704 				rdc_stats[err_chan].errlog.compl_err_type;
705 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
706 			    DDI_NOSLEEP,
707 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
708 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
709 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
710 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
711 			    ERNAME_RDC_ERR_TYPE, DATA_TYPE_UINT8, err_type,
712 			    NULL);
713 			}
714 			break;
715 
716 		case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
717 		case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
718 		case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
719 			{
720 			uint32_t sm;
721 			sm = statsp->
722 				zcp_stats.errlog.state_mach.bits.ldw.state;
723 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
724 			    DDI_NOSLEEP,
725 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
726 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
727 			    sm, DATA_TYPE_UINT32,
728 			    NULL);
729 			break;
730 			}
731 		case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
732 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
733 			    DDI_NOSLEEP,
734 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
735 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
736 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
737 			    NULL);
738 			break;
739 		case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
740 		case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
741 		case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
742 		case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
743 		case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
744 		case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
745 		case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
746 		case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
747 		case NXGE_FM_EREPORT_RXMAC_UNDERFLOW:
748 		case NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP:
749 		case NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP:
750 		case NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP:
751 		case NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP:
752 		case NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP:
753 		case NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP:
754 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
755 			    DDI_NOSLEEP,
756 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
757 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
758 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
759 			    NULL);
760 			break;
761 		case NXGE_FM_EREPORT_TDMC_MBOX_ERR:
762 		case NXGE_FM_EREPORT_TDMC_TX_RING_OFLOW:
763 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
764 			    DDI_NOSLEEP,
765 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
766 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
767 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
768 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
769 			    NULL);
770 			break;
771 		case NXGE_FM_EREPORT_TDMC_PREF_BUF_PAR_ERR:
772 		case NXGE_FM_EREPORT_TDMC_NACK_PREF:
773 		case NXGE_FM_EREPORT_TDMC_NACK_PKT_RD:
774 		case NXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
775 		case NXGE_FM_EREPORT_TDMC_CONF_PART_ERR:
776 		case NXGE_FM_EREPORT_TDMC_PKT_PRT_ERR:
777 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
778 			    DDI_NOSLEEP,
779 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
780 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
781 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
782 			    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
783 			    ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
784 			    statsp->tdc_stats[err_chan].errlog.logl.value,
785 			    ERNAME_TDMC_ERR_LOG1, DATA_TYPE_UINT32,
786 			    statsp->tdc_stats[err_chan].errlog.logh.value,
787 			    DATA_TYPE_UINT32,
788 			    NULL);
789 			break;
790 		case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
791 		case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
792 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
793 			    DDI_NOSLEEP,
794 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
795 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
796 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
797 			    ERNAME_TXC_ROECC_ADDR, DATA_TYPE_UINT16,
798 			    statsp->txc_stats.errlog.ro_st.roecc.
799 			    bits.ldw.ecc_address,
800 			    ERNAME_TXC_ROECC_DATA0, DATA_TYPE_UINT32,
801 			    statsp->txc_stats.errlog.ro_st.d0.
802 			    bits.ldw.ro_ecc_data0,
803 			    ERNAME_TXC_ROECC_DATA1, DATA_TYPE_UINT32,
804 			    statsp->txc_stats.errlog.ro_st.d1.
805 			    bits.ldw.ro_ecc_data1,
806 			    ERNAME_TXC_ROECC_DATA2, DATA_TYPE_UINT32,
807 			    statsp->txc_stats.errlog.ro_st.d2.
808 			    bits.ldw.ro_ecc_data2,
809 			    ERNAME_TXC_ROECC_DATA3, DATA_TYPE_UINT32,
810 			    statsp->txc_stats.errlog.ro_st.d3.
811 			    bits.ldw.ro_ecc_data3,
812 			    ERNAME_TXC_ROECC_DATA4, DATA_TYPE_UINT32,
813 			    statsp->txc_stats.errlog.ro_st.d4.
814 			    bits.ldw.ro_ecc_data4,
815 			    NULL);
816 			break;
817 		case NXGE_FM_EREPORT_TXC_REORDER_ERR:
818 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
819 			    DDI_NOSLEEP,
820 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
821 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
822 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
823 			    ERNAME_TXC_RO_STATE0, DATA_TYPE_UINT32,
824 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st0.value,
825 			    ERNAME_TXC_RO_STATE1, DATA_TYPE_UINT32,
826 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st1.value,
827 			    ERNAME_TXC_RO_STATE2, DATA_TYPE_UINT32,
828 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st2.value,
829 			    ERNAME_TXC_RO_STATE3, DATA_TYPE_UINT32,
830 			    (uint32_t)statsp->txc_stats.errlog.ro_st.st3.value,
831 			    ERNAME_TXC_RO_STATE_CTL, DATA_TYPE_UINT32,
832 			    (uint32_t)statsp->txc_stats.errlog.ro_st.ctl.value,
833 			    ERNAME_TXC_RO_TIDS, DATA_TYPE_UINT32,
834 			    (uint32_t)statsp->txc_stats.errlog.ro_st.tids.value,
835 			    NULL);
836 			break;
837 		case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
838 		case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
839 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
840 			    DDI_NOSLEEP,
841 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
842 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
843 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
844 			    ERNAME_TXC_SFECC_ADDR, DATA_TYPE_UINT32,
845 			    statsp->txc_stats.errlog.sf_st.sfecc.
846 			    bits.ldw.ecc_address,
847 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
848 			    statsp->txc_stats.errlog.sf_st.d0.
849 			    bits.ldw.sf_ecc_data0,
850 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
851 			    statsp->txc_stats.errlog.sf_st.d1.
852 			    bits.ldw.sf_ecc_data1,
853 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
854 			    statsp->txc_stats.errlog.sf_st.d2.
855 			    bits.ldw.sf_ecc_data2,
856 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
857 			    statsp->txc_stats.errlog.sf_st.d3.
858 			    bits.ldw.sf_ecc_data3,
859 			    ERNAME_TXC_SFECC_DATA0, DATA_TYPE_UINT32,
860 			    statsp->txc_stats.errlog.sf_st.d4.
861 			    bits.ldw.sf_ecc_data4,
862 			    NULL);
863 			break;
864 		case NXGE_FM_EREPORT_TXMAC_UNDERFLOW:
865 		case NXGE_FM_EREPORT_TXMAC_OVERFLOW:
866 		case NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR:
867 		case NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR:
868 		case NXGE_FM_EREPORT_XAUI_ERR:
869 		case NXGE_FM_EREPORT_XFP_ERR:
870 		case NXGE_FM_EREPORT_SW_INVALID_PORT_NUM:
871 		case NXGE_FM_EREPORT_SW_INVALID_CHAN_NUM:
872 		case NXGE_FM_EREPORT_SW_INVALID_PARAM:
873 			ddi_fm_ereport_post(nxgep->dip, eclass, ena,
874 			    DDI_NOSLEEP,
875 			    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
876 			    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
877 			    ERNAME_ERR_PORTN, DATA_TYPE_UINT8, err_portn,
878 			    NULL);
879 			break;
880 	}
881 }
882 
883 void
884 nxge_fm_report_error(p_nxge_t nxgep, uint8_t err_portn, uint8_t err_chan,
885 					nxge_fm_ereport_id_t fm_ereport_id)
886 {
887 	nxge_fm_ereport_attr_t		*fm_ereport_attr;
888 
889 	fm_ereport_attr = nxge_fm_get_ereport_attr(fm_ereport_id);
890 	if (fm_ereport_attr != NULL &&
891 	    (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities))) {
892 		nxge_fm_ereport(nxgep, err_portn, err_chan, fm_ereport_attr);
893 		ddi_fm_service_impact(nxgep->dip, fm_ereport_attr->impact);
894 	}
895 }
896 
897 int
898 fm_check_acc_handle(ddi_acc_handle_t handle)
899 {
900 	ddi_fm_error_t err;
901 
902 	ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
903 #ifndef	NXGE_FM_S10
904 	ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
905 #endif
906 	return (err.fme_status);
907 }
908 
909 int
910 fm_check_dma_handle(ddi_dma_handle_t handle)
911 {
912 	ddi_fm_error_t err;
913 
914 	ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
915 	return (err.fme_status);
916 }
917