From cc5d153a0ca794e3781ef34c76f32ad3e991b13d Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Mon, 12 Oct 2009 13:14:05 -0600 Subject: PCI: add support for PCI domains to aer_inject Add support for PCI domains (segments) to aer_inject. Acked-by: Huang Ying Signed-off-by: Andrew Patterson Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aer_inject.c | 46 +++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'drivers/pci/pcie/aer/aer_inject.c') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 62d15f652bb6..ac0b5e7bb3f5 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -23,6 +23,7 @@ #include #include #include +#include #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; -- cgit v1.2.1 From 1d0243559497b9cab00099c49a5ba3222cd6576f Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Mon, 12 Oct 2009 13:14:10 -0600 Subject: PCI: use better error return values in aer_inject Replaced some error return values in aer_inject. Use -ENODEV when we can't find a device and -ENOTTY when the device does not support PCIe AER. Acked-by: Huang Ying Signed-off-by: Andrew Patterson Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aer_inject.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/pci/pcie/aer/aer_inject.c') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index ac0b5e7bb3f5..da2ad6eaee17 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -326,23 +326,23 @@ static int aer_inject(struct aer_error_inj *einj) dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); if (!dev) - return -EINVAL; + return -ENODEV; rpdev = pcie_find_root_port(dev); if (!rpdev) { - ret = -EINVAL; + ret = -ENOTTY; goto out_put; } pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos_cap_err) { - ret = -EIO; + ret = -ENOTTY; goto out_put; } pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever); rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR); if (!rp_pos_cap_err) { - ret = -EIO; + ret = -ENOTTY; goto out_put; } -- cgit v1.2.1 From 476f644edf7c22b47e6a118e4a1e138112a5ef14 Mon Sep 17 00:00:00 2001 From: Andrew Patterson Date: Mon, 12 Oct 2009 13:14:15 -0600 Subject: PCI: fix memory leak in aer_inject Fixed probable typo in aer_inject cleanup code resulting in a memory leak. Acked-by: Huang Ying Signed-off-by: Andrew Patterson Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aer_inject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/pcie/aer/aer_inject.c') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index da2ad6eaee17..2246bf7aee7e 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -474,7 +474,7 @@ static void __exit aer_inject_exit(void) } spin_lock_irqsave(&inject_lock, flags); - list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) { + list_for_each_entry_safe(err, err_next, &einjected, list) { list_del(&err->list); kfree(err); } -- cgit v1.2.1 From b44d7db36480a3b27e78141fc9d6597aa577744b Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Wed, 11 Nov 2009 14:37:24 +0900 Subject: PCIe AER: use pci_is_pcie() Changes for PCIe AER driver to use pci_is_pcie() instead of checking pci_dev->is_pcie. Signed-off-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aer_inject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/pcie/aer/aer_inject.c') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 2246bf7aee7e..7fcd5331b14c 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -281,7 +281,7 @@ out: static struct pci_dev *pcie_find_root_port(struct pci_dev *dev) { while (1) { - if (!dev->is_pcie) + if (!pci_is_pcie(dev)) break; if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) return dev; -- cgit v1.2.1