|
@@ -2223,129 +2223,6 @@ void pci_disable_obff(struct pci_dev *dev)
|
|
|
}
|
|
|
EXPORT_SYMBOL(pci_disable_obff);
|
|
|
|
|
|
-/**
|
|
|
- * pci_ltr_supported - check whether a device supports LTR
|
|
|
- * @dev: PCI device
|
|
|
- *
|
|
|
- * RETURNS:
|
|
|
- * True if @dev supports latency tolerance reporting, false otherwise.
|
|
|
- */
|
|
|
-static bool pci_ltr_supported(struct pci_dev *dev)
|
|
|
-{
|
|
|
- u32 cap;
|
|
|
-
|
|
|
- pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
|
|
|
-
|
|
|
- return cap & PCI_EXP_DEVCAP2_LTR;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * pci_enable_ltr - enable latency tolerance reporting
|
|
|
- * @dev: PCI device
|
|
|
- *
|
|
|
- * Enable LTR on @dev if possible, which means enabling it first on
|
|
|
- * upstream ports.
|
|
|
- *
|
|
|
- * RETURNS:
|
|
|
- * Zero on success, errno on failure.
|
|
|
- */
|
|
|
-int pci_enable_ltr(struct pci_dev *dev)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
- /* Only primary function can enable/disable LTR */
|
|
|
- if (PCI_FUNC(dev->devfn) != 0)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (!pci_ltr_supported(dev))
|
|
|
- return -ENOTSUPP;
|
|
|
-
|
|
|
- /* Enable upstream ports first */
|
|
|
- if (dev->bus->self) {
|
|
|
- ret = pci_enable_ltr(dev->bus->self);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- return pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
|
|
|
- PCI_EXP_DEVCTL2_LTR_EN);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(pci_enable_ltr);
|
|
|
-
|
|
|
-/**
|
|
|
- * pci_disable_ltr - disable latency tolerance reporting
|
|
|
- * @dev: PCI device
|
|
|
- */
|
|
|
-void pci_disable_ltr(struct pci_dev *dev)
|
|
|
-{
|
|
|
- /* Only primary function can enable/disable LTR */
|
|
|
- if (PCI_FUNC(dev->devfn) != 0)
|
|
|
- return;
|
|
|
-
|
|
|
- if (!pci_ltr_supported(dev))
|
|
|
- return;
|
|
|
-
|
|
|
- pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2,
|
|
|
- PCI_EXP_DEVCTL2_LTR_EN);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(pci_disable_ltr);
|
|
|
-
|
|
|
-static int __pci_ltr_scale(int *val)
|
|
|
-{
|
|
|
- int scale = 0;
|
|
|
-
|
|
|
- while (*val > 1023) {
|
|
|
- *val = (*val + 31) / 32;
|
|
|
- scale++;
|
|
|
- }
|
|
|
- return scale;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * pci_set_ltr - set LTR latency values
|
|
|
- * @dev: PCI device
|
|
|
- * @snoop_lat_ns: snoop latency in nanoseconds
|
|
|
- * @nosnoop_lat_ns: nosnoop latency in nanoseconds
|
|
|
- *
|
|
|
- * Figure out the scale and set the LTR values accordingly.
|
|
|
- */
|
|
|
-int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns)
|
|
|
-{
|
|
|
- int pos, ret, snoop_scale, nosnoop_scale;
|
|
|
- u16 val;
|
|
|
-
|
|
|
- if (!pci_ltr_supported(dev))
|
|
|
- return -ENOTSUPP;
|
|
|
-
|
|
|
- snoop_scale = __pci_ltr_scale(&snoop_lat_ns);
|
|
|
- nosnoop_scale = __pci_ltr_scale(&nosnoop_lat_ns);
|
|
|
-
|
|
|
- if (snoop_lat_ns > PCI_LTR_VALUE_MASK ||
|
|
|
- nosnoop_lat_ns > PCI_LTR_VALUE_MASK)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if ((snoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)) ||
|
|
|
- (nosnoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
|
|
|
- if (!pos)
|
|
|
- return -ENOTSUPP;
|
|
|
-
|
|
|
- val = (snoop_scale << PCI_LTR_SCALE_SHIFT) | snoop_lat_ns;
|
|
|
- ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_SNOOP_LAT, val);
|
|
|
- if (ret != 4)
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- val = (nosnoop_scale << PCI_LTR_SCALE_SHIFT) | nosnoop_lat_ns;
|
|
|
- ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_NOSNOOP_LAT, val);
|
|
|
- if (ret != 4)
|
|
|
- return -EIO;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(pci_set_ltr);
|
|
|
-
|
|
|
static int pci_acs_enable;
|
|
|
|
|
|
/**
|