Skip to content
/ linux Public

Commit 7611479

Browse files
l1kSasha Levin
authored andcommitted
PCI/AER: Clear stale errors on reporting agents upon probe
[ Upstream commit e242d09 ] Correctable and Uncorrectable Error Status Registers on reporting agents are cleared upon PCI device enumeration in pci_aer_init() to flush past events. They're cleared again when an error is handled by the AER driver. If an agent reports a new error after pci_aer_init() and before the AER driver has probed on the corresponding Root Port or Root Complex Event Collector, that error is not handled by the AER driver: It clears the Root Error Status Register on probe, but neglects to re-clear the Correctable and Uncorrectable Error Status Registers on reporting agents. The error will eventually be reported when another error occurs. Which is irritating because to an end user it appears as if the earlier error has just happened. Amend the AER driver to clear stale errors on reporting agents upon probe. Skip reporting agents which have not invoked pci_aer_init() yet to avoid using an uninitialized pdev->aer_cap. They're recognizable by the error bits in the Device Control register still being clear. Reporting agents may execute pci_aer_init() after the AER driver has probed, particularly when devices are hotplugged or removed/rescanned via sysfs. For this reason, it continues to be necessary that pci_aer_init() clears Correctable and Uncorrectable Error Status Registers. Reported-by: Lucas Van <lucas.van@intel.com> # off-list Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: Lucas Van <lucas.van@intel.com> Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://patch.msgid.link/3011c2ed30c11f858e35e29939add754adea7478.1769332702.git.lukas@wunner.de Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent da6b1bf commit 7611479

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

drivers/pci/pcie/aer.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,20 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev,
12591259

12601260
}
12611261

1262+
static int clear_status_iter(struct pci_dev *dev, void *data)
1263+
{
1264+
u16 devctl;
1265+
1266+
/* Skip if pci_enable_pcie_error_reporting() hasn't been called yet */
1267+
pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &devctl);
1268+
if (!(devctl & PCI_EXP_AER_FLAGS))
1269+
return 0;
1270+
1271+
pci_aer_clear_status(dev);
1272+
pcie_clear_device_status(dev);
1273+
return 0;
1274+
}
1275+
12621276
/**
12631277
* aer_enable_rootport - enable Root Port's interrupts when receiving messages
12641278
* @rpc: pointer to a Root Port data structure
@@ -1280,9 +1294,19 @@ static void aer_enable_rootport(struct aer_rpc *rpc)
12801294
pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
12811295
SYSTEM_ERROR_INTR_ON_MESG_MASK);
12821296

1283-
/* Clear error status */
1297+
/* Clear error status of this Root Port or RCEC */
12841298
pci_read_config_dword(pdev, aer + PCI_ERR_ROOT_STATUS, &reg32);
12851299
pci_write_config_dword(pdev, aer + PCI_ERR_ROOT_STATUS, reg32);
1300+
1301+
/* Clear error status of agents reporting to this Root Port or RCEC */
1302+
if (reg32 & AER_ERR_STATUS_MASK) {
1303+
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_EC)
1304+
pcie_walk_rcec(pdev, clear_status_iter, NULL);
1305+
else if (pdev->subordinate)
1306+
pci_walk_bus(pdev->subordinate, clear_status_iter,
1307+
NULL);
1308+
}
1309+
12861310
pci_read_config_dword(pdev, aer + PCI_ERR_COR_STATUS, &reg32);
12871311
pci_write_config_dword(pdev, aer + PCI_ERR_COR_STATUS, reg32);
12881312
pci_read_config_dword(pdev, aer + PCI_ERR_UNCOR_STATUS, &reg32);

0 commit comments

Comments
 (0)