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

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



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


 


Rackspace

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