diff options
Diffstat (limited to 'drivers/pci/pcie/aer/aerdrv_core.c')
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 61 |
1 files changed, 19 insertions, 42 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 521e39c1b66d..b1303b32053f 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -27,11 +27,6 @@ #include <linux/kfifo.h> #include "aerdrv.h" -static bool forceload; -static bool nosourceid; -module_param(forceload, bool, 0); -module_param(nosourceid, bool, 0); - #define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) @@ -40,7 +35,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) if (pcie_aer_get_firmware_first(dev)) return -EIO; - if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) + if (!dev->aer_cap) return -EIO; return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); @@ -62,7 +57,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) int pos; u32 status; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + pos = dev->aer_cap; if (!pos) return -EIO; @@ -83,7 +78,7 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) if (!pci_is_pcie(dev)) return -ENODEV; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + pos = dev->aer_cap; if (!pos) return -EIO; @@ -102,6 +97,12 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) return 0; } +int pci_aer_init(struct pci_dev *dev) +{ + dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + return pci_cleanup_aer_error_status_regs(dev); +} + /** * add_error_device - list device to be handled * @e_info: pointer to error info @@ -132,7 +133,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) * When bus id is equal to 0, it might be a bad id * reported by root port. */ - if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { + if ((PCI_BUS_NUM(e_info->id) != 0) && + !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) { /* Device ID match? */ if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) return true; @@ -144,10 +146,10 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) /* * When either - * 1) nosourceid==y; - * 2) bus id is equal to 0. Some ports might lose the bus + * 1) bus id is equal to 0. Some ports might lose the bus * id of error source id; - * 3) There are multiple errors and prior id comparing fails; + * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set + * 3) There are multiple errors and prior ID comparing fails; * We check AER status registers to find possible reporter. */ if (atomic_read(&dev->enable_cnt) == 0) @@ -158,7 +160,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) if (!(reg16 & PCI_EXP_AER_FLAGS)) return false; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + pos = dev->aer_cap; if (!pos) return false; @@ -555,7 +557,7 @@ static void handle_error_source(struct pcie_device *aerdev, * Correctable error does not need software intervention. * No need to go through error recovery process. */ - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + pos = dev->aer_cap; if (pos) pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, info->status); @@ -647,7 +649,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) info->status = 0; info->tlp_header_valid = 0; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); + pos = dev->aer_cap; /* The device might not support AER */ if (!pos) @@ -715,15 +717,8 @@ static inline void aer_process_err_devices(struct pcie_device *p_device, static void aer_isr_one_error(struct pcie_device *p_device, struct aer_err_source *e_src) { - struct aer_err_info *e_info; - - /* struct aer_err_info might be big, so we allocate it with slab */ - e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); - if (!e_info) { - dev_printk(KERN_DEBUG, &p_device->port->dev, - "Can't allocate mem when processing AER errors\n"); - return; - } + struct aer_rpc *rpc = get_service_data(p_device); + struct aer_err_info *e_info = &rpc->e_info; /* * There is a possibility that both correctable error and @@ -762,8 +757,6 @@ static void aer_isr_one_error(struct pcie_device *p_device, if (find_source_device(p_device->port, e_info)) aer_process_err_devices(p_device, e_info); } - - kfree(e_info); } /** @@ -812,19 +805,3 @@ void aer_isr(struct work_struct *work) aer_isr_one_error(p_device, &e_src); mutex_unlock(&rpc->rpc_mutex); } - -/** - * aer_init - provide AER initialization - * @dev: pointer to AER pcie device - * - * Invoked when AER service driver is loaded. - */ -int aer_init(struct pcie_device *dev) -{ - if (forceload) { - dev_printk(KERN_DEBUG, &dev->device, - "aerdrv forceload requested.\n"); - pcie_aer_force_firmware_first(dev->port, 0); - } - return 0; -} |