|
@@ -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;
|
|
|
-}
|