]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
PCI: pass ARI and SR-IOV device information to the hypervisor
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 19 Mar 2009 10:21:46 +0000 (10:21 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 19 Mar 2009 10:21:46 +0000 (10:21 +0000)
PCIe Alternative Routing-ID Interpretation (ARI) ECN defines the Extended
Function -- a function whose function number is greater than 7 within an
ARI Device. Intel VT-d spec 1.2 section 8.3.2 specifies that the Extended
Function is under the scope of the same remapping unit as the traditional
function. The hypervisor needs to know if a function is Extended
Function so it can find proper DMAR for it.

And section 8.3.3 specifies that the SR-IOV Virtual Function is under the
scope of the same remapping unit as the Physical Function. The hypervisor
also needs to know if a function is the Virtual Function and which
Physical Function it's associated with for same reason.

Signed-off-by: Yu Zhao <yu.zhao@intel.com>
drivers/xen/core/pci.c
include/xen/interface/physdev.h

index 57bcf84f57e8932b29033fa0b017497f080564e1..595739f140cbe4583c173e5643cf4d0d754ca939 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <xen/interface/physdev.h>
+#include "../../pci/pci.h"
 
 static int (*pci_bus_probe)(struct device *dev);
 static int (*pci_bus_remove)(struct device *dev);
@@ -15,10 +16,30 @@ static int pci_bus_probe_wrapper(struct device *dev)
        int r;
        struct pci_dev *pci_dev = to_pci_dev(dev);
        struct physdev_manage_pci manage_pci;
-       manage_pci.bus = pci_dev->bus->number;
-       manage_pci.devfn = pci_dev->devfn;
+       struct physdev_manage_pci_ext manage_pci_ext;
 
-       r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, &manage_pci);
+       if (pci_dev->is_virtfn) {
+               memset(&manage_pci_ext, 0, sizeof(manage_pci_ext));
+               manage_pci_ext.bus = pci_dev->bus->number;
+               manage_pci_ext.devfn = pci_dev->devfn;
+               manage_pci_ext.is_virtfn = 1;
+               manage_pci_ext.physfn.bus = pci_dev->physfn->bus->number;
+               manage_pci_ext.physfn.devfn = pci_dev->physfn->devfn;
+               r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
+                                         &manage_pci_ext);
+       } else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
+               memset(&manage_pci_ext, 0, sizeof(manage_pci_ext));
+               manage_pci_ext.bus = pci_dev->bus->number;
+               manage_pci_ext.devfn = pci_dev->devfn;
+               manage_pci_ext.is_extfn = 1;
+               r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
+                                         &manage_pci_ext);
+       } else {
+               manage_pci.bus = pci_dev->bus->number;
+               manage_pci.devfn = pci_dev->devfn;
+               r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add,
+                                         &manage_pci);
+       }
        if (r && r != -ENOSYS)
                return r;
 
index 72a42cf265ce9f5aedfdd6118caca03cf53d1366..b7cae9ddf0472ca5163990645d6ce27369c80679 100644 (file)
@@ -192,6 +192,22 @@ struct physdev_restore_msi {
 typedef struct physdev_restore_msi physdev_restore_msi_t;
 DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t);
 
+#define PHYSDEVOP_manage_pci_add_ext   20
+struct physdev_manage_pci_ext {
+    /* IN */
+    uint8_t bus;
+    uint8_t devfn;
+    unsigned is_extfn;
+    unsigned is_virtfn;
+    struct {
+        uint8_t bus;
+        uint8_t devfn;
+    } physfn;
+};
+
+typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t;
+DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t);
+
 /*
  * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()
  * hypercall since 0x00030202.