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