[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 2/4 v2] PCI: support ARI capability



Support Alternative Routing-ID Interpretation (ARI), which increases the number 
of functions that can be supported by a PCIe endpoint. ARI is required by 
SR-IOV.

PCI-SIG ARI specification can be found at 
http://www.pcisig.com/specifications/pciexpress/specifications/ECN-alt-rid-interpretation-070604.pdf

Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>

---
 drivers/pci/Kconfig      |    7 ++++
 drivers/pci/Makefile     |    2 +
 drivers/pci/ari.c        |   71 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.h        |    8 +++++
 drivers/pci/probe.c      |    3 ++
 include/linux/pci.h      |   25 ++++++++++++++++
 include/linux/pci_regs.h |   14 +++++++++
 7 files changed, 130 insertions(+), 0 deletions(-)
 create mode 100644 drivers/pci/ari.c

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index e1ca425..f43cc46 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -50,3 +50,10 @@ config HT_IRQ
           This allows native hypertransport devices to use interrupts.
 
           If unsure say Y.
+
+config PCI_ARI
+       bool "PCI ARI support"
+       depends on PCI
+       default n
+       help
+         This enables PCI Alternative Routing-ID Interpretation.
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 7d63f8c..96f2767 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -53,3 +53,5 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
 ifeq ($(CONFIG_PCI_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
+
+obj-$(CONFIG_PCI_ARI) += ari.o
diff --git a/drivers/pci/ari.c b/drivers/pci/ari.c
new file mode 100644
index 0000000..3f1a47a
--- /dev/null
+++ b/drivers/pci/ari.c
@@ -0,0 +1,71 @@
+/*
+ * drivers/pci/ari.c
+ *
+ * Copyright (C) 2008 Intel Corporation, Yu Zhao <yu.zhao@xxxxxxxxx>
+ *
+ * PCI Express Alternative Routing-ID Interpretation capability support.
+ */
+
+#include <linux/pci.h>
+
+#include "pci.h"
+
+/**
+ * pci_ari_enable_fwd - enable ARI forwarding
+ * @dev: the PCI device
+ */
+void pci_ari_enable_fwd(struct pci_dev *dev)
+{
+       int pos;
+       u32 cap;
+       u16 ctrl;
+
+       if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+           dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM &&
+           dev->ari_enabled)
+               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;
+
+       dev->ari_enabled = 1;
+       dev_info(&dev->dev, "ARI forwarding enabled.\n");
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+       if (ctrl & PCI_EXP_DEVCTL2_ARI)
+               return;
+
+       ctrl |= PCI_EXP_DEVCTL2_ARI;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+}
+
+/**
+ * pci_ari_next_fn - find next function number
+ * @dev: the PCI device
+ *
+ * Returns function number, or 0 if there are no higher numbered
+ * functions; returns negative on failure.
+ */
+int pci_ari_next_fn(struct pci_dev *dev)
+{
+       int pos;
+       u16 cap;
+
+       if (dev->pcie_type != PCI_EXP_TYPE_ENDPOINT)
+               return -EINVAL;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
+
+       return PCI_ARI_CAP_NFN(cap);
+}
+EXPORT_SYMBOL_GPL(pci_ari_next_fn);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 5abd69c..720a607 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -147,3 +147,11 @@ struct pci_slot_attribute {
 extern int pci_resource_alignment(struct pci_dev *dev, int resno);
 extern int pci_resource_bar(struct pci_dev *dev, int resno,
                            enum pci_bar_type *type);
+
+#ifdef CONFIG_PCI_ARI
+extern void pci_ari_enable_fwd(struct pci_dev *dev);
+#else
+static inline void pci_ari_enable_fwd(struct pci_dev *dev)
+{
+}
+#endif /* CONFIG_PCI_ARI */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 3994ea3..ad7ad35 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1059,6 +1059,9 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
        int func, nr = 0;
        int scan_all_fns;
 
+       if (bus->self)
+               pci_ari_enable_fwd(bus->self);
+
        scan_all_fns = pcibios_scan_all_fns(bus, devfn);
 
        for (func = 0; func < 8; func++, devfn++) {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 4b8018f..8ed7405 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -236,6 +236,7 @@ struct pci_dev {
        unsigned int    broken_parity_status:1; /* Device generates false 
positive parity */
        unsigned int    msi_enabled:1;
        unsigned int    msix_enabled:1;
+       unsigned int    ari_enabled:1;  /* ARI forwarding */
        unsigned int    is_managed:1;
        unsigned int    is_pcie:1;
        pci_dev_flags_t dev_flags;
@@ -1137,5 +1138,29 @@ static inline void pci_mmcfg_early_init(void) { }
 static inline void pci_mmcfg_late_init(void) { }
 #endif
 
+#ifdef CONFIG_PCI_ARI
+/**
+ * pci_ari_fwd_enabled - query ARI forwarding status
+ * @dev: the PCI device
+ *
+ * Returns 1 if ARI forwarding is enabled, or 0 if not enabled;
+ * returns negative on failure.
+ */
+static inline int pci_ari_fwd_enabled(struct pci_dev *dev)
+{
+       return dev->ari_enabled;
+}
+extern int pci_ari_next_fn(struct pci_dev *dev);
+#else
+static inline int pci_ari_fwd_enabled(struct pci_dev *dev)
+{
+       return -EIO;
+}
+static inline int pci_ari_next_fn(struct pci_dev *dev)
+{
+       return -EIO;
+}
+#endif /* CONFIG_PCI_ARI */
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 450684f..eb6686b 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -419,6 +419,10 @@
 #define  PCI_EXP_RTCTL_CRSSVE  0x10    /* CRS Software Visibility Enable */
 #define PCI_EXP_RTCAP          30      /* Root Capabilities */
 #define PCI_EXP_RTSTA          32      /* Root Status */
+#define PCI_EXP_DEVCAP2                36      /* Device Capabilities 2 */
+#define  PCI_EXP_DEVCAP2_ARI   0x20    /* Alternative Routing-ID */
+#define PCI_EXP_DEVCTL2                40      /* Device Control 2 */
+#define  PCI_EXP_DEVCTL2_ARI   0x20    /* Alternative Routing-ID */
 
 /* Extended Capabilities (PCI-X 2.0 and Express) */
 #define PCI_EXT_CAP_ID(header)         (header & 0x0000ffff)
@@ -429,6 +433,7 @@
 #define PCI_EXT_CAP_ID_VC      2
 #define PCI_EXT_CAP_ID_DSN     3
 #define PCI_EXT_CAP_ID_PWR     4
+#define PCI_EXT_CAP_ID_ARI     14
 
 /* Advanced Error Reporting */
 #define PCI_ERR_UNCOR_STATUS   4       /* Uncorrectable Error Status */
@@ -536,5 +541,14 @@
 #define HT_CAPTYPE_GEN3                0xD0    /* Generation 3 hypertransport 
configuration */
 #define HT_CAPTYPE_PM          0xE0    /* Hypertransport powermanagement 
configuration */
 
+/* Alternative Routing-ID Interpretation */
+#define PCI_ARI_CAP            0x04    /* ARI Capability Register */
+#define  PCI_ARI_CAP_MFVC      0x0001  /* MFVC Function Groups Capability */
+#define  PCI_ARI_CAP_ACS       0x0002  /* ACS Function Groups Capability */
+#define  PCI_ARI_CAP_NFN(x)    (((x) >> 8) & 0xff) /* Next Function Number */
+#define PCI_ARI_CTRL           0x06    /* ARI Control Register */
+#define  PCI_ARI_CTRL_MFVC     0x0001  /* MFVC Function Groups Enable */
+#define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
+#define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
 
 #endif /* LINUX_PCI_REGS_H */
-- 
1.5.6.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.