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