WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 4/6] pcie io space multiplex: Linux part: add kernel

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 4/6] pcie io space multiplex: Linux part: add kernel command line to reserve io/memory space for unused pci slot
From: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Date: Thu, 28 May 2009 12:46:48 +0900
Cc: shimada-yxb@xxxxxxxxxxxxxxx, Ian.Jackson@xxxxxxxxxxxxx, Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Delivery-date: Wed, 27 May 2009 20:50:35 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.18 (2008-05-17)
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>

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -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 --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -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 --git a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -7,6 +7,7 @@ obj-y           += access.o bus.o probe.o remove.
 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 --git a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -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 --git a/drivers/pci/reserve.c b/drivers/pci/reserve.c
new file mode 100644
--- /dev/null
+++ b/drivers/pci/reserve.c
@@ -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 --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -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;

Attachment: pci-space-reserve.patch
Description: Text Data

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 4/6] pcie io space multiplex: Linux part: add kernel command line to reserve io/memory space for unused pci slot, Isaku Yamahata <=