WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] PCI: initialize and release SR-IOV ca

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] PCI: initialize and release SR-IOV capability
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 18 Mar 2009 07:25:23 -0700
Delivery-date: Wed, 18 Mar 2009 07:27:08 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1237376344 0
# Node ID fb46e5625c614ac086e852e3633f29309378812f
# Parent  6669e480cb59e70767d835bbd0294ed5266692a9
PCI: initialize and release SR-IOV capability

If a device has the SR-IOV capability, initialize it (set the ARI
Capable Hierarchy in the lowest numbered PF if necessary; calculate
the System Page Size for the VF MMIO, probe the VF Offset, Stride
and BARs). A lock for the VF bus allocation is also initialized if
a PF is the lowest numbered PF.

Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx>
---
 drivers/pci/Kconfig      |    9 ++
 drivers/pci/Makefile     |    2 
 drivers/pci/iov.c        |  175 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.c        |    7 +
 drivers/pci/pci.h        |   37 +++++++++
 drivers/pci/probe.c      |    6 +
 include/linux/pci.h      |   14 +++
 include/linux/pci_regs.h |   33 ++++++++
 8 files changed, 282 insertions(+), 1 deletion(-)

diff -r 6669e480cb59 -r fb46e5625c61 drivers/pci/Kconfig
--- a/drivers/pci/Kconfig       Tue Mar 17 14:27:31 2009 +0000
+++ b/drivers/pci/Kconfig       Wed Mar 18 11:39:04 2009 +0000
@@ -37,3 +37,12 @@ config PCI_GUESTDEV
        help
          Say Y here if you want to reserve PCI device for passthrough.
 
+config PCI_IOV
+       bool "PCI IOV support"
+       depends on PCI
+       help
+         PCI-SIG I/O Virtualization (IOV) Specifications support.
+         Single Root IOV: allows the creation of virtual PCI devices
+         that share the physical resources from a real device.
+
+         When in doubt, say N.
diff -r 6669e480cb59 -r fb46e5625c61 drivers/pci/Makefile
--- a/drivers/pci/Makefile      Tue Mar 17 14:27:31 2009 +0000
+++ b/drivers/pci/Makefile      Wed Mar 18 11:39:04 2009 +0000
@@ -15,6 +15,8 @@ obj-$(CONFIG_HOTPLUG) += hotplug.o
 
 # Build the PCI Hotplug drivers if we were asked to
 obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
+
+obj-$(CONFIG_PCI_IOV) += iov.o
 
 #
 # Some architectures use the generic PCI setup functions
diff -r 6669e480cb59 -r fb46e5625c61 drivers/pci/iov.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/pci/iov.c Wed Mar 18 11:39:04 2009 +0000
@@ -0,0 +1,175 @@
+/*
+ * drivers/pci/iov.c
+ *
+ * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@xxxxxxxxx>
+ *
+ * PCI Express I/O Virtualization (IOV) support.
+ *   Single Root IOV 1.0
+ */
+
+#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include "pci.h"
+
+
+static int sriov_init(struct pci_dev *dev, int pos)
+{
+       int i;
+       int rc;
+       int nres;
+       u32 pgsz;
+       u16 ctrl, total, offset, stride;
+       struct pci_sriov *iov;
+       struct resource *res;
+       struct pci_dev *pdev;
+
+       pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl);
+       if (ctrl & PCI_SRIOV_CTRL_VFE) {
+               pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, 0);
+               ssleep(1);
+       }
+
+       pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total);
+       if (!total)
+               return 0;
+
+       list_for_each_entry(pdev, &dev->bus->devices, bus_list)
+               if (pdev->is_physfn)
+                       break;
+       if (list_empty(&dev->bus->devices) || !pdev->is_physfn)
+               pdev = NULL;
+
+       ctrl = 0;
+       if (!pdev && pci_ari_enabled(dev->bus))
+               ctrl |= PCI_SRIOV_CTRL_ARI;
+
+       pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl);
+       pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, total);
+       pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
+       pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
+       if (!offset || (total > 1 && !stride))
+               return -EIO;
+
+       pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &pgsz);
+       i = PAGE_SHIFT > 12 ? PAGE_SHIFT - 12 : 0;
+       pgsz &= ~((1 << i) - 1);
+       if (!pgsz)
+               return -EIO;
+
+       pgsz &= ~(pgsz - 1);
+       pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
+
+       nres = 0;
+       for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+               res = dev->resource + PCI_IOV_RESOURCES + i;
+               i += __pci_read_base(dev, pci_bar_unknown, res,
+                                    pos + PCI_SRIOV_BAR + i * 4);
+               if (!res->flags)
+                       continue;
+               if ((res->end - res->start + 1) & (PAGE_SIZE - 1)) {
+                       rc = -EIO;
+                       goto failed;
+               }
+               res->end = res->start + (res->end - res->start + 1) * total - 1;
+               nres++;
+       }
+
+       iov = kzalloc(sizeof(*iov), GFP_KERNEL);
+       if (!iov) {
+               rc = -ENOMEM;
+               goto failed;
+       }
+
+       iov->pos = pos;
+       iov->nres = nres;
+       iov->ctrl = ctrl;
+       iov->total = total;
+       iov->offset = offset;
+       iov->stride = stride;
+       iov->pgsz = pgsz;
+       iov->self = dev;
+       pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
+       pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
+
+       if (pdev)
+               iov->dev = pci_dev_get(pdev);
+       else {
+               iov->dev = dev;
+               mutex_init(&iov->lock);
+       }
+
+       dev->sriov = iov;
+       dev->is_physfn = 1;
+
+       return 0;
+
+failed:
+       for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
+               res = dev->resource + PCI_IOV_RESOURCES + i;
+               res->flags = 0;
+       }
+
+       return rc;
+}
+
+static void sriov_release(struct pci_dev *dev)
+{
+       if (dev == dev->sriov->dev)
+               mutex_destroy(&dev->sriov->lock);
+       else
+               pci_dev_put(dev->sriov->dev);
+
+       kfree(dev->sriov);
+       dev->sriov = NULL;
+}
+
+/**
+ * pci_iov_init - initialize the IOV capability
+ * @dev: the PCI device
+ *
+ * Returns 0 on success, or negative on failure.
+ */
+int pci_iov_init(struct pci_dev *dev)
+{
+       int pos;
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
+       if (pos)
+               return sriov_init(dev, pos);
+
+       return -ENODEV;
+}
+
+/**
+ * pci_iov_release - release resources used by the IOV capability
+ * @dev: the PCI device
+ */
+void pci_iov_release(struct pci_dev *dev)
+{
+       if (dev->is_physfn)
+               sriov_release(dev);
+}
+
+/**
+ * pci_iov_resource_bar - get position of the SR-IOV BAR
+ * @dev: the PCI device
+ * @resno: the resource number
+ * @type: the BAR type to be filled in
+ *
+ * Returns position of the BAR encapsulated in the SR-IOV capability.
+ */
+int pci_iov_resource_bar(struct pci_dev *dev, int resno,
+                        enum pci_bar_type *type)
+{
+       if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
+               return 0;
+
+       BUG_ON(!dev->is_physfn);
+
+       *type = pci_bar_unknown;
+
+       return dev->sriov->pos + PCI_SRIOV_BAR +
+               4 * (resno - PCI_IOV_RESOURCES);
+}
diff -r 6669e480cb59 -r fb46e5625c61 drivers/pci/pci.c
--- a/drivers/pci/pci.c Tue Mar 17 14:27:31 2009 +0000
+++ b/drivers/pci/pci.c Wed Mar 18 11:39:04 2009 +0000
@@ -1048,12 +1048,19 @@ pci_set_consistent_dma_mask(struct pci_d
  */
 int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
 {
+       int reg;
+
        if (resno < PCI_ROM_RESOURCE) {
                *type = pci_bar_unknown;
                return PCI_BASE_ADDRESS_0 + 4 * resno;
        } else if (resno == PCI_ROM_RESOURCE) {
                *type = pci_bar_mem32;
                return dev->rom_base_reg;
+       } else if (resno < PCI_BRIDGE_RESOURCES) {
+               /* device specific resource */
+               reg = pci_iov_resource_bar(dev, resno, type);
+               if (reg)
+                       return reg;
        }
 
        dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno);
diff -r 6669e480cb59 -r fb46e5625c61 drivers/pci/pci.h
--- a/drivers/pci/pci.h Tue Mar 17 14:27:31 2009 +0000
+++ b/drivers/pci/pci.h Wed Mar 18 11:39:04 2009 +0000
@@ -132,3 +132,40 @@ static inline int pci_ari_enabled(struct
 {
        return bus->self && bus->self->ari_enabled;
 }
+
+/* Single Root I/O Virtualization */
+struct pci_sriov {
+       int pos;                /* capability position */
+       int nres;               /* number of resources */
+       u32 cap;                /* SR-IOV Capabilities */
+       u16 ctrl;               /* SR-IOV Control */
+       u16 total;              /* total VFs associated with the PF */
+       u16 offset;             /* first VF Routing ID offset */
+       u16 stride;             /* following VF stride */
+       u32 pgsz;               /* page size for BAR alignment */
+       u8 link;                /* Function Dependency Link */
+       struct pci_dev *dev;    /* lowest numbered PF */
+       struct pci_dev *self;   /* this PF */
+       struct mutex lock;      /* lock for VF bus */
+};
+
+#ifdef CONFIG_PCI_IOV
+extern int pci_iov_init(struct pci_dev *dev);
+extern void pci_iov_release(struct pci_dev *dev);
+extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
+                               enum pci_bar_type *type);
+#else
+static inline int pci_iov_init(struct pci_dev *dev)
+{
+       return -ENODEV;
+}
+static inline void pci_iov_release(struct pci_dev *dev)
+
+{
+}
+static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno,
+                                      enum pci_bar_type *type)
+{
+       return 0;
+}
+#endif /* CONFIG_PCI_IOV */
diff -r 6669e480cb59 -r fb46e5625c61 drivers/pci/probe.c
--- a/drivers/pci/probe.c       Tue Mar 17 14:27:31 2009 +0000
+++ b/drivers/pci/probe.c       Wed Mar 18 11:39:04 2009 +0000
@@ -765,6 +765,9 @@ static void pci_release_dev(struct devic
        struct pci_dev *pci_dev;
 
        pci_dev = to_pci_dev(dev);
+
+       pci_iov_release(pci_dev);
+
        kfree(pci_dev);
 }
 
@@ -891,6 +894,9 @@ void __devinit pci_device_add(struct pci
 
        /* Alternative Routing-ID Forwarding */
        pci_enable_ari(dev);
+
+       /* Single Root I/O Virtualization */
+       pci_iov_init(dev);
 
        /*
         * Add the device to our list of discovered devices
diff -r 6669e480cb59 -r fb46e5625c61 include/linux/pci.h
--- a/include/linux/pci.h       Tue Mar 17 14:27:31 2009 +0000
+++ b/include/linux/pci.h       Wed Mar 18 11:39:04 2009 +0000
@@ -77,6 +77,12 @@ enum {
        /* #6: expansion ROM resource */
        PCI_ROM_RESOURCE,
 
+       /* device specific resources */
+#ifdef CONFIG_PCI_IOV
+       PCI_IOV_RESOURCES,
+       PCI_IOV_RESOURCE_END = PCI_IOV_RESOURCES + PCI_SRIOV_NUM_BARS - 1,
+#endif
+
        /* resources assigned to buses behind the bridge */
 #define PCI_BRIDGE_RESOURCE_NUM 4
 
@@ -127,6 +133,8 @@ struct pci_cap_saved_state {
        char cap_nr;
        u32 data[0];
 };
+
+struct pci_sriov;
 
 /*
  * The pci_dev structure is used to describe PCI devices.
@@ -189,13 +197,17 @@ 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_physfn:1;
 
        u32             saved_config_space[16]; /* config space saved at 
suspend time */
        struct hlist_head saved_cap_space;
        struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM 
entry */
        int rom_attr_enabled;           /* has display of the rom attribute 
been enabled? */
        struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file 
for resources */
-       unsigned int    ari_enabled:1;  /* ARI forwarding */
+#ifdef CONFIG_PCI_IOV
+       struct pci_sriov *sriov;        /* SR-IOV capability related */
+#endif
 };
 
 #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
diff -r 6669e480cb59 -r fb46e5625c61 include/linux/pci_regs.h
--- a/include/linux/pci_regs.h  Tue Mar 17 14:27:31 2009 +0000
+++ b/include/linux/pci_regs.h  Wed Mar 18 11:39:04 2009 +0000
@@ -332,6 +332,7 @@
 #define  PCI_EXP_TYPE_UPSTREAM 0x5     /* Upstream Port */
 #define  PCI_EXP_TYPE_DOWNSTREAM 0x6   /* Downstream Port */
 #define  PCI_EXP_TYPE_PCI_BRIDGE 0x7   /* PCI/PCI-X Bridge */
+#define  PCI_EXP_TYPE_RC_END   0x9     /* Root Complex Integrated Endpoint */
 #define PCI_EXP_FLAGS_SLOT     0x0100  /* Slot implemented */
 #define PCI_EXP_FLAGS_IRQ      0x3e00  /* Interrupt message number */
 #define PCI_EXP_DEVCAP         4       /* Device capabilities */
@@ -393,6 +394,7 @@
 #define PCI_EXT_CAP_ID_DSN     3
 #define PCI_EXT_CAP_ID_PWR     4
 #define PCI_EXT_CAP_ID_ARI     14
+#define PCI_EXT_CAP_ID_SRIOV   16
 
 /* Advanced Error Reporting */
 #define PCI_ERR_UNCOR_STATUS   4       /* Uncorrectable Error Status */
@@ -478,4 +480,35 @@
 #define  PCI_ARI_CTRL_ACS      0x0002  /* ACS Function Groups Enable */
 #define  PCI_ARI_CTRL_FG(x)    (((x) >> 4) & 7) /* Function Group */
 
+/* Single Root I/O Virtualization */
+#define PCI_SRIOV_CAP          0x04    /* SR-IOV Capabilities */
+#define  PCI_SRIOV_CAP_VFM     0x01    /* VF Migration Capable */
+#define  PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */
+#define PCI_SRIOV_CTRL         0x08    /* SR-IOV Control */
+#define  PCI_SRIOV_CTRL_VFE    0x01    /* VF Enable */
+#define  PCI_SRIOV_CTRL_VFM    0x02    /* VF Migration Enable */
+#define  PCI_SRIOV_CTRL_INTR   0x04    /* VF Migration Interrupt Enable */
+#define  PCI_SRIOV_CTRL_MSE    0x08    /* VF Memory Space Enable */
+#define  PCI_SRIOV_CTRL_ARI    0x10    /* ARI Capable Hierarchy */
+#define PCI_SRIOV_STATUS       0x0a    /* SR-IOV Status */
+#define  PCI_SRIOV_STATUS_VFM  0x01    /* VF Migration Status */
+#define PCI_SRIOV_INITIAL_VF   0x0c    /* Initial VFs */
+#define PCI_SRIOV_TOTAL_VF     0x0e    /* Total VFs */
+#define PCI_SRIOV_NUM_VF       0x10    /* Number of VFs */
+#define PCI_SRIOV_FUNC_LINK    0x12    /* Function Dependency Link */
+#define PCI_SRIOV_VF_OFFSET    0x14    /* First VF Offset */
+#define PCI_SRIOV_VF_STRIDE    0x16    /* Following VF Stride */
+#define PCI_SRIOV_VF_DID       0x1a    /* VF Device ID */
+#define PCI_SRIOV_SUP_PGSIZE   0x1c    /* Supported Page Sizes */
+#define PCI_SRIOV_SYS_PGSIZE   0x20    /* System Page Size */
+#define PCI_SRIOV_BAR          0x24    /* VF BAR0 */
+#define  PCI_SRIOV_NUM_BARS    6       /* Number of VF BARs */
+#define PCI_SRIOV_VFM          0x3c    /* VF Migration State Array Offset*/
+#define  PCI_SRIOV_VFM_BIR(x)  ((x) & 7)       /* State BIR */
+#define  PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7)    /* State Offset */
+#define  PCI_SRIOV_VFM_UA      0x0     /* Inactive.Unavailable */
+#define  PCI_SRIOV_VFM_MI      0x1     /* Dormant.MigrateIn */
+#define  PCI_SRIOV_VFM_MO      0x2     /* Active.MigrateOut */
+#define  PCI_SRIOV_VFM_AV      0x3     /* Active.Available */
+
 #endif /* LINUX_PCI_REGS_H */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] PCI: initialize and release SR-IOV capability, Xen patchbot-linux-2.6.18-xen <=