PCI: aerdrv: introduce is_error_source
Take core part of find_device_iter() to make a new function is_error_source() that checks given device has report an error or not. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
committed by
Jesse Barnes
parent
98ca3964fe
commit
c887275e6a
@@ -126,14 +126,17 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
|
|||||||
|
|
||||||
#define PCI_BUS(x) (((x) >> 8) & 0xff)
|
#define PCI_BUS(x) (((x) >> 8) & 0xff)
|
||||||
|
|
||||||
static int find_device_iter(struct pci_dev *dev, void *data)
|
/**
|
||||||
|
* is_error_source - check whether the device is source of reported error
|
||||||
|
* @dev: pointer to pci_dev to be checked
|
||||||
|
* @e_info: pointer to reported error info
|
||||||
|
*/
|
||||||
|
static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
u32 status;
|
u32 status, mask;
|
||||||
u32 mask;
|
|
||||||
u16 reg16;
|
u16 reg16;
|
||||||
int result;
|
int result;
|
||||||
struct aer_err_info *e_info = (struct aer_err_info *)data;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When bus id is equal to 0, it might be a bad id
|
* When bus id is equal to 0, it might be a bad id
|
||||||
@@ -142,22 +145,11 @@ static int find_device_iter(struct pci_dev *dev, void *data)
|
|||||||
if (!nosourceid && (PCI_BUS(e_info->id) != 0)) {
|
if (!nosourceid && (PCI_BUS(e_info->id) != 0)) {
|
||||||
result = compare_device_id(dev, e_info);
|
result = compare_device_id(dev, e_info);
|
||||||
if (result)
|
if (result)
|
||||||
add_error_device(e_info, dev);
|
return true;
|
||||||
|
|
||||||
/*
|
/* Continue id comparing if there is no multiple error */
|
||||||
* If there is no multiple error, we stop
|
|
||||||
* or continue based on the id comparing.
|
|
||||||
*/
|
|
||||||
if (!e_info->multi_error_valid)
|
if (!e_info->multi_error_valid)
|
||||||
return result;
|
return false;
|
||||||
|
|
||||||
/*
|
|
||||||
* If there are multiple errors and id does match,
|
|
||||||
* We need continue to search other devices under
|
|
||||||
* the root port. Return 0 means that.
|
|
||||||
*/
|
|
||||||
if (result)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -166,13 +158,14 @@ static int find_device_iter(struct pci_dev *dev, void *data)
|
|||||||
* 2) bus id is equal to 0. Some ports might lose the bus
|
* 2) bus id is equal to 0. Some ports might lose the bus
|
||||||
* id of error source id;
|
* id of error source id;
|
||||||
* 3) There are multiple errors and prior id comparing fails;
|
* 3) There are multiple errors and prior id comparing fails;
|
||||||
* We check AER status registers to find the initial reporter.
|
* We check AER status registers to find possible reporter.
|
||||||
*/
|
*/
|
||||||
if (atomic_read(&dev->enable_cnt) == 0)
|
if (atomic_read(&dev->enable_cnt) == 0)
|
||||||
return 0;
|
return false;
|
||||||
pos = pci_pcie_cap(dev);
|
pos = pci_pcie_cap(dev);
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
/* Check if AER is enabled */
|
/* Check if AER is enabled */
|
||||||
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16);
|
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16);
|
||||||
if (!(reg16 & (
|
if (!(reg16 & (
|
||||||
@@ -180,37 +173,38 @@ static int find_device_iter(struct pci_dev *dev, void *data)
|
|||||||
PCI_EXP_DEVCTL_NFERE |
|
PCI_EXP_DEVCTL_NFERE |
|
||||||
PCI_EXP_DEVCTL_FERE |
|
PCI_EXP_DEVCTL_FERE |
|
||||||
PCI_EXP_DEVCTL_URRE)))
|
PCI_EXP_DEVCTL_URRE)))
|
||||||
return 0;
|
return false;
|
||||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
||||||
if (!pos)
|
if (!pos)
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
status = 0;
|
/* Check if error is recorded */
|
||||||
mask = 0;
|
|
||||||
if (e_info->severity == AER_CORRECTABLE) {
|
if (e_info->severity == AER_CORRECTABLE) {
|
||||||
pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
|
pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
|
||||||
pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask);
|
pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask);
|
||||||
if (status & ~mask) {
|
|
||||||
add_error_device(e_info, dev);
|
|
||||||
goto added;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
|
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
|
||||||
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask);
|
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask);
|
||||||
if (status & ~mask) {
|
}
|
||||||
|
if (status & ~mask)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_device_iter(struct pci_dev *dev, void *data)
|
||||||
|
{
|
||||||
|
struct aer_err_info *e_info = (struct aer_err_info *)data;
|
||||||
|
|
||||||
|
if (is_error_source(dev, e_info)) {
|
||||||
add_error_device(e_info, dev);
|
add_error_device(e_info, dev);
|
||||||
goto added;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
/* If there is only a single error, stop iteration */
|
||||||
|
if (!e_info->multi_error_valid)
|
||||||
added:
|
|
||||||
if (e_info->multi_error_valid)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_source_device - search through device hierarchy for source device
|
* find_source_device - search through device hierarchy for source device
|
||||||
|
|||||||
Reference in New Issue
Block a user