You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
5.0 KiB
127 lines
5.0 KiB
/*
|
|
* PCI AER infomation display library
|
|
*
|
|
* Author: Shawn Lin <shawn.lin@rock-chips.com>
|
|
*
|
|
* Copyright 2025 Rockchip Co., Ltd.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <pci.h>
|
|
#include <errno.h>
|
|
#include <dm/device.h>
|
|
|
|
/**
|
|
* pci_aer_dump - Parse and print AER information in a human-readable format
|
|
* @dev: PCI device
|
|
*
|
|
* Return: 0 on success, negative error code on failure.
|
|
*/
|
|
int pci_aer_dump(struct udevice *udev, pci_dev_t dev)
|
|
{
|
|
int aer_cap_ptr;
|
|
u32 aer_status, aer_mask, aer_severity;
|
|
u32 aer_capabilities;
|
|
struct dm_pci_ops *ops;
|
|
struct udevice *bus;
|
|
|
|
/* Find the AER Capability */
|
|
aer_cap_ptr = dm_pci_find_ext_capability(udev, PCI_EXT_CAP_ID_ERR);
|
|
if (!aer_cap_ptr) {
|
|
printf("AER Capability not found for device %04x:%04x\n",
|
|
PCI_BUS(dev), PCI_DEV(dev));
|
|
return -ENODEV;
|
|
}
|
|
|
|
/* Read AER-related registers */
|
|
dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_STATUS, &aer_status);
|
|
dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_MASK, &aer_mask);
|
|
dm_pci_read_config32(udev, aer_cap_ptr + PCI_AER_SEVERITY, &aer_severity);
|
|
dm_pci_read_config32(udev, aer_cap_ptr + 0x18, &aer_capabilities); /* AER Capabilities Register */
|
|
|
|
/* Print AER Capability information */
|
|
printf("AER Capability found at offset 0x%x\n", aer_cap_ptr);
|
|
|
|
/* Print Uncorrectable Error Status (UES) */
|
|
printf(" UESta: ");
|
|
printf("DLP-%c ", (aer_status & (1 << 0)) ? '+' : '-');
|
|
printf("SDES-%c ", (aer_status & (1 << 1)) ? '+' : '-');
|
|
printf("TLP-%c ", (aer_status & (1 << 2)) ? '+' : '-');
|
|
printf("FCP-%c ", (aer_status & (1 << 3)) ? '+' : '-');
|
|
printf("CmpltTO-%c ", (aer_status & (1 << 4)) ? '+' : '-');
|
|
printf("CmpltAbrt-%c ", (aer_status & (1 << 5)) ? '+' : '-');
|
|
printf("UnxCmplt-%c ", (aer_status & (1 << 6)) ? '+' : '-');
|
|
printf("RxOF-%c ", (aer_status & (1 << 7)) ? '+' : '-');
|
|
printf("MalfTLP-%c ", (aer_status & (1 << 8)) ? '+' : '-');
|
|
printf("ECRC-%c ", (aer_status & (1 << 9)) ? '+' : '-');
|
|
printf("UnsupReq-%c ", (aer_status & (1 << 10)) ? '+' : '-');
|
|
printf("ACSViol-%c\n", (aer_status & (1 << 11)) ? '+' : '-');
|
|
|
|
/* Print Uncorrectable Error Mask (UEMsk) */
|
|
printf(" UEMsk: ");
|
|
printf("DLP-%c ", (aer_mask & (1 << 0)) ? '+' : '-');
|
|
printf("SDES-%c ", (aer_mask & (1 << 1)) ? '+' : '-');
|
|
printf("TLP-%c ", (aer_mask & (1 << 2)) ? '+' : '-');
|
|
printf("FCP-%c ", (aer_mask & (1 << 3)) ? '+' : '-');
|
|
printf("CmpltTO-%c ", (aer_mask & (1 << 4)) ? '+' : '-');
|
|
printf("CmpltAbrt-%c ", (aer_mask & (1 << 5)) ? '+' : '-');
|
|
printf("UnxCmplt-%c ", (aer_mask & (1 << 6)) ? '+' : '-');
|
|
printf("RxOF-%c ", (aer_mask & (1 << 7)) ? '+' : '-');
|
|
printf("MalfTLP-%c ", (aer_mask & (1 << 8)) ? '+' : '-');
|
|
printf("ECRC-%c ", (aer_mask & (1 << 9)) ? '+' : '-');
|
|
printf("UnsupReq-%c ", (aer_mask & (1 << 10)) ? '+' : '-');
|
|
printf("ACSViol-%c\n", (aer_mask & (1 << 11)) ? '+' : '-');
|
|
|
|
/* Print Uncorrectable Error Severity (UESvrt) */
|
|
printf(" UESvrt: ");
|
|
printf("DLP%c ", (aer_severity & (1 << 0)) ? '+' : '-');
|
|
printf("SDES%c ", (aer_severity & (1 << 1)) ? '+' : '-');
|
|
printf("TLP%c ", (aer_severity & (1 << 2)) ? '+' : '-');
|
|
printf("FCP%c ", (aer_severity & (1 << 3)) ? '+' : '-');
|
|
printf("CmpltTO%c ", (aer_severity & (1 << 4)) ? '+' : '-');
|
|
printf("CmpltAbrt%c ", (aer_severity & (1 << 5)) ? '+' : '-');
|
|
printf("UnxCmplt%c ", (aer_severity & (1 << 6)) ? '+' : '-');
|
|
printf("RxOF%c ", (aer_severity & (1 << 7)) ? '+' : '-');
|
|
printf("MalfTLP%c ", (aer_severity & (1 << 8)) ? '+' : '-');
|
|
printf("ECRC%c ", (aer_severity & (1 << 9)) ? '+' : '-');
|
|
printf("UnsupReq%c ", (aer_severity & (1 << 10)) ? '+' : '-');
|
|
printf("ACSViol%c\n", (aer_severity & (1 << 11)) ? '+' : '-');
|
|
|
|
/* Print Correctable Error Status (CESta) */
|
|
printf(" CESta: ");
|
|
printf("RxErr-%c ", (aer_status & (1 << 12)) ? '+' : '-');
|
|
printf("BadTLP-%c ", (aer_status & (1 << 13)) ? '+' : '-');
|
|
printf("BadDLLP-%c ", (aer_status & (1 << 14)) ? '+' : '-');
|
|
printf("Rollover-%c ", (aer_status & (1 << 15)) ? '+' : '-');
|
|
printf("Timeout-%c ", (aer_status & (1 << 16)) ? '+' : '-');
|
|
printf("NonFatalErr-%c\n", (aer_status & (1 << 17)) ? '+' : '-');
|
|
|
|
/* Print Correctable Error Mask (CEMsk) */
|
|
printf(" CEMsk: ");
|
|
printf("RxErr-%c ", (aer_mask & (1 << 12)) ? '+' : '-');
|
|
printf("BadTLP-%c ", (aer_mask & (1 << 13)) ? '+' : '-');
|
|
printf("BadDLLP-%c ", (aer_mask & (1 << 14)) ? '+' : '-');
|
|
printf("Rollover-%c ", (aer_mask & (1 << 15)) ? '+' : '-');
|
|
printf("Timeout-%c ", (aer_mask & (1 << 16)) ? '+' : '-');
|
|
printf("NonFatalErr-%c\n", (aer_mask & (1 << 17)) ? '+' : '-');
|
|
|
|
/* Print AER Capabilities (AERCap) */
|
|
printf(" AERCap: ");
|
|
printf("First Error Pointer: %02x, ", (aer_capabilities >> 0) & 0x1F);
|
|
printf("GenCap%c ", (aer_capabilities & (1 << 5)) ? '+' : '-');
|
|
printf("CGenEn%c ", (aer_capabilities & (1 << 6)) ? '+' : '-');
|
|
printf("ChkCap%c ", (aer_capabilities & (1 << 7)) ? '+' : '-');
|
|
printf("ChkEn%c\n", (aer_capabilities & (1 << 8)) ? '+' : '-');
|
|
|
|
for (bus = udev; device_is_on_pci_bus(bus);)
|
|
bus = bus->parent;
|
|
|
|
ops = pci_get_ops(bus);
|
|
if (ops->vendor_aer_dump)
|
|
return ops->vendor_aer_dump(bus);
|
|
|
|
return 0;
|
|
}
|