Commit 73c47dde authored by Logan Gunthorpe's avatar Logan Gunthorpe Committed by Bjorn Helgaas

PCI: Add device-specific ACS Redirect disable infrastructure

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: default avatarLogan 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: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 3b269185
...@@ -3023,6 +3023,9 @@ static void pci_disable_acs_redir(struct pci_dev *dev) ...@@ -3023,6 +3023,9 @@ static void pci_disable_acs_redir(struct pci_dev *dev)
if (ret != 1) if (ret != 1)
return; return;
if (!pci_dev_specific_disable_acs_redir(dev))
return;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
if (!pos) { if (!pos) {
pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n"); pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n");
......
...@@ -355,6 +355,7 @@ void pci_enable_acs(struct pci_dev *dev); ...@@ -355,6 +355,7 @@ void pci_enable_acs(struct pci_dev *dev);
#ifdef CONFIG_PCI_QUIRKS #ifdef CONFIG_PCI_QUIRKS
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags); 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_enable_acs(struct pci_dev *dev);
int pci_dev_specific_disable_acs_redir(struct pci_dev *dev);
#else #else
static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev, static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
u16 acs_flags) u16 acs_flags)
...@@ -365,6 +366,10 @@ static inline int pci_dev_specific_enable_acs(struct pci_dev *dev) ...@@ -365,6 +366,10 @@ static inline int pci_dev_specific_enable_acs(struct pci_dev *dev)
{ {
return -ENOTTY; return -ENOTTY;
} }
static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
{
return -ENOTTY;
}
#endif #endif
/* PCI error reporting and recovery */ /* PCI error reporting and recovery */
......
...@@ -4553,26 +4553,32 @@ static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev) ...@@ -4553,26 +4553,32 @@ static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev)
return 0; return 0;
} }
static const struct pci_dev_enable_acs { static const struct pci_dev_acs_ops {
u16 vendor; u16 vendor;
u16 device; u16 device;
int (*enable_acs)(struct pci_dev *dev); int (*enable_acs)(struct pci_dev *dev);
} pci_dev_enable_acs[] = { int (*disable_acs_redir)(struct pci_dev *dev);
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs }, } pci_dev_acs_ops[] = {
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_spt_pch_acs }, { 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) 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; int i, ret;
for (i = 0; i < ARRAY_SIZE(pci_dev_enable_acs); i++) { for (i = 0; i < ARRAY_SIZE(pci_dev_acs_ops); i++) {
p = &pci_dev_enable_acs[i]; p = &pci_dev_acs_ops[i];
if ((p->vendor == dev->vendor || if ((p->vendor == dev->vendor ||
p->vendor == (u16)PCI_ANY_ID) && p->vendor == (u16)PCI_ANY_ID) &&
(p->device == dev->device || (p->device == dev->device ||
p->device == (u16)PCI_ANY_ID)) { p->device == (u16)PCI_ANY_ID) &&
p->enable_acs) {
ret = p->enable_acs(dev); ret = p->enable_acs(dev);
if (ret >= 0) if (ret >= 0)
return ret; return ret;
...@@ -4582,6 +4588,27 @@ int pci_dev_specific_enable_acs(struct pci_dev *dev) ...@@ -4582,6 +4588,27 @@ int pci_dev_specific_enable_acs(struct pci_dev *dev)
return -ENOTTY; 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 * The PCI capabilities list for Intel DH895xCC VFs (device ID 0x0443) with
* QuickAssist Technology (QAT) is prematurely terminated in hardware. The * QuickAssist Technology (QAT) is prematurely terminated in hardware. The
......
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