diff options
author | dilpreet <none@none> | 2006-04-23 15:26:28 -0700 |
---|---|---|
committer | dilpreet <none@none> | 2006-04-23 15:26:28 -0700 |
commit | 00d0963faf2e861a4aef6b1bf28f99a5b2b20755 (patch) | |
tree | fe9d65e9bf37e28eaa4e4edc945504656b1ac09c /usr/src/uts/common/os/ddifm.c | |
parent | f1f711336964964c391c797fdd56f4b3904e811d (diff) | |
download | illumos-joyent-00d0963faf2e861a4aef6b1bf28f99a5b2b20755.tar.gz |
PSARC/2006/217 Access and Dma Handle Error Clear Functions
PSARC/2006/235 FMA for PCI Express and Leaf Devices
6193463 hostbridge .esc files don't fully handle pci-pci bridges
6195325 pci eversholt rules need to support multiple levels of pci-pci bridges
6202643 libtopo should provide pcibus information on x86 boxen
6207403 bridge error callbacks need to participate in handle lookup
6236885 ddi_fm_init leaks resources if parent not fm capable
6236895 ddi_fm_dma_err_get and ddi_fm_acc_err_get need to be more resilient
6239835 Need common diagnosis rules for PCI Express
6239838 Need common ereport generation routines for PCI Express error telemetry
6239840 Need common PCI error handling routines
6245935 RFE: enhance bge driver with FMA support
6304815 ddifm.c DDI_DEV_T_ANY ddi_prop_remove(9F) calls should use DDI_DEV_T_NONE
6326796 pci_check_regs() can match wrong node when an error occurs on a config space access
6327032 Provide FMA support for CK8-04/IO-4 PCI express chipsets
6347217 eversholt rules for handling of pci dto errors need changing
6351025 eft assertion failure: ffep != NULL
6360437 check_if_device_is_pciex should add properties for pciex nodes during pci device discovery
6360749 ddi_fm_service_impact() should raise an service impact ereport
6360764 It would be nice for a driver to have some way to clear err_status in a access or dma handle
6373233 bofi fault simulation should be made compatible with fma
6373293 Solaris 10 may not be properly diagnosing the faulty component after injecting an 'IOUE'
6373322 could define generic device driver ereports for internal chip errors
6393895 TOMATILLO_IOMMU_INVALID_ERR is treated as fatal when it need not be
6398325 eversholt can leak memory if there are constraints on both sides of a propagation
6411683 donot bind driver to PCI express disabled slots
6416496 reduce eversholt memory consumption by trimming open fmes
Diffstat (limited to 'usr/src/uts/common/os/ddifm.c')
-rw-r--r-- | usr/src/uts/common/os/ddifm.c | 153 |
1 files changed, 125 insertions, 28 deletions
diff --git a/usr/src/uts/common/os/ddifm.c b/usr/src/uts/common/os/ddifm.c index 6edd829ba8..27cbe064af 100644 --- a/usr/src/uts/common/os/ddifm.c +++ b/usr/src/uts/common/os/ddifm.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -158,19 +157,54 @@ static struct i_ddi_fmkstat ddifm_kstat_template = { void ddi_fm_service_impact(dev_info_t *dip, int svc_impact) { + uint64_t ena; + char buf[FM_MAX_CLASS]; + + ena = fm_ena_generate(0, FM_ENA_FMT1); mutex_enter(&(DEVI(dip)->devi_lock)); if (!DEVI_IS_DEVICE_OFFLINE(dip)) { switch (svc_impact) { case DDI_SERVICE_LOST: DEVI_SET_DEVICE_DOWN(dip); + (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", + DDI_FM_SERVICE_IMPACT, DDI_FM_SERVICE_LOST); + ddi_fm_ereport_post(dip, buf, ena, DDI_NOSLEEP, + FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, + NULL); break; case DDI_SERVICE_DEGRADED: DEVI_SET_DEVICE_DEGRADED(dip); + if (DEVI_IS_DEVICE_DEGRADED(dip)) { + (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", + DDI_FM_SERVICE_IMPACT, + DDI_FM_SERVICE_DEGRADED); + ddi_fm_ereport_post(dip, buf, ena, DDI_NOSLEEP, + FM_VERSION, DATA_TYPE_UINT8, + FM_EREPORT_VERS0, NULL); + } else if (DEVI_IS_DEVICE_DOWN(dip)) { + (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", + DDI_FM_SERVICE_IMPACT, + DDI_FM_SERVICE_LOST); + ddi_fm_ereport_post(dip, buf, ena, DDI_NOSLEEP, + FM_VERSION, DATA_TYPE_UINT8, + FM_EREPORT_VERS0, NULL); + } break; case DDI_SERVICE_RESTORED: DEVI_SET_DEVICE_UP(dip); + (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", + DDI_FM_SERVICE_IMPACT, DDI_FM_SERVICE_RESTORED); + ddi_fm_ereport_post(dip, buf, ena, DDI_NOSLEEP, + FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, + NULL); break; case DDI_SERVICE_UNAFFECTED: + (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", + DDI_FM_SERVICE_IMPACT, DDI_FM_SERVICE_UNAFFECTED); + ddi_fm_ereport_post(dip, buf, ena, DDI_NOSLEEP, + FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, + NULL); + break; default: break; } @@ -210,7 +244,7 @@ erpt_post_sleep(dev_info_t *dip, const char *error_class, uint64_t ena, (void) ddi_pathname(dip, device_path); } - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, + if (ddi_prop_lookup_string(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, DEVID_PROP_NAME, &devid) == DDI_SUCCESS) { fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL, device_path, devid); @@ -391,10 +425,8 @@ ddi_fm_ereport_post(dev_info_t *dip, const char *error_class, uint64_t ena, va_list ap; struct i_ddi_fmhdl *fmhdl = DEVI(dip)->devi_fmhdl; - if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip))) { - i_ddi_drv_ereport_post(dip, DVR_EFMCAP, NULL, sflag); + if (!DDI_FM_EREPORT_CAP(ddi_fm_capable(dip))) return; - } ASSERT(fmhdl); @@ -651,12 +683,11 @@ ddi_fm_init(dev_info_t *dip, int *fmcap, ddi_iblock_cookie_t *ibcp) /* * Initialize support for ereport generation */ - if (DDI_FM_EREPORT_CAP(*fmcap) && - DDI_FM_EREPORT_CAP(ddi_system_fmcap)) { + if (DDI_FM_EREPORT_CAP(*fmcap) && DDI_FM_EREPORT_CAP(pcap)) { fmhdl->fh_errorq = ereport_errorq; - if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + if (ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "fm-ereport-capable", 0) == 0) - (void) ddi_prop_create(DDI_DEV_T_ANY, dip, + (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "fm-ereport-capable", NULL, 0); newcap |= DDI_FM_EREPORT_CAPABLE; @@ -667,9 +698,9 @@ ddi_fm_init(dev_info_t *dip, int *fmcap, ddi_iblock_cookie_t *ibcp) */ if (DDI_FM_ERRCB_CAP(*fmcap) && DDI_FM_ERRCB_CAP(pcap)) { - if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + if (ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "fm-errcb-capable", 0) == 0) - (void) ddi_prop_create(DDI_DEV_T_ANY, dip, + (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "fm-errcb-capable", NULL, 0); newcap |= DDI_FM_ERRCB_CAPABLE; @@ -683,9 +714,9 @@ ddi_fm_init(dev_info_t *dip, int *fmcap, ddi_iblock_cookie_t *ibcp) i_ndi_fmc_create(&fmhdl->fh_dma_cache, 2, ibc); /* Set-up dma chk capability prop */ - if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + if (ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "fm-dmachk-capable", 0) == 0) - (void) ddi_prop_create(DDI_DEV_T_ANY, dip, + (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "fm-dmachk-capable", NULL, 0); newcap |= DDI_FM_DMACHK_CAPABLE; @@ -694,9 +725,9 @@ ddi_fm_init(dev_info_t *dip, int *fmcap, ddi_iblock_cookie_t *ibcp) if (DDI_FM_ACC_ERR_CAP(*fmcap) && DDI_FM_ACC_ERR_CAP(pcap)) { i_ndi_fmc_create(&fmhdl->fh_acc_cache, 2, ibc); /* Set-up dma chk capability prop */ - if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, + if (ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "fm-accchk-capable", 0) == 0) - (void) ddi_prop_create(DDI_DEV_T_ANY, dip, + (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "fm-accchk-capable", NULL, 0); newcap |= DDI_FM_ACCCHK_CAPABLE; @@ -726,20 +757,17 @@ ddi_fm_fini(dev_info_t *dip) { struct i_ddi_fmhdl *fmhdl = DEVI(dip)->devi_fmhdl; + ASSERT(fmhdl); + if (!(DEVI_IS_DETACHING(dip) || DEVI_IS_ATTACHING(dip))) { i_ddi_drv_ereport_post(dip, DVR_ECONTEXT, NULL, DDI_NOSLEEP); return; } - if (DDI_FM_DEFAULT_CAP(fmhdl->fh_cap)) - return; - - ASSERT(fmhdl); - kstat_delete(fmhdl->fh_ksp); if (DDI_FM_EREPORT_CAP(fmhdl->fh_cap)) { - (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, + (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "fm-ereport-capable"); } @@ -750,12 +778,12 @@ ddi_fm_fini(dev_info_t *dip) DDI_FM_ACC_ERR_CAP(fmhdl->fh_cap)) { if (fmhdl->fh_dma_cache != NULL) { i_ndi_fmc_destroy(fmhdl->fh_dma_cache); - (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, + (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "fm-dmachk-capable"); } if (fmhdl->fh_acc_cache != NULL) { i_ndi_fmc_destroy(fmhdl->fh_acc_cache); - (void) ddi_prop_remove(DDI_DEV_T_ANY, dip, + (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "fm-accachk-capable"); } } @@ -791,16 +819,20 @@ ddi_fm_capable(dev_info_t *dip) void ddi_fm_acc_err_get(ddi_acc_handle_t handle, ddi_fm_error_t *de, int version) { - ndi_err_t *errp = ((ddi_acc_impl_t *)handle)->ahi_err; + ndi_err_t *errp; + + if (handle == NULL) + return; if (version != DDI_FME_VER0) { ddi_acc_hdl_t *hp = impl_acc_hdl_get(handle); i_ddi_drv_ereport_post(hp->ah_dip, DVR_EVER, NULL, DDI_NOSLEEP); - cmn_err(CE_PANIC, "ddi_fm_dma_err_get: " + cmn_err(CE_PANIC, "ddi_fm_acc_err_get: " "Invalid driver version\n"); } + errp = ((ddi_acc_impl_t *)handle)->ahi_err; de->fme_status = errp->err_status; de->fme_ena = errp->err_ena; de->fme_flag = errp->err_expected; @@ -810,7 +842,10 @@ ddi_fm_acc_err_get(ddi_acc_handle_t handle, ddi_fm_error_t *de, int version) void ddi_fm_dma_err_get(ddi_dma_handle_t handle, ddi_fm_error_t *de, int version) { - ndi_err_t *errp = &((ddi_dma_impl_t *)handle)->dmai_error; + ndi_err_t *errp; + + if (handle == NULL) + return; if (version != DDI_FME_VER0) { i_ddi_drv_ereport_post(((ddi_dma_impl_t *)handle)->dmai_rdip, @@ -819,6 +854,8 @@ ddi_fm_dma_err_get(ddi_dma_handle_t handle, ddi_fm_error_t *de, int version) "Invalid driver version\n"); } + errp = &((ddi_dma_impl_t *)handle)->dmai_error; + de->fme_status = errp->err_status; de->fme_ena = errp->err_ena; de->fme_flag = errp->err_expected; @@ -826,6 +863,50 @@ ddi_fm_dma_err_get(ddi_dma_handle_t handle, ddi_fm_error_t *de, int version) } void +ddi_fm_acc_err_clear(ddi_acc_handle_t handle, int version) +{ + ndi_err_t *errp; + + if (handle == NULL) + return; + + if (version != DDI_FME_VER0) { + ddi_acc_hdl_t *hp = impl_acc_hdl_get(handle); + + i_ddi_drv_ereport_post(hp->ah_dip, DVR_EVER, NULL, DDI_NOSLEEP); + cmn_err(CE_PANIC, "ddi_fm_acc_err_clear: " + "Invalid driver version\n"); + } + + errp = ((ddi_acc_impl_t *)handle)->ahi_err; + errp->err_status = DDI_FM_OK; + errp->err_ena = 0; + errp->err_expected = DDI_FM_ERR_UNEXPECTED; +} + +void +ddi_fm_dma_err_clear(ddi_dma_handle_t handle, int version) +{ + ndi_err_t *errp; + + if (handle == NULL) + return; + + if (version != DDI_FME_VER0) { + i_ddi_drv_ereport_post(((ddi_dma_impl_t *)handle)->dmai_rdip, + DVR_EVER, NULL, DDI_NOSLEEP); + cmn_err(CE_PANIC, "ddi_fm_dma_err_clear: " + "Invalid driver version\n"); + } + + errp = &((ddi_dma_impl_t *)handle)->dmai_error; + + errp->err_status = DDI_FM_OK; + errp->err_ena = 0; + errp->err_expected = DDI_FM_ERR_UNEXPECTED; +} + +void i_ddi_fm_acc_err_set(ddi_acc_handle_t handle, uint64_t ena, int status, int flag) { @@ -851,3 +932,19 @@ i_ddi_fm_dma_err_set(ddi_dma_handle_t handle, uint64_t ena, int status, hdlp->dmai_error.err_expected = flag; atomic_add_64(&fmhdl->fh_kstat.fek_dma_err.value.ui64, 1); } + +ddi_fmcompare_t +i_ddi_fm_acc_err_cf_get(ddi_acc_handle_t handle) +{ + ddi_acc_impl_t *i_hdlp = (ddi_acc_impl_t *)handle; + + return (i_hdlp->ahi_err->err_cf); +} + +ddi_fmcompare_t +i_ddi_fm_dma_err_cf_get(ddi_dma_handle_t handle) +{ + ddi_dma_impl_t *hdlp = (ddi_dma_impl_t *)handle; + + return (hdlp->dmai_error.err_cf); +} |