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