This patch supports SBDF with "guestdev=" boot parameter and removes
"reassigndev=" boot parameter.
Currently there are three boot parameters which specifics PCI device
for PCI pass-through.
pciback.hide=
guestdev=
reassigndev=
I'd like to simplify them before xen 3.4 is released. To achieve this,
I'd like to make "guestdev=" boot parameter support SBDF, and remove
"reassigndev=".
When we don't need to reassign resources and use device path,
pciback.hide= boot parameter can be used. The parameter is also needed
for backward compatibility.
pciback.hide=(00:01.0)(00:02.0)
When we need to reassign resources or use device path, guestdev= boot
parameter can be used. reassign_resources boot parameter is needed to
reassign resources, too.
guestdev=00:01.0,00:02.0 reassign_resources
guestdev=PNP0A08:0-1.0,PNP0A08:0-2.0
guestdev=PNP0A08:0-1.0,PNP0A08:0-2.0 reassign_resources
With this patch, Isaku-san will not need to add guestioemuldev
boot parameter for IO space multiplexing, though it will be necessary
to add a flag and omit func# from guestdev.
Thanks,
--
Yuji Shimada
Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
diff -r e5d3f2fa3428 Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt Tue Apr 07 10:29:30 2009 +0100
+++ b/Documentation/kernel-parameters.txt Wed Apr 08 16:14:56 2009 +0900
@@ -576,8 +576,9 @@ running once the system is up.
gt96100eth= [NET] MIPS GT96100 Advanced Communication Controller
guestdev= [PCI,ACPI]
- Format: <device path>[,<device path>[,...]]
- Format of device path:
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[...]]
+ Format: {<device path>|<sbdf>}][,{<device
path>|<sbdf>}[,...]]
+ Format of device path:
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]]
+ Format of sbdf: [<segment>:]<bus>:<dev>.<func>
Specifies PCI device for guest domain.
If PCI-PCI bridge is specified, all PCI devices
behind PCI-PCI bridge are reserved.
@@ -1364,12 +1365,6 @@ running once the system is up.
Run specified binary instead of /init from the ramdisk,
used for early userspace startup. See initrd.
- reassigndev= [PCI]
- Format:
[<segment>:]<bus>:<dev>.<func>[,[<segment>:]<bus>:<dev>.<func>[,...]]
- Specifies device to reassign page-aligned memory
- resources. PCI-PCI bridge can be specified, if
- resource windows need to be expanded.
-
reassign_resources
[PCI,ACPI] Use guestdev parameter to reassign device's
resources.
diff -r e5d3f2fa3428 drivers/pci/Makefile
--- a/drivers/pci/Makefile Tue Apr 07 10:29:30 2009 +0100
+++ b/drivers/pci/Makefile Wed Apr 08 16:14:56 2009 +0900
@@ -4,7 +4,6 @@
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
-obj-$(CONFIG_PCI_REASSIGN) += reassigndev.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
diff -r e5d3f2fa3428 drivers/pci/guestdev.c
--- a/drivers/pci/guestdev.c Tue Apr 07 10:29:30 2009 +0100
+++ b/drivers/pci/guestdev.c Wed Apr 08 16:14:56 2009 +0900
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, NEC Corporation.
+ * Copyright (c) 2008, 2009 NEC Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -32,21 +32,36 @@
#define FUNC_NUM_MAX 7
#define INVALID_SEG (-1)
#define INVALID_BBN (-1)
-#define PATH_STR_MAX 128
+#define GUESTDEV_STR_MAX 128
+
+#define GUESTDEV_FLAG_TYPE_MASK 0x3
+#define GUESTDEV_FLAG_DEVICEPATH 0x1
+#define GUESTDEV_FLAG_SBDF 0x2
struct guestdev {
+ int flags;
struct list_head root_list;
- char hid[HID_LEN + 1];
- char uid[UID_LEN + 1];
- int seg;
- int bbn;
- struct guestdev_node *child;
+ union {
+ struct devicepath {
+ char hid[HID_LEN + 1];
+ char uid[UID_LEN + 1];
+ int seg;
+ int bbn;
+ struct devicepath_node *child;
+ } devicepath;
+ struct sbdf {
+ int seg;
+ int bus;
+ int dev;
+ int func;
+ } sbdf;
+ } u;
};
-struct guestdev_node {
+struct devicepath_node {
int dev;
int func;
- struct guestdev_node *child;
+ struct devicepath_node *child;
};
struct pcidev_sbdf {
@@ -67,7 +82,7 @@ LIST_HEAD(guestdev_list);
LIST_HEAD(guestdev_list);
/* Get hid and uid */
-static int pci_get_hid_uid(char *str, char *hid, char *uid)
+static int __init pci_get_hid_uid(char *str, char *hid, char *uid)
{
char *sp, *ep;
int len;
@@ -111,7 +126,7 @@ format_err_end:
}
/* Get device and function */
-static int pci_get_dev_func(char *str, int *dev, int *func)
+static int __init pci_get_dev_func(char *str, int *dev, int *func)
{
if (sscanf(str, "%02x.%01x", dev, func) != 2)
goto format_err_end;
@@ -129,7 +144,7 @@ format_err_end:
}
/* Check extended guestdev parameter format error */
-static int pci_check_extended_guestdev_format(char *str)
+static int __init pci_check_extended_guestdev_format(char *str)
{
int flg;
char *p;
@@ -184,74 +199,75 @@ format_err_end:
}
/* Make guestdev strings */
-static void pci_make_guestdev_path_str(struct guestdev *gdev,
+static void pci_make_guestdev_str(struct guestdev *gdev,
char *gdev_str, int buf_size)
{
- struct guestdev_node *node;
- /* max length for "HID:UID" (hid+uid+':'+'\0') */
- const int hid_uid_len = HID_LEN + UID_LEN + 2;
- /* max length for "-DEV#.FUNC#" (dev+func+'-'+'.'+'\0') */
- const int dev_func_len = DEV_LEN + FUNC_LEN + 3;
+ struct devicepath_node *node;
+ int count;
- /* check buffer size for HID:UID */
- if (buf_size < hid_uid_len)
- return;
+ switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+ case GUESTDEV_FLAG_DEVICEPATH:
+ memset(gdev_str, 0, buf_size);
- memset(gdev_str, 0, buf_size);
+ if (strlen(gdev->u.devicepath.uid))
+ count = snprintf(gdev_str, buf_size, "%s:%s",
+ gdev->u.devicepath.hid,
+ gdev->u.devicepath.uid);
+ else
+ count = snprintf(gdev_str, buf_size, "%s",
+ gdev->u.devicepath.hid);
+ if (count < 0)
+ return;
- if (strlen(gdev->uid))
- sprintf(gdev_str, "%s:%s", gdev->hid, gdev->uid);
- else
- sprintf(gdev_str, "%s", gdev->hid);
- buf_size -= strlen(gdev_str);
-
- node = gdev->child;
- while (node) {
- /* check buffer size for -DEV#.FUNC# */
- if (buf_size < dev_func_len)
- return;
- sprintf(gdev_str + strlen(gdev_str), "-%02x.%01x",
- node->dev, node->func);
- buf_size -= dev_func_len;
- node = node->child;
+ node = gdev->u.devicepath.child;
+ while (node) {
+ gdev_str += count;
+ buf_size -= count;
+ if (buf_size <= 0)
+ return;
+ count = snprintf(gdev_str, buf_size, "-%02x.%01x",
+ node->dev, node->func);
+ if (count < 0)
+ return;
+ node = node->child;
+ }
+ break;
+ case GUESTDEV_FLAG_SBDF:
+ snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x",
+ gdev->u.sbdf.seg, gdev->u.sbdf.bus,
+ gdev->u.sbdf.dev, gdev->u.sbdf.func);
+ break;
+ default:
+ BUG();
}
}
/* Free guestdev and nodes */
-static void pci_free_guestdev(struct guestdev *gdev)
+static void __init pci_free_guestdev(struct guestdev *gdev)
{
- struct guestdev_node *node, *next;
+ struct devicepath_node *node, *next;
if (!gdev)
return;
-
- node = gdev->child;
- while (node) {
- next = node->child;
- kfree(node);
- node = next;
+ if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) {
+ node = gdev->u.devicepath.child;
+ while (node) {
+ next = node->child;
+ kfree(node);
+ node = next;
+ }
}
list_del(&gdev->root_list);
kfree(gdev);
}
-/* Free guestdev_list */
-static void pci_free_guestdev_list(void)
-{
- struct list_head *head, *tmp;
- struct guestdev *gdev;
-
- list_for_each_safe(head, tmp, &guestdev_list) {
- gdev = list_entry(head, struct guestdev, root_list);
- pci_free_guestdev(gdev);
- }
-}
-
/* Copy guestdev and nodes */
-struct guestdev *pci_copy_guestdev(struct guestdev *gdev_src)
+struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
{
struct guestdev *gdev;
- struct guestdev_node *node, *node_src, *node_upper;
+ struct devicepath_node *node, *node_src, *node_upper;
+
+ BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH));
gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
if (!gdev)
@@ -259,14 +275,15 @@ struct guestdev *pci_copy_guestdev(struc
memset(gdev, 0, sizeof(*gdev));
INIT_LIST_HEAD(&gdev->root_list);
- strcpy(gdev->hid, gdev_src->hid);
- strcpy(gdev->uid, gdev_src->uid);
- gdev->seg = gdev_src->seg;
- gdev->bbn = gdev_src->bbn;
+ gdev->flags = gdev_src->flags;
+ strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
+ strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
+ gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
+ gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn;
node_upper = NULL;
- node_src = gdev_src->child;
+ node_src = gdev_src->u.devicepath.child;
while (node_src) {
node = kmalloc(sizeof(*node), GFP_KERNEL);
if (!node)
@@ -275,7 +292,7 @@ struct guestdev *pci_copy_guestdev(struc
node->dev = node_src->dev;
node->func = node_src->func;
if (!node_upper)
- gdev->child = node;
+ gdev->u.devicepath.child = node;
else
node_upper->child = node;
node_upper = node;
@@ -292,12 +309,12 @@ allocate_err_end:
}
/* Make guestdev from path strings */
-static int pci_make_guestdev(char *path_str)
+static int __init pci_make_devicepath_guestdev(char *path_str)
{
char hid[HID_LEN + 1], uid[UID_LEN + 1];
char *sp, *ep;
struct guestdev *gdev, *gdev_org;
- struct guestdev_node *node, *node_tmp;
+ struct devicepath_node *node, *node_tmp;
int dev, func, ret_val;
ret_val = 0;
@@ -319,10 +336,11 @@ static int pci_make_guestdev(char *path_
goto allocate_err_end;
memset(gdev_org, 0, sizeof(*gdev_org));
INIT_LIST_HEAD(&gdev_org->root_list);
- strcpy(gdev_org->hid, hid);
- strcpy(gdev_org->uid, uid);
- gdev_org->seg = INVALID_SEG;
- gdev_org->bbn = INVALID_BBN;
+ gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
+ strcpy(gdev_org->u.devicepath.hid, hid);
+ strcpy(gdev_org->u.devicepath.uid, uid);
+ gdev_org->u.devicepath.seg = INVALID_SEG;
+ gdev_org->u.devicepath.bbn = INVALID_BBN;
gdev = gdev_org;
@@ -335,12 +353,12 @@ static int pci_make_guestdev(char *path_
gdev = pci_copy_guestdev(gdev_org);
if (!gdev) {
ret_val = -ENOMEM;
- goto err_end;
+ goto end;
}
}
continue;
}
- if (pci_get_dev_func(sp, &dev, &func)) {
+ if (gdev && pci_get_dev_func(sp, &dev, &func)) {
node = kmalloc(sizeof(*node), GFP_KERNEL);
if (!node)
goto allocate_err_end;
@@ -348,33 +366,47 @@ static int pci_make_guestdev(char *path_
node->dev = dev;
node->func = func;
/* add node to end of guestdev */
- if (gdev->child) {
- node_tmp = gdev->child;
+ if (gdev->u.devicepath.child) {
+ node_tmp = gdev->u.devicepath.child;
while (node_tmp->child) {
node_tmp = node_tmp->child;
}
node_tmp->child = node;
} else
- gdev->child = node;
- } else
- goto format_err_end;
+ gdev->u.devicepath.child = node;
+ } else if (gdev) {
+ printk(KERN_ERR
+ "PCI: Can't obtain dev# and #func# from %s.\n",
+ sp);
+ ret_val = -EINVAL;
+ if (gdev == gdev_org)
+ goto end;
+ pci_free_guestdev(gdev);
+ gdev = NULL;
+ }
ep = strpbrk(sp, "-|)");
if (!ep)
ep = strchr(sp, '\0');
- /* *ep is '|' OR ')' OR '\0' ? */
+ /* Is *ep '|' OR ')' OR '\0' ? */
if (*ep != '-') {
- list_add_tail(&gdev->root_list, &guestdev_list);
+ if (gdev)
+ list_add_tail(&gdev->root_list, &guestdev_list);
if (*ep == '|') {
/* Between '|' and '|' ? */
if (strchr(ep + 1, '|')) {
gdev = pci_copy_guestdev(gdev_org);
if (!gdev) {
ret_val = -ENOMEM;
- goto err_end;
+ goto end;
}
- } else
+ } else {
gdev = gdev_org;
+ gdev_org = NULL;
+ }
+ } else {
+ gdev_org = NULL;
+ gdev = NULL;
}
}
if (*ep == ')')
@@ -382,21 +414,21 @@ static int pci_make_guestdev(char *path_
sp = ep + 1;
} while (*ep != '\0');
- return ret_val;
+ goto end;
format_err_end:
printk(KERN_ERR
"PCI: The format of the guestdev parameter is illegal. [%s]\n",
path_str);
ret_val = -EINVAL;
- goto err_end;
+ goto end;
allocate_err_end:
printk(KERN_ERR "PCI: Failed to allocate memory.\n");
ret_val = -ENOMEM;
- goto err_end;
+ goto end;
-err_end:
+end:
if (gdev_org && (gdev_org != gdev))
pci_free_guestdev(gdev_org);
if (gdev)
@@ -404,20 +436,44 @@ err_end:
return ret_val;
}
+static int __init pci_make_sbdf_guestdev(char* str)
+{
+ struct guestdev *gdev;
+ int seg, bus, dev, func;
+
+ if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) {
+ seg = 0;
+ if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3)
+ return -EINVAL;
+ }
+ gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
+ if (!gdev) {
+ printk(KERN_ERR "PCI: Failed to allocate memory.\n");
+ return -ENOMEM;
+ }
+ INIT_LIST_HEAD(&gdev->root_list);
+ gdev->flags = GUESTDEV_FLAG_SBDF;
+ gdev->u.sbdf.seg = seg;
+ gdev->u.sbdf.bus = bus;
+ gdev->u.sbdf.dev = dev;
+ gdev->u.sbdf.func = func;
+ list_add_tail(&gdev->root_list, &guestdev_list);
+ return 0;
+}
+
/* Parse guestdev parameter */
static int __init pci_parse_guestdev(void)
{
- int len, ret_val;
+ int len;
char *sp, *ep;
struct list_head *head;
struct guestdev *gdev;
- char path_str[PATH_STR_MAX];
-
- ret_val = 0;
+ char path_str[GUESTDEV_STR_MAX];
+ int ret_val = 0;
len = strlen(guestdev_param);
if (len == 0)
- goto end;
+ return 0;
sp = guestdev_param;
@@ -426,29 +482,26 @@ static int __init pci_parse_guestdev(voi
/* Chop */
if (ep)
*ep = '\0';
- if (!pci_check_extended_guestdev_format(sp)) {
- pci_free_guestdev_list();
- return -EINVAL;
- }
-
- ret_val = pci_make_guestdev(sp);
- if (ret_val) {
- pci_free_guestdev_list();
- return ret_val;
- }
+ ret_val = pci_make_sbdf_guestdev(sp);
+ if (ret_val == -EINVAL) {
+ if (pci_check_extended_guestdev_format(sp)) {
+ ret_val = pci_make_devicepath_guestdev(sp);
+ if (ret_val && ret_val != -EINVAL)
+ break;
+ }
+ } else if (ret_val)
+ break;
sp = ep + 1;
} while (ep);
list_for_each(head, &guestdev_list) {
gdev = list_entry(head, struct guestdev, root_list);
- pci_make_guestdev_path_str(gdev, path_str, PATH_STR_MAX);
+ pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
printk(KERN_DEBUG
"PCI: %s has been reserved for guest domain.\n",
path_str);
}
-
-end:
- return ret_val;
+ return 0;
}
arch_initcall(pci_parse_guestdev);
@@ -478,32 +531,35 @@ static void pci_free_sbdf(struct pcidev_
/* Skip kfree(sbdf) */
}
-/* Is sbdf within guestdev */
-static int pci_sbdf_in_guestdev_sub_tree(struct guestdev *gdev,
+/* Does PCI device belong to sub tree specified by guestdev with device path?
*/
+static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
struct pcidev_sbdf *sbdf)
{
int seg, bbn;
- struct guestdev_node *gdev_node;
+ struct devicepath_node *gdev_node;
struct pcidev_sbdf_node *sbdf_node;
if (!gdev || !sbdf)
return FALSE;
+ BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
+
/* Compare seg and bbn */
- if (gdev->seg == INVALID_SEG ||
- gdev->bbn == INVALID_BBN) {
- if (acpi_pci_get_root_seg_bbn(gdev->hid,
- gdev->uid, &seg, &bbn)) {
- gdev->seg = seg;
- gdev->bbn = bbn;
+ if (gdev->u.devicepath.seg == INVALID_SEG ||
+ gdev->u.devicepath.bbn == INVALID_BBN) {
+ if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid,
+ gdev->u.devicepath.uid, &seg, &bbn)) {
+ gdev->u.devicepath.seg = seg;
+ gdev->u.devicepath.bbn = bbn;
} else
return FALSE;
}
- if (gdev->seg != sbdf->seg || gdev->bbn != sbdf->bus)
+ if (gdev->u.devicepath.seg != sbdf->seg ||
+ gdev->u.devicepath.bbn != sbdf->bus)
return FALSE;
- gdev_node = gdev->child;
+ gdev_node = gdev->u.devicepath.child;
sbdf_node = sbdf->child;
/* Compare dev and func */
@@ -559,29 +615,64 @@ err_end:
return FALSE;
}
-/* Is PCI device belongs to the subtree of the guestdev parameter */
+/* Does PCI device belong to sub tree specified by guestdev with sbdf? */
+static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev)
+{
+ int seg, bus;
+ BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
+ for (;;) {
+ if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
+ continue;
+ if (gdev->u.sbdf.seg == seg && gdev->u.sbdf.bus == bus &&
+ gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
+ gdev->u.sbdf.func == PCI_FUNC(dev->devfn))
+ return TRUE;
+ if (!dev->bus || !dev->bus->self)
+ break;
+ dev = dev->bus->self;
+ }
+ return FALSE;
+}
+
+/* Does PCI device belong to sub tree specified by guestdev parameter? */
int pci_is_guestdev(struct pci_dev *dev)
{
struct guestdev *gdev;
- struct pcidev_sbdf sbdf;
+ struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
struct list_head *head;
- int result;
+ int result = FALSE;
if (!dev)
return FALSE;
- memset(&sbdf, 0 ,sizeof(sbdf));
- if (!pci_get_sbdf_from_pcidev(dev, &sbdf))
- return FALSE;
- result = FALSE;
list_for_each(head, &guestdev_list) {
gdev = list_entry(head, struct guestdev, root_list);
- if (pci_sbdf_in_guestdev_sub_tree(gdev, &sbdf)) {
- result = TRUE;
+ switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+ case GUESTDEV_FLAG_DEVICEPATH:
+ if (sbdf == NULL) {
+ sbdf = &pcidev_sbdf;
+ memset(sbdf, 0 ,sizeof(*sbdf));
+ if (!pci_get_sbdf_from_pcidev(dev, sbdf))
+ goto out;
+ }
+ if (pci_is_in_devicepath_sub_tree(gdev, sbdf)) {
+ result = TRUE;
+ goto out;
+ }
break;
+ case GUESTDEV_FLAG_SBDF:
+ if (pci_is_in_sbdf_sub_tree(gdev, dev)) {
+ result = TRUE;
+ goto out;
+ }
+ break;
+ default:
+ BUG();
}
}
- pci_free_sbdf(&sbdf);
+out:
+ if (sbdf)
+ pci_free_sbdf(sbdf);
return result;
}
EXPORT_SYMBOL(pci_is_guestdev);
@@ -595,30 +686,30 @@ static int __init pci_set_reassign_resou
__setup("reassign_resources", pci_set_reassign_resources);
-int pci_is_guestdev_to_reassign(struct pci_dev *dev)
+int pci_is_reassigndev(struct pci_dev *dev)
{
if (reassign_resources)
return pci_is_guestdev(dev);
return FALSE;
}
-EXPORT_SYMBOL(pci_is_guestdev_to_reassign);
+EXPORT_SYMBOL(pci_is_reassigndev);
-/* Check whether the guestdev exists under the pci root bus */
-static int __init pci_check_guestdev_path_exists(
+/* Check whether the devicepath exists under the pci root bus */
+static int __init pci_check_devicepath_exists(
struct guestdev *gdev, struct pci_bus *bus)
{
- struct guestdev_node *node;
+ struct devicepath_node *node;
struct pci_dev *dev;
- node = gdev->child;
+ BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
+
+ node = gdev->u.devicepath.child;
while (node) {
if (!bus)
return FALSE;
dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
- if (!dev) {
- pci_dev_put(dev);
+ if (!dev)
return FALSE;
- }
bus = dev->subordinate;
node = node->child;
pci_dev_put(dev);
@@ -633,32 +724,58 @@ static int __init pci_check_guestdev_exi
struct guestdev *gdev;
int seg, bbn;
struct pci_bus *bus;
- char path_str[PATH_STR_MAX];
+ struct pci_dev *dev;
+ char path_str[GUESTDEV_STR_MAX];
list_for_each(head, &guestdev_list) {
gdev = list_entry(head, struct guestdev, root_list);
- if (gdev->seg == INVALID_SEG ||
- gdev->bbn == INVALID_BBN) {
- if (acpi_pci_get_root_seg_bbn(gdev->hid,
- gdev->uid, &seg, &bbn)) {
- gdev->seg = seg;
- gdev->bbn = bbn;
- } else {
- pci_make_guestdev_path_str(gdev, path_str,
- PATH_STR_MAX);
+ switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
+ case GUESTDEV_FLAG_DEVICEPATH:
+ if (gdev->u.devicepath.seg == INVALID_SEG ||
+ gdev->u.devicepath.bbn == INVALID_BBN) {
+ if (acpi_pci_get_root_seg_bbn(
+ gdev->u.devicepath.hid,
+ gdev->u.devicepath.uid, &seg, &bbn)) {
+ gdev->u.devicepath.seg = seg;
+ gdev->u.devicepath.bbn = bbn;
+ } else {
+ pci_make_guestdev_str(gdev,
+ path_str, GUESTDEV_STR_MAX);
+ printk(KERN_INFO
+ "PCI: Device does not exist. %s\n",
+ path_str);
+ continue;
+ }
+ }
+
+ bus = pci_find_bus(gdev->u.devicepath.seg,
+ gdev->u.devicepath.bbn);
+ if (!bus ||
+ !pci_check_devicepath_exists(gdev, bus)) {
+ pci_make_guestdev_str(gdev, path_str,
+ GUESTDEV_STR_MAX);
printk(KERN_INFO
"PCI: Device does not exist. %s\n",
path_str);
- continue;
}
- }
-
- bus = pci_find_bus(gdev->seg, gdev->bbn);
- if (!bus || !pci_check_guestdev_path_exists(gdev, bus)) {
- pci_make_guestdev_path_str(gdev, path_str,
- PATH_STR_MAX);
- printk(KERN_INFO
- "PCI: Device does not exist. %s\n", path_str);
+ break;
+ case GUESTDEV_FLAG_SBDF:
+ bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus);
+ if (bus) {
+ dev = pci_get_slot(bus,
+ PCI_DEVFN(gdev->u.sbdf.dev,
+ gdev->u.sbdf.func));
+ if (dev) {
+ pci_dev_put(dev);
+ continue;
+ }
+ }
+ pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
+ printk(KERN_INFO "PCI: Device does not exist. %s\n",
+ path_str);
+ break;
+ default:
+ BUG();
}
}
return 0;
diff -r e5d3f2fa3428 drivers/pci/pci.h
--- a/drivers/pci/pci.h Tue Apr 07 10:29:30 2009 +0100
+++ b/drivers/pci/pci.h Wed Apr 08 16:14:56 2009 +0900
@@ -102,8 +102,10 @@ pci_match_one_device(const struct pci_de
}
#ifdef CONFIG_PCI_REASSIGN
+extern void pci_disable_bridge_window(struct pci_dev *dev);
+#endif
+#ifdef CONFIG_PCI_GUESTDEV
extern int pci_is_reassigndev(struct pci_dev *dev);
-extern void pci_disable_bridge_window(struct pci_dev *dev);
#else
#define pci_is_reassigndev(dev) 0
#endif
diff -r e5d3f2fa3428 drivers/pci/reassigndev.c
--- a/drivers/pci/reassigndev.c Tue Apr 07 10:29:30 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2008, NEC Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include "pci.h"
-
-
-#define REASSIGNDEV_PARAM_MAX (2048)
-#define TOKEN_MAX (12) /* "SSSS:BB:DD.F" length is 12 */
-
-static char param_reassigndev[REASSIGNDEV_PARAM_MAX] = {0};
-
-static int __init pci_reassigndev_setup(char *str)
-{
- strncpy(param_reassigndev, str, REASSIGNDEV_PARAM_MAX);
- param_reassigndev[REASSIGNDEV_PARAM_MAX - 1] = '\0';
- return 1;
-}
-__setup("reassigndev=", pci_reassigndev_setup);
-
-int pci_is_reassigndev(struct pci_dev *dev)
-{
- char dev_str[TOKEN_MAX+1];
- int seg, bus, slot, func;
- int len;
- char *p, *next_str;
- int result;
-
-#ifdef CONFIG_PCI_GUESTDEV
- result = pci_is_guestdev_to_reassign(dev);
- if (result)
- return result;
-#endif /* CONFIG_PCI_GUESTDEV */
-
- p = param_reassigndev;
- for (; p; p = next_str + 1) {
- next_str = strpbrk(p, ",");
- if (next_str) {
- len = next_str - p;
- } else {
- len = strlen(p);
- }
- if (len > 0 && len <= TOKEN_MAX) {
- strncpy(dev_str, p, len);
- *(dev_str + len) = '\0';
-
- if (sscanf(dev_str, "%x:%x:%x.%x",
- &seg, &bus, &slot, &func) != 4) {
- if (sscanf(dev_str, "%x:%x.%x",
- &bus, &slot, &func) == 3) {
- seg = 0;
- } else {
- /* failed to scan strings */
- seg = -1;
- bus = -1;
- }
- }
- if (seg == pci_domain_nr(dev->bus) &&
- bus == dev->bus->number &&
- slot == PCI_SLOT(dev->devfn) &&
- func == PCI_FUNC(dev->devfn)) {
- /* It's a target device */
- return 1;
- }
- }
- if (!next_str)
- break;
- }
-
- return 0;
-}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|