]> xenbits.xensource.com Git - qemu-xen-4.1-testing.git/commitdiff
passthrough: Add AUTO_PHP_DEVFN_MULTI
authorIan Jackson <ian.jackson@eu.citrix.com>
Thu, 25 Jun 2009 17:32:01 +0000 (18:32 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Thu, 25 Jun 2009 17:32:01 +0000 (18:32 +0100)
Up until now there has been a signle magic value that xend can pass to
qemu-xen to signify that qemu-xen should choose a devfn for a pass-through
function.

When supporting multi-function devices in guests, it is useful for xend to
be able to sepcify if a function is to appear in a guest as a
single-function deveice, or as part of a multi-function device.

By adding AUTO_PHP_DEVFN_MULTI to suplement the existing AUTO_PHP_DEVFN,
this patch achieves that goal.

This patch does not break compatibility with xend as the value chosen for
AUTO_PHP_DEVFN_MULTI could never validly be sent by xend up until now.
However, there is a companion change to xend in order to make use of this
feature.

Cc: Dexuan Cui <dexuan.cui@intel.com>
Cc: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
[5/8; cross-compatibility issues with xen-unstable.hg]

hw/pass-through.c
hw/pci.h

index 7aa4771ae97e9591f72f750c300568fd48ed3616..5062b31968a38da3ab448c2a03478fe5b112ed8a 100644 (file)
@@ -859,7 +859,7 @@ static int parse_bdf(char **str, int *seg, int *bus, int *dev, int *func,
     }
     else
     {
-        *vdevfn = AUTO_PHP_DEVFN;
+        *vdevfn = AUTO_PHP_SLOT;
         *opt = token;
     }
 
@@ -902,8 +902,32 @@ static int pci_devfn_match(int bus, int dev, int func, int devfn)
     return 0;
 }
 
+static int find_free_vslot(void)
+{
+    PCIBus *e_bus = dpci_infos.e_bus;
+    int slot, func, devfn;
+
+    for ( slot = 0; slot < NR_PCI_DEV; slot++ )
+    {
+        for ( func = 0; func < NR_PCI_FUNC; func++ )
+        {
+            devfn = PCI_DEVFN(slot, func);
+            if ( test_pci_devfn(devfn) || pci_devfn_in_use(e_bus, devfn) )
+            {
+                break;
+            }
+        }
+        if (func == NR_PCI_FUNC)
+            return slot;
+    }
+
+    /* not found */
+    return -1;
+}
+
+
 /* Insert a new pass-through device into a specific pci devfn.
- * input  dom:bus:dev.func@devfn, chose free one if devfn == AUTO_PHP_DEVFN
+ * input  dom:bus:dev.func@devfn, chose free one if devfn & AUTO_PHP_SLOT
  * return -2: requested devfn not available
  *        -1: no free devfns
  *        >=0: the new hotplug devfn
@@ -912,28 +936,23 @@ static int __insert_to_pci_devfn(int bus, int dev, int func, int devfn,
                                  char *opt)
 {
     PCIBus *e_bus = dpci_infos.e_bus;
-    int slot;
+    int vslot;
 
-    /* preferred virt pci devfn */
-    if ( devfn != AUTO_PHP_DEVFN )
+    if ( devfn & AUTO_PHP_SLOT )
     {
-        if ( !test_pci_devfn(devfn) && !pci_devfn_in_use(e_bus, devfn) )
-            goto found;
-        return -2;
+        vslot = find_free_vslot();
+        if (vslot < 0)
+            return -1;
+        /* The vfunc is provided in the devfn paramter */
+        devfn = PCI_DEVFN(vslot, PCI_FUNC(devfn));
     }
-
-    /* pick a free slot */
-    for ( slot = 0; slot < NR_PCI_DEV; slot++ )
+    else
     {
-        devfn = PCI_DEVFN(slot, 0);
-        if ( !test_pci_devfn(devfn) && !pci_devfn_in_use(e_bus, devfn) )
-            goto found;
+        /* Prefered devfn */
+        if ( test_pci_devfn(devfn) || pci_devfn_in_use(e_bus, devfn) )
+            return -2;
     }
 
-    /* not found */
-    return -1;
-
-found:
     dpci_infos.php_devs[devfn].valid  = 1;
     dpci_infos.php_devs[devfn].r_bus  = bus;
     dpci_infos.php_devs[devfn].r_dev  = dev;
index f9660dc31a8a0de9f4384f7ce464a01255a9795a..30bcb04d62916bb696ae67d9d14746342e750993 100644 (file)
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -255,11 +255,10 @@ void pci_info(void);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
                         pci_map_irq_fn map_irq, const char *name);
 
-#define NR_PCI_FUNC    8
-#define NR_PCI_DEV     32
-#define NR_PCI_DEVFN   (NR_PCI_FUNC * NR_PCI_DEV)
-#define AUTO_PHP_SLOT  NR_PCI_DEV
-#define AUTO_PHP_DEVFN NR_PCI_DEVFN
+#define NR_PCI_FUNC          8
+#define NR_PCI_DEV           32
+#define NR_PCI_DEVFN         (NR_PCI_FUNC * NR_PCI_DEV)
+#define AUTO_PHP_SLOT        0x100
 
 int insert_to_pci_devfn(char *bdf_devfn);
 int test_pci_devfn(int devfn);