Merge branch 'pci/peer-to-peer'
- Add "pci=disable_acs_redir=" parameter to disable ACS redirection for peer-to-peer DMA support (we don't have the peer-to-peer support yet; this is just one piece) (Logan Gunthorpe) * pci/peer-to-peer: PCI: Add ACS Redirect disable quirk for Intel Sunrise Point PCI: Add device-specific ACS Redirect disable infrastructure PCI: Convert device-specific ACS quirks from NULL termination to ARRAY_SIZE PCI: Add "pci=disable_acs_redir=" parameter for peer-to-peer support PCI: Allow specifying devices using a base bus and path of devfns PCI: Make specifying PCI devices in kernel parameters reusable PCI: Hide ACS quirk declarations inside PCI core
This commit is contained in:
@@ -4555,27 +4555,79 @@ static int pci_quirk_enable_intel_spt_pch_acs(struct pci_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pci_dev_enable_acs {
|
||||
static int pci_quirk_disable_intel_spt_pch_acs_redir(struct pci_dev *dev)
|
||||
{
|
||||
int pos;
|
||||
u32 cap, ctrl;
|
||||
|
||||
if (!pci_quirk_intel_spt_pch_acs_match(dev))
|
||||
return -ENOTTY;
|
||||
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
|
||||
if (!pos)
|
||||
return -ENOTTY;
|
||||
|
||||
pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap);
|
||||
pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl);
|
||||
|
||||
ctrl &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC);
|
||||
|
||||
pci_write_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, ctrl);
|
||||
|
||||
pci_info(dev, "Intel SPT PCH root port workaround: disabled ACS redirect\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 },
|
||||
{ 0 }
|
||||
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,
|
||||
.disable_acs_redir = pci_quirk_disable_intel_spt_pch_acs_redir,
|
||||
},
|
||||
};
|
||||
|
||||
int pci_dev_specific_enable_acs(struct pci_dev *dev)
|
||||
{
|
||||
const struct pci_dev_enable_acs *i;
|
||||
int ret;
|
||||
const struct pci_dev_acs_ops *p;
|
||||
int i, ret;
|
||||
|
||||
for (i = pci_dev_enable_acs; i->enable_acs; i++) {
|
||||
if ((i->vendor == dev->vendor ||
|
||||
i->vendor == (u16)PCI_ANY_ID) &&
|
||||
(i->device == dev->device ||
|
||||
i->device == (u16)PCI_ANY_ID)) {
|
||||
ret = i->enable_acs(dev);
|
||||
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->enable_acs) {
|
||||
ret = p->enable_acs(dev);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user