PCI: Add device-specific PCI ACS enable
Some devices support PCI ACS-like features, but don't report it using the standard PCIe capabilities. We already provide hooks for device-specific testing of ACS, but not for device-specific enabling of ACS. This provides that setup hook. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:

committed by
Bjorn Helgaas

parent
38dbfb59d1
commit
2c74424470
@@ -2180,21 +2180,18 @@ void pci_request_acs(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pci_enable_acs - enable ACS if hardware support it
|
* pci_std_enable_acs - enable ACS on devices using standard ACS capabilites
|
||||||
* @dev: the PCI device
|
* @dev: the PCI device
|
||||||
*/
|
*/
|
||||||
void pci_enable_acs(struct pci_dev *dev)
|
static int pci_std_enable_acs(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
u16 cap;
|
u16 cap;
|
||||||
u16 ctrl;
|
u16 ctrl;
|
||||||
|
|
||||||
if (!pci_acs_enable)
|
|
||||||
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)
|
||||||
return;
|
return -ENODEV;
|
||||||
|
|
||||||
pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
|
pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
|
||||||
pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
|
pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
|
||||||
@@ -2212,6 +2209,23 @@ void pci_enable_acs(struct pci_dev *dev)
|
|||||||
ctrl |= (cap & PCI_ACS_UF);
|
ctrl |= (cap & PCI_ACS_UF);
|
||||||
|
|
||||||
pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
|
pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pci_enable_acs - enable ACS if hardware support it
|
||||||
|
* @dev: the PCI device
|
||||||
|
*/
|
||||||
|
void pci_enable_acs(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
if (!pci_acs_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!pci_std_enable_acs(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pci_dev_specific_enable_acs(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
|
static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
|
||||||
|
@@ -3461,3 +3461,28 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
|
|||||||
|
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct pci_dev_enable_acs {
|
||||||
|
u16 vendor;
|
||||||
|
u16 device;
|
||||||
|
int (*enable_acs)(struct pci_dev *dev);
|
||||||
|
} pci_dev_enable_acs[] = {
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
void pci_dev_specific_enable_acs(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
const struct pci_dev_enable_acs *i;
|
||||||
|
int 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);
|
||||||
|
if (ret >= 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1510,6 +1510,7 @@ enum pci_fixup_pass {
|
|||||||
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
|
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
|
||||||
struct pci_dev *pci_get_dma_source(struct pci_dev *dev);
|
struct pci_dev *pci_get_dma_source(struct pci_dev *dev);
|
||||||
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);
|
||||||
|
void pci_dev_specific_enable_acs(struct pci_dev *dev);
|
||||||
#else
|
#else
|
||||||
static inline void pci_fixup_device(enum pci_fixup_pass pass,
|
static inline void pci_fixup_device(enum pci_fixup_pass pass,
|
||||||
struct pci_dev *dev) { }
|
struct pci_dev *dev) { }
|
||||||
@@ -1522,6 +1523,7 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
|
|||||||
{
|
{
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
static inline void pci_dev_specific_enable_acs(struct pci_dev *dev) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
|
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
|
||||||
|
Reference in New Issue
Block a user