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

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
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/stddef.h>
#include "aerdrv.h" #include "aerdrv.h"
struct aer_error_inj { struct aer_error_inj {
...@@ -35,10 +36,12 @@ struct aer_error_inj { ...@@ -35,10 +36,12 @@ struct aer_error_inj {
u32 header_log1; u32 header_log1;
u32 header_log2; u32 header_log2;
u32 header_log3; u32 header_log3;
u16 domain;
}; };
struct aer_error { struct aer_error {
struct list_head list; struct list_head list;
u16 domain;
unsigned int bus; unsigned int bus;
unsigned int devfn; unsigned int devfn;
int pos_cap_err; int pos_cap_err;
...@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list); ...@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list);
/* Protect einjected and pci_bus_ops_list */ /* Protect einjected and pci_bus_ops_list */
static DEFINE_SPINLOCK(inject_lock); static DEFINE_SPINLOCK(inject_lock);
static void aer_error_init(struct aer_error *err, unsigned int bus, static void aer_error_init(struct aer_error *err, u16 domain,
unsigned int devfn, int pos_cap_err) unsigned int bus, unsigned int devfn,
int pos_cap_err)
{ {
INIT_LIST_HEAD(&err->list); INIT_LIST_HEAD(&err->list);
err->domain = domain;
err->bus = bus; err->bus = bus;
err->devfn = devfn; err->devfn = devfn;
err->pos_cap_err = pos_cap_err; err->pos_cap_err = pos_cap_err;
} }
/* inject_lock must be held before calling */ /* 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; struct aer_error *err;
list_for_each_entry(err, &einjected, list) { 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 err;
} }
return NULL; return NULL;
...@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn) ...@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
/* inject_lock must be held before calling */ /* inject_lock must be held before calling */
static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev) 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 */ /* 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, ...@@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
struct aer_error *err; struct aer_error *err;
unsigned long flags; unsigned long flags;
struct pci_ops *ops; struct pci_ops *ops;
int domain;
spin_lock_irqsave(&inject_lock, flags); spin_lock_irqsave(&inject_lock, flags);
if (size != sizeof(u32)) if (size != sizeof(u32))
goto out; 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) if (!err)
goto out; goto out;
...@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size, ...@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
unsigned long flags; unsigned long flags;
int rw1cs; int rw1cs;
struct pci_ops *ops; struct pci_ops *ops;
int domain;
spin_lock_irqsave(&inject_lock, flags); spin_lock_irqsave(&inject_lock, flags);
if (size != sizeof(u32)) if (size != sizeof(u32))
goto out; 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) if (!err)
goto out; goto out;
...@@ -305,7 +324,7 @@ static int aer_inject(struct aer_error_inj *einj) ...@@ -305,7 +324,7 @@ static int aer_inject(struct aer_error_inj *einj)
u32 sever; u32 sever;
int ret = 0; 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) if (!dev)
return -EINVAL; return -EINVAL;
rpdev = pcie_find_root_port(dev); rpdev = pcie_find_root_port(dev);
...@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj) ...@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj)
if (!err) { if (!err) {
err = err_alloc; err = err_alloc;
err_alloc = NULL; 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); list_add(&err->list, &einjected);
} }
err->uncor_status |= einj->uncor_status; err->uncor_status |= einj->uncor_status;
...@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj) ...@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj)
if (!rperr) { if (!rperr) {
rperr = rperr_alloc; rperr = rperr_alloc;
rperr_alloc = NULL; 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); rp_pos_cap_err);
list_add(&rperr->list, &einjected); list_add(&rperr->list, &einjected);
} }
...@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf, ...@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (usize < offsetof(struct aer_error_inj, domain) ||
if (usize != sizeof(struct aer_error_inj)) usize > sizeof(einj))
return -EINVAL; return -EINVAL;
memset(&einj, 0, sizeof(einj));
if (copy_from_user(&einj, ubuf, usize)) if (copy_from_user(&einj, ubuf, usize))
return -EFAULT; return -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment