Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 250090
b: refs/heads/master
c: 48a92a8
h: refs/heads/master
v: v3
  • Loading branch information
Jesse Barnes committed May 11, 2011
1 parent 4202602 commit 79e85ed
Show file tree
Hide file tree
Showing 4 changed files with 115 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: b48d4425b602f5f4978299474743dbea130d940d
refs/heads/master: 48a92a8179b3e677fac07db7bd109e68f020468c
92 changes: 92 additions & 0 deletions trunk/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1887,6 +1887,98 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type)
}
EXPORT_SYMBOL(pci_disable_ido);

/**
* pci_enable_obff - enable optimized buffer flush/fill
* @dev: PCI device
* @type: type of signaling to use
*
* Try to enable @type OBFF signaling on @dev. It will try using WAKE#
* signaling if possible, falling back to message signaling only if
* WAKE# isn't supported. @type should indicate whether the PCIe link
* be brought out of L0s or L1 to send the message. It should be either
* %PCI_EXP_OBFF_SIGNAL_ALWAYS or %PCI_OBFF_SIGNAL_L0.
*
* If your device can benefit from receiving all messages, even at the
* power cost of bringing the link back up from a low power state, use
* %PCI_EXP_OBFF_SIGNAL_ALWAYS. Otherwise, use %PCI_OBFF_SIGNAL_L0 (the
* preferred type).
*
* RETURNS:
* Zero on success, appropriate error number on failure.
*/
int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
{
int pos;
u32 cap;
u16 ctrl;
int ret;

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

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

pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
if (!(cap & PCI_EXP_OBFF_MASK))
return -ENOTSUPP; /* no OBFF support at all */

/* Make sure the topology supports OBFF as well */
if (dev->bus) {
ret = pci_enable_obff(dev->bus->self, type);
if (ret)
return ret;
}

pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
if (cap & PCI_EXP_OBFF_WAKE)
ctrl |= PCI_EXP_OBFF_WAKE_EN;
else {
switch (type) {
case PCI_EXP_OBFF_SIGNAL_L0:
if (!(ctrl & PCI_EXP_OBFF_WAKE_EN))
ctrl |= PCI_EXP_OBFF_MSGA_EN;
break;
case PCI_EXP_OBFF_SIGNAL_ALWAYS:
ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
ctrl |= PCI_EXP_OBFF_MSGB_EN;
break;
default:
WARN(1, "bad OBFF signal type\n");
return -ENOTSUPP;
}
}
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);

return 0;
}
EXPORT_SYMBOL(pci_enable_obff);

/**
* pci_disable_obff - disable optimized buffer flush/fill
* @dev: PCI device
*
* Disable OBFF on @dev.
*/
void pci_disable_obff(struct pci_dev *dev)
{
int pos;
u16 ctrl;

if (!pci_is_pcie(dev))
return;

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

pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
ctrl &= ~PCI_EXP_OBFF_WAKE_EN;
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
}
EXPORT_SYMBOL(pci_disable_obff);

static int pci_acs_enable;

/**
Expand Down
16 changes: 16 additions & 0 deletions trunk/include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,13 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
void pci_enable_ido(struct pci_dev *dev, unsigned long type);
void pci_disable_ido(struct pci_dev *dev, unsigned long type);

enum pci_obff_signal_type {
PCI_EXP_OBFF_SIGNAL_L0,
PCI_EXP_OBFF_SIGNAL_ALWAYS,
};
int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
void pci_disable_obff(struct pci_dev *dev);

/* 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 Expand Up @@ -1220,6 +1227,15 @@ static inline void pci_disable_ido(struct pci_dev *dev, unsigned long type)
{
}

static inline int pci_enable_obff(struct pci_dev *dev, unsigned long type)
{
return 0;
}

static inline void pci_disable_obff(struct pci_dev *dev)
{
}

static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
{
return -EIO;
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 @@ -508,10 +508,16 @@
#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_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_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 */
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */

Expand Down

0 comments on commit 79e85ed

Please sign in to comment.