mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
Merge branch 'pci/aer'
- Update mappings of errors to agent & layer (Lukas Wunner) - Log agent & layer of each individual error when multiple errors detected (Lukas Wunner) - Log Error Source only once, not twice in separate messages (Lukas Wunner) - Emit TLP Log only for unmasked errors (Lukas Wunner) - Support Advisory Non-Fatal Errors (Lukas Wunner) * pci/aer: PCI/AER: Support Advisory Non-Fatal Errors PCI/AER: Move retrieval of FEP and TLP Log into helper PCI/AER: Emit TLP Log only for unmasked errors PCI/AER: Deduplicate logging of Error Source Identification PCI/AER: Log agent & layer for each individual error PCI/AER: Fix mapping of errors to agent & layer
This commit is contained in:
commit
d358e9ad15
|
|
@ -828,6 +828,9 @@ static inline bool pci_dev_binding_disallowed(struct pci_dev *dev)
|
|||
* @tlp_header_valid: Indicates if TLP field contains error information
|
||||
* @status: COR/UNCOR error status
|
||||
* @mask: COR/UNCOR mask
|
||||
* @anfe_status: Advisory Non-Fatal Errors, i.e. Uncorrectable Errors signaled
|
||||
* as Correctable Errors (PCIe r7.0 sec 6.2.4.3). Only used if @severity
|
||||
* is AER_CORRECTABLE and @status has Advisory Non-Fatal Error Status set.
|
||||
* @tlp: Transaction packet information
|
||||
*/
|
||||
struct aer_err_info {
|
||||
|
|
@ -850,6 +853,7 @@ struct aer_err_info {
|
|||
|
||||
unsigned int status;
|
||||
unsigned int mask;
|
||||
u32 anfe_status;
|
||||
struct pcie_tlp_log tlp;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,20 @@ struct aer_info {
|
|||
struct ratelimit_state nonfatal_ratelimit;
|
||||
};
|
||||
|
||||
#define AER_ANFE (PCI_ERR_UNC_UNX_COMP | \
|
||||
PCI_ERR_UNC_ATOMEG | \
|
||||
PCI_ERR_UNC_DMWR_BLK)
|
||||
|
||||
#define AER_POSSIBLE_ANFE (PCI_ERR_UNC_POISON_TLP | \
|
||||
PCI_ERR_UNC_POISON_BLK | \
|
||||
PCI_ERR_UNC_ECRC | \
|
||||
PCI_ERR_UNC_UNSUP | \
|
||||
PCI_ERR_UNC_COMP_TIME | \
|
||||
PCI_ERR_UNC_COMP_ABORT | \
|
||||
PCI_ERR_UNC_ACSV | \
|
||||
PCI_ERR_UNC_TLPPRE | \
|
||||
PCI_ERR_UNC_PCRC_CHECK)
|
||||
|
||||
#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
|
||||
PCI_ERR_UNC_POISON_BLK | \
|
||||
PCI_ERR_UNC_ECRC| \
|
||||
|
|
@ -410,6 +424,15 @@ void pci_aer_init(struct pci_dev *dev)
|
|||
n = pcie_cap_has_rtctl(dev) ? 5 : 4;
|
||||
pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_ERR, sizeof(u32) * n);
|
||||
|
||||
/*
|
||||
* Advisory Non-Fatal Errors are masked by default (PCIe r7.0, sec
|
||||
* 7.8.4.6).
|
||||
*/
|
||||
if (pcie_aer_is_native(dev) && dev->devcap & PCI_EXP_DEVCAP_RBER)
|
||||
pci_clear_and_set_config_dword(dev,
|
||||
dev->aer_cap + PCI_ERR_COR_MASK,
|
||||
PCI_ERR_COR_ADV_NFAT, 0);
|
||||
|
||||
pci_aer_clear_status(dev);
|
||||
|
||||
if (pci_aer_available())
|
||||
|
|
@ -428,23 +451,38 @@ void pci_aer_exit(struct pci_dev *dev)
|
|||
#define AER_AGENT_REQUESTER 1
|
||||
#define AER_AGENT_COMPLETER 2
|
||||
#define AER_AGENT_TRANSMITTER 3
|
||||
#define AER_AGENT_COMPONENT 4
|
||||
#define AER_AGENT_UNDEF 5
|
||||
|
||||
#define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP))
|
||||
0 : PCI_ERR_UNC_COMP_TIME)
|
||||
#define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
0 : PCI_ERR_UNC_COMP_ABORT)
|
||||
#define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
(PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0)
|
||||
(PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : \
|
||||
(PCI_ERR_UNC_POISON_BLK|PCI_ERR_UNC_ATOMEG| \
|
||||
PCI_ERR_UNC_DMWR_BLK|PCI_ERR_UNC_XLAT_BLK| \
|
||||
PCI_ERR_UNC_TLPPRE))
|
||||
#define AER_AGENT_COMPONENT_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
(PCI_ERR_COR_INTERNAL|PCI_ERR_COR_LOG_OVER) : \
|
||||
(PCI_ERR_UNC_INTN|PCI_ERR_UNC_SURPDN))
|
||||
#define AER_AGENT_UNDEF_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
PCI_ERR_COR_ADV_NFAT : 0)
|
||||
|
||||
|
||||
#define AER_GET_AGENT(t, e) \
|
||||
((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \
|
||||
(e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \
|
||||
(e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \
|
||||
(e & AER_AGENT_COMPONENT_MASK(t)) ? AER_AGENT_COMPONENT : \
|
||||
(e & AER_AGENT_UNDEF_MASK(t)) ? AER_AGENT_UNDEF : \
|
||||
AER_AGENT_RECEIVER)
|
||||
|
||||
#define AER_PHYSICAL_LAYER_ERROR 0
|
||||
#define AER_DATA_LINK_LAYER_ERROR 1
|
||||
#define AER_TRANSACTION_LAYER_ERROR 2
|
||||
#define AER_GENERAL_ERROR 3
|
||||
#define AER_UNDEF_ERROR 4
|
||||
|
||||
#define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
PCI_ERR_COR_RCVR : 0)
|
||||
|
|
@ -452,11 +490,17 @@ void pci_aer_exit(struct pci_dev *dev)
|
|||
(PCI_ERR_COR_BAD_TLP| \
|
||||
PCI_ERR_COR_BAD_DLLP| \
|
||||
PCI_ERR_COR_REP_ROLL| \
|
||||
PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP)
|
||||
PCI_ERR_COR_REP_TIMER) : (PCI_ERR_UNC_DLP|PCI_ERR_UNC_SURPDN))
|
||||
#define AER_GENERAL_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
(PCI_ERR_COR_INTERNAL|PCI_ERR_COR_LOG_OVER) : PCI_ERR_UNC_INTN)
|
||||
#define AER_UNDEF_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
|
||||
PCI_ERR_COR_ADV_NFAT : 0)
|
||||
|
||||
#define AER_GET_LAYER_ERROR(t, e) \
|
||||
((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \
|
||||
(e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
|
||||
(e & AER_GENERAL_ERROR_MASK(t)) ? AER_GENERAL_ERROR : \
|
||||
(e & AER_UNDEF_ERROR_MASK(t)) ? AER_UNDEF_ERROR : \
|
||||
AER_TRANSACTION_LAYER_ERROR)
|
||||
|
||||
/*
|
||||
|
|
@ -471,7 +515,9 @@ static const char * const aer_error_severity_string[] = {
|
|||
static const char *aer_error_layer[] = {
|
||||
"Physical Layer",
|
||||
"Data Link Layer",
|
||||
"Transaction Layer"
|
||||
"Transaction Layer",
|
||||
"General",
|
||||
"",
|
||||
};
|
||||
|
||||
static const char *aer_correctable_error_string[] = {
|
||||
|
|
@ -545,10 +591,12 @@ static const char *aer_uncorrectable_error_string[] = {
|
|||
};
|
||||
|
||||
static const char *aer_agent_string[] = {
|
||||
"Receiver ID",
|
||||
"Requester ID",
|
||||
"Completer ID",
|
||||
"Transmitter ID"
|
||||
"Receiver",
|
||||
"Requester",
|
||||
"Completer",
|
||||
"Transmitter",
|
||||
"Component",
|
||||
"",
|
||||
};
|
||||
|
||||
#define aer_stats_dev_attr(name, stats_array, strings_array, \
|
||||
|
|
@ -812,6 +860,46 @@ static int aer_ratelimit(struct pci_dev *dev, unsigned int severity)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 aer_compute_anfe_status(u16 devsta, u32 uncor_status,
|
||||
u32 uncor_mask, u32 uncor_severity)
|
||||
{
|
||||
u32 anfe_status;
|
||||
|
||||
/*
|
||||
* Uncorrectable Errors must be unmasked and have Non-Fatal severity
|
||||
* to qualify as Advisory Non-Fatal Errors (PCIe r7.0 sec 6.2.4.3).
|
||||
*/
|
||||
uncor_status &= ~uncor_mask & ~uncor_severity;
|
||||
|
||||
/* Some Non-Fatal Errors are always Advisory (PCIe r7.0 sec 6.2.7). */
|
||||
anfe_status = uncor_status & AER_ANFE;
|
||||
|
||||
/*
|
||||
* Others may be Advisory at the discretion of the detecting agent.
|
||||
* That's impossible to discern if the agent signaled ERR_NONFATAL
|
||||
* in addition to ERR_COR. Assume none are Advisory in that case
|
||||
* to ensure that the Uncorrectable Error code path is taken.
|
||||
*/
|
||||
if (!(devsta & PCI_EXP_DEVSTA_NFED))
|
||||
anfe_status |= uncor_status & AER_POSSIBLE_ANFE;
|
||||
|
||||
return anfe_status;
|
||||
}
|
||||
|
||||
static u32 aer_get_anfe_status(struct pci_dev *dev)
|
||||
{
|
||||
u32 uncor_status, uncor_mask, uncor_severity;
|
||||
u16 devsta, aer = dev->aer_cap;
|
||||
|
||||
pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_STATUS, &uncor_status);
|
||||
pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &uncor_mask);
|
||||
pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_SEVER, &uncor_severity);
|
||||
pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &devsta);
|
||||
|
||||
return aer_compute_anfe_status(devsta, uncor_status, uncor_mask,
|
||||
uncor_severity);
|
||||
}
|
||||
|
||||
static bool tlp_header_logged(u32 status, u32 capctl)
|
||||
{
|
||||
/* Errors for which a header is always logged (PCIe r7.0 sec 6.2.7) */
|
||||
|
|
@ -830,8 +918,8 @@ static void __aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
|
|||
{
|
||||
const char **strings;
|
||||
unsigned long status = info->status & ~info->mask;
|
||||
const char *errmsg, *agent, *layer;
|
||||
const char *level = info->level;
|
||||
const char *errmsg;
|
||||
int i;
|
||||
|
||||
if (info->severity == AER_CORRECTABLE)
|
||||
|
|
@ -841,10 +929,18 @@ static void __aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
|
|||
|
||||
for_each_set_bit(i, &status, 32) {
|
||||
errmsg = strings[i];
|
||||
if (!errmsg)
|
||||
agent = aer_agent_string[AER_GET_AGENT(info->severity, BIT(i))];
|
||||
layer = aer_error_layer[AER_GET_LAYER_ERROR(info->severity,
|
||||
BIT(i))];
|
||||
if (!errmsg) {
|
||||
errmsg = "Unknown Error Bit";
|
||||
agent = "";
|
||||
layer = "";
|
||||
}
|
||||
|
||||
aer_printk(level, dev, " [%2d] %-22s%s\n", i, errmsg,
|
||||
aer_printk(level, dev, " [%2d] %-17s | %-11s | %-17s%s\n",
|
||||
i, errmsg, agent, layer,
|
||||
info->severity != AER_CORRECTABLE &&
|
||||
info->first_error == i ? " (First)" : "");
|
||||
}
|
||||
}
|
||||
|
|
@ -854,18 +950,18 @@ static void aer_print_source(struct pci_dev *dev, struct aer_err_info *info,
|
|||
{
|
||||
u16 source = info->id;
|
||||
|
||||
pci_info(dev, "%s%s error message received from %04x:%02x:%02x.%d%s\n",
|
||||
pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s\n",
|
||||
info->multi_error_valid ? "Multiple " : "",
|
||||
aer_error_severity_string[info->severity],
|
||||
info->multi_error_valid ? "s received, first one" : " received",
|
||||
pci_domain_nr(dev->bus), PCI_BUS_NUM(source),
|
||||
PCI_SLOT(source), PCI_FUNC(source),
|
||||
found ? "" : " (no details found");
|
||||
found ? "" : " (no details found)");
|
||||
}
|
||||
|
||||
void aer_print_error(struct aer_err_info *info, int i)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
int layer, agent, id;
|
||||
const char *level = info->level;
|
||||
const char *bus_type = aer_err_bus(info);
|
||||
|
||||
|
|
@ -873,39 +969,48 @@ void aer_print_error(struct aer_err_info *info, int i)
|
|||
return;
|
||||
|
||||
dev = info->dev[i];
|
||||
id = pci_dev_id(dev);
|
||||
|
||||
pci_dev_aer_stats_incr(dev, info);
|
||||
trace_aer_event(pci_name(dev), (info->status & ~info->mask),
|
||||
info->severity, info->tlp_header_valid, &info->tlp, bus_type);
|
||||
info->severity, info->tlp_header_valid &&
|
||||
info->severity != AER_CORRECTABLE, &info->tlp,
|
||||
bus_type);
|
||||
|
||||
/*
|
||||
* For Advisory Non-Fatal Errors, record statistics and tracing
|
||||
* even if ratelimited
|
||||
*/
|
||||
if (!info->ratelimit_print[i])
|
||||
return;
|
||||
goto anfe;
|
||||
|
||||
if (!info->status) {
|
||||
pci_err(dev, "%s Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
|
||||
pci_err(dev, "%s Bus Error: severity=%s (Inaccessible)\n",
|
||||
bus_type, aer_error_severity_string[info->severity]);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
layer = AER_GET_LAYER_ERROR(info->severity, info->status);
|
||||
agent = AER_GET_AGENT(info->severity, info->status);
|
||||
|
||||
aer_printk(level, dev, "%s Bus Error: severity=%s, type=%s, (%s)\n",
|
||||
bus_type, aer_error_severity_string[info->severity],
|
||||
aer_error_layer[layer], aer_agent_string[agent]);
|
||||
aer_printk(level, dev, "%s Bus Error: severity=%s\n",
|
||||
bus_type, aer_error_severity_string[info->severity]);
|
||||
|
||||
aer_printk(level, dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
|
||||
dev->vendor, dev->device, info->status, info->mask);
|
||||
|
||||
__aer_print_error(dev, info);
|
||||
|
||||
if (info->tlp_header_valid)
|
||||
if (info->tlp_header_valid && info->severity != AER_CORRECTABLE)
|
||||
pcie_print_tlp_log(dev, &info->tlp, level, dev_fmt(" "));
|
||||
|
||||
out:
|
||||
if (info->id && info->error_dev_num > 1 && info->id == id)
|
||||
pci_err(dev, " Error of this Agent is reported first\n");
|
||||
anfe:
|
||||
/* Recursive invocation for Advisory Non-Fatal Errors */
|
||||
if (info->anfe_status && info->severity == AER_CORRECTABLE) {
|
||||
info->severity = AER_NONFATAL;
|
||||
info->status = info->anfe_status;
|
||||
info->mask = 0;
|
||||
|
||||
aer_print_error(info, i);
|
||||
|
||||
info->severity = AER_CORRECTABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI_PCIEAER
|
||||
|
|
@ -923,13 +1028,15 @@ int cper_severity_to_aer(int cper_severity)
|
|||
EXPORT_SYMBOL_GPL(cper_severity_to_aer);
|
||||
#endif
|
||||
|
||||
void pci_print_aer(struct pci_dev *dev, int aer_severity,
|
||||
struct aer_capability_regs *aer)
|
||||
static void __pci_print_aer(struct pci_dev *dev, int aer_severity,
|
||||
struct aer_capability_regs *aer,
|
||||
bool ratelimit_print, const char *level)
|
||||
{
|
||||
const char *bus_type;
|
||||
int layer, agent, tlp_header_valid = 0;
|
||||
const char *bus_type, *sev;
|
||||
int tlp_header_valid = 0;
|
||||
u32 status, mask;
|
||||
struct aer_err_info info = {
|
||||
.level = level,
|
||||
.severity = aer_severity,
|
||||
.first_error = PCI_ERR_CAP_FEP(aer->cap_control),
|
||||
};
|
||||
|
|
@ -937,12 +1044,13 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
|
|||
if (aer_severity == AER_CORRECTABLE) {
|
||||
status = aer->cor_status;
|
||||
mask = aer->cor_mask;
|
||||
info.level = KERN_WARNING;
|
||||
sev = "cor";
|
||||
} else {
|
||||
status = aer->uncor_status;
|
||||
mask = aer->uncor_mask;
|
||||
info.level = KERN_ERR;
|
||||
tlp_header_valid = tlp_header_logged(status, aer->cap_control);
|
||||
sev = "uncor";
|
||||
tlp_header_valid = tlp_header_logged(status & ~mask,
|
||||
aer->cap_control);
|
||||
}
|
||||
|
||||
info.status = status;
|
||||
|
|
@ -955,17 +1063,17 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
|
|||
trace_aer_event(pci_name(dev), (status & ~mask), aer_severity,
|
||||
tlp_header_valid, &aer->header_log, bus_type);
|
||||
|
||||
if (!aer_ratelimit(dev, info.severity))
|
||||
return;
|
||||
/*
|
||||
* For Advisory Non-Fatal Errors, record statistics and tracing
|
||||
* even if ratelimited
|
||||
*/
|
||||
if (!ratelimit_print)
|
||||
goto anfe;
|
||||
|
||||
layer = AER_GET_LAYER_ERROR(aer_severity, status);
|
||||
agent = AER_GET_AGENT(aer_severity, status);
|
||||
|
||||
aer_printk(info.level, dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n",
|
||||
status, mask);
|
||||
aer_printk(info.level, dev,
|
||||
"aer_%s_status: 0x%08x, aer_%s_mask: 0x%08x\n",
|
||||
sev, status, sev, mask);
|
||||
__aer_print_error(dev, &info);
|
||||
aer_printk(info.level, dev, "aer_layer=%s, aer_agent=%s\n",
|
||||
aer_error_layer[layer], aer_agent_string[agent]);
|
||||
|
||||
if (aer_severity != AER_CORRECTABLE)
|
||||
aer_printk(info.level, dev, "aer_uncor_severity: 0x%08x\n",
|
||||
|
|
@ -974,6 +1082,36 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
|
|||
if (tlp_header_valid)
|
||||
pcie_print_tlp_log(dev, &aer->header_log, info.level,
|
||||
dev_fmt(" "));
|
||||
|
||||
anfe:
|
||||
/* Recursive invocation for Advisory Non-Fatal Errors */
|
||||
if (aer_severity == AER_CORRECTABLE &&
|
||||
info.status & ~info.mask & PCI_ERR_COR_ADV_NFAT) {
|
||||
u32 anfe_status = aer_compute_anfe_status(PCI_EXP_DEVSTA_CED,
|
||||
aer->uncor_status,
|
||||
aer->uncor_mask,
|
||||
aer->uncor_severity);
|
||||
if (anfe_status) {
|
||||
aer->uncor_status = anfe_status;
|
||||
aer->uncor_mask = 0;
|
||||
__pci_print_aer(dev, AER_NONFATAL, aer,
|
||||
ratelimit_print, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pci_print_aer(struct pci_dev *dev, int aer_severity,
|
||||
struct aer_capability_regs *aer)
|
||||
{
|
||||
/*
|
||||
* Precalculate ratelimit counter and log level so that Advisory
|
||||
* Non-Fatal Errors are treated like the accompanying Correctable Error
|
||||
*/
|
||||
bool ratelimit_print = aer_ratelimit(dev, aer_severity);
|
||||
const char *level = aer_severity == AER_CORRECTABLE ? KERN_WARNING
|
||||
: KERN_ERR;
|
||||
|
||||
__pci_print_aer(dev, aer_severity, aer, ratelimit_print, level);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_print_aer);
|
||||
|
||||
|
|
@ -1176,9 +1314,14 @@ static void pci_aer_handle_error(struct pci_dev *dev, struct aer_err_info *info)
|
|||
* Correctable error does not need software intervention.
|
||||
* No need to go through error recovery process.
|
||||
*/
|
||||
if (aer)
|
||||
if (aer) {
|
||||
pci_write_config_dword(dev, aer + PCI_ERR_COR_STATUS,
|
||||
info->status);
|
||||
if (info->anfe_status)
|
||||
pci_write_config_dword(dev,
|
||||
aer + PCI_ERR_UNCOR_STATUS,
|
||||
info->anfe_status);
|
||||
}
|
||||
if (pcie_aer_is_native(dev)) {
|
||||
struct pci_driver *pdrv = dev->driver;
|
||||
|
||||
|
|
@ -1281,6 +1424,27 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
|
|||
EXPORT_SYMBOL_GPL(aer_recover_queue);
|
||||
#endif
|
||||
|
||||
static void aer_get_uncor_info(struct pci_dev *dev, struct aer_err_info *info,
|
||||
u32 status)
|
||||
{
|
||||
u16 aer = dev->aer_cap;
|
||||
u32 aercc;
|
||||
|
||||
/* Get First Error Pointer */
|
||||
pci_read_config_dword(dev, aer + PCI_ERR_CAP, &aercc);
|
||||
info->first_error = PCI_ERR_CAP_FEP(aercc);
|
||||
|
||||
/* Get TLP Prefix/Header Log */
|
||||
if (tlp_header_logged(status, aercc)) {
|
||||
info->tlp_header_valid = 1;
|
||||
pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG,
|
||||
aer + PCI_ERR_PREFIX_LOG,
|
||||
aer_tlp_log_len(dev, aercc),
|
||||
aercc & PCI_ERR_CAP_TLP_LOG_FLIT,
|
||||
&info->tlp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aer_get_device_error_info - read error status from dev and store it to info
|
||||
* @info: pointer to structure to store the error record
|
||||
|
|
@ -1294,7 +1458,6 @@ int aer_get_device_error_info(struct aer_err_info *info, int i)
|
|||
{
|
||||
struct pci_dev *dev;
|
||||
int type, aer;
|
||||
u32 aercc;
|
||||
|
||||
if (i >= AER_MAX_MULTI_ERR_DEVICES)
|
||||
return 0;
|
||||
|
|
@ -1305,6 +1468,7 @@ int aer_get_device_error_info(struct aer_err_info *info, int i)
|
|||
|
||||
/* Must reset in this function */
|
||||
info->status = 0;
|
||||
info->anfe_status = 0;
|
||||
info->tlp_header_valid = 0;
|
||||
info->is_cxl = pcie_is_cxl(dev);
|
||||
|
||||
|
|
@ -1319,6 +1483,10 @@ int aer_get_device_error_info(struct aer_err_info *info, int i)
|
|||
&info->mask);
|
||||
if (!(info->status & ~info->mask))
|
||||
return 0;
|
||||
if (info->status & ~info->mask & PCI_ERR_COR_ADV_NFAT) {
|
||||
info->anfe_status = aer_get_anfe_status(dev);
|
||||
aer_get_uncor_info(dev, info, info->anfe_status);
|
||||
}
|
||||
} else if (type == PCI_EXP_TYPE_ROOT_PORT ||
|
||||
type == PCI_EXP_TYPE_RC_EC ||
|
||||
type == PCI_EXP_TYPE_DOWNSTREAM ||
|
||||
|
|
@ -1332,18 +1500,7 @@ int aer_get_device_error_info(struct aer_err_info *info, int i)
|
|||
if (!(info->status & ~info->mask))
|
||||
return 0;
|
||||
|
||||
/* Get First Error Pointer */
|
||||
pci_read_config_dword(dev, aer + PCI_ERR_CAP, &aercc);
|
||||
info->first_error = PCI_ERR_CAP_FEP(aercc);
|
||||
|
||||
if (tlp_header_logged(info->status, aercc)) {
|
||||
info->tlp_header_valid = 1;
|
||||
pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG,
|
||||
aer + PCI_ERR_PREFIX_LOG,
|
||||
aer_tlp_log_len(dev, aercc),
|
||||
aercc & PCI_ERR_CAP_TLP_LOG_FLIT,
|
||||
&info->tlp);
|
||||
}
|
||||
aer_get_uncor_info(dev, info, info->status & ~info->mask);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user