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

[Xen-devel] [rfc 15/18] ioemu: use struct php_dev to pass around PCI pass-through assignment parameters



Signed-off-by: Simon Horman <horms@xxxxxxxxxxx>

--- 
Fri, 13 Feb 2009 13:50:13 +1100
* Account for vslot supplied for hotplug insert

Fri, 13 Feb 2009 15:22:10 +1100
* Rebased
  from "Restore xenfb.h and atkbd_ translation tables for * xenfbfront"
  to "fix memory/fd leak in pt_msix_init()"
Index: ioemu-remote/hw/pass-through.c
===================================================================
--- ioemu-remote.orig/hw/pass-through.c 2009-02-17 17:55:37.000000000 +0900
+++ ioemu-remote/hw/pass-through.c      2009-02-17 17:56:46.000000000 +0900
@@ -34,6 +34,7 @@ struct php_dev {
     uint8_t r_bus;
     uint8_t r_dev;
     uint8_t r_func;
+    uint8_t v_devfn;
     char *opt;
 };
 static struct dpci_infos {
@@ -726,37 +727,65 @@ static const struct pt_reg_grp_info_tbl 
     }, 
 };
 
+static int cmp_php_dev(const struct php_dev *a, const struct php_dev *b)
+{
+    if (a->r_bus != b->r_bus)
+    {
+        return a->r_bus - b->r_bus;
+    }
+    if (a->r_dev != b->r_dev)
+    {
+        return a->r_dev - b->r_dev;
+    }
+    if (a->r_func != b->r_func)
+    {
+        return a->r_func - b->r_func;
+    }
+
+    return 0;
+}
+
+static void cpy_php_dev(struct php_dev *dst, const struct php_dev *src)
+{
+    memcpy(dst, src, sizeof(*dst));
+}
+
 static int token_value(char *token)
 {
     return strtol(token, NULL, 16);
 }
 
-static int next_bdf(char **str, int *seg, int *bus, int *dev, int *func, char 
**opt)
+static struct php_dev next_bdf(char **str)
 {
     char *token;
     const char *delim = ":.-";
+    struct php_dev bdf;
+
+    memset(&bdf, 0, sizeof(bdf));
 
     if ( !(*str) ||
           ( !strchr(*str, ':') && !strchr(*str, '.')) )
-        return 0;
+        return bdf;
 
     token  = strsep(str, delim);
-    *seg = token_value(token);
+    /* segment */
 
     token  = strsep(str, delim);
-    *bus  = token_value(token);
+    bdf.r_bus  = token_value(token);
 
     token  = strsep(str, delim);
-    *dev  = token_value(token);
+    bdf.r_dev  = token_value(token);
 
     token  = strsep(str, delim);
-    *opt = strchr(token, ',');
-    if (*opt)
-        *(*opt)++ = '\0';
+    bdf.opt = strchr(token, ',');
+    if (bdf.opt)
+        *(bdf.opt)++ = '\0';
 
-    *func  = token_value(token);
+    bdf.r_func  = token_value(token);
 
-    return 1;
+    bdf.valid = 1;
+
+    return bdf;
 }
 
 static int get_next_keyval(char **option, char **key, char **val)
@@ -802,31 +831,31 @@ static void msi_set_enable(struct pt_dev
  *         0: no free hotplug slots, but normal slot should okay
  *        >0: the new hotplug devfn
  */
-static int insert_to_php_devfn(int bus, int dev, int func, int devfn,
-                                char *opt)
+static int insert_to_php_devfn(const struct php_dev *bdf)
 {
     int php_slot, php_func, php_devfn, php_devfn_match;
 
     /* preferred virt pci slot */
-    if ( devfn >= PHP_DEVFN_START && devfn < PHP_DEVFN_END )
+    if ( bdf->v_devfn >= PHP_DEVFN_START && bdf->v_devfn < PHP_DEVFN_END )
     {
-        php_devfn = PCI_TO_PHP_DEVFN(devfn);
-        if ( !dpci_infos.php_devs[php_devfn].valid )
+        php_devfn = PCI_TO_PHP_DEVFN(bdf->v_devfn);
+        if ( !dpci_infos.php_devs[php_devfn].valid ||
+             !cmp_php_dev(&dpci_infos.php_devs[php_devfn], bdf) )
             goto found;
     }
-    if ( devfn != 0 )
+    if ( bdf->v_devfn != 0 )
         return -1;
 
     /* Co-locate functions for the same device in the same slot */
     for ( php_slot = 0; php_slot < PHP_SLOT_LEN; php_slot++ )
     {
-        php_devfn = PCI_DEVFN(php_slot, func);
+        php_devfn = PCI_DEVFN(php_slot, bdf->r_func);
         for ( php_func = 0; php_func < 8; php_func++ )
         {
             php_devfn_match = PCI_DEVFN(php_slot, php_func);
             if ( dpci_infos.php_devs[php_devfn_match].valid &&
-                 dpci_infos.php_devs[php_devfn_match].r_bus == bus &&
-                 dpci_infos.php_devs[php_devfn_match].r_dev == dev &&
+                 dpci_infos.php_devs[php_devfn_match].r_bus == bdf->r_bus &&
+                 dpci_infos.php_devs[php_devfn_match].r_dev == bdf->r_dev &&
                  !dpci_infos.php_devs[php_devfn].valid )
                 goto found;
         }
@@ -844,12 +873,9 @@ static int insert_to_php_devfn(int bus, 
     return 0;
 
 found:
-    dpci_infos.php_devs[php_devfn].valid  = 1;
-    dpci_infos.php_devs[php_devfn].r_bus  = bus;
-    dpci_infos.php_devs[php_devfn].r_dev  = dev;
-    dpci_infos.php_devs[php_devfn].r_func = func;
-    dpci_infos.php_devs[php_devfn].opt = opt;
-    return PHP_TO_PCI_DEVFN(php_devfn);
+    cpy_php_dev(&dpci_infos.php_devs[php_devfn], bdf);
+    dpci_infos.php_devs[php_devfn].v_devfn = PHP_TO_PCI_DEVFN(php_devfn);
+    return dpci_infos.php_devs[php_devfn].v_devfn;
 }
 
 /* Insert a new pass-through device into function 0 of a specific pci slot.
@@ -857,7 +883,8 @@ found:
  */
 int insert_bdf_to_php_devfn(char *bdf_slt)
 {
-    int seg, bus, dev, func, slot;
+    int slot;
+    struct php_dev bdf;
     char *bdf_str, *slt_str, *opt;
     const char *delim="@";
 
@@ -865,12 +892,15 @@ int insert_bdf_to_php_devfn(char *bdf_sl
     slt_str = bdf_slt;
     slot = token_value(slt_str);
 
-    if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt))
+    bdf = next_bdf(&bdf_str);
+    if (!bdf.valid)
     {
         return -1;
     }
 
-    return insert_to_php_devfn(bus, dev, func, PCI_DEVFN(slot, 0), opt);
+    bdf.v_devfn = PCI_DEVFN(slot, 0);
+
+    return insert_to_php_devfn(&bdf);
 
 }
 
@@ -896,22 +926,22 @@ int test_php_devfn(int devfn)
 /* find the pci slot for pass-through dev with specified BDF */
 int bdf_to_php_devfn(char *bdf_str)
 {
-    int seg, bus, dev, func, i;
-    char *opt;
+    int i;
+    struct php_dev bdf;
 
-    if ( !next_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt))
+    bdf = next_bdf(&bdf_str);
+    if (!bdf.valid)
     {
         return -1;
     }
-    PT_LOG("%s: bdf: %04x:%02x.%x\n", __func__, bus, dev, func);
+    PT_LOG("%s: bdf: %04x:%02x.%x\n", __func__, bdf.r_bus, bdf.r_dev,
+           bdf.r_func);
 
     /* locate the virtual pci slot for this VTd device */
     for ( i = 0; i < PHP_DEVFN_LEN; i++ )
     {
         if ( dpci_infos.php_devs[i].valid &&
-           dpci_infos.php_devs[i].r_bus == bus &&
-           dpci_infos.php_devs[i].r_dev  == dev &&
-           dpci_infos.php_devs[i].r_func == func )
+             cmp_php_dev(&dpci_infos.php_devs[i], &bdf) )
         {
             return PHP_TO_PCI_DEVFN(i);
         }
@@ -3093,9 +3123,8 @@ static int pt_msixctrl_reg_write(struct 
 }
 
 static struct pt_dev * register_real_device(PCIBus *e_bus,
-        const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
-        uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access,
-        char *opt)
+        const char *e_dev_name, struct php_dev *bdf,
+        uint32_t machine_irq, struct pci_access *pci_access)
 {
     int rc = -1, i;
     struct pt_dev *assigned_device = NULL;
@@ -3107,14 +3136,14 @@ static struct pt_dev * register_real_dev
     int msi_translate;
 
     PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
-        r_bus, r_dev, r_func);
+        bdf->r_bus, bdf->r_dev, bdf->r_func);
 
     /* Find real device structure */
     for (pci_dev = pci_access->devices; pci_dev != NULL;
          pci_dev = pci_dev->next)
     {
-        if ((r_bus == pci_dev->bus) && (r_dev == pci_dev->dev)
-            && (r_func == pci_dev->func))
+        if ((bdf->r_bus == pci_dev->bus) && (bdf->r_dev == pci_dev->dev)
+            && (bdf->r_func == pci_dev->func))
             break;
     }
     if ( pci_dev == NULL )
@@ -3125,19 +3154,16 @@ static struct pt_dev * register_real_dev
     pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | 
PCI_FILL_SIZES);
     pt_libpci_fixup(pci_dev);
 
-    if ( e_devfn == PCI_DEVFN_AUTO ) {
-        /*indicate a static assignment(not hotplug), so find a free PCI hot 
plug slot */
-        free_devfn = insert_to_php_devfn(r_bus, r_dev, r_func, 0, NULL);
-        if ( free_devfn > 0 )
-            e_devfn = free_devfn;
-        else
-            PT_LOG("Error: no free virtual PCI hot plug slot, thus no live 
migration.\n");
-    }
+    free_devfn = insert_to_php_devfn(bdf);
+    if ( free_devfn <= 0 )
+        PT_LOG("Error: no free virtual PCI hot plug slot, "
+               "thus no live migration.\n");
 
     msi_translate = direct_pci_msitranslate;
-    while (opt) {
-        if (get_next_keyval(&opt, &key, &val)) {
-            PT_LOG("Error: unrecognized PCI assignment option \"%s\"\n", opt);
+    while (bdf->opt) {
+        if (get_next_keyval(&bdf->opt, &key, &val)) {
+            PT_LOG("Error: unrecognized PCI assignment option \"%s\"\n",
+                   bdf->opt);
             break;
         }
 
@@ -3164,7 +3190,7 @@ static struct pt_dev * register_real_dev
 
     /* Register device */
     assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name,
-                                sizeof(struct pt_dev), e_devfn,
+                                sizeof(struct pt_dev), free_devfn,
                                 pt_pci_read_config, pt_pci_write_config);
     if ( assigned_device == NULL )
     {
@@ -3181,9 +3207,9 @@ static struct pt_dev * register_real_dev
 
     /* Assign device */
     machine_bdf.reg = 0;
-    machine_bdf.bus = r_bus;
-    machine_bdf.dev = r_dev;
-    machine_bdf.func = r_func;
+    machine_bdf.bus = bdf->r_bus;
+    machine_bdf.dev = bdf->r_dev;
+    machine_bdf.func = bdf->r_func;
     rc = xc_assign_device(xc_handle, domid, machine_bdf.value);
     if ( rc < 0 )
         PT_LOG("Error: xc_assign_device error %d\n", rc);
@@ -3273,7 +3299,7 @@ static struct pt_dev * register_real_dev
 
 out:
     PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n"
-           "IRQ type = %s\n", r_bus, r_dev, r_func,
+           "IRQ type = %s\n", bdf->r_bus, bdf->r_dev, bdf->r_func,
            assigned_device->msi_trans_en? "MSI-INTx":"INTx");
 
     return assigned_device;
@@ -3353,18 +3379,11 @@ static int unregister_real_device(int ph
 int power_on_php_devfn(int php_devfn)
 {
     struct php_dev *php_dev = &dpci_infos.php_devs[php_devfn];
-    int pci_devfn = PHP_TO_PCI_DEVFN(php_devfn);
     struct pt_dev *pt_dev;
-    pt_dev = 
-        register_real_device(dpci_infos.e_bus,
-            "DIRECT PCI",
-            pci_devfn,
-            php_dev->r_bus,
-            php_dev->r_dev,
-            php_dev->r_func,
-            PT_MACHINE_IRQ_AUTO,
-            dpci_infos.pci_access,
-            php_dev->opt);
+
+    pt_dev = register_real_device(dpci_infos.e_bus, "DIRECT PCI",
+                                  php_dev, PT_MACHINE_IRQ_AUTO,
+                                  dpci_infos.pci_access);
 
     php_dev->opt = NULL;
 
@@ -3381,14 +3400,14 @@ int power_off_php_devfn(int php_devfn)
 
 int pt_init(PCIBus *e_bus, const char *direct_pci)
 {
-    int seg, b, d, f, status = -1;
+    int status = -1;
     struct pt_dev *pt_dev;
     struct pci_access *pci_access;
     char *vslots;
     char slot_str[8];
     char *direct_pci_head = NULL;
     char *direct_pci_p = NULL;
-    char *opt;
+    struct php_dev bdf;
 
     /* Initialize libpci */
     pci_access = pci_alloc();
@@ -3417,14 +3436,20 @@ int pt_init(PCIBus *e_bus, const char *d
     vslots = qemu_mallocz ( strlen(direct_pci) / 3 );
 
     /* Assign given devices to guest */
-    while ( next_bdf(&direct_pci_p, &seg, &b, &d, &f, &opt) )
+    while (1)
     {
+        bdf = next_bdf(&direct_pci_p);
+        if (!bdf.valid)
+        {
+            break;
+        }
         /* Register real device with the emulated bus */
-        pt_dev = register_real_device(e_bus, "DIRECT PCI", PCI_DEVFN_AUTO,
-            b, d, f, PT_MACHINE_IRQ_AUTO, pci_access, opt);
+        pt_dev = register_real_device(e_bus, "DIRECT PCI",
+                                      &bdf, PT_MACHINE_IRQ_AUTO, pci_access);
         if ( pt_dev == NULL )
         {
-            PT_LOG("Error: Registration failed (%02x:%02x.%x)\n", b, d, f);
+            PT_LOG("Error: Registration failed (%02x:%02x.%x)\n",
+                   bdf.r_bus, bdf.r_dev, bdf.r_func);
             goto err;
         }
 

-- 

-- 
Simon Horman
  VA Linux Systems Japan K.K., Sydney, Australia Satellite Office
  H: www.vergenet.net/~horms/             W: www.valinux.co.jp/en


_______________________________________________
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®.