/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* 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
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* CMU-CH ECC support
*/
#include <sys/ddi_impldefs.h>
#include <sys/machsystm.h>
#include <sys/sysmacros.h>
static void pcmu_ecc_disable(pcmu_ecc_t *, int);
void
{
/* LINTED variable */
/*
* Determine the virtual addresses of the streaming cache
*/
"pcmu_ecc_create: ue_afsr=%x, ue_afar=%x\n",
/*
* Register routines to be called from system error handling code.
*/
}
int
{
int ret;
/*
* Install the UE error interrupt handlers.
*/
return (ret);
}
void
{
/*
* Disable UE ECC error interrupts.
*/
/*
* Remove the ECC interrupt handlers.
*/
/*
* Unregister our error handling functions.
*/
/*
* If a timer has been set, unset it.
*/
}
void
{
uint64_t l;
/* LINTED variable */
/*
* Clear any pending ECC errors.
*/
"pcmu_ecc_configure: clearing UE errors\n");
l = (PCMU_ECC_UE_AFSR_E_MASK << PCMU_ECC_UE_AFSR_PE_SHIFT) |
/*
* Enable ECC error detections via the control register.
*/
"pcmu_ecc_configure: enabling UE detection\n");
l = PCMU_ECC_CTRL_ECC_EN;
l |= PCMU_ECC_CTRL_UE_INTEN;
}
void
{
}
void
{
}
{
return (BF_NONE);
}
static void
{
csr &= ~(PCMU_ECC_CTRL_UE_INTEN);
}
/*
* I/O ECC error handling:
*
* Below are the generic functions that handle detected ECC errors.
*
* The registered interrupt handler is pcmu_ecc_intr(), it's function
* is to receive the error, capture some state, and pass that on to
* the pcmu_ecc_err_handler() for reporting purposes.
*
* pcmu_ecc_err_handler() gathers more state(via pcmu_ecc_errstate_get)
* and attempts to handle and report the error. pcmu_ecc_err_handler()
* must determine if we need to panic due to this error (via
* pcmu_ecc_classify, which also decodes the * ECC afsr), and if any
* side effects exist that may have caused or are due * to this error.
* PBM errors related to the ECC error may exist, to report
* them we call pcmu_pbm_err_handler().
*
* To report the error we must also get the syndrome and unum, which can not
* be done in high level interrupted context. Therefore we have an error
* queue(pcmu_ecc_queue) which we dispatch errors to, to report the errors
* (pcmu_ecc_err_drain()).
*
* pcmu_ecc_err_drain() will be called when either the softint is triggered
* or the system is panicing. Either way it will gather more information
* about the error from the CPU(via ecc_cpu_call(), ecc.c), attempt to
* retire the faulty page(if error is a UE), and report the detected error.
*
*/
/*
* Function used to get ECC AFSR register
*/
static uint64_t
{
}
/*
* IO detected ECC error interrupt handler, calls pcmu_ecc_err_handler to post
* error reports and handle the interrupt. Re-entry into pcmu_ecc_err_handler
* is protected by the per-chip mutex pcmu_err_mutex.
*/
{
if (ret == DDI_FM_FATAL) {
/*
* Need delay here to allow CPUs to handle related traps,
* such as FRUs for USIIIi systems.
*/
}
return (DDI_INTR_CLAIMED);
}
/*
* Function used to gather IO ECC error state.
*/
static void
{
/*
* Read the fault registers.
*/
}
/*
* pcmu_ecc_check: Called by pcmu_ecc_err_handler() this function is responsible
* for calling pcmu_pbm_err_handler() and calling their children error
* handlers(via ndi_fm_handler_dispatch()).
*/
static int
{
int ret;
/*
* Need to report any PBM errors which may have caused or
* resulted from this error.
*/
PCI_ECC_CALL) == DDI_FM_FATAL)
ret = DDI_FM_FATAL;
if (ret == DDI_FM_FATAL)
return (DDI_FM_FATAL);
else
return (DDI_FM_NONFATAL);
}
/*
* Function used to handle and log IO detected ECC errors, can be called by
* pcmu_ecc_intr and pcmu_err_callback(trap callback). Protected by
* pcmu_err_mutex.
*/
int
{
/* LINTED variable */
/* LINTED variable */
int fatal = 0;
int nonfatal = 0;
case CBNINTR_UE:
if (pri_err) {
sizeof (pcmu_ecc_errstate_t),
}
if (sec_err) {
ecc_sec_err = *ecc_err_p;
ecc_sec_err.pecc_pri = 0;
&ecc_sec_err);
}
/*
* Check for PCI bus errors that may have resulted from or
* caused this UE.
*/
/*
* Disable all further errors since this will be
* treated as a fatal error.
*/
(void) pcmu_ecc_disable_nowait(pecc_p);
fatal++;
}
break;
default:
return (DDI_FM_OK);
}
/* Clear the errors */
/*
* Clear the interrupt if called by pcmu_ecc_intr and UE error
* or if called by pcmu_ecc_intr and CE error and delayed CE
* interrupt handling is turned off.
*/
return (DDI_FM_OK);
else if (fatal)
return (DDI_FM_FATAL);
return (DDI_FM_NONFATAL);
}
/*
* Function used to drain pcmu_ecc_queue, either during panic or after softint
* is generated, to log IO detected ECC errors.
*/
/* ARGSUSED */
void
{
}
/*
* Function used to post IO detected ECC ereports.
*/
static void
{
char *aux_msg;
aux_msg = "PIO primary uncorrectable error";
} else {
aux_msg = "PIO secondary uncorrectable error";
}
}