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