Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d521000 authored by Lance Ortiz's avatar Lance Ortiz Committed by Tony Luck
Browse files

aerdrv: Enhanced AER logging



This patch will provide a more reliable and easy way for user-space
applications to have access to AER logs rather than reading them from the
message buffer. It also provides a way to notify user-space when an AER
event occurs.

The aer driver is updated to generate a trace event of function 'aer_event'
when a PCIe error is reported over the AER interface.  The trace event was
added to both the interrupt based aer path and the firmware first path.

Signed-off-by: default avatarLance Ortiz <lance.ortiz@hp.com>
Acked-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: default avatarBoris Petkov <bp@alien8.de>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 1ca1d8d5
Loading
Loading
Loading
Loading
+16 −3
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/time.h>
#include <linux/time.h>
#include <linux/cper.h>
#include <linux/cper.h>
#include <linux/acpi.h>
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/aer.h>


/*
/*
@@ -249,6 +250,10 @@ static const char *cper_pcie_port_type_strs[] = {
static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
			    const struct acpi_hest_generic_data *gdata)
			    const struct acpi_hest_generic_data *gdata)
{
{
#ifdef CONFIG_ACPI_APEI_PCIEAER
	struct pci_dev *dev;
#endif

	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
		       pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
		       pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ?
@@ -281,10 +286,18 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
	"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
	"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
#ifdef CONFIG_ACPI_APEI_PCIEAER
#ifdef CONFIG_ACPI_APEI_PCIEAER
	if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
	dev = pci_get_domain_bus_and_slot(pcie->device_id.segment,
		struct aer_capability_regs *aer_regs = (void *)pcie->aer_info;
			pcie->device_id.bus, pcie->device_id.function);
		cper_print_aer(pfx, gdata->error_severity, aer_regs);
	if (!dev) {
		pr_err("PCI AER Cannot get PCI device %04x:%02x:%02x.%d\n",
			pcie->device_id.segment, pcie->device_id.bus,
			pcie->device_id.slot, pcie->device_id.function);
		return;
	}
	}
	if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO)
		cper_print_aer(pfx, dev, gdata->error_severity,
				(struct aer_capability_regs *) pcie->aer_info);
	pci_dev_put(dev);
#endif
#endif
}
}


+8 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,9 @@


#include "aerdrv.h"
#include "aerdrv.h"


#define CREATE_TRACE_POINTS
#include <trace/events/ras.h>

#define AER_AGENT_RECEIVER		0
#define AER_AGENT_RECEIVER		0
#define AER_AGENT_REQUESTER		1
#define AER_AGENT_REQUESTER		1
#define AER_AGENT_COMPLETER		2
#define AER_AGENT_COMPLETER		2
@@ -194,6 +197,8 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
	if (info->id && info->error_dev_num > 1 && info->id == id)
	if (info->id && info->error_dev_num > 1 && info->id == id)
		printk("%s""  Error of this Agent(%04x) is reported first\n",
		printk("%s""  Error of this Agent(%04x) is reported first\n",
			prefix, id);
			prefix, id);
	trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
			info->severity);
}
}


void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
@@ -217,7 +222,7 @@ int cper_severity_to_aer(int cper_severity)
}
}
EXPORT_SYMBOL_GPL(cper_severity_to_aer);
EXPORT_SYMBOL_GPL(cper_severity_to_aer);


void cper_print_aer(const char *prefix, int cper_severity,
void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity,
		    struct aer_capability_regs *aer)
		    struct aer_capability_regs *aer)
{
{
	int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
	int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
@@ -259,5 +264,7 @@ void cper_print_aer(const char *prefix, int cper_severity,
			*(tlp + 8), *(tlp + 15), *(tlp + 14),
			*(tlp + 8), *(tlp + 15), *(tlp + 14),
			*(tlp + 13), *(tlp + 12));
			*(tlp + 13), *(tlp + 12));
	}
	}
	trace_aer_event(dev_name(&dev->dev), (status & ~mask),
			aer_severity);
}
}
#endif
#endif
+2 −2
Original line number Original line Diff line number Diff line
@@ -49,8 +49,8 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
}
}
#endif
#endif


extern void cper_print_aer(const char *prefix, int cper_severity,
extern void cper_print_aer(const char *prefix, struct pci_dev *dev,
			   struct aer_capability_regs *aer);
			   int cper_severity, struct aer_capability_regs *aer);
extern int cper_severity_to_aer(int cper_severity);
extern int cper_severity_to_aer(int cper_severity);
extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
			      int severity);
			      int severity);