xref: /titanic_50/usr/src/uts/common/io/hxge/hxge_fm.c (revision f043ebed17bd76d258204de498eeedb6f8f7eebf)
13dec9fcdSqs148142 /*
23dec9fcdSqs148142  * CDDL HEADER START
33dec9fcdSqs148142  *
43dec9fcdSqs148142  * The contents of this file are subject to the terms of the
53dec9fcdSqs148142  * Common Development and Distribution License (the "License").
63dec9fcdSqs148142  * You may not use this file except in compliance with the License.
73dec9fcdSqs148142  *
83dec9fcdSqs148142  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93dec9fcdSqs148142  * or http://www.opensolaris.org/os/licensing.
103dec9fcdSqs148142  * See the License for the specific language governing permissions
113dec9fcdSqs148142  * and limitations under the License.
123dec9fcdSqs148142  *
133dec9fcdSqs148142  * When distributing Covered Code, include this CDDL HEADER in each
143dec9fcdSqs148142  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153dec9fcdSqs148142  * If applicable, add the following below this CDDL HEADER, with the
163dec9fcdSqs148142  * fields enclosed by brackets "[]" replaced with your own identifying
173dec9fcdSqs148142  * information: Portions Copyright [yyyy] [name of copyright owner]
183dec9fcdSqs148142  *
193dec9fcdSqs148142  * CDDL HEADER END
203dec9fcdSqs148142  */
21*f043ebedSMichael Speer 
223dec9fcdSqs148142 /*
23837c1ac4SStephen Hanson  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
243dec9fcdSqs148142  * Use is subject to license terms.
253dec9fcdSqs148142  */
263dec9fcdSqs148142 
273dec9fcdSqs148142 #include <hxge_impl.h>
283dec9fcdSqs148142 #include <sys/ddifm.h>
293dec9fcdSqs148142 #include <sys/fm/protocol.h>
303dec9fcdSqs148142 #include <sys/fm/util.h>
313dec9fcdSqs148142 #include <sys/fm/io/ddi.h>
323dec9fcdSqs148142 
333dec9fcdSqs148142 static hxge_fm_ereport_attr_t
343dec9fcdSqs148142 *hxge_fm_get_ereport_attr(hxge_fm_ereport_id_t ereport_id);
353dec9fcdSqs148142 
363dec9fcdSqs148142 static int
373dec9fcdSqs148142 hxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data);
383dec9fcdSqs148142 
393dec9fcdSqs148142 hxge_fm_ereport_attr_t hxge_fm_ereport_vmac[] = {
403dec9fcdSqs148142 	{HXGE_FM_EREPORT_VMAC_LINK_DOWN,	"10g_link_down",
413dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
423dec9fcdSqs148142 						DDI_SERVICE_LOST}
433dec9fcdSqs148142 };
443dec9fcdSqs148142 
453dec9fcdSqs148142 hxge_fm_ereport_attr_t hxge_fm_ereport_pfc[] = {
463dec9fcdSqs148142 	/*
473dec9fcdSqs148142 	 * The following are part of LDF 0, non-fatal
483dec9fcdSqs148142 	 */
493dec9fcdSqs148142 	{HXGE_FM_EREPORT_PFC_TCAM_PAR_ERR,	"classifier_tcam_par_err",
503dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
513dec9fcdSqs148142 						DDI_SERVICE_UNAFFECTED},
523dec9fcdSqs148142 	{HXGE_FM_EREPORT_PFC_VLAN_PAR_ERR,	"classifier_vlan_par_err",
533dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
543dec9fcdSqs148142 						DDI_SERVICE_UNAFFECTED},
553dec9fcdSqs148142 	{HXGE_FM_EREPORT_PFC_PKT_DROP,		"classifier_pkt_drop_err",
563dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
573dec9fcdSqs148142 						DDI_SERVICE_UNAFFECTED}
583dec9fcdSqs148142 };
593dec9fcdSqs148142 
603dec9fcdSqs148142 hxge_fm_ereport_attr_t hxge_fm_ereport_rdmc[] = {
613dec9fcdSqs148142 	/*
623dec9fcdSqs148142 	 * The following are part of LDF1, fatal
633dec9fcdSqs148142 	 */
643dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RBR_CPL_TO,	"rxdma_rbr_cpl_to",
653dec9fcdSqs148142 						DDI_FM_DEVICE_NO_RESPONSE,
663dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
673dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_PEU_RESP_ERR,	"rxdma_peu_resp_err",
683dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
693dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
703dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RCR_SHA_PAR,	"rxdma_rcr_sha_par_err",
713dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
723dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
733dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR,	"rxdma_rbr_pre_par_err",
743dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
753dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
763dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RBR_PRE_EMPTY,	"rxdma_rbr_pre_empty_err",
773dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
783dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
793dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RCR_SHA_FULL,	"rxdma_rcr_sha_full",
803dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
813dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
823dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RCRFULL,		"rxdma_rcr_full",
833dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
843dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
853dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RBR_EMPTY,	"rxdma_rbr_empty",
863dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
873dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
883dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RBRFULL,		"rxdma_rbr_full",
893dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
903dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
913dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_RCR_ERR,		"rxdma_completion_err",
923dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
933dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
943dec9fcdSqs148142 	/*
953dec9fcdSqs148142 	 * Control/Data ram received a ecc double bit error.
963dec9fcdSqs148142 	 * Fatal error. Part of Device Error 1
973dec9fcdSqs148142 	 */
983dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_CTRL_FIFO_DED,	"rxdma_ctrl_fifo_ded",
993dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1003dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1013dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_DATA_FIFO_DED,	"rxdma_data_fifo_ded",
1023dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1033dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1043dec9fcdSqs148142 	/*
1053dec9fcdSqs148142 	 * Control/Data ram received a ecc single bit error.
1063dec9fcdSqs148142 	 * Non-Fatal error. Part of Device Error 0
1073dec9fcdSqs148142 	 */
1083dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_CTRL_FIFO_SEC,	"rxdma_ctrl_fifo_sec",
1093dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_CORR,
1103dec9fcdSqs148142 						DDI_SERVICE_UNAFFECTED},
1113dec9fcdSqs148142 	{HXGE_FM_EREPORT_RDMC_DATA_FIFO_SEC,	"rxdma_data_fifo_sec",
1123dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_CORR,
1133dec9fcdSqs148142 						DDI_SERVICE_UNAFFECTED}
1143dec9fcdSqs148142 };
1153dec9fcdSqs148142 
1163dec9fcdSqs148142 hxge_fm_ereport_attr_t hxge_fm_ereport_tdmc[] = {
1173dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_PEU_RESP_ERR,	"txdma_peu_resp_err",
1183dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1193dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1203dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_PKT_SIZE_HDR_ERR,	"txdma_pkt_size_hdr_err",
1213dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1223dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1233dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_RUNT_PKT_DROP_ERR, "txdma_runt_pkt_drop_err",
1243dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1253dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1263dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR,	"txdma_pkt_size_err",
1273dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1283dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1293dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_TX_RNG_OFLOW,	"txdma_tx_rng_oflow",
1303dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1313dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1323dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_PREF_PAR_ERR,	"txdma_pref_par_err",
1333dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1343dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1353dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_TDR_PREF_CPL_TO,	"txdma_tdr_pref_cpl_to",
1363dec9fcdSqs148142 						DDI_FM_DEVICE_NO_RESPONSE,
1373dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1383dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_PKT_CPL_TO,	"txdma_pkt_cpl_to",
1393dec9fcdSqs148142 						DDI_FM_DEVICE_NO_RESPONSE,
1403dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1413dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_INVALID_SOP,	"txdma_invalid_sop",
1423dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1433dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1443dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_UNEXPECTED_SOP,	"txdma_unexpected_sop",
1453dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1463dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1473dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_REORD_TBL_PAR,	"txdma_reord_tbl_par_err",
1483dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1493dec9fcdSqs148142 						DDI_SERVICE_DEGRADED},
1503dec9fcdSqs148142 	{HXGE_FM_EREPORT_TDMC_REORD_BUF_DED,	"txdma_reord_buf_ded_err",
1513dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1523dec9fcdSqs148142 						DDI_SERVICE_DEGRADED}
1533dec9fcdSqs148142 };
1543dec9fcdSqs148142 
1553dec9fcdSqs148142 hxge_fm_ereport_attr_t hxge_fm_ereport_peu[] = {
1563dec9fcdSqs148142 	{HXGE_FM_EREPORT_PEU_ERR,		"peu_peu_err",
1573dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1583dec9fcdSqs148142 						DDI_SERVICE_LOST},
1593dec9fcdSqs148142 	{HXGE_FM_EREPORT_PEU_VNM_PIO_ERR,	"peu_vnm_pio_err",
1603dec9fcdSqs148142 						DDI_FM_DEVICE_INTERN_UNCORR,
1613dec9fcdSqs148142 						DDI_SERVICE_LOST}
1623dec9fcdSqs148142 };
1633dec9fcdSqs148142 
1643dec9fcdSqs148142 hxge_fm_ereport_attr_t hxge_fm_ereport_sw[] = {
1653dec9fcdSqs148142 	{HXGE_FM_EREPORT_SW_INVALID_CHAN_NUM,	"invalid_chan_num",
1663dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1673dec9fcdSqs148142 						DDI_SERVICE_LOST},
1683dec9fcdSqs148142 	{HXGE_FM_EREPORT_SW_INVALID_PARAM,	"invalid_param",
1693dec9fcdSqs148142 						DDI_FM_DEVICE_INVAL_STATE,
1703dec9fcdSqs148142 						DDI_SERVICE_LOST}
1713dec9fcdSqs148142 };
1723dec9fcdSqs148142 
1733dec9fcdSqs148142 void
hxge_fm_init(p_hxge_t hxgep,ddi_device_acc_attr_t * reg_attr,ddi_device_acc_attr_t * desc_attr,ddi_dma_attr_t * dma_attr)1743dec9fcdSqs148142 hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
175*f043ebedSMichael Speer 	ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr)
1763dec9fcdSqs148142 {
1773dec9fcdSqs148142 	ddi_iblock_cookie_t iblk;
1783dec9fcdSqs148142 
1793dec9fcdSqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_fm_init"));
1803dec9fcdSqs148142 
1813dec9fcdSqs148142 	/* fm-capable in hxge.conf can be used to set fm_capabilities. */
1823dec9fcdSqs148142 	hxgep->fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, hxgep->dip,
1833dec9fcdSqs148142 	    DDI_PROP_DONTPASS, "fm-capable",
1843dec9fcdSqs148142 	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1853dec9fcdSqs148142 
1863dec9fcdSqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
1873dec9fcdSqs148142 	    "FM capable = %d\n", hxgep->fm_capabilities));
1883dec9fcdSqs148142 
1893dec9fcdSqs148142 	/*
1903dec9fcdSqs148142 	 * Register capabilities with IO Fault Services. The capabilities
1913dec9fcdSqs148142 	 * set above may not be supported by the parent nexus, in that case
1923dec9fcdSqs148142 	 * some capability bits may be cleared.
1933dec9fcdSqs148142 	 */
1943dec9fcdSqs148142 	if (hxgep->fm_capabilities)
1953dec9fcdSqs148142 		ddi_fm_init(hxgep->dip, &hxgep->fm_capabilities, &iblk);
1963dec9fcdSqs148142 
1973dec9fcdSqs148142 	/*
1983dec9fcdSqs148142 	 * Initialize pci ereport capabilities if ereport capable
1993dec9fcdSqs148142 	 */
2003dec9fcdSqs148142 	if (DDI_FM_EREPORT_CAP(hxgep->fm_capabilities) ||
2013dec9fcdSqs148142 	    DDI_FM_ERRCB_CAP(hxgep->fm_capabilities)) {
2023dec9fcdSqs148142 		pci_ereport_setup(hxgep->dip);
2033dec9fcdSqs148142 	}
2043dec9fcdSqs148142 
2053dec9fcdSqs148142 	/* Register error callback if error callback capable */
2063dec9fcdSqs148142 	if (DDI_FM_ERRCB_CAP(hxgep->fm_capabilities)) {
2073dec9fcdSqs148142 		ddi_fm_handler_register(hxgep->dip,
2083dec9fcdSqs148142 		    hxge_fm_error_cb, (void *) hxgep);
2093dec9fcdSqs148142 	}
2103dec9fcdSqs148142 
2113dec9fcdSqs148142 	/*
2123dec9fcdSqs148142 	 * DDI_FLGERR_ACC indicates:
2133dec9fcdSqs148142 	 * o Driver will check its access handle(s) for faults on
2143dec9fcdSqs148142 	 *   a regular basis by calling ddi_fm_acc_err_get
2153dec9fcdSqs148142 	 * o Driver is able to cope with incorrect results of I/O
2163dec9fcdSqs148142 	 *   operations resulted from an I/O fault
2173dec9fcdSqs148142 	 */
2183dec9fcdSqs148142 	if (DDI_FM_ACC_ERR_CAP(hxgep->fm_capabilities)) {
2193dec9fcdSqs148142 		reg_attr->devacc_attr_access  = DDI_FLAGERR_ACC;
220*f043ebedSMichael Speer 		desc_attr->devacc_attr_access = DDI_FLAGERR_ACC;
2213dec9fcdSqs148142 	} else {
2223dec9fcdSqs148142 		reg_attr->devacc_attr_access  = DDI_DEFAULT_ACC;
223*f043ebedSMichael Speer 		desc_attr->devacc_attr_access = DDI_DEFAULT_ACC;
2243dec9fcdSqs148142 	}
2253dec9fcdSqs148142 
2263dec9fcdSqs148142 	/*
2273dec9fcdSqs148142 	 * DDI_DMA_FLAGERR indicates:
2283dec9fcdSqs148142 	 * o Driver will check its DMA handle(s) for faults on a
2293dec9fcdSqs148142 	 *   regular basis using ddi_fm_dma_err_get
2303dec9fcdSqs148142 	 * o Driver is able to cope with incorrect results of DMA
2313dec9fcdSqs148142 	 *   operations resulted from an I/O fault
2323dec9fcdSqs148142 	 */
2333dec9fcdSqs148142 	if (DDI_FM_DMA_ERR_CAP(hxgep->fm_capabilities))
2343dec9fcdSqs148142 		dma_attr->dma_attr_flags |= DDI_DMA_FLAGERR;
2353dec9fcdSqs148142 	else
2363dec9fcdSqs148142 		dma_attr->dma_attr_flags &= ~DDI_DMA_FLAGERR;
2373dec9fcdSqs148142 
2383dec9fcdSqs148142 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_fm_init"));
2393dec9fcdSqs148142 }
2403dec9fcdSqs148142 
2413dec9fcdSqs148142 void
hxge_fm_fini(p_hxge_t hxgep)2423dec9fcdSqs148142 hxge_fm_fini(p_hxge_t hxgep)
2433dec9fcdSqs148142 {
2443dec9fcdSqs148142 	/* Only unregister FMA capabilities if we registered some */
2453dec9fcdSqs148142 	if (hxgep->fm_capabilities) {
2463dec9fcdSqs148142 		/*
2473dec9fcdSqs148142 		 * Release any resources allocated by pci_ereport_setup()
2483dec9fcdSqs148142 		 */
2493dec9fcdSqs148142 		if (DDI_FM_EREPORT_CAP(hxgep->fm_capabilities) ||
2503dec9fcdSqs148142 		    DDI_FM_ERRCB_CAP(hxgep->fm_capabilities))
2513dec9fcdSqs148142 			pci_ereport_teardown(hxgep->dip);
2523dec9fcdSqs148142 
2533dec9fcdSqs148142 		/*
2543dec9fcdSqs148142 		 * Un-register error callback if error callback capable
2553dec9fcdSqs148142 		 */
2563dec9fcdSqs148142 		if (DDI_FM_ERRCB_CAP(hxgep->fm_capabilities))
2573dec9fcdSqs148142 			ddi_fm_handler_unregister(hxgep->dip);
2583dec9fcdSqs148142 
2593dec9fcdSqs148142 		/* Unregister from IO Fault Services */
2603dec9fcdSqs148142 		ddi_fm_fini(hxgep->dip);
2613dec9fcdSqs148142 	}
2623dec9fcdSqs148142 }
2633dec9fcdSqs148142 
2643dec9fcdSqs148142 
2653dec9fcdSqs148142 /*
2663dec9fcdSqs148142  * Simply call pci_ereport_post which generates ereports for errors
2673dec9fcdSqs148142  * that occur in the PCI local bus configuration status registers.
2683dec9fcdSqs148142  */
2693dec9fcdSqs148142 /*ARGSUSED*/
2703dec9fcdSqs148142 static int
hxge_fm_error_cb(dev_info_t * dip,ddi_fm_error_t * err,const void * impl_data)2713dec9fcdSqs148142 hxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
2723dec9fcdSqs148142 	const void *impl_data)
2733dec9fcdSqs148142 {
2743dec9fcdSqs148142 	pci_ereport_post(dip, err, NULL);
2753dec9fcdSqs148142 	return (err->fme_status);
2763dec9fcdSqs148142 }
2773dec9fcdSqs148142 
2783dec9fcdSqs148142 
2793dec9fcdSqs148142 static hxge_fm_ereport_attr_t *
hxge_fm_get_ereport_attr(hxge_fm_ereport_id_t ereport_id)2803dec9fcdSqs148142 hxge_fm_get_ereport_attr(hxge_fm_ereport_id_t ereport_id)
2813dec9fcdSqs148142 {
2823dec9fcdSqs148142 	hxge_fm_ereport_attr_t	*attr;
2833dec9fcdSqs148142 	uint8_t			blk_id;
2843dec9fcdSqs148142 	uint8_t			index;
2853dec9fcdSqs148142 
2863dec9fcdSqs148142 	/* Extract the block id and the index within the block */
2873dec9fcdSqs148142 	blk_id = ((ereport_id >> EREPORT_FM_ID_SHIFT) & EREPORT_FM_ID_MASK);
2883dec9fcdSqs148142 	index = (ereport_id & EREPORT_INDEX_MASK);
2893dec9fcdSqs148142 
2903dec9fcdSqs148142 	/* Return the appropriate structure of type hxge_fm_ereport_attr_t */
2913dec9fcdSqs148142 	switch (blk_id) {
2923dec9fcdSqs148142 	case FM_SW_ID:
2933dec9fcdSqs148142 		attr = &hxge_fm_ereport_sw[index];
2943dec9fcdSqs148142 		break;
2953dec9fcdSqs148142 	case FM_VMAC_ID:
2963dec9fcdSqs148142 		attr = &hxge_fm_ereport_vmac[index];
2973dec9fcdSqs148142 		break;
2983dec9fcdSqs148142 	case FM_PFC_ID:
2993dec9fcdSqs148142 		attr = &hxge_fm_ereport_pfc[index];
3003dec9fcdSqs148142 		break;
3013dec9fcdSqs148142 	case FM_RXDMA_ID:
3023dec9fcdSqs148142 		attr = &hxge_fm_ereport_rdmc[index];
3033dec9fcdSqs148142 		break;
3043dec9fcdSqs148142 	case FM_TXDMA_ID:
3053dec9fcdSqs148142 		attr = &hxge_fm_ereport_tdmc[index];
3063dec9fcdSqs148142 		break;
3073dec9fcdSqs148142 	case FM_PEU_ID:
3083dec9fcdSqs148142 		attr = &hxge_fm_ereport_peu[index];
3093dec9fcdSqs148142 		break;
3103dec9fcdSqs148142 	default:
3113dec9fcdSqs148142 		attr = NULL;
3123dec9fcdSqs148142 	}
3133dec9fcdSqs148142 
3143dec9fcdSqs148142 	return (attr);
3153dec9fcdSqs148142 }
3163dec9fcdSqs148142 
3173dec9fcdSqs148142 static void
hxge_fm_ereport(p_hxge_t hxgep,uint8_t err_chan,hxge_fm_ereport_attr_t * ereport)3183dec9fcdSqs148142 hxge_fm_ereport(p_hxge_t hxgep, uint8_t err_chan,
3193dec9fcdSqs148142 	hxge_fm_ereport_attr_t *ereport)
3203dec9fcdSqs148142 {
3213dec9fcdSqs148142 	uint64_t		ena;
3223dec9fcdSqs148142 	char			eclass[FM_MAX_CLASS];
3233dec9fcdSqs148142 	char			*err_str;
3243dec9fcdSqs148142 	p_hxge_stats_t		statsp;
3253dec9fcdSqs148142 
3263dec9fcdSqs148142 	(void) snprintf(eclass, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE,
3273dec9fcdSqs148142 	    ereport->eclass);
3283dec9fcdSqs148142 
3293dec9fcdSqs148142 	err_str = ereport->str;
3303dec9fcdSqs148142 	ena = fm_ena_generate(0, FM_ENA_FMT1);
3313dec9fcdSqs148142 	statsp = hxgep->statsp;
3323dec9fcdSqs148142 
3333dec9fcdSqs148142 	switch (ereport->index) {
3343dec9fcdSqs148142 	case HXGE_FM_EREPORT_VMAC_LINK_DOWN:
3353dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
3363dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
3373dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
3383dec9fcdSqs148142 		    NULL);
3393dec9fcdSqs148142 		break;
3403dec9fcdSqs148142 	case HXGE_FM_EREPORT_PFC_TCAM_PAR_ERR:
3413dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
3423dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
3433dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
3443dec9fcdSqs148142 		    ERNAME_PFC_TCAM_ERR, DATA_TYPE_UINT32,
3453dec9fcdSqs148142 		    statsp->pfc_stats.tcam_parity_err,
3463dec9fcdSqs148142 		    NULL);
3473dec9fcdSqs148142 		break;
3483dec9fcdSqs148142 	case HXGE_FM_EREPORT_PFC_VLAN_PAR_ERR:
3493dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
3503dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
3513dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
3523dec9fcdSqs148142 		    ERNAME_PFC_VLAN_ERR, DATA_TYPE_UINT32,
3533dec9fcdSqs148142 		    statsp->pfc_stats.vlan_parity_err,
3543dec9fcdSqs148142 		    NULL);
3553dec9fcdSqs148142 		break;
3563dec9fcdSqs148142 	case HXGE_FM_EREPORT_PFC_PKT_DROP:
3573dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
3583dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
3593dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
3603dec9fcdSqs148142 		    ERNAME_PFC_PKT_DROP, DATA_TYPE_UINT32,
3613dec9fcdSqs148142 		    statsp->pfc_stats.pkt_drop,
3623dec9fcdSqs148142 		    NULL);
3633dec9fcdSqs148142 		break;
3643dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RBR_CPL_TO:
3653dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_PEU_RESP_ERR:
3663dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RCRFULL:
3673dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RBR_EMPTY:
3683dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RBRFULL:
3693dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RBR_PRE_EMPTY:
3703dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RCR_SHA_FULL:
3713dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
3723dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
3733dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
3743dec9fcdSqs148142 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
3753dec9fcdSqs148142 		    NULL);
3763dec9fcdSqs148142 		break;
3773dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
3783dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RCR_SHA_PAR: {
3793dec9fcdSqs148142 		uint32_t err_log;
3803dec9fcdSqs148142 		hxge_rx_ring_stats_t *rdc_statsp;
3813dec9fcdSqs148142 
3823dec9fcdSqs148142 		rdc_statsp = &statsp->rdc_stats[err_chan];
3833dec9fcdSqs148142 		if (ereport->index == HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
3843dec9fcdSqs148142 			err_log = (uint32_t)
3853dec9fcdSqs148142 			    rdc_statsp->errlog.pre_par.value;
3863dec9fcdSqs148142 		else
3873dec9fcdSqs148142 			err_log = (uint32_t)
3883dec9fcdSqs148142 			    rdc_statsp->errlog.sha_par.value;
3893dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
3903dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
3913dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
3923dec9fcdSqs148142 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
3933dec9fcdSqs148142 		    ERNAME_RDMC_PAR_ERR_LOG, DATA_TYPE_UINT8, err_log,
3943dec9fcdSqs148142 		    NULL);
3953dec9fcdSqs148142 		}
3963dec9fcdSqs148142 		break;
3973dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_RCR_ERR: {
3983dec9fcdSqs148142 		uint8_t err_type;
3993dec9fcdSqs148142 		err_type = statsp->rdc_stats[err_chan].errlog.compl_err_type;
4003dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4013dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4023dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4033dec9fcdSqs148142 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
4043dec9fcdSqs148142 		    ERNAME_RDC_ERR_TYPE, DATA_TYPE_UINT8, err_type,
4053dec9fcdSqs148142 		    NULL);
4063dec9fcdSqs148142 		}
4073dec9fcdSqs148142 		break;
4083dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_CTRL_FIFO_SEC:
4093dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_CTRL_FIFO_DED:
4103dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_DATA_FIFO_SEC:
4113dec9fcdSqs148142 	case HXGE_FM_EREPORT_RDMC_DATA_FIFO_DED:
4123dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4133dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4143dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4153dec9fcdSqs148142 		    NULL);
4163dec9fcdSqs148142 		break;
4173dec9fcdSqs148142 
4183dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_PEU_RESP_ERR:
4193dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_TX_RNG_OFLOW:
4203dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_PKT_SIZE_HDR_ERR:
4213dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_RUNT_PKT_DROP_ERR:
4223dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
4233dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_TDR_PREF_CPL_TO:
4243dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_PKT_CPL_TO:
4253dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_INVALID_SOP:
4263dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_UNEXPECTED_SOP:
4273dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4283dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4293dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4303dec9fcdSqs148142 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
4313dec9fcdSqs148142 		    NULL);
4323dec9fcdSqs148142 		break;
4333dec9fcdSqs148142 
4343dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_PREF_PAR_ERR:
4353dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4363dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4373dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4383dec9fcdSqs148142 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
4393dec9fcdSqs148142 		    ERNAME_TDC_PREF_PAR_LOG, DATA_TYPE_UINT32,
4403dec9fcdSqs148142 		    statsp->tdc_stats[err_chan].errlog.value, NULL);
4413dec9fcdSqs148142 		break;
4423dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_REORD_TBL_PAR:
4433dec9fcdSqs148142 	case HXGE_FM_EREPORT_TDMC_REORD_BUF_DED:
4443dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4453dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4463dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4473dec9fcdSqs148142 		    NULL);
4483dec9fcdSqs148142 		break;
4493dec9fcdSqs148142 
4503dec9fcdSqs148142 	case HXGE_FM_EREPORT_PEU_ERR:
4513dec9fcdSqs148142 	case HXGE_FM_EREPORT_PEU_VNM_PIO_ERR:
4523dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4533dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4543dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4553dec9fcdSqs148142 		    NULL);
4563dec9fcdSqs148142 		break;
4573dec9fcdSqs148142 
4583dec9fcdSqs148142 	case HXGE_FM_EREPORT_SW_INVALID_CHAN_NUM:
4593dec9fcdSqs148142 	case HXGE_FM_EREPORT_SW_INVALID_PARAM:
4603dec9fcdSqs148142 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
4613dec9fcdSqs148142 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
4623dec9fcdSqs148142 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
4633dec9fcdSqs148142 		    NULL);
4643dec9fcdSqs148142 		break;
4653dec9fcdSqs148142 	}
4663dec9fcdSqs148142 }
4673dec9fcdSqs148142 
4683dec9fcdSqs148142 void
hxge_fm_report_error(p_hxge_t hxgep,uint8_t err_chan,hxge_fm_ereport_id_t fm_ereport_id)4693dec9fcdSqs148142 hxge_fm_report_error(p_hxge_t hxgep, uint8_t err_chan,
4703dec9fcdSqs148142 	hxge_fm_ereport_id_t fm_ereport_id)
4713dec9fcdSqs148142 {
4723dec9fcdSqs148142 	hxge_fm_ereport_attr_t	*fm_ereport_attr;
4733dec9fcdSqs148142 
4743dec9fcdSqs148142 	fm_ereport_attr = hxge_fm_get_ereport_attr(fm_ereport_id);
4753dec9fcdSqs148142 
4763dec9fcdSqs148142 	if (fm_ereport_attr != NULL &&
4773dec9fcdSqs148142 	    (DDI_FM_EREPORT_CAP(hxgep->fm_capabilities))) {
4783dec9fcdSqs148142 		hxge_fm_ereport(hxgep, err_chan, fm_ereport_attr);
4793dec9fcdSqs148142 		ddi_fm_service_impact(hxgep->dip, fm_ereport_attr->impact);
4803dec9fcdSqs148142 	}
4813dec9fcdSqs148142 }
4823dec9fcdSqs148142 
4833dec9fcdSqs148142 int
fm_check_acc_handle(ddi_acc_handle_t handle)4843dec9fcdSqs148142 fm_check_acc_handle(ddi_acc_handle_t handle)
4853dec9fcdSqs148142 {
4863dec9fcdSqs148142 	ddi_fm_error_t err;
4873dec9fcdSqs148142 
4883dec9fcdSqs148142 	ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
4893dec9fcdSqs148142 	ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
4903dec9fcdSqs148142 
4913dec9fcdSqs148142 	return (err.fme_status);
4923dec9fcdSqs148142 }
4933dec9fcdSqs148142 
4943dec9fcdSqs148142 int
fm_check_dma_handle(ddi_dma_handle_t handle)4953dec9fcdSqs148142 fm_check_dma_handle(ddi_dma_handle_t handle)
4963dec9fcdSqs148142 {
4973dec9fcdSqs148142 	ddi_fm_error_t err;
4983dec9fcdSqs148142 
4993dec9fcdSqs148142 	ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
5003dec9fcdSqs148142 	return (err.fme_status);
5013dec9fcdSqs148142 }
502