[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] linux/pci: reserve io/memory space for bridge
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1243501203 -3600 # Node ID c7c92f868aa15fd352a3469dbc54b2c90b79724f # Parent b998614e2e2a8cb9aecf1253f02eba7ed55bf614 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@xxxxxxxxxxxxx> --- Documentation/kernel-parameters.txt | 7 + drivers/pci/Kconfig | 8 ++ drivers/pci/Makefile | 1 drivers/pci/pci.h | 15 +++ drivers/pci/reserve.c | 143 ++++++++++++++++++++++++++++++++++++ drivers/pci/setup-bus.c | 4 - 6 files changed, 176 insertions(+), 2 deletions(-) diff -r b998614e2e2a -r c7c92f868aa1 Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Thu May 28 09:59:18 2009 +0100 +++ b/Documentation/kernel-parameters.txt Thu May 28 10:00:03 2009 +0100 @@ -1259,6 +1259,13 @@ running once the system is up. IXP2000 systems where the bus has to be configured a certain way for adjunct CPUs. + pci_reserve= [PCI] + Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...] + Format of sbdf: [<segment>:]<bus>:<dev>.<func> + Specifies the least reserved io size or memory size + which is assigned to PCI bridge even when no child + pci device exists. This is useful with PCI hotplug. + pcmv= [HW,PCMCIA] BadgePAD 4 pd. [PARIDE] diff -r b998614e2e2a -r c7c92f868aa1 drivers/pci/Kconfig --- a/drivers/pci/Kconfig Thu May 28 09:59:18 2009 +0100 +++ b/drivers/pci/Kconfig Thu May 28 10:00:03 2009 +0100 @@ -43,6 +43,14 @@ config PCI_IOMULTI default y help Say Y here if you need io multiplexing. + +config PCI_RESERVE + bool "PCI IO/MEMORY space reserve" + depends on PCI + default y + help + Say Y here if you need PCI IO/MEMORY space reserve + config PCI_IOV bool "PCI IOV support" depends on PCI diff -r b998614e2e2a -r c7c92f868aa1 drivers/pci/Makefile --- a/drivers/pci/Makefile Thu May 28 09:59:18 2009 +0100 +++ b/drivers/pci/Makefile Thu May 28 10:00:03 2009 +0100 @@ -7,6 +7,7 @@ obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o obj-$(CONFIG_PCI_IOMULTI) += iomulti.o +obj-$(CONFIG_PCI_RESERVE) += reserve.o # Build PCI Express stuff if needed obj-$(CONFIG_PCIEPORTBUS) += pcie/ diff -r b998614e2e2a -r c7c92f868aa1 drivers/pci/pci.h --- a/drivers/pci/pci.h Thu May 28 09:59:18 2009 +0100 +++ b/drivers/pci/pci.h Thu May 28 10:00:03 2009 +0100 @@ -189,3 +189,18 @@ static inline int pci_iov_bus_range(stru return 0; } #endif /* CONFIG_PCI_IOV */ + +#ifdef CONFIG_PCI_RESERVE +unsigned long pci_reserve_size_io(struct pci_bus *bus); +unsigned long pci_reserve_size_mem(struct pci_bus *bus); +#else +static inline unsigned long pci_reserve_size_io(struct pci_bus *bus) +{ + return 0; +} + +static inline unsigned long pci_reserve_size_mem(struct pci_bus *bus) +{ + return 0; +} +#endif /* CONFIG_PCI_RESERVE */ diff -r b998614e2e2a -r c7c92f868aa1 drivers/pci/reserve.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/pci/reserve.c Thu May 28 10:00:03 2009 +0100 @@ -0,0 +1,143 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (c) 2009 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + */ + +#include <linux/kernel.h> +#include <linux/pci.h> + +#include <asm/setup.h> + +static char pci_reserve_param[COMMAND_LINE_SIZE]; + +/* pci_reserve= [PCI] + * Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...] + * Format of sbdf: [<segment>:]<bus>:<dev>.<func> + */ +static int pci_reserve_parse_size(const char *str, + unsigned long *io_size, + unsigned long *mem_size) +{ + if (sscanf(str, "io%lx", io_size) == 1 || + sscanf(str, "IO%lx", io_size) == 1) + return 0; + + if (sscanf(str, "mem%lx", mem_size) == 1 || + sscanf(str, "MEM%lx", mem_size) == 1) + return 0; + + return -EINVAL; +} + +static int pci_reserve_parse_one(const char *str, + int *seg, int *bus, int *dev, int *func, + unsigned long *io_size, + unsigned long *mem_size) +{ + char *p; + + *io_size = 0; + *mem_size = 0; + + 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; + } + } + + p = strchr(str, '+'); + if (p == NULL) + return -EINVAL; + p++; + if (pci_reserve_parse_size(p, io_size, mem_size)) + return -EINVAL; + + p = strchr(str, '+'); + if (p != NULL) { + p++; + pci_reserve_parse_size(p, io_size, mem_size); + } + return 0; +} + +static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags) +{ + char *sp; + char *ep; + + int seg; + int bus; + int dev; + int func; + + unsigned long io_size; + unsigned long mem_size; + + sp = pci_reserve_param; + + do { + ep = strchr(sp, ','); + if (ep) + *ep = '\0'; /* chomp */ + + if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func, + &io_size, &mem_size) == 0) { + if (pci_domain_nr(pbus) == seg && + pbus->number == bus && + PCI_SLOT(pbus->self->devfn) == dev && + PCI_FUNC(pbus->self->devfn) == func) { + switch (flags) { + case IORESOURCE_IO: + return io_size; + case IORESOURCE_MEM: + return mem_size; + default: + break; + } + } + } + + if (ep) { + *ep = ','; /* restore chomp'ed ',' for later */ + ep++; + } + sp = ep; + } while (ep); + + return 0; +} + +unsigned long pci_reserve_size_io(struct pci_bus *pbus) +{ + return pci_reserve_size(pbus, IORESOURCE_IO); +} + +unsigned long pci_reserve_size_mem(struct pci_bus *pbus) +{ + return pci_reserve_size(pbus, IORESOURCE_MEM); +} + +static int __init pci_reserve_setup(char *str) +{ + if (strlen(str) > sizeof(pci_reserve_param)) + return 0; + strcpy(pci_reserve_param, str); + return 1; +} +__setup("pci_reserve=", pci_reserve_setup); diff -r b998614e2e2a -r c7c92f868aa1 drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Thu May 28 09:59:18 2009 +0100 +++ b/drivers/pci/setup-bus.c Thu May 28 10:00:03 2009 +0100 @@ -315,7 +315,7 @@ pbus_size_io(struct pci_bus *bus) #if defined(CONFIG_ISA) || defined(CONFIG_EISA) size = (size & 0xff) + ((size & ~0xffUL) << 2); #endif - size = ROUND_UP(size + size1, 4096); + size = ROUND_UP(max(size + size1, pci_reserve_size_io(bus)), 4096); if (!size) { b_res->flags = 0; return; @@ -393,7 +393,7 @@ pbus_size_mem(struct pci_bus *bus, unsig min_align = align1 >> 1; align += aligns[order]; } - size = ROUND_UP(size, min_align); + size = ROUND_UP(max(size, pci_reserve_size_mem(bus)), min_align); if (!size) { b_res->flags = 0; return 1; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |