Home | History | Annotate | Download | only in hxge
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <hxge_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 hxge_fm_ereport_attr_t
     35 *hxge_fm_get_ereport_attr(hxge_fm_ereport_id_t ereport_id);
     36 
     37 static int
     38 hxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data);
     39 
     40 hxge_fm_ereport_attr_t hxge_fm_ereport_vmac[] = {
     41 	{HXGE_FM_EREPORT_VMAC_LINK_DOWN,	"10g_link_down",
     42 						DDI_FM_DEVICE_INTERN_UNCORR,
     43 						DDI_SERVICE_LOST}
     44 };
     45 
     46 hxge_fm_ereport_attr_t hxge_fm_ereport_pfc[] = {
     47 	/*
     48 	 * The following are part of LDF 0, non-fatal
     49 	 */
     50 	{HXGE_FM_EREPORT_PFC_TCAM_PAR_ERR,	"classifier_tcam_par_err",
     51 						DDI_FM_DEVICE_INTERN_UNCORR,
     52 						DDI_SERVICE_UNAFFECTED},
     53 	{HXGE_FM_EREPORT_PFC_VLAN_PAR_ERR,	"classifier_vlan_par_err",
     54 						DDI_FM_DEVICE_INTERN_UNCORR,
     55 						DDI_SERVICE_UNAFFECTED},
     56 	{HXGE_FM_EREPORT_PFC_PKT_DROP,		"classifier_pkt_drop_err",
     57 						DDI_FM_DEVICE_INTERN_UNCORR,
     58 						DDI_SERVICE_UNAFFECTED}
     59 };
     60 
     61 hxge_fm_ereport_attr_t hxge_fm_ereport_rdmc[] = {
     62 	/*
     63 	 * The following are part of LDF1, fatal
     64 	 */
     65 	{HXGE_FM_EREPORT_RDMC_RBR_CPL_TO,	"rxdma_rbr_cpl_to",
     66 						DDI_FM_DEVICE_NO_RESPONSE,
     67 						DDI_SERVICE_DEGRADED},
     68 	{HXGE_FM_EREPORT_RDMC_PEU_RESP_ERR,	"rxdma_peu_resp_err",
     69 						DDI_FM_DEVICE_INVAL_STATE,
     70 						DDI_SERVICE_DEGRADED},
     71 	{HXGE_FM_EREPORT_RDMC_RCR_SHA_PAR,	"rxdma_rcr_sha_par_err",
     72 						DDI_FM_DEVICE_INTERN_UNCORR,
     73 						DDI_SERVICE_DEGRADED},
     74 	{HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR,	"rxdma_rbr_pre_par_err",
     75 						DDI_FM_DEVICE_INTERN_UNCORR,
     76 						DDI_SERVICE_DEGRADED},
     77 	{HXGE_FM_EREPORT_RDMC_RBR_PRE_EMPTY,	"rxdma_rbr_pre_empty_err",
     78 						DDI_FM_DEVICE_INTERN_UNCORR,
     79 						DDI_SERVICE_DEGRADED},
     80 	{HXGE_FM_EREPORT_RDMC_RCR_SHA_FULL,	"rxdma_rcr_sha_full",
     81 						DDI_FM_DEVICE_INVAL_STATE,
     82 						DDI_SERVICE_DEGRADED},
     83 	{HXGE_FM_EREPORT_RDMC_RCRFULL,		"rxdma_rcr_full",
     84 						DDI_FM_DEVICE_INVAL_STATE,
     85 						DDI_SERVICE_DEGRADED},
     86 	{HXGE_FM_EREPORT_RDMC_RBR_EMPTY,	"rxdma_rbr_empty",
     87 						DDI_FM_DEVICE_INVAL_STATE,
     88 						DDI_SERVICE_DEGRADED},
     89 	{HXGE_FM_EREPORT_RDMC_RBRFULL,		"rxdma_rbr_full",
     90 						DDI_FM_DEVICE_INVAL_STATE,
     91 						DDI_SERVICE_DEGRADED},
     92 	{HXGE_FM_EREPORT_RDMC_RCR_ERR,		"rxdma_completion_err",
     93 						DDI_FM_DEVICE_INTERN_UNCORR,
     94 						DDI_SERVICE_DEGRADED},
     95 	/*
     96 	 * Control/Data ram received a ecc double bit error.
     97 	 * Fatal error. Part of Device Error 1
     98 	 */
     99 	{HXGE_FM_EREPORT_RDMC_CTRL_FIFO_DED,	"rxdma_ctrl_fifo_ded",
    100 						DDI_FM_DEVICE_INTERN_UNCORR,
    101 						DDI_SERVICE_DEGRADED},
    102 	{HXGE_FM_EREPORT_RDMC_DATA_FIFO_DED,	"rxdma_data_fifo_ded",
    103 						DDI_FM_DEVICE_INTERN_UNCORR,
    104 						DDI_SERVICE_DEGRADED},
    105 	/*
    106 	 * Control/Data ram received a ecc single bit error.
    107 	 * Non-Fatal error. Part of Device Error 0
    108 	 */
    109 	{HXGE_FM_EREPORT_RDMC_CTRL_FIFO_SEC,	"rxdma_ctrl_fifo_sec",
    110 						DDI_FM_DEVICE_INTERN_CORR,
    111 						DDI_SERVICE_UNAFFECTED},
    112 	{HXGE_FM_EREPORT_RDMC_DATA_FIFO_SEC,	"rxdma_data_fifo_sec",
    113 						DDI_FM_DEVICE_INTERN_CORR,
    114 						DDI_SERVICE_UNAFFECTED}
    115 };
    116 
    117 hxge_fm_ereport_attr_t hxge_fm_ereport_tdmc[] = {
    118 	{HXGE_FM_EREPORT_TDMC_PEU_RESP_ERR,	"txdma_peu_resp_err",
    119 						DDI_FM_DEVICE_INVAL_STATE,
    120 						DDI_SERVICE_DEGRADED},
    121 	{HXGE_FM_EREPORT_TDMC_PKT_SIZE_HDR_ERR,	"txdma_pkt_size_hdr_err",
    122 						DDI_FM_DEVICE_INVAL_STATE,
    123 						DDI_SERVICE_DEGRADED},
    124 	{HXGE_FM_EREPORT_TDMC_RUNT_PKT_DROP_ERR, "txdma_runt_pkt_drop_err",
    125 						DDI_FM_DEVICE_INVAL_STATE,
    126 						DDI_SERVICE_DEGRADED},
    127 	{HXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR,	"txdma_pkt_size_err",
    128 						DDI_FM_DEVICE_INVAL_STATE,
    129 						DDI_SERVICE_DEGRADED},
    130 	{HXGE_FM_EREPORT_TDMC_TX_RNG_OFLOW,	"txdma_tx_rng_oflow",
    131 						DDI_FM_DEVICE_INVAL_STATE,
    132 						DDI_SERVICE_DEGRADED},
    133 	{HXGE_FM_EREPORT_TDMC_PREF_PAR_ERR,	"txdma_pref_par_err",
    134 						DDI_FM_DEVICE_INTERN_UNCORR,
    135 						DDI_SERVICE_DEGRADED},
    136 	{HXGE_FM_EREPORT_TDMC_TDR_PREF_CPL_TO,	"txdma_tdr_pref_cpl_to",
    137 						DDI_FM_DEVICE_NO_RESPONSE,
    138 						DDI_SERVICE_DEGRADED},
    139 	{HXGE_FM_EREPORT_TDMC_PKT_CPL_TO,	"txdma_pkt_cpl_to",
    140 						DDI_FM_DEVICE_NO_RESPONSE,
    141 						DDI_SERVICE_DEGRADED},
    142 	{HXGE_FM_EREPORT_TDMC_INVALID_SOP,	"txdma_invalid_sop",
    143 						DDI_FM_DEVICE_INVAL_STATE,
    144 						DDI_SERVICE_DEGRADED},
    145 	{HXGE_FM_EREPORT_TDMC_UNEXPECTED_SOP,	"txdma_unexpected_sop",
    146 						DDI_FM_DEVICE_INVAL_STATE,
    147 						DDI_SERVICE_DEGRADED},
    148 	{HXGE_FM_EREPORT_TDMC_REORD_TBL_PAR,	"txdma_reord_tbl_par_err",
    149 						DDI_FM_DEVICE_INTERN_UNCORR,
    150 						DDI_SERVICE_DEGRADED},
    151 	{HXGE_FM_EREPORT_TDMC_REORD_BUF_DED,	"txdma_reord_buf_ded_err",
    152 						DDI_FM_DEVICE_INTERN_UNCORR,
    153 						DDI_SERVICE_DEGRADED}
    154 };
    155 
    156 hxge_fm_ereport_attr_t hxge_fm_ereport_peu[] = {
    157 	{HXGE_FM_EREPORT_PEU_ERR,		"peu_peu_err",
    158 						DDI_FM_DEVICE_INTERN_UNCORR,
    159 						DDI_SERVICE_LOST},
    160 	{HXGE_FM_EREPORT_PEU_VNM_PIO_ERR,	"peu_vnm_pio_err",
    161 						DDI_FM_DEVICE_INTERN_UNCORR,
    162 						DDI_SERVICE_LOST}
    163 };
    164 
    165 hxge_fm_ereport_attr_t hxge_fm_ereport_sw[] = {
    166 	{HXGE_FM_EREPORT_SW_INVALID_CHAN_NUM,	"invalid_chan_num",
    167 						DDI_FM_DEVICE_INVAL_STATE,
    168 						DDI_SERVICE_LOST},
    169 	{HXGE_FM_EREPORT_SW_INVALID_PARAM,	"invalid_param",
    170 						DDI_FM_DEVICE_INVAL_STATE,
    171 						DDI_SERVICE_LOST}
    172 };
    173 
    174 void
    175 hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr,
    176 	ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr)
    177 {
    178 	ddi_iblock_cookie_t iblk;
    179 
    180 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_fm_init"));
    181 
    182 	/* fm-capable in hxge.conf can be used to set fm_capabilities. */
    183 	hxgep->fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY, hxgep->dip,
    184 	    DDI_PROP_DONTPASS, "fm-capable",
    185 	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE);
    186 
    187 	HXGE_DEBUG_MSG((hxgep, DDI_CTL,
    188 	    "FM capable = %d\n", hxgep->fm_capabilities));
    189 
    190 	/*
    191 	 * Register capabilities with IO Fault Services. The capabilities
    192 	 * set above may not be supported by the parent nexus, in that case
    193 	 * some capability bits may be cleared.
    194 	 */
    195 	if (hxgep->fm_capabilities)
    196 		ddi_fm_init(hxgep->dip, &hxgep->fm_capabilities, &iblk);
    197 
    198 	/*
    199 	 * Initialize pci ereport capabilities if ereport capable
    200 	 */
    201 	if (DDI_FM_EREPORT_CAP(hxgep->fm_capabilities) ||
    202 	    DDI_FM_ERRCB_CAP(hxgep->fm_capabilities)) {
    203 		pci_ereport_setup(hxgep->dip);
    204 	}
    205 
    206 	/* Register error callback if error callback capable */
    207 	if (DDI_FM_ERRCB_CAP(hxgep->fm_capabilities)) {
    208 		ddi_fm_handler_register(hxgep->dip,
    209 		    hxge_fm_error_cb, (void *) hxgep);
    210 	}
    211 
    212 	/*
    213 	 * DDI_FLGERR_ACC indicates:
    214 	 * o Driver will check its access handle(s) for faults on
    215 	 *   a regular basis by calling ddi_fm_acc_err_get
    216 	 * o Driver is able to cope with incorrect results of I/O
    217 	 *   operations resulted from an I/O fault
    218 	 */
    219 	if (DDI_FM_ACC_ERR_CAP(hxgep->fm_capabilities)) {
    220 		reg_attr->devacc_attr_access  = DDI_FLAGERR_ACC;
    221 		desc_attr->devacc_attr_access = DDI_FLAGERR_ACC;
    222 	} else {
    223 		reg_attr->devacc_attr_access  = DDI_DEFAULT_ACC;
    224 		desc_attr->devacc_attr_access = DDI_DEFAULT_ACC;
    225 	}
    226 
    227 	/*
    228 	 * DDI_DMA_FLAGERR indicates:
    229 	 * o Driver will check its DMA handle(s) for faults on a
    230 	 *   regular basis using ddi_fm_dma_err_get
    231 	 * o Driver is able to cope with incorrect results of DMA
    232 	 *   operations resulted from an I/O fault
    233 	 */
    234 	if (DDI_FM_DMA_ERR_CAP(hxgep->fm_capabilities))
    235 		dma_attr->dma_attr_flags |= DDI_DMA_FLAGERR;
    236 	else
    237 		dma_attr->dma_attr_flags &= ~DDI_DMA_FLAGERR;
    238 
    239 	HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_fm_init"));
    240 }
    241 
    242 void
    243 hxge_fm_fini(p_hxge_t hxgep)
    244 {
    245 	/* Only unregister FMA capabilities if we registered some */
    246 	if (hxgep->fm_capabilities) {
    247 		/*
    248 		 * Release any resources allocated by pci_ereport_setup()
    249 		 */
    250 		if (DDI_FM_EREPORT_CAP(hxgep->fm_capabilities) ||
    251 		    DDI_FM_ERRCB_CAP(hxgep->fm_capabilities))
    252 			pci_ereport_teardown(hxgep->dip);
    253 
    254 		/*
    255 		 * Un-register error callback if error callback capable
    256 		 */
    257 		if (DDI_FM_ERRCB_CAP(hxgep->fm_capabilities))
    258 			ddi_fm_handler_unregister(hxgep->dip);
    259 
    260 		/* Unregister from IO Fault Services */
    261 		ddi_fm_fini(hxgep->dip);
    262 	}
    263 }
    264 
    265 
    266 /*
    267  * Simply call pci_ereport_post which generates ereports for errors
    268  * that occur in the PCI local bus configuration status registers.
    269  */
    270 /*ARGSUSED*/
    271 static int
    272 hxge_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
    273 	const void *impl_data)
    274 {
    275 	pci_ereport_post(dip, err, NULL);
    276 	return (err->fme_status);
    277 }
    278 
    279 
    280 static hxge_fm_ereport_attr_t *
    281 hxge_fm_get_ereport_attr(hxge_fm_ereport_id_t ereport_id)
    282 {
    283 	hxge_fm_ereport_attr_t	*attr;
    284 	uint8_t			blk_id;
    285 	uint8_t			index;
    286 
    287 	/* Extract the block id and the index within the block */
    288 	blk_id = ((ereport_id >> EREPORT_FM_ID_SHIFT) & EREPORT_FM_ID_MASK);
    289 	index = (ereport_id & EREPORT_INDEX_MASK);
    290 
    291 	/* Return the appropriate structure of type hxge_fm_ereport_attr_t */
    292 	switch (blk_id) {
    293 	case FM_SW_ID:
    294 		attr = &hxge_fm_ereport_sw[index];
    295 		break;
    296 	case FM_VMAC_ID:
    297 		attr = &hxge_fm_ereport_vmac[index];
    298 		break;
    299 	case FM_PFC_ID:
    300 		attr = &hxge_fm_ereport_pfc[index];
    301 		break;
    302 	case FM_RXDMA_ID:
    303 		attr = &hxge_fm_ereport_rdmc[index];
    304 		break;
    305 	case FM_TXDMA_ID:
    306 		attr = &hxge_fm_ereport_tdmc[index];
    307 		break;
    308 	case FM_PEU_ID:
    309 		attr = &hxge_fm_ereport_peu[index];
    310 		break;
    311 	default:
    312 		attr = NULL;
    313 	}
    314 
    315 	return (attr);
    316 }
    317 
    318 static void
    319 hxge_fm_ereport(p_hxge_t hxgep, uint8_t err_chan,
    320 	hxge_fm_ereport_attr_t *ereport)
    321 {
    322 	uint64_t		ena;
    323 	char			eclass[FM_MAX_CLASS];
    324 	char			*err_str;
    325 	p_hxge_stats_t		statsp;
    326 
    327 	(void) snprintf(eclass, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE,
    328 	    ereport->eclass);
    329 
    330 	err_str = ereport->str;
    331 	ena = fm_ena_generate(0, FM_ENA_FMT1);
    332 	statsp = hxgep->statsp;
    333 
    334 	switch (ereport->index) {
    335 	case HXGE_FM_EREPORT_VMAC_LINK_DOWN:
    336 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    337 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    338 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    339 		    NULL);
    340 		break;
    341 	case HXGE_FM_EREPORT_PFC_TCAM_PAR_ERR:
    342 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    343 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    344 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    345 		    ERNAME_PFC_TCAM_ERR, DATA_TYPE_UINT32,
    346 		    statsp->pfc_stats.tcam_parity_err,
    347 		    NULL);
    348 		break;
    349 	case HXGE_FM_EREPORT_PFC_VLAN_PAR_ERR:
    350 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    351 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    352 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    353 		    ERNAME_PFC_VLAN_ERR, DATA_TYPE_UINT32,
    354 		    statsp->pfc_stats.vlan_parity_err,
    355 		    NULL);
    356 		break;
    357 	case HXGE_FM_EREPORT_PFC_PKT_DROP:
    358 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    359 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    360 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    361 		    ERNAME_PFC_PKT_DROP, DATA_TYPE_UINT32,
    362 		    statsp->pfc_stats.pkt_drop,
    363 		    NULL);
    364 		break;
    365 	case HXGE_FM_EREPORT_RDMC_RBR_CPL_TO:
    366 	case HXGE_FM_EREPORT_RDMC_PEU_RESP_ERR:
    367 	case HXGE_FM_EREPORT_RDMC_RCRFULL:
    368 	case HXGE_FM_EREPORT_RDMC_RBR_EMPTY:
    369 	case HXGE_FM_EREPORT_RDMC_RBRFULL:
    370 	case HXGE_FM_EREPORT_RDMC_RBR_PRE_EMPTY:
    371 	case HXGE_FM_EREPORT_RDMC_RCR_SHA_FULL:
    372 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    373 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    374 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    375 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
    376 		    NULL);
    377 		break;
    378 	case HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR:
    379 	case HXGE_FM_EREPORT_RDMC_RCR_SHA_PAR: {
    380 		uint32_t err_log;
    381 		hxge_rx_ring_stats_t *rdc_statsp;
    382 
    383 		rdc_statsp = &statsp->rdc_stats[err_chan];
    384 		if (ereport->index == HXGE_FM_EREPORT_RDMC_RBR_PRE_PAR)
    385 			err_log = (uint32_t)
    386 			    rdc_statsp->errlog.pre_par.value;
    387 		else
    388 			err_log = (uint32_t)
    389 			    rdc_statsp->errlog.sha_par.value;
    390 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    391 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    392 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    393 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
    394 		    ERNAME_RDMC_PAR_ERR_LOG, DATA_TYPE_UINT8, err_log,
    395 		    NULL);
    396 		}
    397 		break;
    398 	case HXGE_FM_EREPORT_RDMC_RCR_ERR: {
    399 		uint8_t err_type;
    400 		err_type = statsp->rdc_stats[err_chan].errlog.compl_err_type;
    401 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    402 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    403 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    404 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
    405 		    ERNAME_RDC_ERR_TYPE, DATA_TYPE_UINT8, err_type,
    406 		    NULL);
    407 		}
    408 		break;
    409 	case HXGE_FM_EREPORT_RDMC_CTRL_FIFO_SEC:
    410 	case HXGE_FM_EREPORT_RDMC_CTRL_FIFO_DED:
    411 	case HXGE_FM_EREPORT_RDMC_DATA_FIFO_SEC:
    412 	case HXGE_FM_EREPORT_RDMC_DATA_FIFO_DED:
    413 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    414 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    415 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    416 		    NULL);
    417 		break;
    418 
    419 	case HXGE_FM_EREPORT_TDMC_PEU_RESP_ERR:
    420 	case HXGE_FM_EREPORT_TDMC_TX_RNG_OFLOW:
    421 	case HXGE_FM_EREPORT_TDMC_PKT_SIZE_HDR_ERR:
    422 	case HXGE_FM_EREPORT_TDMC_RUNT_PKT_DROP_ERR:
    423 	case HXGE_FM_EREPORT_TDMC_PKT_SIZE_ERR:
    424 	case HXGE_FM_EREPORT_TDMC_TDR_PREF_CPL_TO:
    425 	case HXGE_FM_EREPORT_TDMC_PKT_CPL_TO:
    426 	case HXGE_FM_EREPORT_TDMC_INVALID_SOP:
    427 	case HXGE_FM_EREPORT_TDMC_UNEXPECTED_SOP:
    428 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    429 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    430 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    431 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
    432 		    NULL);
    433 		break;
    434 
    435 	case HXGE_FM_EREPORT_TDMC_PREF_PAR_ERR:
    436 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    437 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    438 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    439 		    ERNAME_ERR_DCHAN, DATA_TYPE_UINT8, err_chan,
    440 		    ERNAME_TDC_PREF_PAR_LOG, DATA_TYPE_UINT32,
    441 		    statsp->tdc_stats[err_chan].errlog.value, NULL);
    442 		break;
    443 	case HXGE_FM_EREPORT_TDMC_REORD_TBL_PAR:
    444 	case HXGE_FM_EREPORT_TDMC_REORD_BUF_DED:
    445 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    446 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    447 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    448 		    NULL);
    449 		break;
    450 
    451 	case HXGE_FM_EREPORT_PEU_ERR:
    452 	case HXGE_FM_EREPORT_PEU_VNM_PIO_ERR:
    453 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    454 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    455 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    456 		    NULL);
    457 		break;
    458 
    459 	case HXGE_FM_EREPORT_SW_INVALID_CHAN_NUM:
    460 	case HXGE_FM_EREPORT_SW_INVALID_PARAM:
    461 		ddi_fm_ereport_post(hxgep->dip, eclass, ena, DDI_NOSLEEP,
    462 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0,
    463 		    ERNAME_DETAILED_ERR_TYPE, DATA_TYPE_STRING, err_str,
    464 		    NULL);
    465 		break;
    466 	}
    467 }
    468 
    469 void
    470 hxge_fm_report_error(p_hxge_t hxgep, uint8_t err_chan,
    471 	hxge_fm_ereport_id_t fm_ereport_id)
    472 {
    473 	hxge_fm_ereport_attr_t	*fm_ereport_attr;
    474 
    475 	fm_ereport_attr = hxge_fm_get_ereport_attr(fm_ereport_id);
    476 
    477 	if (fm_ereport_attr != NULL &&
    478 	    (DDI_FM_EREPORT_CAP(hxgep->fm_capabilities))) {
    479 		hxge_fm_ereport(hxgep, err_chan, fm_ereport_attr);
    480 		ddi_fm_service_impact(hxgep->dip, fm_ereport_attr->impact);
    481 	}
    482 }
    483 
    484 int
    485 fm_check_acc_handle(ddi_acc_handle_t handle)
    486 {
    487 	ddi_fm_error_t err;
    488 
    489 	ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION);
    490 	ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
    491 
    492 	return (err.fme_status);
    493 }
    494 
    495 int
    496 fm_check_dma_handle(ddi_dma_handle_t handle)
    497 {
    498 	ddi_fm_error_t err;
    499 
    500 	ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION);
    501 	return (err.fme_status);
    502 }
    503