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

Commit cc5d153a authored by Andrew Patterson's avatar Andrew Patterson Committed by Jesse Barnes
Browse files

PCI: add support for PCI domains to aer_inject



Add support for PCI domains (segments) to aer_inject.

Acked-by: default avatarHuang Ying <ying.huang@intel.com>
Signed-off-by: default avatarAndrew Patterson <andrew.patterson@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 3c299dc2
Loading
Loading
Loading
Loading
+34 −12
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/stddef.h>
#include "aerdrv.h"

struct aer_error_inj {
@@ -35,10 +36,12 @@ struct aer_error_inj {
	u32 header_log1;
	u32 header_log2;
	u32 header_log3;
	u16 domain;
};

struct aer_error {
	struct list_head list;
	u16 domain;
	unsigned int bus;
	unsigned int devfn;
	int pos_cap_err;
@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list);
/* Protect einjected and pci_bus_ops_list */
static DEFINE_SPINLOCK(inject_lock);

static void aer_error_init(struct aer_error *err, unsigned int bus,
			   unsigned int devfn, int pos_cap_err)
static void aer_error_init(struct aer_error *err, u16 domain,
			   unsigned int bus, unsigned int devfn,
			   int pos_cap_err)
{
	INIT_LIST_HEAD(&err->list);
	err->domain = domain;
	err->bus = bus;
	err->devfn = devfn;
	err->pos_cap_err = pos_cap_err;
}

/* inject_lock must be held before calling */
static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
static struct aer_error *__find_aer_error(u16 domain, unsigned int bus,
					  unsigned int devfn)
{
	struct aer_error *err;

	list_for_each_entry(err, &einjected, list) {
		if (bus == err->bus && devfn == err->devfn)
		if (domain == err->domain &&
		    bus == err->bus &&
		    devfn == err->devfn)
			return err;
	}
	return NULL;
@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
/* inject_lock must be held before calling */
static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
{
	return __find_aer_error(dev->bus->number, dev->devfn);
	int domain = pci_domain_nr(dev->bus);
	if (domain < 0)
		return NULL;
	return __find_aer_error((u16)domain, dev->bus->number, dev->devfn);
}

/* inject_lock must be held before calling */
@@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
	struct aer_error *err;
	unsigned long flags;
	struct pci_ops *ops;
	int domain;

	spin_lock_irqsave(&inject_lock, flags);
	if (size != sizeof(u32))
		goto out;
	err = __find_aer_error(bus->number, devfn);
	domain = pci_domain_nr(bus);
	if (domain < 0)
		goto out;
	err = __find_aer_error((u16)domain, bus->number, devfn);
	if (!err)
		goto out;

@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
	unsigned long flags;
	int rw1cs;
	struct pci_ops *ops;
	int domain;

	spin_lock_irqsave(&inject_lock, flags);
	if (size != sizeof(u32))
		goto out;
	err = __find_aer_error(bus->number, devfn);
	domain = pci_domain_nr(bus);
	if (domain < 0)
		goto out;
	err = __find_aer_error((u16)domain, bus->number, devfn);
	if (!err)
		goto out;

@@ -305,7 +324,7 @@ static int aer_inject(struct aer_error_inj *einj)
	u32 sever;
	int ret = 0;

	dev = pci_get_bus_and_slot(einj->bus, devfn);
	dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
	if (!dev)
		return -EINVAL;
	rpdev = pcie_find_root_port(dev);
@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj)
	if (!err) {
		err = err_alloc;
		err_alloc = NULL;
		aer_error_init(err, einj->bus, devfn, pos_cap_err);
		aer_error_init(err, einj->domain, einj->bus, devfn,
			       pos_cap_err);
		list_add(&err->list, &einjected);
	}
	err->uncor_status |= einj->uncor_status;
@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj)
	if (!rperr) {
		rperr = rperr_alloc;
		rperr_alloc = NULL;
		aer_error_init(rperr, rpdev->bus->number, rpdev->devfn,
		aer_error_init(rperr, pci_domain_nr(rpdev->bus),
			       rpdev->bus->number, rpdev->devfn,
			       rp_pos_cap_err);
		list_add(&rperr->list, &einjected);
	}
@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (usize != sizeof(struct aer_error_inj))
	if (usize < offsetof(struct aer_error_inj, domain) ||
	    usize > sizeof(einj))
		return -EINVAL;

	memset(&einj, 0, sizeof(einj));
	if (copy_from_user(&einj, ubuf, usize))
		return -EFAULT;