- Update Xen patches to c/s 1011.
[opensuse:kernel-source.git] / patches.xen / pci-reserve
1 Subject: linux/pci: reserve io/memory space for bridge
2 From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1010:10eae161c153)
3 Patch-mainline: n/a
4
5 reserve io/memory space for bridge which will be used later
6 by PCI hotplug.
7
8 Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
9 Acked-by: jbeulich@novell.com
10
11 --- sle11sp1-2010-03-11.orig/Documentation/kernel-parameters.txt        2010-03-11 09:11:45.000000000 +0100
12 +++ sle11sp1-2010-03-11/Documentation/kernel-parameters.txt     2010-03-11 09:11:54.000000000 +0100
13 @@ -1994,6 +1994,13 @@ and is between 256 and 4096 characters. 
14                                 off: Turn ECRC off
15                                 on: Turn ECRC on.
16  
17 +       pci_reserve=    [PCI]
18 +                       Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
19 +                       Format of sbdf: [<segment>:]<bus>:<dev>.<func>
20 +                       Specifies the least reserved io size or memory size
21 +                       which is assigned to PCI bridge even when no child
22 +                       pci device exists. This is useful with PCI hotplug.
23 +
24         pcie_aspm=      [PCIE] Forcibly enable or disable PCIe Active State Power
25                         Management.
26                 off     Disable ASPM.
27 --- sle11sp1-2010-03-11.orig/drivers/pci/Kconfig        2009-12-04 10:27:46.000000000 +0100
28 +++ sle11sp1-2010-03-11/drivers/pci/Kconfig     2009-12-04 10:27:49.000000000 +0100
29 @@ -56,6 +56,13 @@ config PCI_IOMULTI
30         help
31           Say Y here if you need io multiplexing.
32  
33 +config PCI_RESERVE
34 +       bool "PCI IO/MEMORY space reserve"
35 +       depends on PCI && XEN_PRIVILEGED_GUEST
36 +       default y
37 +       help
38 +         Say Y here if you need PCI IO/MEMORY space reserve
39 +
40  config PCI_STUB
41         tristate "PCI Stub driver"
42         depends on PCI
43 --- sle11sp1-2010-03-11.orig/drivers/pci/Makefile       2009-12-04 10:27:46.000000000 +0100
44 +++ sle11sp1-2010-03-11/drivers/pci/Makefile    2009-12-04 10:27:49.000000000 +0100
45 @@ -9,6 +9,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
46  obj-$(CONFIG_SYSFS) += slot.o
47  obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o
48  obj-$(CONFIG_PCI_IOMULTI) += iomulti.o
49 +obj-$(CONFIG_PCI_RESERVE) += reserve.o
50  
51  obj-$(CONFIG_PCI_LEGACY) += legacy.o
52  CFLAGS_legacy.o += -Wno-deprecated-declarations
53 --- sle11sp1-2010-03-11.orig/drivers/pci/pci.h  2009-12-04 10:27:46.000000000 +0100
54 +++ sle11sp1-2010-03-11/drivers/pci/pci.h       2009-12-04 10:27:49.000000000 +0100
55 @@ -318,4 +318,19 @@ extern int pci_is_iomuldev(struct pci_de
56  #define pci_is_iomuldev(dev)   0
57  #endif
58  
59 +#ifdef CONFIG_PCI_RESERVE
60 +unsigned long pci_reserve_size_io(struct pci_bus *bus);
61 +unsigned long pci_reserve_size_mem(struct pci_bus *bus);
62 +#else
63 +static inline unsigned long pci_reserve_size_io(struct pci_bus *bus)
64 +{
65 +       return 0;
66 +}
67 +
68 +static inline unsigned long pci_reserve_size_mem(struct pci_bus *bus)
69 +{
70 +       return 0;
71 +}
72 +#endif /* CONFIG_PCI_RESERVE */
73 +
74  #endif /* DRIVERS_PCI_H */
75 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
76 +++ sle11sp1-2010-03-11/drivers/pci/reserve.c   2010-03-24 14:00:05.000000000 +0100
77 @@ -0,0 +1,138 @@
78 +/*
79 + * This program is free software; you can redistribute it and/or modify
80 + * it under the terms of the GNU General Public License as published by
81 + * the Free Software Foundation; either version 2 of the License, or
82 + * (at your option) any later version.
83 + *
84 + * This program is distributed in the hope that it will be useful,
85 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
86 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
87 + * GNU General Public License for more details.
88 + *
89 + * You should have received a copy of the GNU General Public License
90 + * along with this program; if not, write to the Free Software
91 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
92 + *
93 + * Copyright (c) 2009 Isaku Yamahata
94 + *                    VA Linux Systems Japan K.K.
95 + *
96 + */
97 +
98 +#include <linux/kernel.h>
99 +#include <linux/pci.h>
100 +
101 +#include <asm/setup.h>
102 +
103 +static char pci_reserve_param[COMMAND_LINE_SIZE];
104 +
105 +/* pci_reserve=        [PCI]
106 + * Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
107 + * Format of sbdf: [<segment>:]<bus>:<dev>.<func>
108 + */
109 +static int pci_reserve_parse_size(const char *str,
110 +                                 unsigned long *io_size,
111 +                                 unsigned long *mem_size)
112 +{
113 +       if (sscanf(str, "io%lx", io_size) == 1 ||
114 +           sscanf(str, "IO%lx", io_size) == 1)
115 +               return 0;
116 +
117 +       if (sscanf(str, "mem%lx", mem_size) == 1 ||
118 +           sscanf(str, "MEM%lx", mem_size) == 1)
119 +               return 0;
120 +
121 +       return -EINVAL;
122 +}
123 +
124 +static int pci_reserve_parse_one(const char *str,
125 +                                int *seg, int *bus, int *dev, int *func,
126 +                                unsigned long *io_size,
127 +                                unsigned long *mem_size)
128 +{
129 +       char *p;
130 +
131 +       *io_size = 0;
132 +       *mem_size = 0;
133 +
134 +       if (sscanf(str, "%x:%x:%x.%x", seg, bus, dev, func) != 4) {
135 +               *seg = 0;
136 +               if (sscanf(str, "%x:%x.%x", bus, dev, func) != 3) {
137 +                       return -EINVAL;
138 +               }
139 +       }
140 +
141 +       p = strchr(str, '+');
142 +       if (p == NULL)
143 +               return -EINVAL;
144 +       if (pci_reserve_parse_size(++p, io_size, mem_size))
145 +               return -EINVAL;
146 +
147 +       p = strchr(p, '+');
148 +       return p ? pci_reserve_parse_size(p + 1, io_size, mem_size) : 0;
149 +}
150 +
151 +static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags)
152 +{
153 +       char *sp;
154 +       char *ep;
155 +
156 +       int seg;
157 +       int bus;
158 +       int dev;
159 +       int func;
160 +
161 +       unsigned long io_size;
162 +       unsigned long mem_size;
163 +
164 +       sp = pci_reserve_param;
165 +
166 +       do {
167 +               ep = strchr(sp, ',');
168 +               if (ep)
169 +                       *ep = '\0';     /* chomp */
170 +
171 +               if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func,
172 +                                         &io_size, &mem_size) == 0) {
173 +                       if (pci_domain_nr(pbus) == seg &&
174 +                           pbus->number == bus &&
175 +                           PCI_SLOT(pbus->self->devfn) == dev &&
176 +                           PCI_FUNC(pbus->self->devfn) == func) {
177 +                               switch (flags) {
178 +                               case IORESOURCE_IO:
179 +                                       return io_size;
180 +                               case IORESOURCE_MEM:
181 +                                       return mem_size;
182 +                               default:
183 +                                       break;
184 +                               }
185 +                       }
186 +               }
187 +
188 +               if (ep) {
189 +                       *ep = ',';      /* restore chomp'ed ',' for later */
190 +                       ep++;
191 +               }
192 +               sp = ep;
193 +       } while (ep);
194 +
195 +       return 0;
196 +}
197 +
198 +unsigned long pci_reserve_size_io(struct pci_bus *pbus)
199 +{
200 +       return pci_reserve_size(pbus, IORESOURCE_IO);
201 +}
202 +
203 +unsigned long pci_reserve_size_mem(struct pci_bus *pbus)
204 +{
205 +       return pci_reserve_size(pbus, IORESOURCE_MEM);
206 +}
207 +
208 +static int __init pci_reserve_setup(char *str)
209 +{
210 +       if (strlen(str) >= sizeof(pci_reserve_param))
211 +               return 0;
212 +       strlcpy(pci_reserve_param, str, sizeof(pci_reserve_param));
213 +       return 1;
214 +}
215 +__setup("pci_reserve=", pci_reserve_setup);
216 --- sle11sp1-2010-03-11.orig/drivers/pci/setup-bus.c    2010-03-11 09:10:12.000000000 +0100
217 +++ sle11sp1-2010-03-11/drivers/pci/setup-bus.c 2010-03-11 09:12:00.000000000 +0100
218 @@ -337,7 +337,7 @@ static void pbus_size_io(struct pci_bus 
219  #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
220         size = (size & 0xff) + ((size & ~0xffUL) << 2);
221  #endif
222 -       size = ALIGN(size + size1, 4096);
223 +       size = ALIGN(max(size + size1, pci_reserve_size_io(bus)), 4096);
224         if (!size) {
225                 b_res->flags = 0;
226                 return;
227 @@ -417,7 +417,8 @@ static int pbus_size_mem(struct pci_bus 
228                         min_align = align1 >> 1;
229                 align += aligns[order];
230         }
231 -       size = ALIGN(size, min_align);
232 +       size = ALIGN(max(size, (resource_size_t)pci_reserve_size_mem(bus)),
233 +                    min_align);
234         if (!size) {
235                 b_res->flags = 0;
236                 return 1;