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

[Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 14 Apr 2009 13:05:04 -0700
Delivery-date: Tue, 14 Apr 2009 13:05:37 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1239685530 -32400
# Node ID e75edb8d2c441434b03d098873d0bb7d0b029c1c
# Parent  b8bef3d2d3c37043c8c554c87aa5be7c63bc0957
# Parent  a3ad7a5f2dcd1486264ece9e1772a3713d700e91
merge with linux-2.6.18-xen.hg
---
 drivers/pci/reassigndev.c           |   87 ------
 Documentation/kernel-parameters.txt |   11 
 drivers/pci/Makefile                |    1 
 drivers/pci/guestdev.c              |  449 ++++++++++++++++++++++--------------
 drivers/pci/pci.h                   |    4 
 drivers/xen/netfront/accel.c        |   43 ++-
 6 files changed, 317 insertions(+), 278 deletions(-)

diff -r b8bef3d2d3c3 -r e75edb8d2c44 Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt       Tue Apr 07 11:31:17 2009 +0900
+++ b/Documentation/kernel-parameters.txt       Tue Apr 14 14:05:30 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 b8bef3d2d3c3 -r e75edb8d2c44 drivers/pci/Makefile
--- a/drivers/pci/Makefile      Tue Apr 07 11:31:17 2009 +0900
+++ b/drivers/pci/Makefile      Tue Apr 14 14:05:30 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 b8bef3d2d3c3 -r e75edb8d2c44 drivers/pci/guestdev.c
--- a/drivers/pci/guestdev.c    Tue Apr 07 11:31:17 2009 +0900
+++ b/drivers/pci/guestdev.c    Tue Apr 14 14:05:30 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;
-
-       /* check buffer size for HID:UID */
-       if (buf_size < hid_uid_len)
-               return;
-
-       memset(gdev_str, 0, buf_size);
-
-       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)
+       struct devicepath_node *node;
+       int count;
+
+       switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+       case GUESTDEV_FLAG_DEVICEPATH:
+               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;
-               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)
-{
-       struct guestdev_node *node, *next;
+static void __init pci_free_guestdev(struct guestdev *gdev)
+{
+       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;
+/* Copy guestdev and nodes */
+struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
+{
        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 *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;
-
-err_end:
+       goto 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;
-                       break;
-               }
-       }
-       pci_free_sbdf(&sbdf);
+               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();
+               }
+       }
+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);
-
-/* Check whether the guestdev exists under the pci root bus */
-static int __init pci_check_guestdev_path_exists(
+EXPORT_SYMBOL(pci_is_reassigndev);
+
+/* 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 b8bef3d2d3c3 -r e75edb8d2c44 drivers/pci/pci.h
--- a/drivers/pci/pci.h Tue Apr 07 11:31:17 2009 +0900
+++ b/drivers/pci/pci.h Tue Apr 14 14:05:30 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 b8bef3d2d3c3 -r e75edb8d2c44 drivers/pci/reassigndev.c
--- a/drivers/pci/reassigndev.c Tue Apr 07 11:31:17 2009 +0900
+++ /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;
-}
diff -r b8bef3d2d3c3 -r e75edb8d2c44 drivers/xen/netfront/accel.c
--- a/drivers/xen/netfront/accel.c      Tue Apr 07 11:31:17 2009 +0900
+++ b/drivers/xen/netfront/accel.c      Tue Apr 14 14:05:30 2009 +0900
@@ -50,6 +50,8 @@ static int netfront_load_accelerator(str
 static int netfront_load_accelerator(struct netfront_info *np, 
                                     struct xenbus_device *dev, 
                                     const char *frontend);
+
+static void netfront_accelerator_remove_watch(struct netfront_info *np);
 
 /*
  * List of all netfront accelerator plugin modules available.  Each
@@ -164,8 +166,11 @@ void netfront_accelerator_add_watch(stru
 {
        int err;
        
-       /* Check we're not trying to overwrite an existing watch */
-       BUG_ON(np->accel_vif_state.accel_watch.node != NULL);
+       /* 
+        * If old watch exists, e.g. from before suspend/resume,
+        * remove it now 
+        */
+       netfront_accelerator_remove_watch(np);
 
        /* Get a watch on the accelerator plugin */
        err = xenbus_watch_path2(np->xbdev, np->xbdev->otherend, 
@@ -180,6 +185,19 @@ void netfront_accelerator_add_watch(stru
 }
 
 
+static void 
+netfront_accelerator_purge_watch(struct netfront_accel_vif_state *vif_state)
+{
+       flush_workqueue(accel_watch_workqueue);
+
+       /* Clean up any state left from watch */
+       if (vif_state->accel_frontend != NULL) {
+               kfree(vif_state->accel_frontend);
+               vif_state->accel_frontend = NULL;
+       }
+}
+
+
 static
 void netfront_accelerator_remove_watch(struct netfront_info *np)
 {
@@ -191,13 +209,7 @@ void netfront_accelerator_remove_watch(s
                kfree(vif_state->accel_watch.node);
                vif_state->accel_watch.node = NULL;
 
-               flush_workqueue(accel_watch_workqueue);
-
-               /* Clean up any state left from watch */
-               if (vif_state->accel_frontend != NULL) {
-                       kfree(vif_state->accel_frontend);
-                       vif_state->accel_frontend = NULL;
-               }
+               netfront_accelerator_purge_watch(vif_state);
        }       
 }
 
@@ -670,8 +682,6 @@ int netfront_accelerator_suspend(struct 
 {
        int rc = 0;
        
-       netfront_accelerator_remove_watch(np);
-
        mutex_lock(&accelerator_mutex);
 
        /* Check that we've got a device that was accelerated */
@@ -692,13 +702,16 @@ int netfront_accelerator_suspend_cancel(
 int netfront_accelerator_suspend_cancel(struct netfront_info *np,
                                        struct xenbus_device *dev)
 {
+       netfront_accelerator_purge_watch(&np->accel_vif_state);
+
        /* 
-        * Setting the watch will cause it to fire and probe the
-        * accelerator, so no need to call accelerator_probe_new_vif()
-        * directly here
+        * Gratuitously fire the watch handler to reinstate the
+        * configured accelerator
         */
        if (dev->state == XenbusStateConnected)
-               netfront_accelerator_add_watch(np);
+               queue_work(accel_watch_workqueue, 
+                          &np->accel_vif_state.accel_work);
+
        return 0;
 }
 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg, Xen patchbot-linux-2.6.18-xen <=