Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 250091
b: refs/heads/master
c: 51c2e0a
h: refs/heads/master
i:
  250089: 4202602
  250087: cab158d
v: v3
  • Loading branch information
Jesse Barnes committed May 11, 2011
1 parent 79e85ed commit 5a3b24c
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 48a92a8179b3e677fac07db7bd109e68f020468c
refs/heads/master: 51c2e0a7e5bc7ed1384cc68cfb95e702571500c9
149 changes: 149 additions & 0 deletions trunk/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1979,6 +1979,155 @@ 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.
*/
bool pci_ltr_supported(struct pci_dev *dev)
{
int pos;
u32 cap;

if (!pci_is_pcie(dev))
return false;

pos = pci_pcie_cap(dev);
if (!pos)
return false;

pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);

return cap & PCI_EXP_DEVCAP2_LTR;
}
EXPORT_SYMBOL(pci_ltr_supported);

/**
* 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 pos;
u16 ctrl;
int ret;

if (!pci_ltr_supported(dev))
return -ENOTSUPP;

pos = pci_pcie_cap(dev);
if (!pos)
return -ENOTSUPP;

/* Only primary function can enable/disable LTR */
if (PCI_FUNC(dev->devfn) != 0)
return -EINVAL;

/* Enable upstream ports first */
if (dev->bus) {
ret = pci_enable_ltr(dev->bus->self);
if (ret)
return ret;
}

pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
ctrl |= PCI_EXP_LTR_EN;
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);

return 0;
}
EXPORT_SYMBOL(pci_enable_ltr);

/**
* pci_disable_ltr - disable latency tolerance reporting
* @dev: PCI device
*/
void pci_disable_ltr(struct pci_dev *dev)
{
int pos;
u16 ctrl;

if (!pci_ltr_supported(dev))
return;

pos = pci_pcie_cap(dev);
if (!pos)
return;

/* Only primary function can enable/disable LTR */
if (PCI_FUNC(dev->devfn) != 0)
return;

pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
ctrl &= ~PCI_EXP_LTR_EN;
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
}
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;

/**
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,11 @@ enum pci_obff_signal_type {
int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
void pci_disable_obff(struct pci_dev *dev);

bool pci_ltr_supported(struct pci_dev *dev);
int pci_enable_ltr(struct pci_dev *dev);
void pci_disable_ltr(struct pci_dev *dev);
int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns);

/* For use by arch with custom probe code */
void set_pcie_port_type(struct pci_dev *pdev);
void set_pcie_hotplug_bridge(struct pci_dev *pdev);
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/linux/pci_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,13 +508,15 @@
#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */
#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 */
#define PCI_EXP_OBFF_MASK 0xc0000 /* OBFF support mechanism */
#define PCI_EXP_OBFF_MSG 0x40000 /* New message signaling */
#define PCI_EXP_OBFF_WAKE 0x80000 /* Re-use WAKE# for OBFF */
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */
#define PCI_EXP_IDO_REQ_EN 0x100 /* ID-based ordering request enable */
#define PCI_EXP_IDO_CMP_EN 0x200 /* ID-based ordering completion enable */
#define PCI_EXP_LTR_EN 0x400 /* Latency tolerance reporting */
#define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */
#define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */
#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
Expand All @@ -535,6 +537,7 @@
#define PCI_EXT_CAP_ID_ARI 14
#define PCI_EXT_CAP_ID_ATS 15
#define PCI_EXT_CAP_ID_SRIOV 16
#define PCI_EXT_CAP_ID_LTR 24

/* Advanced Error Reporting */
#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
Expand Down Expand Up @@ -691,6 +694,12 @@
#define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */
#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */

#define PCI_LTR_MAX_SNOOP_LAT 0x4
#define PCI_LTR_MAX_NOSNOOP_LAT 0x6
#define PCI_LTR_VALUE_MASK 0x000003ff
#define PCI_LTR_SCALE_MASK 0x00001c00
#define PCI_LTR_SCALE_SHIFT 10

/* Access Control Service */
#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
#define PCI_ACS_SV 0x01 /* Source Validation */
Expand Down

0 comments on commit 5a3b24c

Please sign in to comment.