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

Commit d9cdfb87 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/aer' into next

* pci/aer:
  PCI/AER: Consolidate HEST error source parsers
  PCI/AER: Ignore non-PCIe AER error sources in aer_hest_parse()
  PCI/AER: Clean up error printing code a bit
  PCI/AER: Add a TLP header print helper
parents e338e49d 3620437a
Loading
Loading
Loading
Loading
+29 −19
Original line number Original line Diff line number Diff line
@@ -50,14 +50,37 @@ struct aer_hest_parse_info {
	int firmware_first;
	int firmware_first;
};
};


static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
{
	if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
	    hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
	    hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
		return 1;
	return 0;
}

static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
{
{
	struct aer_hest_parse_info *info = data;
	struct aer_hest_parse_info *info = data;
	struct acpi_hest_aer_common *p;
	struct acpi_hest_aer_common *p;
	int ff;
	int ff;


	if (!hest_source_is_pcie_aer(hest_hdr))
		return 0;

	p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
	p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
	ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
	ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);

	/*
	 * If no specific device is supplied, determine whether
	 * FIRMWARE_FIRST is set for *any* PCIe device.
	 */
	if (!info->pci_dev) {
		info->firmware_first |= ff;
		return 0;
	}

	/* Otherwise, check the specific device */
	if (p->flags & ACPI_HEST_GLOBAL) {
	if (p->flags & ACPI_HEST_GLOBAL) {
		if (hest_match_type(hest_hdr, info->pci_dev))
		if (hest_match_type(hest_hdr, info->pci_dev))
			info->firmware_first = ff;
			info->firmware_first = ff;
@@ -97,33 +120,20 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev)


static bool aer_firmware_first;
static bool aer_firmware_first;


static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data)
{
	struct acpi_hest_aer_common *p;

	if (aer_firmware_first)
		return 0;

	switch (hest_hdr->type) {
	case ACPI_HEST_TYPE_AER_ROOT_PORT:
	case ACPI_HEST_TYPE_AER_ENDPOINT:
	case ACPI_HEST_TYPE_AER_BRIDGE:
		p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
		aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
	default:
		return 0;
	}
}

/**
/**
 * aer_acpi_firmware_first - Check if APEI should control AER.
 * aer_acpi_firmware_first - Check if APEI should control AER.
 */
 */
bool aer_acpi_firmware_first(void)
bool aer_acpi_firmware_first(void)
{
{
	static bool parsed = false;
	static bool parsed = false;
	struct aer_hest_parse_info info = {
		.pci_dev	= NULL,	/* Check all PCIe devices */
		.firmware_first	= 0,
	};


	if (!parsed) {
	if (!parsed) {
		apei_hest_parse(aer_hest_parse_aff, NULL);
		apei_hest_parse(aer_hest_parse, &info);
		aer_firmware_first = info.firmware_first;
		parsed = true;
		parsed = true;
	}
	}
	return aer_firmware_first;
	return aer_firmware_first;
+48 −47
Original line number Original line Diff line number Diff line
@@ -124,6 +124,21 @@ static const char *aer_agent_string[] = {
	"Transmitter ID"
	"Transmitter ID"
};
};


static void __print_tlp_header(struct pci_dev *dev,
			       struct aer_header_log_regs *t)
{
	unsigned char *tlp = (unsigned char *)&t;

	dev_err(&dev->dev, "  TLP Header:"
		" %02x%02x%02x%02x %02x%02x%02x%02x"
		" %02x%02x%02x%02x %02x%02x%02x%02x\n",
		*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
		*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
		*(tlp + 11), *(tlp + 10), *(tlp + 9),
		*(tlp + 8), *(tlp + 15), *(tlp + 14),
		*(tlp + 13), *(tlp + 12));
}

static void __aer_print_error(struct pci_dev *dev,
static void __aer_print_error(struct pci_dev *dev,
			      struct aer_err_info *info)
			      struct aer_err_info *info)
{
{
@@ -153,15 +168,16 @@ static void __aer_print_error(struct pci_dev *dev,


void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
{
{
	int layer, agent;
	int id = ((dev->bus->number << 8) | dev->devfn);
	int id = ((dev->bus->number << 8) | dev->devfn);


	if (info->status == 0) {
	if (!info->status) {
		dev_err(&dev->dev,
		dev_err(&dev->dev,
			"PCIe Bus Error: severity=%s, type=Unaccessible, "
			"PCIe Bus Error: severity=%s, type=Unaccessible, "
			"id=%04x(Unregistered Agent ID)\n",
			"id=%04x(Unregistered Agent ID)\n",
			aer_error_severity_string[info->severity], id);
			aer_error_severity_string[info->severity], id);
	} else {
		goto out;
		int layer, agent;
	}


	layer = AER_GET_LAYER_ERROR(info->severity, info->status);
	layer = AER_GET_LAYER_ERROR(info->severity, info->status);
	agent = AER_GET_AGENT(info->severity, info->status);
	agent = AER_GET_AGENT(info->severity, info->status);
@@ -178,23 +194,13 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)


	__aer_print_error(dev, info);
	__aer_print_error(dev, info);


		if (info->tlp_header_valid) {
	if (info->tlp_header_valid)
			unsigned char *tlp = (unsigned char *) &info->tlp;
		__print_tlp_header(dev, &info->tlp);
			dev_err(&dev->dev, "  TLP Header:"
				" %02x%02x%02x%02x %02x%02x%02x%02x"
				" %02x%02x%02x%02x %02x%02x%02x%02x\n",
				*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
				*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
				*(tlp + 11), *(tlp + 10), *(tlp + 9),
				*(tlp + 8), *(tlp + 15), *(tlp + 14),
				*(tlp + 13), *(tlp + 12));
		}
	}


out:
	if (info->id && info->error_dev_num > 1 && info->id == id)
	if (info->id && info->error_dev_num > 1 && info->id == id)
		dev_err(&dev->dev,
		dev_err(&dev->dev, "  Error of this Agent(%04x) is reported first\n", id);
			   "  Error of this Agent(%04x) is reported first\n",

			id);
	trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
	trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
			info->severity);
			info->severity);
}
}
@@ -228,6 +234,7 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity,
	const char **status_strs;
	const char **status_strs;


	aer_severity = cper_severity_to_aer(cper_severity);
	aer_severity = cper_severity_to_aer(cper_severity);

	if (aer_severity == AER_CORRECTABLE) {
	if (aer_severity == AER_CORRECTABLE) {
		status = aer->cor_status;
		status = aer->cor_status;
		mask = aer->cor_mask;
		mask = aer->cor_mask;
@@ -240,28 +247,22 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity,
		status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string);
		status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string);
		tlp_header_valid = status & AER_LOG_TLP_MASKS;
		tlp_header_valid = status & AER_LOG_TLP_MASKS;
	}
	}

	layer = AER_GET_LAYER_ERROR(aer_severity, status);
	layer = AER_GET_LAYER_ERROR(aer_severity, status);
	agent = AER_GET_AGENT(aer_severity, status);
	agent = AER_GET_AGENT(aer_severity, status);
	dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n",

	       status, mask);
	dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);
	cper_print_bits("", status, status_strs, status_strs_size);
	cper_print_bits("", status, status_strs, status_strs_size);
	dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n",
	dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n",
		aer_error_layer[layer], aer_agent_string[agent]);
		aer_error_layer[layer], aer_agent_string[agent]);

	if (aer_severity != AER_CORRECTABLE)
	if (aer_severity != AER_CORRECTABLE)
		dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n",
		dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n",
			aer->uncor_severity);
			aer->uncor_severity);
	if (tlp_header_valid) {

		const unsigned char *tlp;
	if (tlp_header_valid)
		tlp = (const unsigned char *)&aer->header_log;
		__print_tlp_header(dev, &aer->header_log);
		dev_err(&dev->dev, "aer_tlp_header:"

			" %02x%02x%02x%02x %02x%02x%02x%02x"
			" %02x%02x%02x%02x %02x%02x%02x%02x\n",
			*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
			*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
			*(tlp + 11), *(tlp + 10), *(tlp + 9),
			*(tlp + 8), *(tlp + 15), *(tlp + 14),
			*(tlp + 13), *(tlp + 12));
	}
	trace_aer_event(dev_name(&dev->dev), (status & ~mask),
	trace_aer_event(dev_name(&dev->dev), (status & ~mask),
			aer_severity);
			aer_severity);
}
}