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

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



# 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


 


Rackspace

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