Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 316470
b: refs/heads/master
c: c463b8c
h: refs/heads/master
v: v3
  • Loading branch information
Myron Stowe authored and Bjorn Helgaas committed Jun 12, 2012
1 parent 5bc9046 commit a352b45
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cb97ae3485955401d637bd269b0d24d3cd3fd3ec
refs/heads/master: c463b8cb9350cf1230cefe467a1cf279140a5437
65 changes: 50 additions & 15 deletions trunk/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
return pos;
}

/**
* pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure
* @dev: PCI device to check
*
* Like pci_pcie_cap() but also checks that the PCIe capability version is
* >= 2. Note that v1 capability structures could be sparse in that not
* all register fields were required. v2 requires the entire structure to
* be present size wise, while still allowing for non-implemented registers
* to exist but they must be hardwired to 0.
*
* Due to the differences in the versions of capability structures, one
* must be careful not to try and access non-existant registers that may
* exist in early versions - v1 - of Express devices.
*
* Returns the offset of the PCIe capability structure as long as the
* capability version is >= 2; otherwise 0 is returned.
*/
static int pci_pcie_cap2(struct pci_dev *dev)
{
u16 flags;
int pos;

pos = pci_pcie_cap(dev);
if (pos) {
pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
if ((flags & PCI_EXP_FLAGS_VERS) < 2)
pos = 0;
}

return pos;
}

/**
* pci_find_ext_capability - Find an extended capability
* @dev: PCI device to query
Expand Down Expand Up @@ -1983,7 +2015,7 @@ void pci_enable_ari(struct pci_dev *dev)
{
int pos;
u32 cap;
u16 flags, ctrl;
u16 ctrl;
struct pci_dev *bridge;

if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
Expand All @@ -1997,15 +2029,11 @@ void pci_enable_ari(struct pci_dev *dev)
if (!bridge)
return;

pos = pci_pcie_cap(bridge);
/* ARI is a PCIe cap v2 feature */
pos = pci_pcie_cap2(bridge);
if (!pos)
return;

/* ARI is a PCIe v2 feature */
pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags);
if ((flags & PCI_EXP_FLAGS_VERS) < 2)
return;

pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
if (!(cap & PCI_EXP_DEVCAP2_ARI))
return;
Expand All @@ -2018,7 +2046,7 @@ void pci_enable_ari(struct pci_dev *dev)
}

/**
* pci_enable_ido - enable ID-based ordering on a device
* pci_enable_ido - enable ID-based Ordering on a device
* @dev: the PCI device
* @type: which types of IDO to enable
*
Expand All @@ -2031,7 +2059,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type)
int pos;
u16 ctrl;

pos = pci_pcie_cap(dev);
/* ID-based Ordering is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;

Expand All @@ -2054,7 +2083,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type)
int pos;
u16 ctrl;

pos = pci_pcie_cap(dev);
/* ID-based Ordering is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;

Expand Down Expand Up @@ -2093,7 +2123,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
u16 ctrl;
int ret;

pos = pci_pcie_cap(dev);
/* OBFF is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return -ENOTSUPP;

Expand Down Expand Up @@ -2143,7 +2174,8 @@ void pci_disable_obff(struct pci_dev *dev)
int pos;
u16 ctrl;

pos = pci_pcie_cap(dev);
/* OBFF is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;

Expand All @@ -2165,7 +2197,8 @@ static bool pci_ltr_supported(struct pci_dev *dev)
int pos;
u32 cap;

pos = pci_pcie_cap(dev);
/* LTR is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return false;

Expand Down Expand Up @@ -2193,7 +2226,8 @@ int pci_enable_ltr(struct pci_dev *dev)
if (!pci_ltr_supported(dev))
return -ENOTSUPP;

pos = pci_pcie_cap(dev);
/* LTR is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return -ENOTSUPP;

Expand Down Expand Up @@ -2228,7 +2262,8 @@ void pci_disable_ltr(struct pci_dev *dev)
if (!pci_ltr_supported(dev))
return;

pos = pci_pcie_cap(dev);
/* LTR is a PCIe cap v2 feature */
pos = pci_pcie_cap2(dev);
if (!pos)
return;

Expand Down
6 changes: 6 additions & 0 deletions trunk/include/linux/pci_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,12 @@
#define PCI_EXP_RTSTA 32 /* Root Status */
#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */
#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */
/*
* Note that the following PCI Express 'Capability Structure' registers
* were introduced with 'Capability Version' 0x2 (v2). These registers
* do not exist on devices with Capability Version 1. Use pci_pcie_cap2()
* to use these fields safely.
*/
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */
#define PCI_EXP_DEVCAP2_LTR 0x800 /* Latency tolerance reporting */
Expand Down

0 comments on commit a352b45

Please sign in to comment.