[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |