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-devel

[Xen-devel] [PATCH] dom0 linux: support SBDF with "guestdev=" and remove

To: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>, Isaku Yamahata <yamahata@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] dom0 linux: support SBDF with "guestdev=" and remove "reassigndev="
From: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
Date: Wed, 08 Apr 2009 17:30:37 +0900
Cc:
Delivery-date: Wed, 08 Apr 2009 01:34:08 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
This patch supports SBDF with "guestdev=" boot parameter and removes
"reassigndev=" boot parameter.

Currently there are three boot parameters which specifics PCI device
for PCI pass-through.

        pciback.hide=
        guestdev=
        reassigndev=

I'd like to simplify them before xen 3.4 is released. To achieve this,
I'd like to make "guestdev=" boot parameter support SBDF, and remove
"reassigndev=".


When we don't need to reassign resources and use device path,
pciback.hide= boot parameter can be used. The parameter is also needed
for backward compatibility.

    pciback.hide=(00:01.0)(00:02.0)

When we need to reassign resources or use device path, guestdev= boot
parameter can be used. reassign_resources boot parameter is needed to
reassign resources, too.

    guestdev=00:01.0,00:02.0 reassign_resources
    guestdev=PNP0A08:0-1.0,PNP0A08:0-2.0
    guestdev=PNP0A08:0-1.0,PNP0A08:0-2.0 reassign_resources


With this patch, Isaku-san will not need to add guestioemuldev
boot parameter for IO space multiplexing, though it will be necessary
to add a flag and omit func# from guestdev.

Thanks,
--
Yuji Shimada


Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>

diff -r e5d3f2fa3428 Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt       Tue Apr 07 10:29:30 2009 +0100
+++ b/Documentation/kernel-parameters.txt       Wed Apr 08 16:14:56 2009 +0900
@@ -576,8 +576,9 @@ running once the system is up.
        gt96100eth=     [NET] MIPS GT96100 Advanced Communication Controller
 
        guestdev=       [PCI,ACPI]
-                       Format: <device path>[,<device path>[,...]]
-                       Format of device path: 
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[...]]
+                       Format: {<device path>|<sbdf>}][,{<device 
path>|<sbdf>}[,...]]
+                       Format of device path: 
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]]
+                       Format of sbdf: [<segment>:]<bus>:<dev>.<func>
                        Specifies PCI device for guest domain.
                        If PCI-PCI bridge is specified, all PCI devices
                        behind PCI-PCI bridge are reserved.
@@ -1364,12 +1365,6 @@ running once the system is up.
                        Run specified binary instead of /init from the ramdisk,
                        used for early userspace startup. See initrd.
 
-       reassigndev=    [PCI]
-                       Format: 
[<segment>:]<bus>:<dev>.<func>[,[<segment>:]<bus>:<dev>.<func>[,...]]
-                       Specifies device to reassign page-aligned memory
-                       resources. PCI-PCI bridge can be specified, if
-                       resource windows need to be expanded.
-
        reassign_resources
                        [PCI,ACPI] Use guestdev parameter to reassign device's
                        resources.
diff -r e5d3f2fa3428 drivers/pci/Makefile
--- a/drivers/pci/Makefile      Tue Apr 07 10:29:30 2009 +0100
+++ b/drivers/pci/Makefile      Wed Apr 08 16:14:56 2009 +0900
@@ -4,7 +4,6 @@
 
 obj-y          += access.o bus.o probe.o remove.o pci.o quirks.o \
                        pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
-obj-$(CONFIG_PCI_REASSIGN) += reassigndev.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
 
diff -r e5d3f2fa3428 drivers/pci/guestdev.c
--- a/drivers/pci/guestdev.c    Tue Apr 07 10:29:30 2009 +0100
+++ b/drivers/pci/guestdev.c    Wed Apr 08 16:14:56 2009 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, NEC Corporation.
+ * Copyright (c) 2008, 2009 NEC Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -32,21 +32,36 @@
 #define FUNC_NUM_MAX 7
 #define INVALID_SEG (-1)
 #define INVALID_BBN (-1)
-#define PATH_STR_MAX 128
+#define GUESTDEV_STR_MAX 128
+
+#define GUESTDEV_FLAG_TYPE_MASK 0x3
+#define GUESTDEV_FLAG_DEVICEPATH 0x1
+#define GUESTDEV_FLAG_SBDF 0x2
 
 struct guestdev {
+       int flags;
        struct list_head root_list;
-       char hid[HID_LEN + 1];
-       char uid[UID_LEN + 1];
-       int seg;
-       int bbn;
-       struct guestdev_node *child;
+       union {
+               struct devicepath {
+                       char hid[HID_LEN + 1];
+                       char uid[UID_LEN + 1];
+                       int seg;
+                       int bbn;
+                       struct devicepath_node *child;
+               } devicepath;
+               struct sbdf {
+                       int seg;
+                       int bus;
+                       int dev;
+                       int func;
+               } sbdf;
+       } u;
 };
 
-struct guestdev_node {
+struct devicepath_node {
        int dev;
        int func;
-       struct guestdev_node *child;
+       struct devicepath_node *child;
 };
 
 struct pcidev_sbdf {
@@ -67,7 +82,7 @@ LIST_HEAD(guestdev_list);
 LIST_HEAD(guestdev_list);
 
 /* Get hid and uid */
-static int pci_get_hid_uid(char *str, char *hid, char *uid)
+static int __init pci_get_hid_uid(char *str, char *hid, char *uid)
 {
        char *sp, *ep;
        int len;
@@ -111,7 +126,7 @@ format_err_end:
 }
 
 /* Get device and function */
-static int pci_get_dev_func(char *str, int *dev, int *func)
+static int __init pci_get_dev_func(char *str, int *dev, int *func)
 {
        if (sscanf(str, "%02x.%01x", dev, func) != 2)
                goto format_err_end;
@@ -129,7 +144,7 @@ format_err_end:
 }
 
 /* Check extended guestdev parameter format error */
-static int pci_check_extended_guestdev_format(char *str)
+static int __init pci_check_extended_guestdev_format(char *str)
 {
        int flg;
        char *p;
@@ -184,74 +199,75 @@ format_err_end:
 }
 
 /* Make guestdev strings */
-static void pci_make_guestdev_path_str(struct guestdev *gdev,
+static void pci_make_guestdev_str(struct guestdev *gdev,
                                        char *gdev_str, int buf_size)
 {
-       struct guestdev_node *node;
-       /* max length for "HID:UID" (hid+uid+':'+'\0') */
-       const int hid_uid_len = HID_LEN + UID_LEN + 2;
-       /* max length for "-DEV#.FUNC#" (dev+func+'-'+'.'+'\0') */
-       const int dev_func_len = DEV_LEN + FUNC_LEN + 3;
+       struct devicepath_node *node;
+       int count;
 
-       /* check buffer size for HID:UID */
-       if (buf_size < hid_uid_len)
-               return;
+       switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+       case GUESTDEV_FLAG_DEVICEPATH:
+               memset(gdev_str, 0, buf_size);
 
-       memset(gdev_str, 0, buf_size);
+               if (strlen(gdev->u.devicepath.uid))
+                       count = snprintf(gdev_str, buf_size, "%s:%s",
+                                               gdev->u.devicepath.hid,
+                                               gdev->u.devicepath.uid);
+               else
+                       count = snprintf(gdev_str, buf_size, "%s",
+                                                gdev->u.devicepath.hid);
+               if (count < 0)
+                       return;
 
-       if (strlen(gdev->uid))
-               sprintf(gdev_str, "%s:%s", gdev->hid, gdev->uid);
-       else
-               sprintf(gdev_str, "%s", gdev->hid);
-       buf_size -= strlen(gdev_str);
-
-       node = gdev->child;
-       while (node) {
-               /* check buffer size for -DEV#.FUNC# */
-               if (buf_size < dev_func_len)
-                       return;
-               sprintf(gdev_str + strlen(gdev_str), "-%02x.%01x",
-                       node->dev, node->func);
-               buf_size -= dev_func_len;
-               node = node->child;
+               node = gdev->u.devicepath.child;
+               while (node) {
+                       gdev_str += count;
+                       buf_size -= count;
+                       if (buf_size <= 0)
+                               return;
+                       count = snprintf(gdev_str, buf_size, "-%02x.%01x",
+                               node->dev, node->func);
+                       if (count < 0)
+                               return;
+                       node = node->child;
+               }
+               break;
+       case GUESTDEV_FLAG_SBDF:
+               snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x",
+                                       gdev->u.sbdf.seg, gdev->u.sbdf.bus,
+                                       gdev->u.sbdf.dev, gdev->u.sbdf.func);
+               break;
+       default:
+               BUG();
        }
 }
 
 /* Free guestdev and nodes */
-static void pci_free_guestdev(struct guestdev *gdev)
+static void __init pci_free_guestdev(struct guestdev *gdev)
 {
-       struct guestdev_node *node, *next;
+       struct devicepath_node *node, *next;
 
        if (!gdev)
                return;
-
-       node = gdev->child;
-       while (node) {
-               next = node->child;
-               kfree(node);
-               node = next;
+       if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) {
+               node = gdev->u.devicepath.child;
+               while (node) {
+                       next = node->child;
+                       kfree(node);
+                       node = next;
+               }
        }
        list_del(&gdev->root_list);
        kfree(gdev);
 }
 
-/* Free guestdev_list */
-static void pci_free_guestdev_list(void)
-{
-       struct list_head *head, *tmp;
-       struct guestdev *gdev;
-
-       list_for_each_safe(head, tmp, &guestdev_list) {
-               gdev = list_entry(head, struct guestdev, root_list);
-               pci_free_guestdev(gdev);
-       }
-}
-
 /* Copy guestdev and nodes */
-struct guestdev *pci_copy_guestdev(struct guestdev *gdev_src)
+struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
 {
        struct guestdev *gdev;
-       struct guestdev_node *node, *node_src, *node_upper;
+       struct devicepath_node *node, *node_src, *node_upper;
+
+       BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH));
 
        gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
        if (!gdev)
@@ -259,14 +275,15 @@ struct guestdev *pci_copy_guestdev(struc
 
        memset(gdev, 0, sizeof(*gdev));
        INIT_LIST_HEAD(&gdev->root_list);
-       strcpy(gdev->hid, gdev_src->hid);
-       strcpy(gdev->uid, gdev_src->uid);
-       gdev->seg = gdev_src->seg;
-       gdev->bbn = gdev_src->bbn;
+       gdev->flags = gdev_src->flags;
+       strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
+       strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
+       gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
+       gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn;
 
        node_upper = NULL;
 
-       node_src = gdev_src->child;
+       node_src = gdev_src->u.devicepath.child;
        while (node_src) {
                node = kmalloc(sizeof(*node), GFP_KERNEL);
                if (!node)
@@ -275,7 +292,7 @@ struct guestdev *pci_copy_guestdev(struc
                node->dev = node_src->dev;
                node->func = node_src->func;
                if (!node_upper)
-                       gdev->child = node;
+                       gdev->u.devicepath.child = node;
                else
                        node_upper->child = node;
                node_upper = node;
@@ -292,12 +309,12 @@ allocate_err_end:
 }
 
 /* Make guestdev from path strings */
-static int pci_make_guestdev(char *path_str)
+static int __init pci_make_devicepath_guestdev(char *path_str)
 {
        char hid[HID_LEN + 1], uid[UID_LEN + 1];
        char *sp, *ep;
        struct guestdev *gdev, *gdev_org;
-       struct guestdev_node *node, *node_tmp;
+       struct devicepath_node *node, *node_tmp;
        int dev, func, ret_val;
 
        ret_val = 0;
@@ -319,10 +336,11 @@ static int pci_make_guestdev(char *path_
                goto allocate_err_end;
        memset(gdev_org, 0, sizeof(*gdev_org));
        INIT_LIST_HEAD(&gdev_org->root_list);
-       strcpy(gdev_org->hid, hid);
-       strcpy(gdev_org->uid, uid);
-       gdev_org->seg = INVALID_SEG;
-       gdev_org->bbn = INVALID_BBN;
+       gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
+       strcpy(gdev_org->u.devicepath.hid, hid);
+       strcpy(gdev_org->u.devicepath.uid, uid);
+       gdev_org->u.devicepath.seg = INVALID_SEG;
+       gdev_org->u.devicepath.bbn = INVALID_BBN;
 
        gdev = gdev_org;
 
@@ -335,12 +353,12 @@ static int pci_make_guestdev(char *path_
                                gdev = pci_copy_guestdev(gdev_org);
                                if (!gdev) {
                                        ret_val = -ENOMEM;
-                                       goto err_end;
+                                       goto end;
                                }
                        }
                        continue;
                }
-               if (pci_get_dev_func(sp, &dev, &func)) {
+               if (gdev && pci_get_dev_func(sp, &dev, &func)) {
                        node = kmalloc(sizeof(*node), GFP_KERNEL);
                        if (!node)
                                goto allocate_err_end;
@@ -348,33 +366,47 @@ static int pci_make_guestdev(char *path_
                        node->dev = dev;
                        node->func = func;
                        /* add node to end of guestdev */
-                       if (gdev->child) {
-                               node_tmp = gdev->child;
+                       if (gdev->u.devicepath.child) {
+                               node_tmp = gdev->u.devicepath.child;
                                while (node_tmp->child) {
                                        node_tmp = node_tmp->child;
                                }
                                node_tmp->child = node;
                        } else
-                               gdev->child = node;
-               } else
-                       goto format_err_end;
+                               gdev->u.devicepath.child = node;
+               } else if (gdev) {
+                       printk(KERN_ERR
+                               "PCI: Can't obtain dev# and #func# from %s.\n",
+                               sp);
+                       ret_val = -EINVAL;
+                       if (gdev == gdev_org)
+                               goto end;
+                       pci_free_guestdev(gdev);
+                       gdev = NULL;
+               }
 
                ep = strpbrk(sp, "-|)");
                if (!ep)
                        ep = strchr(sp, '\0');
-               /* *ep is '|' OR ')' OR '\0' ? */
+               /* Is *ep '|' OR ')' OR '\0' ? */
                if (*ep != '-') {
-                       list_add_tail(&gdev->root_list, &guestdev_list);
+                       if (gdev)
+                               list_add_tail(&gdev->root_list, &guestdev_list);
                        if (*ep == '|') {
                                /* Between '|' and '|' ? */
                                if (strchr(ep + 1, '|')) {
                                        gdev = pci_copy_guestdev(gdev_org);
                                        if (!gdev) {
                                                ret_val = -ENOMEM;
-                                               goto err_end;
+                                               goto end;
                                        }
-                               } else
+                               } else {
                                        gdev = gdev_org;
+                                       gdev_org = NULL;
+                               }
+                       } else {
+                               gdev_org = NULL;
+                               gdev = NULL;
                        }
                }
                if (*ep == ')')
@@ -382,21 +414,21 @@ static int pci_make_guestdev(char *path_
                sp = ep + 1;
        } while (*ep != '\0');
 
-       return ret_val;
+       goto end;
 
 format_err_end:
        printk(KERN_ERR
                "PCI: The format of the guestdev parameter is illegal. [%s]\n",
                path_str);
        ret_val = -EINVAL;
-       goto err_end;
+       goto end;
 
 allocate_err_end:
        printk(KERN_ERR "PCI: Failed to allocate memory.\n");
        ret_val = -ENOMEM;
-       goto err_end;
+       goto end;
 
-err_end:
+end:
        if (gdev_org && (gdev_org != gdev))
                pci_free_guestdev(gdev_org);
        if (gdev)
@@ -404,20 +436,44 @@ err_end:
        return ret_val;
 }
 
+static int __init pci_make_sbdf_guestdev(char* str)
+{
+       struct guestdev *gdev;
+       int seg, bus, dev, func;
+
+       if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) {
+               seg = 0;
+               if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3)
+                       return -EINVAL;
+       }
+       gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
+       if (!gdev) {
+               printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+               return -ENOMEM;
+       }
+       INIT_LIST_HEAD(&gdev->root_list);
+       gdev->flags = GUESTDEV_FLAG_SBDF;
+       gdev->u.sbdf.seg = seg;
+       gdev->u.sbdf.bus = bus;
+       gdev->u.sbdf.dev = dev;
+       gdev->u.sbdf.func = func;
+       list_add_tail(&gdev->root_list, &guestdev_list);
+       return 0;
+}
+
 /* Parse guestdev parameter */
 static int __init pci_parse_guestdev(void)
 {
-       int len, ret_val;
+       int len;
        char *sp, *ep;
        struct list_head *head;
        struct guestdev *gdev;
-       char path_str[PATH_STR_MAX];
-
-       ret_val = 0;
+       char path_str[GUESTDEV_STR_MAX];
+       int ret_val = 0;
 
        len = strlen(guestdev_param);
        if (len == 0)
-               goto end;
+               return 0;
 
        sp = guestdev_param;
 
@@ -426,29 +482,26 @@ static int __init pci_parse_guestdev(voi
                /* Chop */
                if (ep)
                        *ep = '\0';
-               if (!pci_check_extended_guestdev_format(sp)) {
-                       pci_free_guestdev_list();
-                       return -EINVAL;
-               }
-
-               ret_val = pci_make_guestdev(sp);
-               if (ret_val) {
-                       pci_free_guestdev_list();
-                       return ret_val;
-               }
+               ret_val = pci_make_sbdf_guestdev(sp);
+               if (ret_val == -EINVAL) {
+                       if (pci_check_extended_guestdev_format(sp)) {
+                               ret_val = pci_make_devicepath_guestdev(sp);
+                               if (ret_val && ret_val != -EINVAL)
+                                       break;
+                       }
+               } else if (ret_val)
+                       break;
                sp = ep + 1;
        } while (ep);
 
        list_for_each(head, &guestdev_list) {
                gdev = list_entry(head, struct guestdev, root_list);
-               pci_make_guestdev_path_str(gdev, path_str, PATH_STR_MAX);
+               pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
                printk(KERN_DEBUG
                        "PCI: %s has been reserved for guest domain.\n",
                        path_str);
        }
-
-end:
-       return ret_val;
+       return 0;
 }
 
 arch_initcall(pci_parse_guestdev);
@@ -478,32 +531,35 @@ static void pci_free_sbdf(struct pcidev_
        /* Skip kfree(sbdf) */
 }
 
-/* Is sbdf within guestdev */
-static int pci_sbdf_in_guestdev_sub_tree(struct guestdev *gdev, 
+/* Does PCI device belong to sub tree specified by guestdev with device path? 
*/
+static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
                                        struct pcidev_sbdf *sbdf)
 {
        int seg, bbn;
-       struct guestdev_node *gdev_node;
+       struct devicepath_node *gdev_node;
        struct pcidev_sbdf_node *sbdf_node;
 
        if (!gdev || !sbdf)
                return FALSE;
 
+       BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
+
        /* Compare seg and bbn */
-       if (gdev->seg == INVALID_SEG || 
-           gdev->bbn == INVALID_BBN) {
-               if (acpi_pci_get_root_seg_bbn(gdev->hid, 
-                   gdev->uid, &seg, &bbn)) {
-                       gdev->seg = seg;
-                       gdev->bbn = bbn;
+       if (gdev->u.devicepath.seg == INVALID_SEG ||
+           gdev->u.devicepath.bbn == INVALID_BBN) {
+               if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid,
+                   gdev->u.devicepath.uid, &seg, &bbn)) {
+                       gdev->u.devicepath.seg = seg;
+                       gdev->u.devicepath.bbn = bbn;
                } else
                        return FALSE;
        }
 
-       if (gdev->seg != sbdf->seg || gdev->bbn != sbdf->bus)
+       if (gdev->u.devicepath.seg != sbdf->seg ||
+           gdev->u.devicepath.bbn != sbdf->bus)
                return FALSE;
 
-       gdev_node = gdev->child;
+       gdev_node = gdev->u.devicepath.child;
        sbdf_node = sbdf->child;
 
        /* Compare dev and func */
@@ -559,29 +615,64 @@ err_end:
        return FALSE;
 }
 
-/* Is PCI device belongs to the subtree of the guestdev parameter */
+/* Does PCI device belong to sub tree specified by guestdev with sbdf? */
+static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev)
+{
+       int seg, bus;
+       BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
+       for (;;) {
+               if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
+                       continue;
+               if (gdev->u.sbdf.seg == seg && gdev->u.sbdf.bus == bus &&
+                       gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
+                       gdev->u.sbdf.func == PCI_FUNC(dev->devfn))
+                       return TRUE;
+               if (!dev->bus || !dev->bus->self)
+                       break;
+               dev = dev->bus->self;
+       }
+       return FALSE;
+}
+
+/* Does PCI device belong to sub tree specified by guestdev parameter? */
 int pci_is_guestdev(struct pci_dev *dev)
 {
        struct guestdev *gdev;
-       struct pcidev_sbdf sbdf;
+       struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
        struct list_head *head;
-       int result;
+       int result = FALSE;
 
        if (!dev)
                return FALSE;
-       memset(&sbdf, 0 ,sizeof(sbdf));
-       if (!pci_get_sbdf_from_pcidev(dev, &sbdf))
-               return FALSE;
 
-       result = FALSE;
        list_for_each(head, &guestdev_list) {
                gdev = list_entry(head, struct guestdev, root_list);
-               if (pci_sbdf_in_guestdev_sub_tree(gdev, &sbdf)) {
-                       result = TRUE;
+               switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+               case GUESTDEV_FLAG_DEVICEPATH:
+                       if (sbdf == NULL) {
+                               sbdf = &pcidev_sbdf;
+                               memset(sbdf, 0 ,sizeof(*sbdf));
+                               if (!pci_get_sbdf_from_pcidev(dev, sbdf))
+                                       goto out;
+                       }
+                       if (pci_is_in_devicepath_sub_tree(gdev, sbdf)) {
+                               result = TRUE;
+                               goto out;
+                       }
                        break;
+               case GUESTDEV_FLAG_SBDF:
+                       if (pci_is_in_sbdf_sub_tree(gdev, dev)) {
+                               result = TRUE;
+                               goto out;
+                       }
+                       break;
+               default:
+                       BUG();
                }
        }
-       pci_free_sbdf(&sbdf);
+out:
+       if (sbdf)
+               pci_free_sbdf(sbdf);
        return result;
 }
 EXPORT_SYMBOL(pci_is_guestdev);
@@ -595,30 +686,30 @@ static int __init pci_set_reassign_resou
 
 __setup("reassign_resources", pci_set_reassign_resources);
 
-int pci_is_guestdev_to_reassign(struct pci_dev *dev)
+int pci_is_reassigndev(struct pci_dev *dev)
 {
        if (reassign_resources)
                return pci_is_guestdev(dev);
        return FALSE;
 }
-EXPORT_SYMBOL(pci_is_guestdev_to_reassign);
+EXPORT_SYMBOL(pci_is_reassigndev);
 
-/* Check whether the guestdev exists under the pci root bus */
-static int __init pci_check_guestdev_path_exists(
+/* Check whether the devicepath exists under the pci root bus */
+static int __init pci_check_devicepath_exists(
                struct guestdev *gdev, struct pci_bus *bus)
 {
-       struct guestdev_node *node;
+       struct devicepath_node *node;
        struct pci_dev *dev;
 
-       node = gdev->child;
+       BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
+
+       node = gdev->u.devicepath.child;
        while (node) {
                if (!bus)
                        return FALSE;
                dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
-               if (!dev) {
-                       pci_dev_put(dev);
+               if (!dev)
                        return FALSE;
-               }
                bus = dev->subordinate;
                node = node->child;
                pci_dev_put(dev);
@@ -633,32 +724,58 @@ static int __init pci_check_guestdev_exi
        struct guestdev *gdev;
        int seg, bbn;
        struct pci_bus *bus;
-       char path_str[PATH_STR_MAX];
+       struct pci_dev *dev;
+       char path_str[GUESTDEV_STR_MAX];
 
        list_for_each(head, &guestdev_list) {
                gdev = list_entry(head, struct guestdev, root_list);
-               if (gdev->seg == INVALID_SEG ||
-                       gdev->bbn == INVALID_BBN) {
-                       if (acpi_pci_get_root_seg_bbn(gdev->hid,
-                               gdev->uid, &seg, &bbn)) {
-                               gdev->seg = seg;
-                               gdev->bbn = bbn;
-                       } else {
-                               pci_make_guestdev_path_str(gdev, path_str,
-                                       PATH_STR_MAX);
+               switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+               case GUESTDEV_FLAG_DEVICEPATH:
+                       if (gdev->u.devicepath.seg == INVALID_SEG ||
+                               gdev->u.devicepath.bbn == INVALID_BBN) {
+                               if (acpi_pci_get_root_seg_bbn(
+                                       gdev->u.devicepath.hid,
+                                       gdev->u.devicepath.uid, &seg, &bbn)) {
+                                       gdev->u.devicepath.seg = seg;
+                                       gdev->u.devicepath.bbn = bbn;
+                               } else {
+                                       pci_make_guestdev_str(gdev,
+                                               path_str, GUESTDEV_STR_MAX);
+                                       printk(KERN_INFO
+                                       "PCI: Device does not exist. %s\n",
+                                       path_str);
+                                       continue;
+                               }
+                       }
+
+                       bus = pci_find_bus(gdev->u.devicepath.seg,
+                                               gdev->u.devicepath.bbn);
+                       if (!bus ||
+                               !pci_check_devicepath_exists(gdev, bus)) {
+                               pci_make_guestdev_str(gdev, path_str,
+                                       GUESTDEV_STR_MAX);
                                printk(KERN_INFO
                                        "PCI: Device does not exist. %s\n",
                                        path_str);
-                               continue;
                        }
-               }
-
-               bus = pci_find_bus(gdev->seg, gdev->bbn);
-               if (!bus || !pci_check_guestdev_path_exists(gdev, bus)) {
-                       pci_make_guestdev_path_str(gdev, path_str,
-                               PATH_STR_MAX);
-                       printk(KERN_INFO
-                               "PCI: Device does not exist. %s\n", path_str);
+                       break;
+               case GUESTDEV_FLAG_SBDF:
+                       bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus);
+                       if (bus) {
+                               dev = pci_get_slot(bus,
+                                       PCI_DEVFN(gdev->u.sbdf.dev,
+                                                       gdev->u.sbdf.func));
+                               if (dev) {
+                                       pci_dev_put(dev);
+                                       continue;
+                               }
+                       }
+                       pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
+                       printk(KERN_INFO "PCI: Device does not exist. %s\n",
+                                                               path_str);
+                       break;
+               default:
+                       BUG();
                }
        }
        return 0;
diff -r e5d3f2fa3428 drivers/pci/pci.h
--- a/drivers/pci/pci.h Tue Apr 07 10:29:30 2009 +0100
+++ b/drivers/pci/pci.h Wed Apr 08 16:14:56 2009 +0900
@@ -102,8 +102,10 @@ pci_match_one_device(const struct pci_de
 }
 
 #ifdef CONFIG_PCI_REASSIGN
+extern void pci_disable_bridge_window(struct pci_dev *dev);
+#endif
+#ifdef CONFIG_PCI_GUESTDEV
 extern int pci_is_reassigndev(struct pci_dev *dev);
-extern void pci_disable_bridge_window(struct pci_dev *dev);
 #else
 #define pci_is_reassigndev(dev) 0
 #endif
diff -r e5d3f2fa3428 drivers/pci/reassigndev.c
--- a/drivers/pci/reassigndev.c Tue Apr 07 10:29:30 2009 +0100
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2008, NEC Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include "pci.h"
-
-
-#define        REASSIGNDEV_PARAM_MAX   (2048)
-#define        TOKEN_MAX       (12)    /* "SSSS:BB:DD.F" length is 12 */
-
-static char param_reassigndev[REASSIGNDEV_PARAM_MAX] = {0};
-
-static int __init pci_reassigndev_setup(char *str)
-{
-       strncpy(param_reassigndev, str, REASSIGNDEV_PARAM_MAX);
-       param_reassigndev[REASSIGNDEV_PARAM_MAX - 1] = '\0';
-       return 1;
-}
-__setup("reassigndev=", pci_reassigndev_setup);
-
-int pci_is_reassigndev(struct pci_dev *dev)
-{
-       char dev_str[TOKEN_MAX+1];
-       int seg, bus, slot, func;
-       int len;
-       char *p, *next_str;
-       int result;
-
-#ifdef CONFIG_PCI_GUESTDEV
-       result = pci_is_guestdev_to_reassign(dev);
-       if (result)
-               return  result;
-#endif /* CONFIG_PCI_GUESTDEV */
-
-       p = param_reassigndev;
-       for (; p; p = next_str + 1) {
-               next_str = strpbrk(p, ",");
-               if (next_str) {
-                       len = next_str - p;
-               } else {
-                       len = strlen(p);
-               }
-               if (len > 0 && len <= TOKEN_MAX) {
-                       strncpy(dev_str, p, len);
-                       *(dev_str + len) = '\0';
-
-                       if (sscanf(dev_str, "%x:%x:%x.%x", 
-                               &seg, &bus, &slot, &func) != 4) {
-                               if (sscanf(dev_str, "%x:%x.%x", 
-                                       &bus, &slot, &func) == 3) {
-                                       seg = 0;
-                               } else {
-                                       /* failed to scan strings */
-                                       seg = -1;
-                                       bus = -1;
-                               }
-                       }
-                       if (seg == pci_domain_nr(dev->bus) &&
-                           bus == dev->bus->number &&
-                           slot == PCI_SLOT(dev->devfn) &&
-                           func == PCI_FUNC(dev->devfn)) {
-                               /* It's a target device */
-                               return 1;
-                       }
-               }
-               if (!next_str)
-                       break;
-       }
-
-       return 0;
-}


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