]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PCI: Add device-specific ACS Redirect disable infrastructure
authorLogan Gunthorpe <logang@deltatee.com>
Thu, 9 Aug 2018 21:51:43 +0000 (16:51 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Thu, 9 Aug 2018 22:48:28 +0000 (17:48 -0500)
Intel Sunrise Point (SPT) PCH hardware has an implementation of the ACS
bits that does not comply with the PCIe standard.  To deal with this we
need device-specific quirks to disable ACS redirection.

Add a new pci_dev_specific_disable_acs_redir() quirk and a new
.disable_acs_redir() function pointer for use by non-compliant devices.  No
functional change intended.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
[bhelgaas: split to separate patch, move
pci_dev_specific_disable_acs_redir() declarations to drivers/pci/pci.h]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/quirks.c

index 822577d9b39e8df035bf68107616fc841decb592..17d8de109556fe169fd880ef5ca9228ce7b7b030 100644 (file)
@@ -3023,6 +3023,9 @@ static void pci_disable_acs_redir(struct pci_dev *dev)
        if (ret != 1)
                return;
 
+       if (!pci_dev_specific_disable_acs_redir(dev))
+               return;
+
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
        if (!pos) {
                pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n");
index a1224fef3409d54ea23dd1cf3676e499afacb3c0..04f5035d12c63b71e684d7ca5bf7cf8d70f6453a 100644 (file)
@@ -355,6 +355,7 @@ void pci_enable_acs(struct pci_dev *dev);
 #ifdef CONFIG_PCI_QUIRKS
 int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
 int pci_dev_specific_enable_acs(struct pci_dev *dev);
+int pci_dev_specific_disable_acs_redir(struct pci_dev *dev);
 #else
 static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
                                               u16 acs_flags)
@@ -365,6 +366,10 @@ static inline int pci_dev_specific_enable_acs(struct pci_dev *dev)
 {
        return -ENOTTY;
 }
+static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
+{
+       return -ENOTTY;
+}
 #endif
 
 /* PCI error reporting and recovery */
index 823d8e4b4b376f5725a331d92d5ac359c4773f9b..4f79631159eba8143f227bcbff1fd4290694ddff 100644 (file)
@@ -4553,26 +4553,32 @@ static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev)
        return 0;
 }
 
-static const struct pci_dev_enable_acs {
+static const struct pci_dev_acs_ops {
        u16 vendor;
        u16 device;
        int (*enable_acs)(struct pci_dev *dev);
-} pci_dev_enable_acs[] = {
-       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs },
-       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_spt_pch_acs },
+       int (*disable_acs_redir)(struct pci_dev *dev);
+} pci_dev_acs_ops[] = {
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+           .enable_acs = pci_quirk_enable_intel_pch_acs,
+       },
+       { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+           .enable_acs = pci_quirk_enable_intel_spt_pch_acs,
+       },
 };
 
 int pci_dev_specific_enable_acs(struct pci_dev *dev)
 {
-       const struct pci_dev_enable_acs *p;
+       const struct pci_dev_acs_ops *p;
        int i, ret;
 
-       for (i = 0; i < ARRAY_SIZE(pci_dev_enable_acs); i++) {
-               p = &pci_dev_enable_acs[i];
+       for (i = 0; i < ARRAY_SIZE(pci_dev_acs_ops); i++) {
+               p = &pci_dev_acs_ops[i];
                if ((p->vendor == dev->vendor ||
                     p->vendor == (u16)PCI_ANY_ID) &&
                    (p->device == dev->device ||
-                    p->device == (u16)PCI_ANY_ID)) {
+                    p->device == (u16)PCI_ANY_ID) &&
+                   p->enable_acs) {
                        ret = p->enable_acs(dev);
                        if (ret >= 0)
                                return ret;
@@ -4582,6 +4588,27 @@ int pci_dev_specific_enable_acs(struct pci_dev *dev)
        return -ENOTTY;
 }
 
+int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
+{
+       const struct pci_dev_acs_ops *p;
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(pci_dev_acs_ops); i++) {
+               p = &pci_dev_acs_ops[i];
+               if ((p->vendor == dev->vendor ||
+                    p->vendor == (u16)PCI_ANY_ID) &&
+                   (p->device == dev->device ||
+                    p->device == (u16)PCI_ANY_ID) &&
+                   p->disable_acs_redir) {
+                       ret = p->disable_acs_redir(dev);
+                       if (ret >= 0)
+                               return ret;
+               }
+       }
+
+       return -ENOTTY;
+}
+
 /*
  * The PCI capabilities list for Intel DH895xCC VFs (device ID 0x0443) with
  * QuickAssist Technology (QAT) is prematurely terminated in hardware.  The