Commit 5a20930f authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/err'

- Recognize disconnected devices so we don't bother trying to set them to
  "frozen" or "normal" state (Christoph Hellwig)

- Clear PCI Status register during enumeration in case firmware left errors
  logged (Kai-Heng Feng)

- Configure ECRC for every device, including hot-added ones (Stefan Roese)

- Keep AER error reporting enabled for switches (Stefan Roese)

- Enable error reporting for all devices that support AER (Stefan Roese)

- Iterate over error counters instead of error strings to avoid printing
  junk in AER sysfs counters (Mohamed Khalfella)

* pci/err:
  PCI/AER: Iterate over error counters instead of error strings
  PCI/AER: Enable error reporting when AER is native
  PCI/portdrv: Don't disable AER reporting in get_port_device_capability()
  PCI/AER: Configure ECRC for every device
  PCI: Clear PCI_STATUS when setting up device
  PCI/ERR: Recognize disconnected devices in report_error_detected()
parents dc525311 5e6ae050
...@@ -392,6 +392,11 @@ void pci_aer_init(struct pci_dev *dev) ...@@ -392,6 +392,11 @@ void pci_aer_init(struct pci_dev *dev)
pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_ERR, sizeof(u32) * n); pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_ERR, sizeof(u32) * n);
pci_aer_clear_status(dev); pci_aer_clear_status(dev);
if (pci_aer_available())
pci_enable_pcie_error_reporting(dev);
pcie_set_ecrc_checking(dev);
} }
void pci_aer_exit(struct pci_dev *dev) void pci_aer_exit(struct pci_dev *dev)
...@@ -538,7 +543,7 @@ static const char *aer_agent_string[] = { ...@@ -538,7 +543,7 @@ static const char *aer_agent_string[] = {
u64 *stats = pdev->aer_stats->stats_array; \ u64 *stats = pdev->aer_stats->stats_array; \
size_t len = 0; \ size_t len = 0; \
\ \
for (i = 0; i < ARRAY_SIZE(strings_array); i++) { \ for (i = 0; i < ARRAY_SIZE(pdev->aer_stats->stats_array); i++) {\
if (strings_array[i]) \ if (strings_array[i]) \
len += sysfs_emit_at(buf, len, "%s %llu\n", \ len += sysfs_emit_at(buf, len, "%s %llu\n", \
strings_array[i], \ strings_array[i], \
...@@ -1228,9 +1233,6 @@ static int set_device_error_reporting(struct pci_dev *dev, void *data) ...@@ -1228,9 +1233,6 @@ static int set_device_error_reporting(struct pci_dev *dev, void *data)
pci_disable_pcie_error_reporting(dev); pci_disable_pcie_error_reporting(dev);
} }
if (enable)
pcie_set_ecrc_checking(dev);
return 0; return 0;
} }
...@@ -1347,6 +1349,11 @@ static int aer_probe(struct pcie_device *dev) ...@@ -1347,6 +1349,11 @@ static int aer_probe(struct pcie_device *dev)
struct device *device = &dev->device; struct device *device = &dev->device;
struct pci_dev *port = dev->port; struct pci_dev *port = dev->port;
BUILD_BUG_ON(ARRAY_SIZE(aer_correctable_error_string) <
AER_MAX_TYPEOF_COR_ERRS);
BUILD_BUG_ON(ARRAY_SIZE(aer_uncorrectable_error_string) <
AER_MAX_TYPEOF_UNCOR_ERRS);
/* Limit to Root Ports or Root Complex Event Collectors */ /* Limit to Root Ports or Root Complex Event Collectors */
if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) && if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) &&
(pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT)) (pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT))
......
...@@ -55,10 +55,14 @@ static int report_error_detected(struct pci_dev *dev, ...@@ -55,10 +55,14 @@ static int report_error_detected(struct pci_dev *dev,
device_lock(&dev->dev); device_lock(&dev->dev);
pdrv = dev->driver; pdrv = dev->driver;
if (!pci_dev_set_io_state(dev, state) || if (pci_dev_is_disconnected(dev)) {
!pdrv || vote = PCI_ERS_RESULT_DISCONNECT;
!pdrv->err_handler || } else if (!pci_dev_set_io_state(dev, state)) {
!pdrv->err_handler->error_detected) { pci_info(dev, "can't recover (state transition %u -> %u invalid)\n",
dev->error_state, state);
vote = PCI_ERS_RESULT_NONE;
} else if (!pdrv || !pdrv->err_handler ||
!pdrv->err_handler->error_detected) {
/* /*
* If any device in the subtree does not have an error_detected * If any device in the subtree does not have an error_detected
* callback, PCI_ERS_RESULT_NO_AER_DRIVER prevents subsequent * callback, PCI_ERS_RESULT_NO_AER_DRIVER prevents subsequent
......
...@@ -222,15 +222,8 @@ static int get_port_device_capability(struct pci_dev *dev) ...@@ -222,15 +222,8 @@ static int get_port_device_capability(struct pci_dev *dev)
#ifdef CONFIG_PCIEAER #ifdef CONFIG_PCIEAER
if (dev->aer_cap && pci_aer_available() && if (dev->aer_cap && pci_aer_available() &&
(pcie_ports_native || host->native_aer)) { (pcie_ports_native || host->native_aer))
services |= PCIE_PORT_SERVICE_AER; services |= PCIE_PORT_SERVICE_AER;
/*
* Disable AER on this port in case it's been enabled by the
* BIOS (the AER service driver will enable it when necessary).
*/
pci_disable_pcie_error_reporting(dev);
}
#endif #endif
/* Root Ports and Root Complex Event Collectors may generate PMEs */ /* Root Ports and Root Complex Event Collectors may generate PMEs */
......
...@@ -1890,6 +1890,9 @@ int pci_setup_device(struct pci_dev *dev) ...@@ -1890,6 +1890,9 @@ int pci_setup_device(struct pci_dev *dev)
dev->broken_intx_masking = pci_intx_mask_broken(dev); dev->broken_intx_masking = pci_intx_mask_broken(dev);
/* Clear errors left from system firmware */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
switch (dev->hdr_type) { /* header type */ switch (dev->hdr_type) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */ case PCI_HEADER_TYPE_NORMAL: /* standard header */
if (class == PCI_CLASS_BRIDGE_PCI) if (class == PCI_CLASS_BRIDGE_PCI)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment