diff options
author | Yu Zhao <yu.zhao@intel.com> | 2008-10-14 14:02:53 +0800 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-10-20 10:54:32 -0700 |
commit | 58c3a727cb73b75a9104d295f096cca12959a5a5 (patch) | |
tree | 70f1fe31f1ec12021777b6c6c49167356a864749 /drivers | |
parent | 201de56eb22f1ff3f36804bc70cbff220b50f067 (diff) | |
download | linux-3.10-58c3a727cb73b75a9104d295f096cca12959a5a5.tar.gz linux-3.10-58c3a727cb73b75a9104d295f096cca12959a5a5.tar.bz2 linux-3.10-58c3a727cb73b75a9104d295f096cca12959a5a5.zip |
PCI: support PCIe ARI capability
This patch adds support for PCI Express Alternative Routing-ID
Interpretation (ARI) capability.
The ARI capability extends the Function Number field of the PCI Express
Endpoint by reusing the Device Number which is otherwise hardwired to 0.
With ARI, an Endpoint can have up to 256 functions.
Signed-off-by: Yu Zhao <yu.zhao@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/pci.c | 32 | ||||
-rw-r--r-- | drivers/pci/pci.h | 12 | ||||
-rw-r--r-- | drivers/pci/probe.c | 3 |
3 files changed, 47 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 553ca665795..4db261e13e6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1299,6 +1299,38 @@ void pci_pm_init(struct pci_dev *dev) } } +/** + * pci_enable_ari - enable ARI forwarding if hardware support it + * @dev: the PCI device + */ +void pci_enable_ari(struct pci_dev *dev) +{ + int pos; + u32 cap; + u16 ctrl; + + if (!dev->is_pcie) + return; + + if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && + dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) + return; + + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return; + + pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); + if (!(cap & PCI_EXP_DEVCAP2_ARI)) + return; + + pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); + ctrl |= PCI_EXP_DEVCTL2_ARI; + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + + dev->ari_enabled = 1; +} + int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 601abdc8dd9..39684c1415c 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -151,4 +151,16 @@ struct pci_slot_attribute { }; #define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr) +extern void pci_enable_ari(struct pci_dev *dev); +/** + * pci_ari_enabled - query ARI forwarding status + * @dev: the PCI device + * + * Returns 1 if ARI forwarding is enabled, or 0 if not enabled; + */ +static inline int pci_ari_enabled(struct pci_dev *dev) +{ + return dev->ari_enabled; +} + #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8c158b9abd4..3141e8deeac 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1025,6 +1025,9 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Vital Product Data */ pci_vpd_pci22_init(dev); + + /* Alternative Routing-ID Forwarding */ + pci_enable_ari(dev); } void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) |