diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 12:18:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 12:18:16 -0800 |
commit | 11bd04f6f35621193311c32e0721142b073a7794 (patch) | |
tree | 00979740582bb26e8d3756bf3526c85f19f66a46 /drivers/pci/pcie/aer/aer_inject.c | |
parent | 4e2ccdb0409146f8cf64a11b6ef82a9c928ced2a (diff) | |
parent | 9e0b5b2c447ad0caa075a5cfef86def62e1782ff (diff) | |
download | linux-11bd04f6f35621193311c32e0721142b073a7794.tar.bz2 |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (109 commits)
PCI: fix coding style issue in pci_save_state()
PCI: add pci_request_acs
PCI: fix BUG_ON triggered by logical PCIe root port removal
PCI: remove ifdefed pci_cleanup_aer_correct_error_status
PCI: unconditionally clear AER uncorr status register during cleanup
x86/PCI: claim SR-IOV BARs in pcibios_allocate_resource
PCI: portdrv: remove redundant definitions
PCI: portdrv: remove unnecessary struct pcie_port_data
PCI: portdrv: minor cleanup for pcie_port_device_register
PCI: portdrv: add missing irq cleanup
PCI: portdrv: enable device before irq initialization
PCI: portdrv: cleanup service irqs initialization
PCI: portdrv: check capabilities first
PCI: portdrv: move PME capability check
PCI: portdrv: remove redundant pcie type calculation
PCI: portdrv: cleanup pcie_device registration
PCI: portdrv: remove redundant pcie_port_device_probe
PCI: Always set prefetchable base/limit upper32 registers
PCI: read-modify-write the pcie device control register when initiating pcie flr
PCI: show dma_mask bits in /sys
...
Fixed up conflicts in:
arch/x86/kernel/amd_iommu_init.c
drivers/pci/dmar.c
drivers/pci/hotplug/acpiphp_glue.c
Diffstat (limited to 'drivers/pci/pcie/aer/aer_inject.c')
-rw-r--r-- | drivers/pci/pcie/aer/aer_inject.c | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 62d15f652bb6..7fcd5331b14c 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -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; @@ -262,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; @@ -305,25 +324,25 @@ 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; + 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; } @@ -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; @@ -452,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); } |