mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-27 15:36:48 +00:00

Flit mode introduced in PCIe r6.0 alters how the TLP Header Log is presented through AER and DPC Capability registers. The TLP Prefix Log Register is not present with Flit mode, and the register becomes an extension of the TLP Header Log (PCIe r6.1 secs 7.8.4.12 & 7.9.14.13). Adapt pcie_read_tlp_log() and struct pcie_tlp_log to read and store the extended TLP Header Log when the Link is in Flit mode. As the Prefix Log and Extended TLP Header are not present at the same time, a C union can be used. Determining whether the error occurred while the Link was in Flit mode is a bit complicated. In case of AER, the Advanced Error Capabilities and Control Register directly tells whether the error was logged in Flit mode or not (PCIe r6.1 sec 7.8.4.7). The DPC Capability (PCIe r6.1 sec 7.9.14), unfortunately, does not contain the same information. Unlike AER, the DPC Capability does not provide a way to discern whether the error was logged in Flit mode (this is confirmed by PCI WG to be an oversight in the spec). DPC will bring the Link down immediately following an error, which makes it impossible to acquire the Flit Mode Status directly from the Link Status 2 register because Flit Mode Status is only set in certain Link states (PCIe r6.1 sec 7.5.3.20). As a workaround, use the flit_mode value stored into the struct pci_bus. Link: https://lore.kernel.org/r/20250207161836.2755-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
74 lines
1.8 KiB
C
74 lines
1.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) 2006 Intel Corp.
|
|
* Tom Long Nguyen (tom.l.nguyen@intel.com)
|
|
* Zhang Yanmin (yanmin.zhang@intel.com)
|
|
*/
|
|
|
|
#ifndef _AER_H_
|
|
#define _AER_H_
|
|
|
|
#include <linux/errno.h>
|
|
#include <linux/types.h>
|
|
|
|
#define AER_NONFATAL 0
|
|
#define AER_FATAL 1
|
|
#define AER_CORRECTABLE 2
|
|
#define DPC_FATAL 3
|
|
|
|
/*
|
|
* AER and DPC capabilities TLP Logging register sizes (PCIe r6.2, sec 7.8.4
|
|
* & 7.9.14).
|
|
*/
|
|
#define PCIE_STD_NUM_TLP_HEADERLOG 4
|
|
#define PCIE_STD_MAX_TLP_PREFIXLOG 4
|
|
#define PCIE_STD_MAX_TLP_HEADERLOG (PCIE_STD_NUM_TLP_HEADERLOG + 10)
|
|
|
|
struct pci_dev;
|
|
|
|
struct pcie_tlp_log {
|
|
union {
|
|
u32 dw[PCIE_STD_MAX_TLP_HEADERLOG];
|
|
struct {
|
|
u32 _do_not_use[PCIE_STD_NUM_TLP_HEADERLOG];
|
|
u32 prefix[PCIE_STD_MAX_TLP_PREFIXLOG];
|
|
};
|
|
};
|
|
u8 header_len; /* Length of the Logged TLP Header in DWORDs */
|
|
bool flit; /* TLP was logged when in Flit mode */
|
|
};
|
|
|
|
struct aer_capability_regs {
|
|
u32 header;
|
|
u32 uncor_status;
|
|
u32 uncor_mask;
|
|
u32 uncor_severity;
|
|
u32 cor_status;
|
|
u32 cor_mask;
|
|
u32 cap_control;
|
|
struct pcie_tlp_log header_log;
|
|
u32 root_command;
|
|
u32 root_status;
|
|
u16 cor_err_source;
|
|
u16 uncor_err_source;
|
|
};
|
|
|
|
#if defined(CONFIG_PCIEAER)
|
|
int pci_aer_clear_nonfatal_status(struct pci_dev *dev);
|
|
int pcie_aer_is_native(struct pci_dev *dev);
|
|
#else
|
|
static inline int pci_aer_clear_nonfatal_status(struct pci_dev *dev)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
static inline int pcie_aer_is_native(struct pci_dev *dev) { return 0; }
|
|
#endif
|
|
|
|
void pci_print_aer(struct pci_dev *dev, int aer_severity,
|
|
struct aer_capability_regs *aer);
|
|
int cper_severity_to_aer(int cper_severity);
|
|
void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
|
|
int severity, struct aer_capability_regs *aer_regs);
|
|
#endif //_AER_H_
|
|
|