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: Thu, 08 Jan 2009 06:58:15 -0800
Delivery-date: Thu, 08 Jan 2009 07:06:34 -0800
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 1231298514 -32400
# Node ID 28acedb66302a29c9ef14a3084b4736d3fc192f1
# Parent  79bf5894b3f93e5742a43d05572156b23e8fffbe
# Parent  79e82ae1bad02c0dfb504db3153599e52a0affb3
merge with linux-2.6.18-xen.hg
---
 Documentation/kernel-parameters.txt |   15 
 drivers/acpi/pci_root.c             |   65 +++
 drivers/acpi/scan.c                 |   47 +-
 drivers/pci/Kconfig                 |    7 
 drivers/pci/Makefile                |    1 
 drivers/pci/guestdev.c              |  668 ++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.h                   |    8 
 drivers/pci/quirks.c                |    2 
 drivers/pci/reassigndev.c           |   13 
 drivers/pci/setup-bus.c             |    2 
 drivers/pci/setup-res.c             |    6 
 drivers/xen/evtchn/evtchn.c         |   18 
 drivers/xen/pciback/pci_stub.c      |   10 
 include/acpi/acpi_bus.h             |   10 
 include/asm-x86_64/setup.h          |    2 
 include/linux/acpi.h                |    1 
 include/linux/pci.h                 |    4 
 17 files changed, 850 insertions(+), 29 deletions(-)

diff -r 79bf5894b3f9 -r 28acedb66302 Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt       Mon Jan 05 14:13:49 2009 +0900
+++ b/Documentation/kernel-parameters.txt       Wed Jan 07 12:21:54 2009 +0900
@@ -1240,6 +1240,21 @@ running once the system is up.
                                bootloader. This is currently used on
                                IXP2000 systems where the bus has to be
                                configured a certain way for adjunct CPUs.
+               reassigndev=
+                               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
+                               Use guestdev parameter to reassign device's
+                               resources.
+               guestdev=
+                               Format: <device path>[,<device path>[,...]]
+                               Format of device path: 
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[...]]
+                               Specifies PCI device for guest domain.
+                               If PCI-PCI bridge is specified, all
+                               PCI devices behind PCI-PCI bridge are
+                               reserved.
 
        pcmv=           [HW,PCMCIA] BadgePAD 4
 
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/acpi/pci_root.c
--- a/drivers/acpi/pci_root.c   Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/acpi/pci_root.c   Wed Jan 07 12:21:54 2009 +0900
@@ -151,6 +151,36 @@ static acpi_status try_get_root_bridge_b
        return AE_OK;
 }
 
+ssize_t
+acpi_device_seg_show(struct acpi_device *acpi_dev, char *buf) 
+{
+       struct list_head *entry;
+
+       list_for_each(entry, &acpi_pci_roots) {
+               struct acpi_pci_root *root;
+               root = list_entry(entry, struct acpi_pci_root, node);
+               if (root->device == acpi_dev)
+                       return sprintf(buf, "%04x\n", root->id.segment);
+       }
+       return 0;
+}
+ACPI_DEVICE_ATTR(seg, 0444, acpi_device_seg_show, NULL);
+
+ssize_t
+acpi_device_bbn_show(struct acpi_device *acpi_dev, char *buf) 
+{
+       struct list_head *entry;
+
+       list_for_each(entry, &acpi_pci_roots) {
+               struct acpi_pci_root *root;
+               root = list_entry(entry, struct acpi_pci_root, node);
+               if (root->device == acpi_dev)
+                       return sprintf(buf, "%02x\n", root->id.bus);
+       }
+       return 0;
+}
+ACPI_DEVICE_ATTR(bbn, 0444, acpi_device_bbn_show, NULL);
+
 static int acpi_pci_root_add(struct acpi_device *device)
 {
        int result = 0;
@@ -298,6 +328,12 @@ static int acpi_pci_root_add(struct acpi
        if (ACPI_SUCCESS(status))
                result = acpi_pci_irq_add_prt(device->handle, root->id.segment,
                                              root->id.bus);
+       if (result)
+               goto end;
+
+       sysfs_create_file(&device->kobj, &acpi_device_attr_seg.attr);
+
+       sysfs_create_file(&device->kobj, &acpi_device_attr_bbn.attr);
 
       end:
        if (result) {
@@ -356,3 +392,32 @@ static int __init acpi_pci_root_init(voi
 }
 
 subsys_initcall(acpi_pci_root_init);
+
+int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn)
+{
+       struct list_head *entry;
+
+       list_for_each(entry, &acpi_pci_roots) {
+               struct acpi_pci_root *root;
+               root = list_entry(entry, struct acpi_pci_root, node);
+               if (!root->device->flags.hardware_id)
+                       continue;
+
+               if (strcmp(root->device->pnp.hardware_id, hid))
+                       continue;
+
+               if (!root->device->flags.unique_id) {
+                       if (strlen(uid))
+                               continue;
+               } else {
+                       if (strcmp(root->device->pnp.unique_id, uid))
+                               continue;
+               }
+
+               *seg = (int)root->id.segment;
+               *bbn = (int)root->id.bus;
+               return TRUE;
+       }
+       return FALSE;
+}
+EXPORT_SYMBOL(acpi_pci_get_root_seg_bbn);
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/acpi/scan.c
--- a/drivers/acpi/scan.c       Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/acpi/scan.c       Wed Jan 07 12:21:54 2009 +0900
@@ -31,12 +31,6 @@ static void acpi_device_release(struct k
        kfree(dev->pnp.cid_list);
        kfree(dev);
 }
-
-struct acpi_device_attribute {
-       struct attribute attr;
-        ssize_t(*show) (struct acpi_device *, char *);
-        ssize_t(*store) (struct acpi_device *, const char *, size_t);
-};
 
 typedef void acpi_device_sysfs_files(struct kobject *,
                                     const struct attribute *);
@@ -110,6 +104,42 @@ static struct kset acpi_namespace_kset =
        .ktype = &ktype_acpi_ns,
        .uevent_ops = &namespace_uevent_ops,
 };
+
+static ssize_t
+acpi_device_hid_show(struct acpi_device *acpi_dev, char *buf) 
+{
+       return sprintf(buf, "%s\n", acpi_dev->pnp.hardware_id);
+}
+ACPI_DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+
+static ssize_t
+acpi_device_uid_show(struct acpi_device *acpi_dev, char *buf) 
+{
+       return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+ACPI_DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+
+static int acpi_device_setup_files(struct acpi_device *dev)
+{
+       int result = 0;
+
+       if (dev->flags.hardware_id) {
+               result = sysfs_create_file(&dev->kobj,
+                                       &acpi_device_attr_hid.attr);
+               if (result)
+                       goto end;
+       }
+
+       if (dev->flags.unique_id) {
+               result = sysfs_create_file(&dev->kobj,
+                                       &acpi_device_attr_uid.attr);
+               if (result)
+                       goto end;
+       }
+
+      end:
+       return result;
+}
 
 static void acpi_device_register(struct acpi_device *device,
                                 struct acpi_device *parent)
@@ -146,6 +176,7 @@ static void acpi_device_register(struct 
                printk(KERN_WARNING "%s: kobject_register error: %d\n",
                        __FUNCTION__, err);
        create_sysfs_device_files(device);
+       acpi_device_setup_files(device);
 }
 
 static void acpi_device_unregister(struct acpi_device *device, int type)
@@ -343,10 +374,6 @@ static int acpi_bus_get_wakeup_device_fl
    -------------------------------------------------------------------------- 
*/
 static ssize_t acpi_eject_store(struct acpi_device *device,
                                const char *buf, size_t count);
-
-#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
-static struct acpi_device_attribute acpi_device_attr_##_name = \
-               __ATTR(_name, _mode, _show, _store)
 
 ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
 
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/Kconfig
--- a/drivers/pci/Kconfig       Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/Kconfig       Wed Jan 07 12:21:54 2009 +0900
@@ -30,3 +30,10 @@ config PCI_DEBUG
 
          When in doubt, say N.
 
+config PCI_GUESTDEV
+       bool "PCI Device Reservation for Passthrough"
+       depends on PCI
+       default y
+       help
+         Say Y here if you want to reserve PCI device for passthrough.
+
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/Makefile
--- a/drivers/pci/Makefile      Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/Makefile      Wed Jan 07 12:21:54 2009 +0900
@@ -6,6 +6,7 @@ obj-y           += access.o bus.o probe.o remove.
                        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
 
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/guestdev.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/pci/guestdev.c    Wed Jan 07 12:21:54 2009 +0900
@@ -0,0 +1,668 @@
+/*
+ * 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/list.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <asm-x86_64/setup.h>
+
+#define HID_LEN 8
+#define UID_LEN 8
+#define DEV_LEN 2
+#define FUNC_LEN 1
+#define DEV_NUM_MAX 31
+#define FUNC_NUM_MAX 7
+#define INVALID_SEG (-1)
+#define INVALID_BBN (-1)
+#define PATH_STR_MAX 128
+
+struct guestdev {
+       struct list_head root_list;
+       char hid[HID_LEN + 1];
+       char uid[UID_LEN + 1];
+       int seg;
+       int bbn;
+       struct guestdev_node *child;
+};
+
+struct guestdev_node {
+       int dev;
+       int func;
+       struct guestdev_node *child;
+};
+
+struct pcidev_sbdf {
+       int seg;
+       int bus;
+       struct pcidev_sbdf_node *child;
+};
+
+struct pcidev_sbdf_node {
+       int dev;
+       int func;
+       struct pcidev_sbdf_node *child;
+};
+
+static int reassign_resources = 0;
+
+static char guestdev_param[COMMAND_LINE_SIZE];
+LIST_HEAD(guestdev_list);
+
+/* Get hid and uid */
+static int pci_get_hid_uid(char *str, char *hid, char *uid)
+{
+       char *sp, *ep;
+       int len;
+
+       sp = str;
+       ep = strchr(sp, ':');
+       if (!ep) {
+               ep = strchr(sp, '-');
+               if (!ep)
+                       goto format_err_end;
+       }
+       /* hid length */
+       len = ep - sp;
+       if (len <= 0 || HID_LEN < len)
+               goto format_err_end;
+
+       strncpy(hid, sp, len);
+       hid[len] = '\0';
+
+       if (*ep == '-') { /* no uid */
+               uid[0] = '\0';
+               return TRUE;
+       }
+
+       sp = ep + 1;
+       ep = strchr(sp, '-');
+       if (!ep)
+               ep = strchr(sp, '\0');
+
+       /* uid length */
+       len = ep - sp;
+       if (len <= 0 || UID_LEN < len)
+               goto format_err_end;
+
+       strncpy(uid, sp, len);
+       uid[len] = '\0';
+       return TRUE;
+
+format_err_end:
+       return FALSE;
+}
+
+/* Get device and function */
+static int pci_get_dev_func(char *str, int *dev, int *func)
+{
+       if (sscanf(str, "%02x.%01x", dev, func) != 2)
+               goto format_err_end;
+
+       if (*dev < 0 || DEV_NUM_MAX < *dev)
+               goto format_err_end;
+
+       if (*func < 0 || FUNC_NUM_MAX < *func)
+               goto format_err_end;
+
+       return TRUE;
+
+format_err_end:
+       return FALSE;
+}
+
+/* Check extended guestdev parameter format error */
+static int pci_check_extended_guestdev_format(char *str)
+{
+       int flg;
+       char *p;
+
+       /* Check extended format */
+       if (strpbrk(str, "(|)") == NULL)
+               return TRUE;
+
+       flg = 0;
+       p = str;
+       while (*p) {
+               switch (*p) {
+               case '(':
+                       /* Check nesting error */
+                       if (flg != 0)
+                               goto format_err_end;
+                       flg = 1;
+                       /* Check position of '(' is head or
+                          previos charactor of '(' is not '-'. */
+                       if (p == str || *(p - 1) != '-')
+                               goto format_err_end;
+                       break;
+               case ')':
+                       /* Check nesting error */
+                       if (flg != 1)
+                               goto format_err_end;
+                       flg = 0;
+                       /* Check next charactor of ')' is not '\0' */
+                       if (*(p + 1) != '\0')
+                               goto format_err_end;
+                       break;
+               case '|':
+                       /* Check position of '|' is outside of '(' and ')' */
+                       if (flg != 1)
+                               goto format_err_end;
+                       break;
+               default:
+                       break;
+               }
+               p++;
+       }
+       /* Check number of '(' and ')' are not equal */
+       if (flg != 0)
+               goto format_err_end;
+       return TRUE;
+
+format_err_end:
+       printk(KERN_ERR
+               "PCI: The format of the guestdev parameter is illegal. [%s]\n",
+               str);
+       return FALSE;
+}
+
+/* Make guestdev strings */
+static void pci_make_guestdev_path_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)
+                       return;
+               sprintf(gdev_str + strlen(gdev_str), "-%02x.%01x",
+                       node->dev, node->func);
+               buf_size -= dev_func_len;
+               node = node->child;
+       }
+}
+
+/* Free guestdev and nodes */
+static void pci_free_guestdev(struct guestdev *gdev)
+{
+       struct guestdev_node *node, *next;
+
+       if (!gdev)
+               return;
+
+       node = gdev->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 *gdev;
+       struct guestdev_node *node, *node_src, *node_upper;
+
+       gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
+       if (!gdev)
+               goto allocate_err_end;
+
+       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;
+
+       node_upper = NULL;
+
+       node_src = gdev_src->child;
+       while (node_src) {
+               node = kmalloc(sizeof(*node), GFP_KERNEL);
+               if (!node)
+                       goto allocate_err_end;
+               memset(node, 0, sizeof(*node));
+               node->dev = node_src->dev;
+               node->func = node_src->func;
+               if (!node_upper)
+                       gdev->child = node;
+               else
+                       node_upper->child = node;
+               node_upper = node;
+               node_src = node_src->child;
+       }
+
+       return gdev;
+
+allocate_err_end:
+       if (gdev)
+               pci_free_guestdev(gdev);
+       printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+       return NULL;
+}
+
+/* Make guestdev from path strings */
+static int pci_make_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;
+       int dev, func, ret_val;
+
+       ret_val = 0;
+       gdev = gdev_org = NULL;
+       sp = path_str;
+       /* Look for end of hid:uid'-' */
+       ep = strchr(sp, '-');
+       /* Only hid, uid. (No dev, func) */
+       if (!ep)
+               goto format_err_end;
+
+       memset(hid, 0 ,sizeof(hid));
+       memset(uid, 0, sizeof(uid));
+       if (!pci_get_hid_uid(sp, hid, uid))
+               goto format_err_end;
+
+       gdev_org = kmalloc(sizeof(*gdev_org), GFP_KERNEL);
+       if (!gdev_org)
+               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 = gdev_org;
+
+       sp = ep + 1;
+       ep = sp;
+       do {
+               if (*sp == '(') {
+                       sp++;
+                       if (strchr(sp, '|')) {
+                               gdev = pci_copy_guestdev(gdev_org);
+                               if (!gdev) {
+                                       ret_val = -ENOMEM;
+                                       goto err_end;
+                               }
+                       }
+                       continue;
+               }
+               if (pci_get_dev_func(sp, &dev, &func)) {
+                       node = kmalloc(sizeof(*node), GFP_KERNEL);
+                       if (!node)
+                               goto allocate_err_end;
+                       memset(node, 0, sizeof(*node));
+                       node->dev = dev;
+                       node->func = func;
+                       /* add node to end of guestdev */
+                       if (gdev->child) {
+                               node_tmp = gdev->child;
+                               while (node_tmp->child) {
+                                       node_tmp = node_tmp->child;
+                               }
+                               node_tmp->child = node;
+                       } else
+                               gdev->child = node;
+               } else
+                       goto format_err_end;
+
+               ep = strpbrk(sp, "-|)");
+               if (!ep)
+                       ep = strchr(sp, '\0');
+               /* *ep is '|' OR ')' OR '\0' ? */
+               if (*ep != '-') {
+                       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;
+                                       }
+                               } else
+                                       gdev = gdev_org;
+                       }
+               }
+               if (*ep == ')')
+                       ep++;
+               sp = ep + 1;
+       } while (*ep != '\0');
+
+       return ret_val;
+
+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;
+
+allocate_err_end:
+       printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+       ret_val = -ENOMEM;
+       goto err_end;
+
+err_end:
+       if (gdev_org && (gdev_org != gdev))
+               pci_free_guestdev(gdev_org);
+       if (gdev)
+               pci_free_guestdev(gdev);
+       return ret_val;
+}
+
+/* Parse guestdev parameter */
+static int __init pci_parse_guestdev(void)
+{
+       int len, ret_val;
+       char *sp, *ep;
+       struct list_head *head;
+       struct guestdev *gdev;
+       char path_str[PATH_STR_MAX];
+
+       ret_val = 0;
+
+       len = strlen(guestdev_param);
+       if (len == 0)
+               goto end;
+
+       sp = guestdev_param;
+
+       do {
+               ep = strchr(sp, ',');
+               /* 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;
+               }
+               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);
+               printk(KERN_DEBUG
+                       "PCI: %s has been reserved for guest domain.\n",
+                       path_str);
+       }
+
+end:
+       return ret_val;
+}
+
+arch_initcall(pci_parse_guestdev);
+
+/* Get command line */
+static int __init pci_guestdev_setup(char *str)
+{
+       if (strlen(str) >= COMMAND_LINE_SIZE)
+               return 0;
+       strcpy(guestdev_param, str);
+       return 1;
+}
+
+__setup("guestdev=", pci_guestdev_setup);
+
+/* Free sbdf and nodes */
+static void pci_free_sbdf(struct pcidev_sbdf *sbdf)
+{
+       struct pcidev_sbdf_node *node, *next;
+
+       node = sbdf->child;
+       while (node) {
+               next = node->child;
+               kfree(node);
+               node = next;
+       }
+       /* Skip kfree(sbdf) */
+}
+
+/* Is sbdf within guestdev */
+static int pci_sbdf_in_guestdev_sub_tree(struct guestdev *gdev, 
+                                       struct pcidev_sbdf *sbdf)
+{
+       int seg, bbn;
+       struct guestdev_node *gdev_node;
+       struct pcidev_sbdf_node *sbdf_node;
+
+       if (!gdev || !sbdf)
+               return FALSE;
+
+       /* 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;
+               } else
+                       return FALSE;
+       }
+
+       if (gdev->seg != sbdf->seg || gdev->bbn != sbdf->bus)
+               return FALSE;
+
+       gdev_node = gdev->child;
+       sbdf_node = sbdf->child;
+
+       /* Compare dev and func */
+       while (gdev_node) {
+               if (!sbdf_node)
+                       return FALSE;
+               if (gdev_node->dev != sbdf_node->dev ||
+                   gdev_node->func != sbdf_node->func)
+                       return FALSE;
+               gdev_node = gdev_node->child;
+               sbdf_node = sbdf_node->child;
+       }
+       return TRUE;
+}
+
+/* Get sbdf from device */
+static int pci_get_sbdf_from_pcidev(
+       struct pci_dev *dev, struct pcidev_sbdf *sbdf)
+{
+       struct pcidev_sbdf_node *node;
+
+       if (!dev)
+               return FALSE;
+
+       for(;;) {
+               node = kmalloc(sizeof(*node), GFP_KERNEL);
+               if (!node) {
+                       printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+                       goto err_end;
+               }
+               memset(node, 0, sizeof(*node));
+               node->dev = PCI_SLOT(dev->devfn);
+               node->func = PCI_FUNC(dev->devfn);
+
+               if (!sbdf->child)
+                       sbdf->child = node;
+               else {
+                       node->child = sbdf->child;
+                       sbdf->child = node;
+               }
+               if (!dev->bus)
+                       goto err_end;
+               if (!dev->bus->self)
+                       break;
+               dev = dev->bus->self;
+       }
+       if (sscanf(dev->dev.bus_id, "%04x:%02x", &sbdf->seg, &sbdf->bus) != 2)
+               goto err_end;
+       return TRUE;
+
+err_end:
+       pci_free_sbdf(sbdf);
+       return FALSE;
+}
+
+/* Is PCI device belongs to the subtree of the guestdev parameter */
+int pci_is_guestdev(struct pci_dev *dev)
+{
+       struct guestdev *gdev;
+       struct pcidev_sbdf sbdf;
+       struct list_head *head;
+       int result;
+
+       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);
+       return result;
+}
+EXPORT_SYMBOL(pci_is_guestdev);
+
+static int __init pci_set_reassign_resources(char *str)
+{
+       reassign_resources = 1;
+
+       return 1;
+}
+
+__setup("reassign_resources", pci_set_reassign_resources);
+
+int pci_is_guestdev_to_reassign(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(
+               struct guestdev *gdev, struct pci_bus *bus)
+{
+       struct guestdev_node *node;
+       struct pci_dev *dev;
+
+       node = gdev->child;
+       while (node) {
+               if (!bus)
+                       return FALSE;
+               dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
+               if (!dev) {
+                       pci_dev_put(dev);
+                       return FALSE;
+               }
+               bus = dev->subordinate;
+               node = node->child;
+               pci_dev_put(dev);
+       }
+       return TRUE;
+}
+
+/* Check whether the guestdev exists in the PCI device tree */
+static int __init pci_check_guestdev_exists(void)
+{
+       struct list_head *head;
+       struct guestdev *gdev;
+       int seg, bbn;
+       struct pci_bus *bus;
+       char path_str[PATH_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);
+                               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);
+               }
+       }
+       return 0;
+}
+
+fs_initcall(pci_check_guestdev_exists);
+
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/pci.h
--- a/drivers/pci/pci.h Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/pci.h Wed Jan 07 12:21:54 2009 +0900
@@ -100,8 +100,12 @@ pci_match_one_device(const struct pci_de
 }
 
 #ifdef CONFIG_PCI_REASSIGN
-extern int is_reassigndev(struct pci_dev *dev);
+extern int pci_is_reassigndev(struct pci_dev *dev);
 extern void pci_disable_bridge_window(struct pci_dev *dev);
 #else
-#define is_reassigndev(dev) 0
+#define pci_is_reassigndev(dev) 0
 #endif
+
+#ifdef CONFIG_PCI_GUESTDEV
+int pci_is_guestdev_to_reassign(struct pci_dev *dev);
+#endif /* CONFIG_PCI_GUESTDEV */
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/quirks.c
--- a/drivers/pci/quirks.c      Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/quirks.c      Wed Jan 07 12:21:54 2009 +0900
@@ -36,7 +36,7 @@ static void __devinit quirk_release_reso
        int i;
        struct resource *r;
 
-       if (is_reassigndev(dev)) {
+       if (pci_is_reassigndev(dev)) {
                if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
                    (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
                        /* PCI Host Bridge isn't a target device */
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/reassigndev.c
--- a/drivers/pci/reassigndev.c Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/reassigndev.c Wed Jan 07 12:21:54 2009 +0900
@@ -26,20 +26,27 @@
 
 static char param_reassigndev[REASSIGNDEV_PARAM_MAX] = {0};
 
-static int __init reassigndev_setup(char *str)
+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=", reassigndev_setup);
+__setup("reassigndev=", pci_reassigndev_setup);
 
-int is_reassigndev(struct pci_dev *dev)
+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) {
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c   Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/setup-bus.c   Wed Jan 07 12:21:54 2009 +0900
@@ -345,7 +345,7 @@ pbus_size_mem(struct pci_bus *bus, unsig
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                int i;
-               int reassign = is_reassigndev(dev);
+               int reassign = pci_is_reassigndev(dev);
 
                for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                        struct resource *r = &dev->resource[i];
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c   Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/pci/setup-res.c   Wed Jan 07 12:21:54 2009 +0900
@@ -138,7 +138,7 @@ int pci_assign_resource(struct pci_dev *
        struct resource *res = dev->resource + resno;
        resource_size_t size, min, align;
        int ret;
-       int reassigndev = is_reassigndev(dev);
+       int reassigndev = pci_is_reassigndev(dev);
 
        size = res->end - res->start + 1;
        min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
@@ -234,7 +234,7 @@ pdev_sort_resources(struct pci_dev *dev,
 pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
 {
        int i;
-       int reassigndev = is_reassigndev(dev);
+       int reassigndev = pci_is_reassigndev(dev);
 
        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                struct resource *r;
@@ -271,7 +271,7 @@ pdev_sort_resources(struct pci_dev *dev,
                                        ln->res->start;
                                if ((idx < PCI_BRIDGE_RESOURCES) &&
                                    (ln->res->flags & IORESOURCE_MEM) &&
-                                   is_reassigndev(ln->dev))
+                                   pci_is_reassigndev(ln->dev))
                                        align = ALIGN(align, PAGE_SIZE);
                        }
                        if (r_align > align) {
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/xen/evtchn/evtchn.c
--- a/drivers/xen/evtchn/evtchn.c       Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/xen/evtchn/evtchn.c       Wed Jan 07 12:21:54 2009 +0900
@@ -497,20 +497,22 @@ static int __cpuinit evtchn_cpu_notify(s
 {
        int hotcpu = (unsigned long)hcpu;
        cpumask_t map = cpu_online_map;
-       int port, newcpu;
+       int i, j, newcpu;
        struct per_user_data *u;
 
        switch (action) {
        case CPU_DOWN_PREPARE:
                cpu_clear(hotcpu, map);
                spin_lock_irq(&port_user_lock);
-               for (port = 0; port < NR_EVENT_CHANNELS; port++) {
-                       if ((u = port_user[port]) != NULL && 
-                           u->bind_cpu == hotcpu &&
-                           (newcpu = next_bind_cpu(map)) < NR_CPUS) {
-                               rebind_evtchn_to_cpu(port, newcpu);
-                               u->bind_cpu = newcpu;
-                       }
+               for (i = 0; i < NR_EVENT_CHANNELS; i++) {
+                       u = port_user[i];
+                       if ((u == NULL) || (u->bind_cpu != hotcpu))
+                               continue;
+                       newcpu = next_bind_cpu(map);
+                       for (j = i; j < NR_EVENT_CHANNELS; j++)
+                               if (port_user[j] == u)
+                                       rebind_evtchn_to_cpu(j, newcpu);
+                       u->bind_cpu = newcpu;
                }
                spin_unlock_irq(&port_user_lock);
                break;
diff -r 79bf5894b3f9 -r 28acedb66302 drivers/xen/pciback/pci_stub.c
--- a/drivers/xen/pciback/pci_stub.c    Mon Jan 05 14:13:49 2009 +0900
+++ b/drivers/xen/pciback/pci_stub.c    Wed Jan 07 12:21:54 2009 +0900
@@ -427,6 +427,16 @@ static int __devinit pcistub_probe(struc
 
                dev_info(&dev->dev, "seizing device\n");
                err = pcistub_seize(dev);
+#ifdef CONFIG_PCI_GUESTDEV
+       } else if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
+               if (!pci_is_guestdev(dev)) {
+                       err = -ENODEV;
+                       goto out;
+               }
+
+               dev_info(&dev->dev, "seizing device\n");
+               err = pcistub_seize(dev);
+#endif /* CONFIG_PCI_GUESTDEV */
        } else
                /* Didn't find the device */
                err = -ENODEV;
diff -r 79bf5894b3f9 -r 28acedb66302 include/acpi/acpi_bus.h
--- a/include/acpi/acpi_bus.h   Mon Jan 05 14:13:49 2009 +0900
+++ b/include/acpi/acpi_bus.h   Wed Jan 07 12:21:54 2009 +0900
@@ -359,6 +359,16 @@ acpi_handle acpi_get_pci_rootbridge_hand
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
 #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data))
 
+#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
+static struct acpi_device_attribute acpi_device_attr_##_name = \
+               __ATTR(_name, _mode, _show, _store)
+
+struct acpi_device_attribute {
+       struct attribute attr;
+       ssize_t(*show) (struct acpi_device *, char *);
+       ssize_t(*store) (struct acpi_device *, const char *, size_t);
+};
+
 #endif /* CONFIG_ACPI */
 
 #endif /*__ACPI_BUS_H__*/
diff -r 79bf5894b3f9 -r 28acedb66302 include/asm-x86_64/setup.h
--- a/include/asm-x86_64/setup.h        Mon Jan 05 14:13:49 2009 +0900
+++ b/include/asm-x86_64/setup.h        Wed Jan 07 12:21:54 2009 +0900
@@ -1,6 +1,6 @@
 #ifndef _x8664_SETUP_H
 #define _x8664_SETUP_H
 
-#define COMMAND_LINE_SIZE      256
+#define COMMAND_LINE_SIZE      1024
 
 #endif
diff -r 79bf5894b3f9 -r 28acedb66302 include/linux/acpi.h
--- a/include/linux/acpi.h      Mon Jan 05 14:13:49 2009 +0900
+++ b/include/linux/acpi.h      Wed Jan 07 12:21:54 2009 +0900
@@ -406,6 +406,7 @@ void acpi_table_print (struct acpi_table
 void acpi_table_print (struct acpi_table_header *header, unsigned long 
phys_addr);
 void acpi_table_print_madt_entry (acpi_table_entry_header *madt);
 void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
+int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn);
 
 /* the following four functions are architecture-dependent */
 #ifdef CONFIG_HAVE_ARCH_PARSE_SRAT
diff -r 79bf5894b3f9 -r 28acedb66302 include/linux/pci.h
--- a/include/linux/pci.h       Mon Jan 05 14:13:49 2009 +0900
+++ b/include/linux/pci.h       Wed Jan 07 12:21:54 2009 +0900
@@ -804,5 +804,9 @@ extern int pci_pci_problems;
 #define PCIPCI_VSFX            16
 #define PCIPCI_ALIMAGIK                32
 
+#ifdef CONFIG_PCI_GUESTDEV
+int pci_is_guestdev(struct pci_dev *dev);
+#endif /* CONFIG_PCI_GUESTDEV */
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */

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

<Prev in Thread] Current Thread [Next in Thread>