]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI/AER: Remove HEST/FIRMWARE_FIRST parsing for AER ownership
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Tue, 26 May 2020 23:18:29 +0000 (16:18 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 1 Jun 2020 17:02:29 +0000 (12:02 -0500)
Commit c100beb9ccfb ("PCI/AER: Use only _OSC to determine AER ownership")
removed the use of HEST in determining AER ownership, but the AER driver
still used HEST to verify AER ownership in some of its APIs.

Per the ACPI spec v6.3, sec 18.3.2.4, some HEST table entries contain a
FIRMWARE_FIRST bit, but that bit does not tell us anything about ownership
of the AER capability.

Remove parsing of HEST to look for FIRMWARE_FIRST.

Add pcie_aer_is_native() for the places that need to know whether the OS
owns the AER capability.

[bhelgaas: commit log, reorder patch, remove unused __aer_firmware_first]
Link: https://lore.kernel.org/r/9a37f53a4e6ff4942ff8e18dbb20b00e16c47341.1590534843.git.sathyanarayanan.kuppuswamy@linux.intel.com
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pcie/aer.c
drivers/pci/pcie/dpc.c
drivers/pci/pcie/portdrv.h
include/linux/pci.h

index efc26773cc6ddb5fc6d68bddc2da556ef45ecd2e..803273ba30db398d401a71322f3d71d47e7cebc2 100644 (file)
@@ -217,118 +217,22 @@ void pcie_ecrc_get_policy(char *str)
 }
 #endif /* CONFIG_PCIE_ECRC */
 
-#ifdef CONFIG_ACPI_APEI
-static inline int hest_match_pci(struct acpi_hest_aer_common *p,
-                                struct pci_dev *pci)
-{
-       return   ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) &&
-                ACPI_HEST_BUS(p->bus)     == pci->bus->number &&
-                p->device                 == PCI_SLOT(pci->devfn) &&
-                p->function               == PCI_FUNC(pci->devfn);
-}
-
-static inline bool hest_match_type(struct acpi_hest_header *hest_hdr,
-                               struct pci_dev *dev)
-{
-       u16 hest_type = hest_hdr->type;
-       u8 pcie_type = pci_pcie_type(dev);
-
-       if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT &&
-               pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
-           (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT &&
-               pcie_type == PCI_EXP_TYPE_ENDPOINT) ||
-           (hest_type == ACPI_HEST_TYPE_AER_BRIDGE &&
-               (dev->class >> 16) == PCI_BASE_CLASS_BRIDGE))
-               return true;
-       return false;
-}
-
-struct aer_hest_parse_info {
-       struct pci_dev *pci_dev;
-       int firmware_first;
-};
-
-static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
-{
-       if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
-           hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
-           hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
-               return 1;
-       return 0;
-}
-
-static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
-{
-       struct aer_hest_parse_info *info = data;
-       struct acpi_hest_aer_common *p;
-       int ff;
-
-       if (!hest_source_is_pcie_aer(hest_hdr))
-               return 0;
-
-       p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
-       ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
-
-       /*
-        * If no specific device is supplied, determine whether
-        * FIRMWARE_FIRST is set for *any* PCIe device.
-        */
-       if (!info->pci_dev) {
-               info->firmware_first |= ff;
-               return 0;
-       }
-
-       /* Otherwise, check the specific device */
-       if (p->flags & ACPI_HEST_GLOBAL) {
-               if (hest_match_type(hest_hdr, info->pci_dev))
-                       info->firmware_first = ff;
-       } else
-               if (hest_match_pci(p, info->pci_dev))
-                       info->firmware_first = ff;
-
-       return 0;
-}
-
-static void aer_set_firmware_first(struct pci_dev *pci_dev)
-{
-       int rc;
-       struct aer_hest_parse_info info = {
-               .pci_dev        = pci_dev,
-               .firmware_first = 0,
-       };
-
-       rc = apei_hest_parse(aer_hest_parse, &info);
-
-       if (rc)
-               pci_dev->__aer_firmware_first = 0;
-       else
-               pci_dev->__aer_firmware_first = info.firmware_first;
-       pci_dev->__aer_firmware_first_valid = 1;
-}
+#define        PCI_EXP_AER_FLAGS       (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
+                                PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
 
-int pcie_aer_get_firmware_first(struct pci_dev *dev)
+int pcie_aer_is_native(struct pci_dev *dev)
 {
-       if (!pci_is_pcie(dev))
-               return 0;
+       struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
 
-       if (pcie_ports_native)
+       if (!dev->aer_cap)
                return 0;
 
-       if (!dev->__aer_firmware_first_valid)
-               aer_set_firmware_first(dev);
-       return dev->__aer_firmware_first;
+       return pcie_ports_native || host->native_aer;
 }
-#endif
-
-#define        PCI_EXP_AER_FLAGS       (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
-                                PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
 
 int pci_enable_pcie_error_reporting(struct pci_dev *dev)
 {
-       if (pcie_aer_get_firmware_first(dev))
-               return -EIO;
-
-       if (!dev->aer_cap)
+       if (!pcie_aer_is_native(dev))
                return -EIO;
 
        return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS);
@@ -337,7 +241,7 @@ EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
 
 int pci_disable_pcie_error_reporting(struct pci_dev *dev)
 {
-       if (pcie_aer_get_firmware_first(dev))
+       if (!pcie_aer_is_native(dev))
                return -EIO;
 
        return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
@@ -362,7 +266,7 @@ int pci_aer_clear_nonfatal_status(struct pci_dev *dev)
        if (!pos)
                return -EIO;
 
-       if (pcie_aer_get_firmware_first(dev))
+       if (!pcie_aer_is_native(dev))
                return -EIO;
 
        /* Clear status bits for ERR_NONFATAL errors only */
@@ -385,7 +289,7 @@ void pci_aer_clear_fatal_status(struct pci_dev *dev)
        if (!pos)
                return;
 
-       if (pcie_aer_get_firmware_first(dev))
+       if (!pcie_aer_is_native(dev))
                return;
 
        /* Clear status bits for ERR_FATAL errors only */
@@ -435,7 +339,7 @@ int pci_aer_raw_clear_status(struct pci_dev *dev)
 
 int pci_aer_clear_status(struct pci_dev *dev)
 {
-       if (pcie_aer_get_firmware_first(dev))
+       if (!pcie_aer_is_native(dev))
                return -EIO;
 
        return pci_aer_raw_clear_status(dev);
index 762170423fddae99333f95c1cb449d35f089b88d..0993d51abf0388810eb57daa02eb8a4e99e93fcc 100644 (file)
@@ -284,7 +284,7 @@ static int dpc_probe(struct pcie_device *dev)
        int status;
        u16 ctl, cap;
 
-       if (pcie_aer_get_firmware_first(pdev) && !pcie_ports_dpc_native)
+       if (!pcie_aer_is_native(pdev) && !pcie_ports_dpc_native)
                return -ENOTSUPP;
 
        status = devm_request_threaded_irq(device, dev->irq, dpc_irq,
index 64b5e081cdb29525dde1ec4b80b1179263bab31d..af7cf237432aca71c45bb4ce412e311872551817 100644 (file)
@@ -29,8 +29,10 @@ extern bool pcie_ports_dpc_native;
 
 #ifdef CONFIG_PCIEAER
 int pcie_aer_init(void);
+int pcie_aer_is_native(struct pci_dev *dev);
 #else
 static inline int pcie_aer_init(void) { return 0; }
+static inline int pcie_aer_is_native(struct pci_dev *dev) { return 0; }
 #endif
 
 #ifdef CONFIG_HOTPLUG_PCI_PCIE
@@ -147,16 +149,5 @@ static inline bool pcie_pme_no_msi(void) { return false; }
 static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
 #endif /* !CONFIG_PCIE_PME */
 
-#ifdef CONFIG_ACPI_APEI
-int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
-#else
-static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
-{
-       if (pci_dev->__aer_firmware_first_valid)
-               return pci_dev->__aer_firmware_first;
-       return 0;
-}
-#endif
-
 struct device *pcie_port_find_device(struct pci_dev *dev, u32 service);
 #endif /* _PORTDRV_H_ */
index 83ce1cdf567618052c65a2609ea4b1bd70cfe2ab..43f265830eca56ecad56603589a02d967354960e 100644 (file)
@@ -420,8 +420,6 @@ struct pci_dev {
         * mappings to make sure they cannot access arbitrary memory.
         */
        unsigned int    untrusted:1;
-       unsigned int    __aer_firmware_first_valid:1;
-       unsigned int    __aer_firmware_first:1;
        unsigned int    broken_intx_masking:1;  /* INTx masking can't be used */
        unsigned int    io_window_1k:1;         /* Intel bridge 1K I/O windows */
        unsigned int    irq_managed:1;