ia64/linux-2.6.18-xen.hg

changeset 858:e75edb8d2c44

merge with linux-2.6.18-xen.hg
author Isaku Yamahata <yamahata@valinux.co.jp>
date Tue Apr 14 14:05:30 2009 +0900 (2009-04-14)
parents b8bef3d2d3c3 a3ad7a5f2dcd
children 35b981251e10
files drivers/pci/reassigndev.c
line diff
     1.1 --- a/Documentation/kernel-parameters.txt	Tue Apr 07 11:31:17 2009 +0900
     1.2 +++ b/Documentation/kernel-parameters.txt	Tue Apr 14 14:05:30 2009 +0900
     1.3 @@ -576,8 +576,9 @@ running once the system is up.
     1.4  	gt96100eth=	[NET] MIPS GT96100 Advanced Communication Controller
     1.5  
     1.6  	guestdev=	[PCI,ACPI]
     1.7 -			Format: <device path>[,<device path>[,...]]
     1.8 -			Format of device path: <hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[...]]
     1.9 +			Format: {<device path>|<sbdf>}][,{<device path>|<sbdf>}[,...]]
    1.10 +			Format of device path: <hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]]
    1.11 +			Format of sbdf: [<segment>:]<bus>:<dev>.<func>
    1.12  			Specifies PCI device for guest domain.
    1.13  			If PCI-PCI bridge is specified, all PCI devices
    1.14  			behind PCI-PCI bridge are reserved.
    1.15 @@ -1364,12 +1365,6 @@ running once the system is up.
    1.16  			Run specified binary instead of /init from the ramdisk,
    1.17  			used for early userspace startup. See initrd.
    1.18  
    1.19 -	reassigndev=	[PCI]
    1.20 -			Format: [<segment>:]<bus>:<dev>.<func>[,[<segment>:]<bus>:<dev>.<func>[,...]]
    1.21 -			Specifies device to reassign page-aligned memory
    1.22 -			resources. PCI-PCI bridge can be specified, if
    1.23 -			resource windows need to be expanded.
    1.24 -
    1.25  	reassign_resources
    1.26  			[PCI,ACPI] Use guestdev parameter to reassign device's
    1.27  			resources.
     2.1 --- a/drivers/pci/Makefile	Tue Apr 07 11:31:17 2009 +0900
     2.2 +++ b/drivers/pci/Makefile	Tue Apr 14 14:05:30 2009 +0900
     2.3 @@ -4,7 +4,6 @@
     2.4  
     2.5  obj-y		+= access.o bus.o probe.o remove.o pci.o quirks.o \
     2.6  			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
     2.7 -obj-$(CONFIG_PCI_REASSIGN) += reassigndev.o
     2.8  obj-$(CONFIG_PROC_FS) += proc.o
     2.9  obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
    2.10  
     3.1 --- a/drivers/pci/guestdev.c	Tue Apr 07 11:31:17 2009 +0900
     3.2 +++ b/drivers/pci/guestdev.c	Tue Apr 14 14:05:30 2009 +0900
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2008, NEC Corporation.
     3.6 + * Copyright (c) 2008, 2009 NEC Corporation.
     3.7   *
     3.8   * This program is free software; you can redistribute it and/or modify it
     3.9   * under the terms and conditions of the GNU General Public License,
    3.10 @@ -32,21 +32,36 @@
    3.11  #define FUNC_NUM_MAX 7
    3.12  #define INVALID_SEG (-1)
    3.13  #define INVALID_BBN (-1)
    3.14 -#define PATH_STR_MAX 128
    3.15 +#define GUESTDEV_STR_MAX 128
    3.16 +
    3.17 +#define GUESTDEV_FLAG_TYPE_MASK 0x3
    3.18 +#define GUESTDEV_FLAG_DEVICEPATH 0x1
    3.19 +#define GUESTDEV_FLAG_SBDF 0x2
    3.20  
    3.21  struct guestdev {
    3.22 +	int flags;
    3.23  	struct list_head root_list;
    3.24 -	char hid[HID_LEN + 1];
    3.25 -	char uid[UID_LEN + 1];
    3.26 -	int seg;
    3.27 -	int bbn;
    3.28 -	struct guestdev_node *child;
    3.29 +	union {
    3.30 +		struct devicepath {
    3.31 +			char hid[HID_LEN + 1];
    3.32 +			char uid[UID_LEN + 1];
    3.33 +			int seg;
    3.34 +			int bbn;
    3.35 +			struct devicepath_node *child;
    3.36 +		} devicepath;
    3.37 +		struct sbdf {
    3.38 +			int seg;
    3.39 +			int bus;
    3.40 +			int dev;
    3.41 +			int func;
    3.42 +		} sbdf;
    3.43 +	} u;
    3.44  };
    3.45  
    3.46 -struct guestdev_node {
    3.47 +struct devicepath_node {
    3.48  	int dev;
    3.49  	int func;
    3.50 -	struct guestdev_node *child;
    3.51 +	struct devicepath_node *child;
    3.52  };
    3.53  
    3.54  struct pcidev_sbdf {
    3.55 @@ -67,7 +82,7 @@ static char guestdev_param[COMMAND_LINE_
    3.56  LIST_HEAD(guestdev_list);
    3.57  
    3.58  /* Get hid and uid */
    3.59 -static int pci_get_hid_uid(char *str, char *hid, char *uid)
    3.60 +static int __init pci_get_hid_uid(char *str, char *hid, char *uid)
    3.61  {
    3.62  	char *sp, *ep;
    3.63  	int len;
    3.64 @@ -111,7 +126,7 @@ format_err_end:
    3.65  }
    3.66  
    3.67  /* Get device and function */
    3.68 -static int pci_get_dev_func(char *str, int *dev, int *func)
    3.69 +static int __init pci_get_dev_func(char *str, int *dev, int *func)
    3.70  {
    3.71  	if (sscanf(str, "%02x.%01x", dev, func) != 2)
    3.72  		goto format_err_end;
    3.73 @@ -129,7 +144,7 @@ format_err_end:
    3.74  }
    3.75  
    3.76  /* Check extended guestdev parameter format error */
    3.77 -static int pci_check_extended_guestdev_format(char *str)
    3.78 +static int __init pci_check_extended_guestdev_format(char *str)
    3.79  {
    3.80  	int flg;
    3.81  	char *p;
    3.82 @@ -184,74 +199,75 @@ format_err_end:
    3.83  }
    3.84  
    3.85  /* Make guestdev strings */
    3.86 -static void pci_make_guestdev_path_str(struct guestdev *gdev,
    3.87 +static void pci_make_guestdev_str(struct guestdev *gdev,
    3.88  					char *gdev_str, int buf_size)
    3.89  {
    3.90 -	struct guestdev_node *node;
    3.91 -	/* max length for "HID:UID" (hid+uid+':'+'\0') */
    3.92 -	const int hid_uid_len = HID_LEN + UID_LEN + 2;
    3.93 -	/* max length for "-DEV#.FUNC#" (dev+func+'-'+'.'+'\0') */
    3.94 -	const int dev_func_len = DEV_LEN + FUNC_LEN + 3;
    3.95 -
    3.96 -	/* check buffer size for HID:UID */
    3.97 -	if (buf_size < hid_uid_len)
    3.98 -		return;
    3.99 -
   3.100 -	memset(gdev_str, 0, buf_size);
   3.101 +	struct devicepath_node *node;
   3.102 +	int count;
   3.103  
   3.104 -	if (strlen(gdev->uid))
   3.105 -		sprintf(gdev_str, "%s:%s", gdev->hid, gdev->uid);
   3.106 -	else
   3.107 -		sprintf(gdev_str, "%s", gdev->hid);
   3.108 -	buf_size -= strlen(gdev_str);
   3.109 +	switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
   3.110 +	case GUESTDEV_FLAG_DEVICEPATH:
   3.111 +		memset(gdev_str, 0, buf_size);
   3.112  
   3.113 -	node = gdev->child;
   3.114 -	while (node) {
   3.115 -		/* check buffer size for -DEV#.FUNC# */
   3.116 -		if (buf_size < dev_func_len)
   3.117 +		if (strlen(gdev->u.devicepath.uid))
   3.118 +			count = snprintf(gdev_str, buf_size, "%s:%s",
   3.119 +						gdev->u.devicepath.hid,
   3.120 +						gdev->u.devicepath.uid);
   3.121 +		else
   3.122 +			count = snprintf(gdev_str, buf_size, "%s",
   3.123 +						 gdev->u.devicepath.hid);
   3.124 +		if (count < 0)
   3.125  			return;
   3.126 -		sprintf(gdev_str + strlen(gdev_str), "-%02x.%01x",
   3.127 -			node->dev, node->func);
   3.128 -		buf_size -= dev_func_len;
   3.129 -		node = node->child;
   3.130 +
   3.131 +		node = gdev->u.devicepath.child;
   3.132 +		while (node) {
   3.133 +			gdev_str += count;
   3.134 +			buf_size -= count;
   3.135 +			if (buf_size <= 0)
   3.136 +				return;
   3.137 +			count = snprintf(gdev_str, buf_size, "-%02x.%01x",
   3.138 +				node->dev, node->func);
   3.139 +			if (count < 0)
   3.140 +				return;
   3.141 +			node = node->child;
   3.142 +		}
   3.143 +		break;
   3.144 +	case GUESTDEV_FLAG_SBDF:
   3.145 +		snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x",
   3.146 +					gdev->u.sbdf.seg, gdev->u.sbdf.bus,
   3.147 +					gdev->u.sbdf.dev, gdev->u.sbdf.func);
   3.148 +		break;
   3.149 +	default:
   3.150 +		BUG();
   3.151  	}
   3.152  }
   3.153  
   3.154  /* Free guestdev and nodes */
   3.155 -static void pci_free_guestdev(struct guestdev *gdev)
   3.156 +static void __init pci_free_guestdev(struct guestdev *gdev)
   3.157  {
   3.158 -	struct guestdev_node *node, *next;
   3.159 +	struct devicepath_node *node, *next;
   3.160  
   3.161  	if (!gdev)
   3.162  		return;
   3.163 -
   3.164 -	node = gdev->child;
   3.165 -	while (node) {
   3.166 -		next = node->child;
   3.167 -		kfree(node);
   3.168 -		node = next;
   3.169 +	if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) {
   3.170 +		node = gdev->u.devicepath.child;
   3.171 +		while (node) {
   3.172 +			next = node->child;
   3.173 +			kfree(node);
   3.174 +			node = next;
   3.175 +		}
   3.176  	}
   3.177  	list_del(&gdev->root_list);
   3.178  	kfree(gdev);
   3.179  }
   3.180  
   3.181 -/* Free guestdev_list */
   3.182 -static void pci_free_guestdev_list(void)
   3.183 -{
   3.184 -	struct list_head *head, *tmp;
   3.185 -	struct guestdev *gdev;
   3.186 -
   3.187 -	list_for_each_safe(head, tmp, &guestdev_list) {
   3.188 -		gdev = list_entry(head, struct guestdev, root_list);
   3.189 -		pci_free_guestdev(gdev);
   3.190 -	}
   3.191 -}
   3.192 -
   3.193  /* Copy guestdev and nodes */
   3.194 -struct guestdev *pci_copy_guestdev(struct guestdev *gdev_src)
   3.195 +struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src)
   3.196  {
   3.197  	struct guestdev *gdev;
   3.198 -	struct guestdev_node *node, *node_src, *node_upper;
   3.199 +	struct devicepath_node *node, *node_src, *node_upper;
   3.200 +
   3.201 +	BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH));
   3.202  
   3.203  	gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
   3.204  	if (!gdev)
   3.205 @@ -259,14 +275,15 @@ struct guestdev *pci_copy_guestdev(struc
   3.206  
   3.207  	memset(gdev, 0, sizeof(*gdev));
   3.208  	INIT_LIST_HEAD(&gdev->root_list);
   3.209 -	strcpy(gdev->hid, gdev_src->hid);
   3.210 -	strcpy(gdev->uid, gdev_src->uid);
   3.211 -	gdev->seg = gdev_src->seg;
   3.212 -	gdev->bbn = gdev_src->bbn;
   3.213 +	gdev->flags = gdev_src->flags;
   3.214 +	strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
   3.215 +	strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
   3.216 +	gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
   3.217 +	gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn;
   3.218  
   3.219  	node_upper = NULL;
   3.220  
   3.221 -	node_src = gdev_src->child;
   3.222 +	node_src = gdev_src->u.devicepath.child;
   3.223  	while (node_src) {
   3.224  		node = kmalloc(sizeof(*node), GFP_KERNEL);
   3.225  		if (!node)
   3.226 @@ -275,7 +292,7 @@ struct guestdev *pci_copy_guestdev(struc
   3.227  		node->dev = node_src->dev;
   3.228  		node->func = node_src->func;
   3.229  		if (!node_upper)
   3.230 -			gdev->child = node;
   3.231 +			gdev->u.devicepath.child = node;
   3.232  		else
   3.233  			node_upper->child = node;
   3.234  		node_upper = node;
   3.235 @@ -292,12 +309,12 @@ allocate_err_end:
   3.236  }
   3.237  
   3.238  /* Make guestdev from path strings */
   3.239 -static int pci_make_guestdev(char *path_str)
   3.240 +static int __init pci_make_devicepath_guestdev(char *path_str)
   3.241  {
   3.242  	char hid[HID_LEN + 1], uid[UID_LEN + 1];
   3.243  	char *sp, *ep;
   3.244  	struct guestdev *gdev, *gdev_org;
   3.245 -	struct guestdev_node *node, *node_tmp;
   3.246 +	struct devicepath_node *node, *node_tmp;
   3.247  	int dev, func, ret_val;
   3.248  
   3.249  	ret_val = 0;
   3.250 @@ -319,10 +336,11 @@ static int pci_make_guestdev(char *path_
   3.251  		goto allocate_err_end;
   3.252  	memset(gdev_org, 0, sizeof(*gdev_org));
   3.253  	INIT_LIST_HEAD(&gdev_org->root_list);
   3.254 -	strcpy(gdev_org->hid, hid);
   3.255 -	strcpy(gdev_org->uid, uid);
   3.256 -	gdev_org->seg = INVALID_SEG;
   3.257 -	gdev_org->bbn = INVALID_BBN;
   3.258 +	gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
   3.259 +	strcpy(gdev_org->u.devicepath.hid, hid);
   3.260 +	strcpy(gdev_org->u.devicepath.uid, uid);
   3.261 +	gdev_org->u.devicepath.seg = INVALID_SEG;
   3.262 +	gdev_org->u.devicepath.bbn = INVALID_BBN;
   3.263  
   3.264  	gdev = gdev_org;
   3.265  
   3.266 @@ -335,12 +353,12 @@ static int pci_make_guestdev(char *path_
   3.267  				gdev = pci_copy_guestdev(gdev_org);
   3.268  				if (!gdev) {
   3.269  					ret_val = -ENOMEM;
   3.270 -					goto err_end;
   3.271 +					goto end;
   3.272  				}
   3.273  			}
   3.274  			continue;
   3.275  		}
   3.276 -		if (pci_get_dev_func(sp, &dev, &func)) {
   3.277 +		if (gdev && pci_get_dev_func(sp, &dev, &func)) {
   3.278  			node = kmalloc(sizeof(*node), GFP_KERNEL);
   3.279  			if (!node)
   3.280  				goto allocate_err_end;
   3.281 @@ -348,33 +366,47 @@ static int pci_make_guestdev(char *path_
   3.282  			node->dev = dev;
   3.283  			node->func = func;
   3.284  			/* add node to end of guestdev */
   3.285 -			if (gdev->child) {
   3.286 -				node_tmp = gdev->child;
   3.287 +			if (gdev->u.devicepath.child) {
   3.288 +				node_tmp = gdev->u.devicepath.child;
   3.289  				while (node_tmp->child) {
   3.290  					node_tmp = node_tmp->child;
   3.291  				}
   3.292  				node_tmp->child = node;
   3.293  			} else
   3.294 -				gdev->child = node;
   3.295 -		} else
   3.296 -			goto format_err_end;
   3.297 +				gdev->u.devicepath.child = node;
   3.298 +		} else if (gdev) {
   3.299 +			printk(KERN_ERR
   3.300 +				"PCI: Can't obtain dev# and #func# from %s.\n",
   3.301 +				sp);
   3.302 +			ret_val = -EINVAL;
   3.303 +			if (gdev == gdev_org)
   3.304 +				goto end;
   3.305 +			pci_free_guestdev(gdev);
   3.306 +			gdev = NULL;
   3.307 +		}
   3.308  
   3.309  		ep = strpbrk(sp, "-|)");
   3.310  		if (!ep)
   3.311  			ep = strchr(sp, '\0');
   3.312 -		/* *ep is '|' OR ')' OR '\0' ? */
   3.313 +		/* Is *ep '|' OR ')' OR '\0' ? */
   3.314  		if (*ep != '-') {
   3.315 -			list_add_tail(&gdev->root_list, &guestdev_list);
   3.316 +			if (gdev)
   3.317 +				list_add_tail(&gdev->root_list, &guestdev_list);
   3.318  			if (*ep == '|') {
   3.319  				/* Between '|' and '|' ? */
   3.320  				if (strchr(ep + 1, '|')) {
   3.321  					gdev = pci_copy_guestdev(gdev_org);
   3.322  					if (!gdev) {
   3.323  						ret_val = -ENOMEM;
   3.324 -						goto err_end;
   3.325 +						goto end;
   3.326  					}
   3.327 -				} else
   3.328 +				} else {
   3.329  					gdev = gdev_org;
   3.330 +					gdev_org = NULL;
   3.331 +				}
   3.332 +			} else {
   3.333 +				gdev_org = NULL;
   3.334 +				gdev = NULL;
   3.335  			}
   3.336  		}
   3.337  		if (*ep == ')')
   3.338 @@ -382,21 +414,21 @@ static int pci_make_guestdev(char *path_
   3.339  		sp = ep + 1;
   3.340  	} while (*ep != '\0');
   3.341  
   3.342 -	return ret_val;
   3.343 +	goto end;
   3.344  
   3.345  format_err_end:
   3.346  	printk(KERN_ERR
   3.347  		"PCI: The format of the guestdev parameter is illegal. [%s]\n",
   3.348  		path_str);
   3.349  	ret_val = -EINVAL;
   3.350 -	goto err_end;
   3.351 +	goto end;
   3.352  
   3.353  allocate_err_end:
   3.354  	printk(KERN_ERR "PCI: Failed to allocate memory.\n");
   3.355  	ret_val = -ENOMEM;
   3.356 -	goto err_end;
   3.357 +	goto end;
   3.358  
   3.359 -err_end:
   3.360 +end:
   3.361  	if (gdev_org && (gdev_org != gdev))
   3.362  		pci_free_guestdev(gdev_org);
   3.363  	if (gdev)
   3.364 @@ -404,20 +436,44 @@ err_end:
   3.365  	return ret_val;
   3.366  }
   3.367  
   3.368 +static int __init pci_make_sbdf_guestdev(char* str)
   3.369 +{
   3.370 +	struct guestdev *gdev;
   3.371 +	int seg, bus, dev, func;
   3.372 +
   3.373 +	if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) {
   3.374 +		seg = 0;
   3.375 +		if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3)
   3.376 +			return -EINVAL;
   3.377 +	}
   3.378 +	gdev = kmalloc(sizeof(*gdev), GFP_KERNEL);
   3.379 +	if (!gdev) {
   3.380 +		printk(KERN_ERR "PCI: Failed to allocate memory.\n");
   3.381 +		return -ENOMEM;
   3.382 +	}
   3.383 +	INIT_LIST_HEAD(&gdev->root_list);
   3.384 +	gdev->flags = GUESTDEV_FLAG_SBDF;
   3.385 +	gdev->u.sbdf.seg = seg;
   3.386 +	gdev->u.sbdf.bus = bus;
   3.387 +	gdev->u.sbdf.dev = dev;
   3.388 +	gdev->u.sbdf.func = func;
   3.389 +	list_add_tail(&gdev->root_list, &guestdev_list);
   3.390 +	return 0;
   3.391 +}
   3.392 +
   3.393  /* Parse guestdev parameter */
   3.394  static int __init pci_parse_guestdev(void)
   3.395  {
   3.396 -	int len, ret_val;
   3.397 +	int len;
   3.398  	char *sp, *ep;
   3.399  	struct list_head *head;
   3.400  	struct guestdev *gdev;
   3.401 -	char path_str[PATH_STR_MAX];
   3.402 -
   3.403 -	ret_val = 0;
   3.404 +	char path_str[GUESTDEV_STR_MAX];
   3.405 +	int ret_val = 0;
   3.406  
   3.407  	len = strlen(guestdev_param);
   3.408  	if (len == 0)
   3.409 -		goto end;
   3.410 +		return 0;
   3.411  
   3.412  	sp = guestdev_param;
   3.413  
   3.414 @@ -426,29 +482,26 @@ static int __init pci_parse_guestdev(voi
   3.415  		/* Chop */
   3.416  		if (ep)
   3.417  			*ep = '\0';
   3.418 -		if (!pci_check_extended_guestdev_format(sp)) {
   3.419 -			pci_free_guestdev_list();
   3.420 -			return -EINVAL;
   3.421 -		}
   3.422 -
   3.423 -		ret_val = pci_make_guestdev(sp);
   3.424 -		if (ret_val) {
   3.425 -			pci_free_guestdev_list();
   3.426 -			return ret_val;
   3.427 -		}
   3.428 +		ret_val = pci_make_sbdf_guestdev(sp);
   3.429 +		if (ret_val == -EINVAL) {
   3.430 +			if (pci_check_extended_guestdev_format(sp)) {
   3.431 +				ret_val = pci_make_devicepath_guestdev(sp);
   3.432 +				if (ret_val && ret_val != -EINVAL)
   3.433 +					break;
   3.434 +			}
   3.435 +		} else if (ret_val)
   3.436 +			break;
   3.437  		sp = ep + 1;
   3.438  	} while (ep);
   3.439  
   3.440  	list_for_each(head, &guestdev_list) {
   3.441  		gdev = list_entry(head, struct guestdev, root_list);
   3.442 -		pci_make_guestdev_path_str(gdev, path_str, PATH_STR_MAX);
   3.443 +		pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
   3.444  		printk(KERN_DEBUG
   3.445  			"PCI: %s has been reserved for guest domain.\n",
   3.446  			path_str);
   3.447  	}
   3.448 -
   3.449 -end:
   3.450 -	return ret_val;
   3.451 +	return 0;
   3.452  }
   3.453  
   3.454  arch_initcall(pci_parse_guestdev);
   3.455 @@ -478,32 +531,35 @@ static void pci_free_sbdf(struct pcidev_
   3.456  	/* Skip kfree(sbdf) */
   3.457  }
   3.458  
   3.459 -/* Is sbdf within guestdev */
   3.460 -static int pci_sbdf_in_guestdev_sub_tree(struct guestdev *gdev, 
   3.461 +/* Does PCI device belong to sub tree specified by guestdev with device path? */
   3.462 +static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
   3.463  					struct pcidev_sbdf *sbdf)
   3.464  {
   3.465  	int seg, bbn;
   3.466 -	struct guestdev_node *gdev_node;
   3.467 +	struct devicepath_node *gdev_node;
   3.468  	struct pcidev_sbdf_node *sbdf_node;
   3.469  
   3.470  	if (!gdev || !sbdf)
   3.471  		return FALSE;
   3.472  
   3.473 +	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
   3.474 +
   3.475  	/* Compare seg and bbn */
   3.476 -	if (gdev->seg == INVALID_SEG || 
   3.477 -	    gdev->bbn == INVALID_BBN) {
   3.478 -		if (acpi_pci_get_root_seg_bbn(gdev->hid, 
   3.479 -		    gdev->uid, &seg, &bbn)) {
   3.480 -			gdev->seg = seg;
   3.481 -			gdev->bbn = bbn;
   3.482 +	if (gdev->u.devicepath.seg == INVALID_SEG ||
   3.483 +	    gdev->u.devicepath.bbn == INVALID_BBN) {
   3.484 +		if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid,
   3.485 +		    gdev->u.devicepath.uid, &seg, &bbn)) {
   3.486 +			gdev->u.devicepath.seg = seg;
   3.487 +			gdev->u.devicepath.bbn = bbn;
   3.488  		} else
   3.489  			return FALSE;
   3.490  	}
   3.491  
   3.492 -	if (gdev->seg != sbdf->seg || gdev->bbn != sbdf->bus)
   3.493 +	if (gdev->u.devicepath.seg != sbdf->seg ||
   3.494 +	    gdev->u.devicepath.bbn != sbdf->bus)
   3.495  		return FALSE;
   3.496  
   3.497 -	gdev_node = gdev->child;
   3.498 +	gdev_node = gdev->u.devicepath.child;
   3.499  	sbdf_node = sbdf->child;
   3.500  
   3.501  	/* Compare dev and func */
   3.502 @@ -559,29 +615,64 @@ err_end:
   3.503  	return FALSE;
   3.504  }
   3.505  
   3.506 -/* Is PCI device belongs to the subtree of the guestdev parameter */
   3.507 +/* Does PCI device belong to sub tree specified by guestdev with sbdf? */
   3.508 +static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev)
   3.509 +{
   3.510 +	int seg, bus;
   3.511 +	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
   3.512 +	for (;;) {
   3.513 +		if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
   3.514 +			continue;
   3.515 +		if (gdev->u.sbdf.seg == seg && gdev->u.sbdf.bus == bus &&
   3.516 +			gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
   3.517 +			gdev->u.sbdf.func == PCI_FUNC(dev->devfn))
   3.518 +			return TRUE;
   3.519 +		if (!dev->bus || !dev->bus->self)
   3.520 +			break;
   3.521 +		dev = dev->bus->self;
   3.522 +	}
   3.523 +	return FALSE;
   3.524 +}
   3.525 +
   3.526 +/* Does PCI device belong to sub tree specified by guestdev parameter? */
   3.527  int pci_is_guestdev(struct pci_dev *dev)
   3.528  {
   3.529  	struct guestdev *gdev;
   3.530 -	struct pcidev_sbdf sbdf;
   3.531 +	struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
   3.532  	struct list_head *head;
   3.533 -	int result;
   3.534 +	int result = FALSE;
   3.535  
   3.536  	if (!dev)
   3.537  		return FALSE;
   3.538 -	memset(&sbdf, 0 ,sizeof(sbdf));
   3.539 -	if (!pci_get_sbdf_from_pcidev(dev, &sbdf))
   3.540 -		return FALSE;
   3.541  
   3.542 -	result = FALSE;
   3.543  	list_for_each(head, &guestdev_list) {
   3.544  		gdev = list_entry(head, struct guestdev, root_list);
   3.545 -		if (pci_sbdf_in_guestdev_sub_tree(gdev, &sbdf)) {
   3.546 -			result = TRUE;
   3.547 +		switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
   3.548 +		case GUESTDEV_FLAG_DEVICEPATH:
   3.549 +			if (sbdf == NULL) {
   3.550 +				sbdf = &pcidev_sbdf;
   3.551 +				memset(sbdf, 0 ,sizeof(*sbdf));
   3.552 +				if (!pci_get_sbdf_from_pcidev(dev, sbdf))
   3.553 +					goto out;
   3.554 +			}
   3.555 +			if (pci_is_in_devicepath_sub_tree(gdev, sbdf)) {
   3.556 +				result = TRUE;
   3.557 +				goto out;
   3.558 +			}
   3.559  			break;
   3.560 +		case GUESTDEV_FLAG_SBDF:
   3.561 +			if (pci_is_in_sbdf_sub_tree(gdev, dev)) {
   3.562 +				result = TRUE;
   3.563 +				goto out;
   3.564 +			}
   3.565 +			break;
   3.566 +		default:
   3.567 +			BUG();
   3.568  		}
   3.569  	}
   3.570 -	pci_free_sbdf(&sbdf);
   3.571 +out:
   3.572 +	if (sbdf)
   3.573 +		pci_free_sbdf(sbdf);
   3.574  	return result;
   3.575  }
   3.576  EXPORT_SYMBOL(pci_is_guestdev);
   3.577 @@ -595,30 +686,30 @@ static int __init pci_set_reassign_resou
   3.578  
   3.579  __setup("reassign_resources", pci_set_reassign_resources);
   3.580  
   3.581 -int pci_is_guestdev_to_reassign(struct pci_dev *dev)
   3.582 +int pci_is_reassigndev(struct pci_dev *dev)
   3.583  {
   3.584  	if (reassign_resources)
   3.585  		return pci_is_guestdev(dev);
   3.586  	return FALSE;
   3.587  }
   3.588 -EXPORT_SYMBOL(pci_is_guestdev_to_reassign);
   3.589 +EXPORT_SYMBOL(pci_is_reassigndev);
   3.590  
   3.591 -/* Check whether the guestdev exists under the pci root bus */
   3.592 -static int __init pci_check_guestdev_path_exists(
   3.593 +/* Check whether the devicepath exists under the pci root bus */
   3.594 +static int __init pci_check_devicepath_exists(
   3.595  		struct guestdev *gdev, struct pci_bus *bus)
   3.596  {
   3.597 -	struct guestdev_node *node;
   3.598 +	struct devicepath_node *node;
   3.599  	struct pci_dev *dev;
   3.600  
   3.601 -	node = gdev->child;
   3.602 +	BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH));
   3.603 +
   3.604 +	node = gdev->u.devicepath.child;
   3.605  	while (node) {
   3.606  		if (!bus)
   3.607  			return FALSE;
   3.608  		dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func));
   3.609 -		if (!dev) {
   3.610 -			pci_dev_put(dev);
   3.611 +		if (!dev)
   3.612  			return FALSE;
   3.613 -		}
   3.614  		bus = dev->subordinate;
   3.615  		node = node->child;
   3.616  		pci_dev_put(dev);
   3.617 @@ -633,32 +724,58 @@ static int __init pci_check_guestdev_exi
   3.618  	struct guestdev *gdev;
   3.619  	int seg, bbn;
   3.620  	struct pci_bus *bus;
   3.621 -	char path_str[PATH_STR_MAX];
   3.622 +	struct pci_dev *dev;
   3.623 +	char path_str[GUESTDEV_STR_MAX];
   3.624  
   3.625  	list_for_each(head, &guestdev_list) {
   3.626  		gdev = list_entry(head, struct guestdev, root_list);
   3.627 -		if (gdev->seg == INVALID_SEG ||
   3.628 -			gdev->bbn == INVALID_BBN) {
   3.629 -			if (acpi_pci_get_root_seg_bbn(gdev->hid,
   3.630 -				gdev->uid, &seg, &bbn)) {
   3.631 -				gdev->seg = seg;
   3.632 -				gdev->bbn = bbn;
   3.633 -			} else {
   3.634 -				pci_make_guestdev_path_str(gdev, path_str,
   3.635 -					PATH_STR_MAX);
   3.636 +		switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) {
   3.637 +		case GUESTDEV_FLAG_DEVICEPATH:
   3.638 +			if (gdev->u.devicepath.seg == INVALID_SEG ||
   3.639 +				gdev->u.devicepath.bbn == INVALID_BBN) {
   3.640 +				if (acpi_pci_get_root_seg_bbn(
   3.641 +					gdev->u.devicepath.hid,
   3.642 +					gdev->u.devicepath.uid, &seg, &bbn)) {
   3.643 +					gdev->u.devicepath.seg = seg;
   3.644 +					gdev->u.devicepath.bbn = bbn;
   3.645 +				} else {
   3.646 +					pci_make_guestdev_str(gdev,
   3.647 +						path_str, GUESTDEV_STR_MAX);
   3.648 +					printk(KERN_INFO
   3.649 +					"PCI: Device does not exist. %s\n",
   3.650 +					path_str);
   3.651 +					continue;
   3.652 +				}
   3.653 +			}
   3.654 +
   3.655 +			bus = pci_find_bus(gdev->u.devicepath.seg,
   3.656 +						gdev->u.devicepath.bbn);
   3.657 +			if (!bus ||
   3.658 +				!pci_check_devicepath_exists(gdev, bus)) {
   3.659 +				pci_make_guestdev_str(gdev, path_str,
   3.660 +					GUESTDEV_STR_MAX);
   3.661  				printk(KERN_INFO
   3.662  					"PCI: Device does not exist. %s\n",
   3.663  					path_str);
   3.664 -				continue;
   3.665  			}
   3.666 -		}
   3.667 -
   3.668 -		bus = pci_find_bus(gdev->seg, gdev->bbn);
   3.669 -		if (!bus || !pci_check_guestdev_path_exists(gdev, bus)) {
   3.670 -			pci_make_guestdev_path_str(gdev, path_str,
   3.671 -				PATH_STR_MAX);
   3.672 -			printk(KERN_INFO
   3.673 -				"PCI: Device does not exist. %s\n", path_str);
   3.674 +			break;
   3.675 +		case GUESTDEV_FLAG_SBDF:
   3.676 +			bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus);
   3.677 +			if (bus) {
   3.678 +				dev = pci_get_slot(bus,
   3.679 +					PCI_DEVFN(gdev->u.sbdf.dev,
   3.680 +							gdev->u.sbdf.func));
   3.681 +				if (dev) {
   3.682 +					pci_dev_put(dev);
   3.683 +					continue;
   3.684 +				}
   3.685 +			}
   3.686 +			pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX);
   3.687 +			printk(KERN_INFO "PCI: Device does not exist. %s\n",
   3.688 +								path_str);
   3.689 +			break;
   3.690 +		default:
   3.691 +			BUG();
   3.692  		}
   3.693  	}
   3.694  	return 0;
     4.1 --- a/drivers/pci/pci.h	Tue Apr 07 11:31:17 2009 +0900
     4.2 +++ b/drivers/pci/pci.h	Tue Apr 14 14:05:30 2009 +0900
     4.3 @@ -102,8 +102,10 @@ pci_match_one_device(const struct pci_de
     4.4  }
     4.5  
     4.6  #ifdef CONFIG_PCI_REASSIGN
     4.7 +extern void pci_disable_bridge_window(struct pci_dev *dev);
     4.8 +#endif
     4.9 +#ifdef CONFIG_PCI_GUESTDEV
    4.10  extern int pci_is_reassigndev(struct pci_dev *dev);
    4.11 -extern void pci_disable_bridge_window(struct pci_dev *dev);
    4.12  #else
    4.13  #define pci_is_reassigndev(dev) 0
    4.14  #endif
     5.1 --- a/drivers/pci/reassigndev.c	Tue Apr 07 11:31:17 2009 +0900
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,87 +0,0 @@
     5.4 -/*
     5.5 - * Copyright (c) 2008, NEC Corporation.
     5.6 - *
     5.7 - * This program is free software; you can redistribute it and/or modify it
     5.8 - * under the terms and conditions of the GNU General Public License,
     5.9 - * version 2, as published by the Free Software Foundation.
    5.10 - *
    5.11 - * This program is distributed in the hope it will be useful, but WITHOUT
    5.12 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.13 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    5.14 - * more details.
    5.15 - *
    5.16 - * You should have received a copy of the GNU General Public License along with
    5.17 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    5.18 - * Place - Suite 330, Boston, MA 02111-1307 USA.
    5.19 - */
    5.20 -
    5.21 -#include <linux/kernel.h>
    5.22 -#include <linux/pci.h>
    5.23 -#include <linux/string.h>
    5.24 -#include "pci.h"
    5.25 -
    5.26 -
    5.27 -#define	REASSIGNDEV_PARAM_MAX	(2048)
    5.28 -#define	TOKEN_MAX	(12)	/* "SSSS:BB:DD.F" length is 12 */
    5.29 -
    5.30 -static char param_reassigndev[REASSIGNDEV_PARAM_MAX] = {0};
    5.31 -
    5.32 -static int __init pci_reassigndev_setup(char *str)
    5.33 -{
    5.34 -	strncpy(param_reassigndev, str, REASSIGNDEV_PARAM_MAX);
    5.35 -	param_reassigndev[REASSIGNDEV_PARAM_MAX - 1] = '\0';
    5.36 -	return 1;
    5.37 -}
    5.38 -__setup("reassigndev=", pci_reassigndev_setup);
    5.39 -
    5.40 -int pci_is_reassigndev(struct pci_dev *dev)
    5.41 -{
    5.42 -	char dev_str[TOKEN_MAX+1];
    5.43 -	int seg, bus, slot, func;
    5.44 -	int len;
    5.45 -	char *p, *next_str;
    5.46 -	int result;
    5.47 -
    5.48 -#ifdef CONFIG_PCI_GUESTDEV
    5.49 -	result = pci_is_guestdev_to_reassign(dev);
    5.50 -	if (result)
    5.51 -		return	result;
    5.52 -#endif /* CONFIG_PCI_GUESTDEV */
    5.53 -
    5.54 -	p = param_reassigndev;
    5.55 -	for (; p; p = next_str + 1) {
    5.56 -		next_str = strpbrk(p, ",");
    5.57 -		if (next_str) {
    5.58 -			len = next_str - p;
    5.59 -		} else {
    5.60 -			len = strlen(p);
    5.61 -		}
    5.62 -		if (len > 0 && len <= TOKEN_MAX) {
    5.63 -			strncpy(dev_str, p, len);
    5.64 -			*(dev_str + len) = '\0';
    5.65 -
    5.66 -			if (sscanf(dev_str, "%x:%x:%x.%x", 
    5.67 -				&seg, &bus, &slot, &func) != 4) {
    5.68 -				if (sscanf(dev_str, "%x:%x.%x", 
    5.69 -					&bus, &slot, &func) == 3) {
    5.70 -					seg = 0;
    5.71 -				} else {
    5.72 -					/* failed to scan strings */
    5.73 -					seg = -1;
    5.74 -					bus = -1;
    5.75 -				}
    5.76 -			}
    5.77 -			if (seg == pci_domain_nr(dev->bus) &&
    5.78 -			    bus == dev->bus->number &&
    5.79 -			    slot == PCI_SLOT(dev->devfn) &&
    5.80 -			    func == PCI_FUNC(dev->devfn)) {
    5.81 -				/* It's a target device */
    5.82 -				return 1;
    5.83 -			}
    5.84 -		}
    5.85 -		if (!next_str)
    5.86 -			break;
    5.87 -	}
    5.88 -
    5.89 -	return 0;
    5.90 -}
     6.1 --- a/drivers/xen/netfront/accel.c	Tue Apr 07 11:31:17 2009 +0900
     6.2 +++ b/drivers/xen/netfront/accel.c	Tue Apr 14 14:05:30 2009 +0900
     6.3 @@ -51,6 +51,8 @@ static int netfront_load_accelerator(str
     6.4  				     struct xenbus_device *dev, 
     6.5  				     const char *frontend);
     6.6  
     6.7 +static void netfront_accelerator_remove_watch(struct netfront_info *np);
     6.8 +
     6.9  /*
    6.10   * List of all netfront accelerator plugin modules available.  Each
    6.11   * list entry is of type struct netfront_accelerator.
    6.12 @@ -164,8 +166,11 @@ void netfront_accelerator_add_watch(stru
    6.13  {
    6.14  	int err;
    6.15  	
    6.16 -	/* Check we're not trying to overwrite an existing watch */
    6.17 -	BUG_ON(np->accel_vif_state.accel_watch.node != NULL);
    6.18 +	/* 
    6.19 +	 * If old watch exists, e.g. from before suspend/resume,
    6.20 +	 * remove it now 
    6.21 +	 */
    6.22 +	netfront_accelerator_remove_watch(np);
    6.23  
    6.24  	/* Get a watch on the accelerator plugin */
    6.25  	err = xenbus_watch_path2(np->xbdev, np->xbdev->otherend, 
    6.26 @@ -180,6 +185,19 @@ void netfront_accelerator_add_watch(stru
    6.27  }
    6.28  
    6.29  
    6.30 +static void 
    6.31 +netfront_accelerator_purge_watch(struct netfront_accel_vif_state *vif_state)
    6.32 +{
    6.33 +	flush_workqueue(accel_watch_workqueue);
    6.34 +
    6.35 +	/* Clean up any state left from watch */
    6.36 +	if (vif_state->accel_frontend != NULL) {
    6.37 +		kfree(vif_state->accel_frontend);
    6.38 +		vif_state->accel_frontend = NULL;
    6.39 +	}
    6.40 +}
    6.41 +
    6.42 +
    6.43  static
    6.44  void netfront_accelerator_remove_watch(struct netfront_info *np)
    6.45  {
    6.46 @@ -191,13 +209,7 @@ void netfront_accelerator_remove_watch(s
    6.47  		kfree(vif_state->accel_watch.node);
    6.48  		vif_state->accel_watch.node = NULL;
    6.49  
    6.50 -		flush_workqueue(accel_watch_workqueue);
    6.51 -
    6.52 -		/* Clean up any state left from watch */
    6.53 -		if (vif_state->accel_frontend != NULL) {
    6.54 -			kfree(vif_state->accel_frontend);
    6.55 -			vif_state->accel_frontend = NULL;
    6.56 -		}
    6.57 +		netfront_accelerator_purge_watch(vif_state);
    6.58  	}	
    6.59  }
    6.60  
    6.61 @@ -670,8 +682,6 @@ int netfront_accelerator_suspend(struct 
    6.62  {
    6.63  	int rc = 0;
    6.64  	
    6.65 -	netfront_accelerator_remove_watch(np);
    6.66 -
    6.67  	mutex_lock(&accelerator_mutex);
    6.68  
    6.69   	/* Check that we've got a device that was accelerated */
    6.70 @@ -692,13 +702,16 @@ int netfront_accelerator_suspend(struct 
    6.71  int netfront_accelerator_suspend_cancel(struct netfront_info *np,
    6.72   					struct xenbus_device *dev)
    6.73  {
    6.74 +	netfront_accelerator_purge_watch(&np->accel_vif_state);
    6.75 +
    6.76  	/* 
    6.77 -	 * Setting the watch will cause it to fire and probe the
    6.78 -	 * accelerator, so no need to call accelerator_probe_new_vif()
    6.79 -	 * directly here
    6.80 +	 * Gratuitously fire the watch handler to reinstate the
    6.81 +	 * configured accelerator
    6.82  	 */
    6.83  	if (dev->state == XenbusStateConnected)
    6.84 -		netfront_accelerator_add_watch(np);
    6.85 +		queue_work(accel_watch_workqueue, 
    6.86 +			   &np->accel_vif_state.accel_work);
    6.87 +
    6.88  	return 0;
    6.89  }
    6.90