ia64/linux-2.6.18-xen.hg

diff drivers/pci/reserve.c @ 884:c7c92f868aa1

linux/pci: reserve io/memory space for bridge

reserve io/memory space for bridge which will be used later
by PCI hotplug.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 28 10:00:03 2009 +0100 (2009-05-28)
parents
children 20be7f6d414a
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/drivers/pci/reserve.c	Thu May 28 10:00:03 2009 +0100
     1.3 @@ -0,0 +1,143 @@
     1.4 +/*
     1.5 + * This program is free software; you can redistribute it and/or modify
     1.6 + * it under the terms of the GNU General Public License as published by
     1.7 + * the Free Software Foundation; either version 2 of the License, or
     1.8 + * (at your option) any later version.
     1.9 + *
    1.10 + * This program is distributed in the hope that it will be useful,
    1.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.13 + * GNU General Public License for more details.
    1.14 + *
    1.15 + * You should have received a copy of the GNU General Public License
    1.16 + * along with this program; if not, write to the Free Software
    1.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    1.18 + *
    1.19 + * Copyright (c) 2009 Isaku Yamahata
    1.20 + *                    VA Linux Systems Japan K.K.
    1.21 + *
    1.22 + */
    1.23 +
    1.24 +#include <linux/kernel.h>
    1.25 +#include <linux/pci.h>
    1.26 +
    1.27 +#include <asm/setup.h>
    1.28 +
    1.29 +static char pci_reserve_param[COMMAND_LINE_SIZE];
    1.30 +
    1.31 +/* pci_reserve=	[PCI]
    1.32 + * Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
    1.33 + * Format of sbdf: [<segment>:]<bus>:<dev>.<func>
    1.34 + */
    1.35 +static int pci_reserve_parse_size(const char *str,
    1.36 +				  unsigned long *io_size,
    1.37 +				  unsigned long *mem_size)
    1.38 +{
    1.39 +	if (sscanf(str, "io%lx", io_size) == 1 ||
    1.40 +	    sscanf(str, "IO%lx", io_size) == 1)
    1.41 +		return 0;
    1.42 +
    1.43 +	if (sscanf(str, "mem%lx", mem_size) == 1 ||
    1.44 +	    sscanf(str, "MEM%lx", mem_size) == 1)
    1.45 +		return 0;
    1.46 +
    1.47 +	return -EINVAL;
    1.48 +}
    1.49 +
    1.50 +static int pci_reserve_parse_one(const char *str,
    1.51 +				 int *seg, int *bus, int *dev, int *func,
    1.52 +				 unsigned long *io_size,
    1.53 +				 unsigned long *mem_size)
    1.54 +{
    1.55 +	char *p;
    1.56 +
    1.57 +	*io_size = 0;
    1.58 +	*mem_size = 0;
    1.59 +
    1.60 +	if (sscanf(str, "%x:%x:%x.%x", seg, bus, dev, func) != 4) {
    1.61 +		*seg = 0;
    1.62 +		if (sscanf(str, "%x:%x.%x", bus, dev, func) != 3) {
    1.63 +			return -EINVAL;
    1.64 +		}
    1.65 +	}
    1.66 +
    1.67 +	p = strchr(str, '+');
    1.68 +	if (p == NULL)
    1.69 +		return -EINVAL;
    1.70 +	p++;
    1.71 +	if (pci_reserve_parse_size(p, io_size, mem_size))
    1.72 +		return -EINVAL;
    1.73 +
    1.74 +	p = strchr(str, '+');
    1.75 +	if (p != NULL) {
    1.76 +		p++;
    1.77 +		pci_reserve_parse_size(p, io_size, mem_size);
    1.78 +	}
    1.79 +	return 0;
    1.80 +}
    1.81 +
    1.82 +static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags)
    1.83 +{
    1.84 +	char *sp;
    1.85 +	char *ep;
    1.86 +
    1.87 +	int seg;
    1.88 +	int bus;
    1.89 +	int dev;
    1.90 +	int func;
    1.91 +
    1.92 +	unsigned long io_size;
    1.93 +	unsigned long mem_size;
    1.94 +
    1.95 +	sp = pci_reserve_param;
    1.96 +
    1.97 +	do {
    1.98 +		ep = strchr(sp, ',');
    1.99 +		if (ep)
   1.100 +			*ep = '\0';	/* chomp */
   1.101 +
   1.102 +		if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func,
   1.103 +					  &io_size, &mem_size) == 0) {
   1.104 +			if (pci_domain_nr(pbus) == seg &&
   1.105 +			    pbus->number == bus &&
   1.106 +			    PCI_SLOT(pbus->self->devfn) == dev &&
   1.107 +			    PCI_FUNC(pbus->self->devfn) == func) {
   1.108 +				switch (flags) {
   1.109 +				case IORESOURCE_IO:
   1.110 +					return io_size;
   1.111 +				case IORESOURCE_MEM:
   1.112 +					return mem_size;
   1.113 +				default:
   1.114 +					break;
   1.115 +				}
   1.116 +			}
   1.117 +		}
   1.118 +
   1.119 +		if (ep) {
   1.120 +			*ep = ',';	/* restore chomp'ed ',' for later */
   1.121 +			ep++;
   1.122 +		}
   1.123 +		sp = ep;
   1.124 +	} while (ep);
   1.125 +
   1.126 +	return 0;
   1.127 +}
   1.128 +
   1.129 +unsigned long pci_reserve_size_io(struct pci_bus *pbus)
   1.130 +{
   1.131 +	return pci_reserve_size(pbus, IORESOURCE_IO);
   1.132 +}
   1.133 +
   1.134 +unsigned long pci_reserve_size_mem(struct pci_bus *pbus)
   1.135 +{
   1.136 +	return pci_reserve_size(pbus, IORESOURCE_MEM);
   1.137 +}
   1.138 +
   1.139 +static int __init pci_reserve_setup(char *str)
   1.140 +{
   1.141 +	if (strlen(str) > sizeof(pci_reserve_param))
   1.142 +		return 0;
   1.143 +	strcpy(pci_reserve_param, str);
   1.144 +	return 1;
   1.145 +}
   1.146 +__setup("pci_reserve=", pci_reserve_setup);