pcie_error.c revision 28cae8e27cd02e5b8df9666bb34af9786c217a1a
/*
* 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"
/*
* Library file that has code for PCIe error handling
*/
#include <sys/sysmacros.h>
#include <sys/pci_impl.h>
#include <sys/sysmacros.h>
#include <sys/pcie_impl.h>
extern uint32_t pcie_expected_ue_mask;
#ifdef DEBUG
#define PCIE_ERROR_DBG pcie_error_dbg
static void pcie_error_dbg(char *fmt, ...);
#else /* DEBUG */
#define PCIE_ERROR_DBG 0 &&
#endif /* DEBUG */
/* Variables to control error settings */
/* Device Command Register */
PCI_COMM_ME | \
PCI_COMM_MAE | \
/* PCI-Express Device Control Register */
/* PCI-Express AER Root Control Register */
/* PCI-Express Root Error Command Register */
/*
* PCI-Express related masks (AER only)
* Can be defined to mask off certain types of AER errors
* By default all are set to 0; as no errors are masked
*/
/*
* PCI-Express related severity (AER only)
* Used to set the severity levels of errors detected by devices on the PCI
* Express fabric, which in turn results in either a fatal or nonfatal error
* message to the root complex. A set bit (1) indictates a fatal error, an
* unset one is nonfatal. For more information refer to the PCI Express Base
* default values are set below:
*/
/*
* By default, error handling is enabled
* Enable error handling flags. There are two flags
* pcie_error_disable_flag : disable AER, Baseline error handling, SERR
* default value = 0 (do not disable error handling)
* 1 (disable all error handling)
*
* pcie_serr_disable_flag : disable SERR only (in RCR and command reg)
* default value = 1 (disable SERR bits)
* 0 (enable SERR handling)
*
* pcie_aer_disable_flag : disable AER only
* default value = 1 (disable AER bits)
* 0 (enable AER handling)
*
* NOTE: pci_serr_disable_flag is a subset of pcie_error_disable_flag
* If pcie_error_disable_flag is set; then pcie_serr_disable_flag is ignored
* Above is also true for pcie_aer_disable_flag
*/
/*
* Function prototypes
*/
boolean_t *);
/*
* PCI-Express error initialization.
*/
int
{
int status;
return (DDI_FAILURE);
return (status);
}
/*
* PCI-Express CK8-04 child device de-initialization.
*/
void
{
return;
}
/*
* Enable generic pci-express interrupts and error handling.
*/
int
{
/*
* flag to turn this off
*/
return (DDI_SUCCESS);
/* Determine the configuration header type */
PCIE_ERROR_DBG("%s: header_type=%x\n",
/* Look for PCIe capability */
if (aer_ptr != PCI_CAP_NEXT_PTR_NULL)
"pcie-aer-pointer", aer_ptr);
}
/* Setup the device's command register */
/* shouldn't happen; just in case */
if (command_reg & PCI_COMM_SERR_ENABLE)
}
/* Check io and mem ranges for empty bridges */
if ((empty_io_range == B_TRUE) &&
(pcie_command_default & PCI_COMM_IO)) {
PCIE_ERROR_DBG("%s: No I/O range found\n",
}
if ((empty_mem_range == B_TRUE) &&
(pcie_command_default & PCI_COMM_MAE)) {
PCIE_ERROR_DBG("%s: No Mem range found\n",
}
/*
* If the device has a bus control register then program it
* based on the settings in the command register.
*/
if (pcie_command_default & PCI_COMM_SERR_ENABLE) {
if (pcie_serr_disable_flag &&
cap_ptr != PCI_CAP_NEXT_PTR_NULL &&
else
}
}
/*
* Clear any pending errors
*/
/* No PCIe; just return */
if (cap_ptr == PCI_CAP_NEXT_PTR_NULL)
return (DDI_SUCCESS);
/*
* Enable PCI-Express Baseline Error Handling
*/
/*
* For Nvidia chipset, call pcie_nvidia_error_init().
*
* For non-Nvidia Root Ports, disable UR for all child devices by
* changing the default ue mask (for AER devices) and the default
* device control value (for non-AER device).
*/
else if (dev_type == PCIE_PCIECAP_DEV_TYPE_ROOT) {
}
PCIE_ERROR_DBG("%s: device control=0x%x->0x%x\n",
/*
* Enable PCI-Express Advanced Error Handling if Exists
*/
if (aer_ptr == PCIE_EXT_CAP_NEXT_PTR_NULL)
return (DDI_SUCCESS);
return (DDI_SUCCESS);
if (dev_type == PCIE_PCIECAP_DEV_TYPE_UP ||
/* Set Uncorrectable error severity */
PCIE_ERROR_DBG("%s: AER UCE severity=0x%x->0x%x\n",
aer_ptr + PCIE_AER_UCE_SERV));
/* Enable Uncorrectable errors */
/* Enable Correctable errors */
/*
* Enable Secondary Uncorrectable errors if this is a bridge
*/
if (!(dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI))
return (DDI_SUCCESS);
/* Set Secondary Uncorrectable error severity */
PCIE_ERROR_DBG("%s: AER SUCE severity=0x%x->0x%x\n",
/*
* Enable secondary bus errors
*/
PCIE_ERROR_DBG("%s: AER SUCE mask=0x%x->0x%x\n",
return (DDI_SUCCESS);
}
static void
{
0xf0) << 8);
/*
* Assuming that a zero based io_range[0] implies an
* invalid I/O range. Likewise for mem_range[0].
*/
if (val == 0)
*empty_io_range = B_TRUE;
0xfff0) << 16);
if (val == 0)
}
}
static void
{
/* Program SERR_FORWARD bit in NV_XVR_INTR_BCR */
PCIE_ERROR_DBG("%s: PCIe NV_XVR_INTR_BCR=0x%x->0x%x\n",
(rc_ctl | pcie_root_ctrl_default));
PCIE_ERROR_DBG("%s: PCIe Root Control Register=0x%x->0x%x\n",
/* Root Error Command Register */
if (!aer_ptr || pcie_aer_disable_flag)
return;
PCIE_ERROR_DBG("%s: PCIe AER Root Error Command "
/* Also enable ECRC checking */
if (rc_ctl & PCIE_AER_CTL_ECRC_GEN_CAP)
}
/*
* Disable generic pci-express interrupts and error handling.
*/
void
{
return;
/* Determine the configuration header type */
/* Clear the device's command register (SERR and PARITY detect) */
/*
* If the device has a bus control register then clear
* SERR, Master Abort and Parity detect
*/
if ((pcie_command_default & PCI_COMM_SERR_ENABLE) ||
}
if (cap_ptr == PCI_CAP_NEXT_PTR_NULL)
return;
/* Disable PCI-Express Baseline Error Handling */
"pcie-aer-pointer", PCIE_EXT_CAP_NEXT_PTR_NULL);
/*
*/
if (aer_ptr == PCIE_EXT_CAP_NEXT_PTR_NULL)
return;
/* Disable AER bits */
if (!pcie_aer_disable_flag) {
/* Disable Uncorrectable errors */
/* Disable Correctable errors */
/* Disable Secondary Uncorrectable errors if this is a bridge */
if (!(dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI))
return;
}
}
static void
{
if (!pcie_serr_disable_flag) {
}
/* Root Error Command Register */
if (aer_ptr && !pcie_aer_disable_flag) {
/* Disable ECRC checking */
if (rc_ctl & PCIE_AER_CTL_ECRC_GEN_CAP)
}
}
/*
* Clear any pending errors
*/
static void
{
/* 1. clear the Advanced PCIe Errors */
}
/* 2. clear the PCIe Errors */
if (cap_ptr) {
}
/* 3. clear the Legacy PCI Errors */
if (dev_type == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) {
}
}
/*
* Helper Function to traverse the pci-express config space looking
* for the pci-express capability id pointer.
*/
static uint16_t
{
/*
* Check if capabilities list is supported. If not then it is a PCI
* device.
*/
return (PCI_CAP_NEXT_PTR_NULL);
break;
} else if (cap == 0xff)
return (PCI_CAP_NEXT_PTR_NULL);
}
return (caps_ptr);
}
/*
* Helper Function to traverse the pci-express extended config space looking
* for the pci-express capability id pointer.
*/
static uint16_t
{
while ((hdr_next_ptr != PCIE_EXT_CAP_NEXT_PTR_NULL) &&
(hdr_cap_id != PCIE_EXT_CAP_ID_AER)) {
}
if (hdr_cap_id == PCIE_EXT_CAP_ID_AER)
return (PCIE_EXT_CAP_NEXT_PTR_NULL);
}
#ifdef DEBUG
static void
pcie_error_dbg(char *fmt, ...)
{
if (!pcie_error_debug_flags)
return;
}
#endif /* DEBUG */