static int find_device_iter(struct pci_dev *dev, void *data) { int pos; u32 status; u32 mask; u16 reg16; 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 * reported by root port. */ if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { result = compare_device_id(dev, e_info); if (result) add_error_device(e_info, dev); /* * If there is no multiple error, we stop * or continue based on the id comparing. */ if (!e_info->multi_error_valid) return result; /* * 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; } /* * When either * 1) nosourceid==y; * 2) 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; * We check AER status registers to find the initial reporter. */ if (atomic_read(&dev->enable_cnt) == 0) return 0; pos = pci_pcie_cap(dev); if (!pos) return 0; /* Check if AER is enabled */ pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); if (!(reg16 & ( PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE))) return 0; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos) return 0; status = 0; mask = 0; 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_MASK, &mask); if (status & ~mask) { add_error_device(e_info, dev); goto added; } } else { pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask); if (status & ~mask) { add_error_device(e_info, dev); goto added; } } return 0; added: if (e_info->multi_error_valid) return 0; else return 1; }
static int find_device_iter(struct pci_dev *dev, void *data) { int pos; u32 status; u32 mask; u16 reg16; int result; struct aer_err_info *e_info = (struct aer_err_info *)data; if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { result = compare_device_id(dev, e_info); if (result) add_error_device(e_info, dev); if (!e_info->multi_error_valid) return result; if (result) return 0; } if (atomic_read(&dev->enable_cnt) == 0) return 0; pos = pci_find_capability(dev, PCI_CAP_ID_EXP); if (!pos) return 0; pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); if (!(reg16 & ( PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE))) return 0; pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos) return 0; status = 0; mask = 0; 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_MASK, &mask); if (status & ~mask) { add_error_device(e_info, dev); goto added; } } else { pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask); if (status & ~mask) { add_error_device(e_info, dev); goto added; } } return 0; added: if (e_info->multi_error_valid) return 0; else return 1; }