summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/ddifm.c
diff options
context:
space:
mode:
authordilpreet <none@none>2006-04-23 15:26:28 -0700
committerdilpreet <none@none>2006-04-23 15:26:28 -0700
commit00d0963faf2e861a4aef6b1bf28f99a5b2b20755 (patch)
treefe9d65e9bf37e28eaa4e4edc945504656b1ac09c /usr/src/uts/common/os/ddifm.c
parentf1f711336964964c391c797fdd56f4b3904e811d (diff)
downloadillumos-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.c153
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);
+}