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

Commit 457d9d08 authored by Prarit Bhargava's avatar Prarit Bhargava Committed by Jesse Barnes
Browse files

PCI: aer-inject: Override PCIe AER Mask Registers



I have several systems which have the same problem:  The PCIe AER
corrected and uncorrected masks have all the error bits set.  This
results in the inablility to test with the aer_inject module & utility
on those systems.

Add the 'aer_mask_override' module parameter which will override the
corrected or uncorrected masks for a PCI device.  The mask will have the
bit corresponding to the status passed into the aer_inject() function.

After this patch it is possible to successfully use the aer_inject
utility on those PCI slots.

Successfully tested by me on a Dell and Intel whitebox which exhibited
the mask problem.

Signed-off-by: default avatarPrarit Bhargava <prarit@redhat.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 3449248c
Loading
Loading
Loading
Loading
+28 −3
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@
#include <linux/stddef.h>
#include "aerdrv.h"

/* Override the existing corrected and uncorrected error masks */
static int aer_mask_override;
module_param(aer_mask_override, bool, 0);

struct aer_error_inj {
	u8 bus;
	u8 dev;
@@ -322,7 +326,7 @@ static int aer_inject(struct aer_error_inj *einj)
	unsigned long flags;
	unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
	int pos_cap_err, rp_pos_cap_err;
	u32 sever, cor_mask, uncor_mask;
	u32 sever, cor_mask, uncor_mask, cor_mask_orig, uncor_mask_orig;
	int ret = 0;

	dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
@@ -361,6 +365,18 @@ static int aer_inject(struct aer_error_inj *einj)
		goto out_put;
	}

	if (aer_mask_override) {
		cor_mask_orig = cor_mask;
		cor_mask &= !(einj->cor_status);
		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
				       cor_mask);

		uncor_mask_orig = uncor_mask;
		uncor_mask &= !(einj->uncor_status);
		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
				       uncor_mask);
	}

	spin_lock_irqsave(&inject_lock, flags);

	err = __find_aer_error_by_dev(dev);
@@ -378,14 +394,16 @@ static int aer_inject(struct aer_error_inj *einj)
	err->header_log2 = einj->header_log2;
	err->header_log3 = einj->header_log3;

	if (einj->cor_status && !(einj->cor_status & ~cor_mask)) {
	if (!aer_mask_override && einj->cor_status &&
	    !(einj->cor_status & ~cor_mask)) {
		ret = -EINVAL;
		printk(KERN_WARNING "The correctable error(s) is masked "
				"by device\n");
		spin_unlock_irqrestore(&inject_lock, flags);
		goto out_put;
	}
	if (einj->uncor_status && !(einj->uncor_status & ~uncor_mask)) {
	if (!aer_mask_override && einj->uncor_status &&
	    !(einj->uncor_status & ~uncor_mask)) {
		ret = -EINVAL;
		printk(KERN_WARNING "The uncorrectable error(s) is masked "
				"by device\n");
@@ -425,6 +443,13 @@ static int aer_inject(struct aer_error_inj *einj)
	}
	spin_unlock_irqrestore(&inject_lock, flags);

	if (aer_mask_override) {
		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
				       cor_mask_orig);
		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
				       uncor_mask_orig);
	}

	ret = pci_bus_set_aer_ops(dev->bus);
	if (ret)
		goto out_put;