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

[Xen-changelog] [qemu-xen-unstable] passthrough: use devfn instead of slots as the unit for pass-through



commit 7551a514dd944a5155747071135bac11deb61c43
Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date:   Thu Jun 25 18:30:25 2009 +0100

    passthrough: use devfn instead of slots as the unit for pass-through
    
    This is part of support for multi-function PCI devices in guests
    
    Instead of reading a slot number from xend, read a devfn.
    This and subsequent other changes will allow xend to ask
    for more than one function to be inserted into a single slot -
    by specifying which function of the slot should be used.
    
    This is a minimal patch for this change. A subsequent
    patch that has a lot of noise to rename slot to devfn follows.
    
    This patch breaks compatibility with xend and corresponding
    patches to xend are required.
    
    Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx>
    Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
    Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
    
    [3/8; cross-compatibility issues with xen-unstable.hg]
---
 hw/pass-through.c |   40 ++++++++++++++--------------
 hw/pci.h          |    7 +++-
 hw/piix4acpi.c    |   75 ++++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 79 insertions(+), 43 deletions(-)

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 07ca751..d19fb82 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -103,7 +103,7 @@ struct php_dev {
 };
 struct dpci_infos {
 
-    struct php_dev php_devs[NR_PCI_DEV];
+    struct php_dev php_devs[NR_PCI_DEVFN];
 
     PCIBus *e_bus;
     struct pci_access *pci_access;
@@ -859,7 +859,7 @@ static int parse_bdf(char **str, int *seg, int *bus, int 
*dev, int *func,
     }
     else
     {
-        *vslot = AUTO_PHP_SLOT;
+        *vslot = AUTO_PHP_DEVFN;
         *opt = token;
     }
 
@@ -903,30 +903,30 @@ static int pci_slot_match(int bus, int dev, int func, int 
slot)
 }
 
 /* Insert a new pass-through device into a specific pci slot.
- * input  dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_SLOT
+ * input  dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_DEVFN
  * return -2: requested slot not available
  *        -1: no free slots
  *        >=0: the new hotplug slot
  */
-static int __insert_to_pci_slot(int bus, int dev, int func, int slot,
+static int __insert_to_pci_slot(int bus, int dev, int func, int devfn,
                                 char *opt)
 {
     PCIBus *e_bus = dpci_infos.e_bus;
+    int slot;
 
-    /* preferred virt pci slot */
-    if ( slot != AUTO_PHP_SLOT)
+    /* preferred virt pci devfn */
+    if ( devfn != AUTO_PHP_DEVFN )
     {
-        if ( !test_pci_slot(slot) &&
-             !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) )
+        if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) )
             goto found;
         return -2;
     }
 
-    /* slot == 0, pick up a free one */
+    /* pick a free slot */
     for ( slot = 0; slot < NR_PCI_DEV; slot++ )
     {
-        if ( !test_pci_slot(slot) &&
-             !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) )
+        devfn = PCI_DEVFN(slot, 0);
+        if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) )
             goto found;
     }
 
@@ -934,12 +934,12 @@ static int __insert_to_pci_slot(int bus, int dev, int 
func, int slot,
     return -1;
 
 found:
-    dpci_infos.php_devs[slot].valid  = 1;
-    dpci_infos.php_devs[slot].r_bus  = bus;
-    dpci_infos.php_devs[slot].r_dev  = dev;
-    dpci_infos.php_devs[slot].r_func = func;
-    dpci_infos.php_devs[slot].opt = opt;
-    return slot;
+    dpci_infos.php_devs[devfn].valid  = 1;
+    dpci_infos.php_devs[devfn].r_bus  = bus;
+    dpci_infos.php_devs[devfn].r_dev  = dev;
+    dpci_infos.php_devs[devfn].r_func = func;
+    dpci_infos.php_devs[devfn].opt = opt;
+    return devfn;
 }
 
 /* Insert a new pass-through device into a specific pci slot.
@@ -966,7 +966,7 @@ int insert_to_pci_slot(char *bdf_slt)
  */
 int test_pci_slot(int slot)
 {
-    if ( slot < 0 || slot >= NR_PCI_DEV )
+    if ( slot < 0 || slot >= NR_PCI_DEVFN )
         return -1;
 
     if ( dpci_infos.php_devs[slot].valid )
@@ -987,7 +987,7 @@ int bdf_to_slot(char *bdf_str)
     }
 
     /* locate the virtual pci slot for this VTd device */
-    for ( i = 0; i < NR_PCI_DEV; i++ )
+    for ( i = 0; i < NR_PCI_DEVFN; i++ )
     {
         if ( pci_slot_match(bus, dev, func, i) )
             return i;
@@ -4037,7 +4037,7 @@ static struct pt_dev * register_real_device(PCIBus *e_bus,
 
     /* Register device */
     assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name,
-                                sizeof(struct pt_dev), PCI_DEVFN(e_slot, 0),
+                                sizeof(struct pt_dev), e_slot,
                                 pt_pci_read_config, pt_pci_write_config);
     if ( assigned_device == NULL )
     {
diff --git a/hw/pci.h b/hw/pci.h
index d45b80c..b5947f3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -255,8 +255,11 @@ 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_DEV 32
-#define AUTO_PHP_SLOT NR_PCI_DEV
+#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
 
 int insert_to_pci_slot(char*);
 int test_pci_slot(int);
diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
index d5c5c35..836abd5 100644
--- a/hw/piix4acpi.c
+++ b/hw/piix4acpi.c
@@ -33,6 +33,8 @@
 #include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>
 
+#include <pci/header.h>
+
 /* PM1a_CNT bits, as defined in the ACPI specification. */
 #define SCI_EN            (1 <<  0)
 #define GBL_RLS           (1 <<  2)
@@ -276,7 +278,7 @@ static void acpi_php_writeb(void *opaque, uint32_t addr, 
uint32_t val)
             hotplug_slots->plug_slot = 0;
 
             /* power off the slot */
-            power_off_php_slot(slot);
+            power_off_php_slot(PCI_DEVFN(slot, 0));
 
             /* signal the CP ACPI hot remove done. */
             xenstore_record_dm_state("pci-removed");
@@ -459,17 +461,32 @@ static void acpi_sci_intr(GPEState *s)
     }
 }
 
-void acpi_php_del(int slot)
+void acpi_php_del(int devfn)
 {
     GPEState *s = &gpe_state;
+    int slot, func;
+
+    slot = PCI_SLOT(devfn);
+    func = PCI_FUNC(devfn);
 
-    if ( test_pci_slot(slot) < 0 ) {
-        fprintf(logfile, "hot remove: pci slot %d "
-                "is not used by a hotplug device.\n", slot);
+    if ( test_pci_slot(devfn) < 0 ) {
+        fprintf(logfile, "hot remove: pci slot 0x%02x, function 0x%x "
+                "is not used by a hotplug device.\n", slot, func);
 
         return;
     }
 
+    /* ACPI PHP can only work on slots
+     * So only remove zero-functions -
+     * which will remove all other fucntions of the same device in the
+     * guest.
+     */
+    if ( func ) {
+        fprintf(logfile, "hot remove: Attempt to remove non-zero function "
+                "slot=0x%02x func=0x%0x.\n", slot, func);
+        return;
+    }
+
     /* update the php controller status */
     php_slots.plug_evt = PHP_EVT_REMOVE;
     php_slots.plug_slot = slot;
@@ -478,18 +495,19 @@ void acpi_php_del(int slot)
     acpi_sci_intr(s);
 }
 
-void acpi_php_add(int slot)
+void acpi_php_add(int devfn)
 {
     GPEState *s = &gpe_state;
     char ret_str[30];
+    int slot, func;
 
-    if ( slot < 0 ) {
-        fprintf(logfile, "hot add pci slot %d exceed.\n", slot);
+    if ( devfn < 0 ) {
+        fprintf(logfile, "hot add pci devfn %d exceed.\n", devfn);
 
-        if ( slot == -1 )
-            sprintf(ret_str, "no free hotplug slots");
-        else if ( slot == -2 )
-            sprintf(ret_str, "wrong bdf or vslot");
+        if ( devfn == -1 )
+            sprintf(ret_str, "no free hotplug devfn");
+        else if ( devfn == -2 )
+            sprintf(ret_str, "wrong bdf or vdevfn");
 
         if ( strlen(ret_str) > 0 )
             xenstore_record_dm("parameter", ret_str);
@@ -497,25 +515,40 @@ void acpi_php_add(int slot)
         return;
     }
 
-    /* update the php controller status */
-    php_slots.plug_evt = PHP_EVT_ADD;
-    php_slots.plug_slot = slot;
+    /* ACPI PHP can only work on slots
+     * For function 0 we do a full hot-add.
+     * For other functions we just register the device with the hypervisor.
+     * Assuming that function 0 is added after non-zero functions,
+     * its ACPI PHP event will cause all previously registered functions
+     * to be added to the guest.
+     */
 
-    /* update the slot status as present */
-    php_slots.status[slot] = 0xf;
+    slot = PCI_SLOT(devfn);
+    func = PCI_FUNC(devfn);
 
-    /* power on the slot */
-    power_on_php_slot(slot);
+    if ( !func )
+    {
+        /* update the php controller status */
+        php_slots.plug_evt = PHP_EVT_ADD;
+        php_slots.plug_slot = slot;
+
+        /* update the slot status as present */
+        php_slots.status[slot] = 0xf;
+    }
+
+    /* power on the function */
+    power_on_php_slot(devfn);
 
     /* tell Control panel which slot for the new pass-throgh dev */
-    sprintf(ret_str, "0x%02x", slot);
+    sprintf(ret_str, "0x%02x", devfn);
     xenstore_record_dm("parameter", ret_str);
 
     /* signal the CP ACPI hot insert done */
     xenstore_record_dm_state("pci-inserted");
 
     /* generate a SCI interrupt */
-    acpi_sci_intr(s);
+    if ( !func )
+        acpi_sci_intr(s);
 }
 
 #endif /* CONFIG_PASSTHROUGH */
--
generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git

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


 


Rackspace

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