]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/60004_pci-reassign-resources.patch1
Fix core28 updater kernel version
[people/pmueller/ipfire-2.x.git] / src / patches / 60004_pci-reassign-resources.patch1
CommitLineData
cc90b958
BS
1Subject: xen/dom0: Reassign memory resources to device for pci passthrough
2From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 745:2268be46c75e)
3Patch-mainline: obsolete
4Acked-by: jbeulich@novell.com
5
6Index: head-2008-12-01/drivers/pci/Makefile
7===================================================================
8--- head-2008-12-01.orig/drivers/pci/Makefile 2008-12-01 10:53:15.000000000 +0100
9+++ head-2008-12-01/drivers/pci/Makefile 2008-10-21 13:09:46.000000000 +0200
10@@ -4,6 +4,7 @@
11
12 obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
13 pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
14+obj-$(CONFIG_PCI_REASSIGN) += reassigndev.o
15 obj-$(CONFIG_PROC_FS) += proc.o
16
17 # Build PCI Express stuff if needed
18Index: head-2008-12-01/drivers/pci/pci.h
19===================================================================
20--- head-2008-12-01.orig/drivers/pci/pci.h 2008-12-01 10:53:15.000000000 +0100
21+++ head-2008-12-01/drivers/pci/pci.h 2008-10-21 13:09:01.000000000 +0200
22@@ -144,3 +144,9 @@ struct pci_slot_attribute {
23 };
24 #define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
25
26+#ifdef CONFIG_PCI_REASSIGN
27+extern int is_reassigndev(struct pci_dev *dev);
28+extern void pci_disable_bridge_window(struct pci_dev *dev);
29+#else
30+#define is_reassigndev(dev) 0
31+#endif
32Index: head-2008-12-01/drivers/pci/quirks.c
33===================================================================
34--- head-2008-12-01.orig/drivers/pci/quirks.c 2008-12-01 10:53:15.000000000 +0100
35+++ head-2008-12-01/drivers/pci/quirks.c 2008-10-29 10:52:40.000000000 +0100
36@@ -24,6 +24,54 @@
37 #include <linux/kallsyms.h>
38 #include "pci.h"
39
40+#ifdef CONFIG_PCI_REASSIGN
41+/*
42+ * This quirk function disables the device and releases resources
43+ * which is specified by kernel's boot parameter 'reassigndev'.
44+ * Later on, kernel will assign page-aligned memory resource back
45+ * to that device.
46+ */
47+static void __devinit quirk_release_resources(struct pci_dev *dev)
48+{
49+ int i;
50+ struct resource *r;
51+
52+ if (is_reassigndev(dev)) {
53+ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
54+ (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
55+ /* PCI Host Bridge isn't a target device */
56+ return;
57+ }
58+ printk(KERN_INFO
59+ "PCI: Disable device and release resources [%s].\n",
60+ pci_name(dev));
61+ pci_disable_device(dev);
62+
63+ for (i=0; i < PCI_NUM_RESOURCES; i++) {
64+ r = &dev->resource[i];
65+ if (!(r->flags & IORESOURCE_MEM))
66+ continue;
67+
68+ r->end = r->end - r->start;
69+ r->start = 0;
70+
71+ if (i < PCI_BRIDGE_RESOURCES) {
72+ pci_update_resource(dev, r, i);
73+ }
74+ }
75+ /* need to disable bridge's resource window,
76+ * to make kernel enable to reassign new resource
77+ * window later on.
78+ */
79+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
80+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
81+ pci_disable_bridge_window(dev);
82+ }
83+ }
84+}
85+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_release_resources);
86+#endif
87+
88 /* The Mellanox Tavor device gives false positive parity errors
89 * Mark this device with a broken_parity_status, to allow
90 * PCI scanning code to "skip" this now blacklisted device.
91Index: head-2008-12-01/drivers/pci/reassigndev.c
92===================================================================
93--- /dev/null 1970-01-01 00:00:00.000000000 +0000
94+++ head-2008-12-01/drivers/pci/reassigndev.c 2008-10-21 13:13:38.000000000 +0200
95@@ -0,0 +1,80 @@
96+/*
97+ * Copyright (c) 2008, NEC Corporation.
98+ *
99+ * This program is free software; you can redistribute it and/or modify it
100+ * under the terms and conditions of the GNU General Public License,
101+ * version 2, as published by the Free Software Foundation.
102+ *
103+ * This program is distributed in the hope it will be useful, but WITHOUT
104+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
105+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
106+ * more details.
107+ *
108+ * You should have received a copy of the GNU General Public License along with
109+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
110+ * Place - Suite 330, Boston, MA 02111-1307 USA.
111+ */
112+
113+#include <linux/kernel.h>
114+#include <linux/pci.h>
115+#include <linux/string.h>
116+#include "pci.h"
117+
118+
119+#define REASSIGNDEV_PARAM_MAX (2048)
120+#define TOKEN_MAX (12) /* "SSSS:BB:DD.F" length is 12 */
121+
122+static char param_reassigndev[REASSIGNDEV_PARAM_MAX] = {0};
123+
124+static int __init reassigndev_setup(char *str)
125+{
126+ strncpy(param_reassigndev, str, REASSIGNDEV_PARAM_MAX);
127+ param_reassigndev[REASSIGNDEV_PARAM_MAX - 1] = '\0';
128+ return 1;
129+}
130+__setup("reassigndev=", reassigndev_setup);
131+
132+int is_reassigndev(struct pci_dev *dev)
133+{
134+ char dev_str[TOKEN_MAX+1];
135+ int seg, bus, slot, func;
136+ int len;
137+ char *p, *next_str;
138+
139+ p = param_reassigndev;
140+ for (; p; p = next_str + 1) {
141+ next_str = strpbrk(p, ",");
142+ if (next_str) {
143+ len = next_str - p;
144+ } else {
145+ len = strlen(p);
146+ }
147+ if (len > 0 && len <= TOKEN_MAX) {
148+ strncpy(dev_str, p, len);
149+ *(dev_str + len) = '\0';
150+
151+ if (sscanf(dev_str, "%x:%x:%x.%x",
152+ &seg, &bus, &slot, &func) != 4) {
153+ if (sscanf(dev_str, "%x:%x.%x",
154+ &bus, &slot, &func) == 3) {
155+ seg = 0;
156+ } else {
157+ /* failed to scan strings */
158+ seg = -1;
159+ bus = -1;
160+ }
161+ }
162+ if (seg == pci_domain_nr(dev->bus) &&
163+ bus == dev->bus->number &&
164+ slot == PCI_SLOT(dev->devfn) &&
165+ func == PCI_FUNC(dev->devfn)) {
166+ /* It's a target device */
167+ return 1;
168+ }
169+ }
170+ if (!next_str)
171+ break;
172+ }
173+
174+ return 0;
175+}
176Index: head-2008-12-01/drivers/pci/setup-bus.c
177===================================================================
178--- head-2008-12-01.orig/drivers/pci/setup-bus.c 2008-12-01 10:53:15.000000000 +0100
179+++ head-2008-12-01/drivers/pci/setup-bus.c 2008-10-21 13:09:01.000000000 +0200
180@@ -26,6 +26,7 @@
181 #include <linux/cache.h>
182 #include <linux/slab.h>
183
184+#include "pci.h"
185
186 static void pbus_assign_resources_sorted(struct pci_bus *bus)
187 {
188@@ -343,7 +344,8 @@ static int pbus_size_mem(struct pci_bus
189
190 list_for_each_entry(dev, &bus->devices, bus_list) {
191 int i;
192-
193+ int reassign = is_reassigndev(dev);
194+
195 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
196 struct resource *r = &dev->resource[i];
197 resource_size_t r_size;
198@@ -351,6 +353,10 @@ static int pbus_size_mem(struct pci_bus
199 if (r->parent || (r->flags & mask) != type)
200 continue;
201 r_size = r->end - r->start + 1;
202+
203+ if ((i < PCI_BRIDGE_RESOURCES) && reassign)
204+ r_size = ALIGN(r_size, PAGE_SIZE);
205+
206 /* For bridges size != alignment */
207 align = resource_alignment(r);
208 order = __ffs(align) - 20;
209Index: head-2008-12-01/drivers/pci/setup-res.c
210===================================================================
211--- head-2008-12-01.orig/drivers/pci/setup-res.c 2008-12-01 10:53:15.000000000 +0100
212+++ head-2008-12-01/drivers/pci/setup-res.c 2008-12-01 11:10:02.000000000 +0100
213@@ -126,6 +126,21 @@ int pci_claim_resource(struct pci_dev *d
214 return err;
215 }
216
217+#ifdef CONFIG_PCI_REASSIGN
218+void pci_disable_bridge_window(struct pci_dev *dev)
219+{
220+ printk(KERN_DEBUG "PCI: Disable bridge window on %s\n", pci_name(dev));
221+
222+ /* MMIO Base/Limit */
223+ pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
224+
225+ /* Prefetchable MMIO Base/Limit */
226+ pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
227+ pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
228+ pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
229+}
230+#endif
231+
232 int pci_assign_resource(struct pci_dev *dev, int resno)
233 {
234 struct pci_bus *bus = dev->bus;
235@@ -144,6 +159,10 @@ int pci_assign_resource(struct pci_dev *
236 (unsigned long long)res->end, res->flags);
237 return -EINVAL;
238 }
239+ if (resno < PCI_BRIDGE_RESOURCES
240+ && is_reassigndev(dev)
241+ && (res->flags & IORESOURCE_MEM))
242+ align = ALIGN(align, PAGE_SIZE);
243
244 /* First, try exact prefetching match.. */
245 ret = pci_bus_alloc_resource(bus, res, size, align, min,
246@@ -169,8 +188,15 @@ int pci_assign_resource(struct pci_dev *
247 (unsigned long long)res->end);
248 } else {
249 res->flags &= ~IORESOURCE_STARTALIGN;
250- if (resno < PCI_BRIDGE_RESOURCES)
251+ if (resno < PCI_BRIDGE_RESOURCES) {
252+#ifdef CONFIG_PCI_REASSIGN
253+ printk(KERN_DEBUG "PCI: Assign resource(%d) on %s "
254+ "%016llx - %016llx\n", resno, pci_name(dev),
255+ (unsigned long long)res->start,
256+ (unsigned long long)res->end);
257+#endif
258 pci_update_resource(dev, res, resno);
259+ }
260 }
261
262 return ret;
263@@ -208,6 +234,12 @@ int pci_assign_resource_fixed(struct pci
264 (unsigned long long)res->start,
265 (unsigned long long)res->end);
266 } else if (resno < PCI_BRIDGE_RESOURCES) {
267+#ifdef CONFIG_PCI_REASSIGN
268+ printk(KERN_DEBUG "PCI: Assign resource(%d) on %s "
269+ "%016llx - %016llx\n", resno, pci_name(dev),
270+ (unsigned long long)res->start,
271+ (unsigned long long)res->end);
272+#endif
273 pci_update_resource(dev, res, resno);
274 }
275
276@@ -220,6 +252,7 @@ EXPORT_SYMBOL_GPL(pci_assign_resource_fi
277 void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
278 {
279 int i;
280+ int reassigndev = is_reassigndev(dev);
281
282 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
283 struct resource *r;
284@@ -242,12 +275,22 @@ void pdev_sort_resources(struct pci_dev
285 (unsigned long long)r->end, r->flags);
286 continue;
287 }
288+ if (i < PCI_BRIDGE_RESOURCES && (r->flags & IORESOURCE_MEM) &&
289+ reassigndev)
290+ r_align = ALIGN(r_align, PAGE_SIZE);
291+
292 for (list = head; ; list = list->next) {
293 resource_size_t align = 0;
294 struct resource_list *ln = list->next;
295
296- if (ln)
297+ if (ln) {
298 align = resource_alignment(ln->res);
299+ if (ln->res - ln->dev->resource <
300+ PCI_BRIDGE_RESOURCES &&
301+ (ln->res->flags & IORESOURCE_MEM) &&
302+ is_reassigndev(ln->dev))
303+ align = ALIGN(align, PAGE_SIZE);
304+ }
305
306 if (r_align > align) {
307 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);