Blame view

drivers/pci/setup-bus.c 33.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /*
   *	drivers/pci/setup-bus.c
   *
   * Extruded from code written by
   *      Dave Rusling (david.rusling@reo.mts.dec.com)
   *      David Mosberger (davidm@cs.arizona.edu)
   *	David Miller (davem@redhat.com)
   *
   * Support routines for initializing a PCI subsystem.
   */
  
  /*
   * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
   *	     PCI-PCI bridges cleanup, sorted resource allocation.
   * Feb 2002, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
   *	     Converted to allocation in 3 passes, which gives
   *	     tighter packing. Prefetchable range support.
   */
  
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/errno.h>
  #include <linux/ioport.h>
  #include <linux/cache.h>
  #include <linux/slab.h>
6faf17f6f   Chris Wright   PCI SR-IOV: corre...
28
  #include "pci.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

568ddef87   Yinghai Lu   PCI: add failed_l...
30
31
32
33
34
35
  struct resource_list_x {
  	struct resource_list_x *next;
  	struct resource *res;
  	struct pci_dev *dev;
  	resource_size_t start;
  	resource_size_t end;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
36
  	resource_size_t add_size;
2bbc69422   Ram Pai   PCI : ability to ...
37
  	resource_size_t min_align;
568ddef87   Yinghai Lu   PCI: add failed_l...
38
39
  	unsigned long flags;
  };
094732a52   Ram Pai   PCI: data structu...
40
41
42
43
44
45
46
47
48
  #define free_list(type, head) do {                      \
  	struct type *list, *tmp;			\
  	for (list = (head)->next; list;) {		\
  		tmp = list;				\
  		list = list->next;			\
  		kfree(tmp);				\
  	}						\
  	(head)->next = NULL;				\
  } while (0)
f483d3923   Ram Pai   PCI: conditional ...
49
50
51
52
53
54
  int pci_realloc_enable = 0;
  #define pci_realloc_enabled() pci_realloc_enable
  void pci_realloc(void)
  {
  	pci_realloc_enable = 1;
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
55
56
57
58
59
60
61
62
63
64
65
  /**
   * add_to_list() - add a new resource tracker to the list
   * @head:	Head of the list
   * @dev:	device corresponding to which the resource
   *		belongs
   * @res:	The resource to be tracked
   * @add_size:	additional size to be optionally added
   *              to the resource
   */
  static void add_to_list(struct resource_list_x *head,
  		 struct pci_dev *dev, struct resource *res,
2bbc69422   Ram Pai   PCI : ability to ...
66
  		 resource_size_t add_size, resource_size_t min_align)
568ddef87   Yinghai Lu   PCI: add failed_l...
67
68
69
70
71
72
73
  {
  	struct resource_list_x *list = head;
  	struct resource_list_x *ln = list->next;
  	struct resource_list_x *tmp;
  
  	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
  	if (!tmp) {
c8adf9a3e   Ram Pai   PCI: pre-allocate...
74
75
  		pr_warning("add_to_list: kmalloc() failed!
  ");
568ddef87   Yinghai Lu   PCI: add failed_l...
76
77
78
79
80
81
82
83
84
  		return;
  	}
  
  	tmp->next = ln;
  	tmp->res = res;
  	tmp->dev = dev;
  	tmp->start = res->start;
  	tmp->end = res->end;
  	tmp->flags = res->flags;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
85
  	tmp->add_size = add_size;
2bbc69422   Ram Pai   PCI : ability to ...
86
  	tmp->min_align = min_align;
568ddef87   Yinghai Lu   PCI: add failed_l...
87
88
  	list->next = tmp;
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
89
90
91
  static void add_to_failed_list(struct resource_list_x *head,
  				struct pci_dev *dev, struct resource *res)
  {
2bbc69422   Ram Pai   PCI : ability to ...
92
93
94
  	add_to_list(head, dev, res,
  			0 /* dont care */,
  			0 /* dont care */);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
95
  }
6841ec681   Yinghai Lu   PCI: introduce pc...
96
97
  static void __dev_sort_resources(struct pci_dev *dev,
  				 struct resource_list *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  {
6841ec681   Yinghai Lu   PCI: introduce pc...
99
  	u16 class = dev->class >> 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

6841ec681   Yinghai Lu   PCI: introduce pc...
101
102
103
  	/* Don't touch classless devices or host bridges or ioapics.  */
  	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104

6841ec681   Yinghai Lu   PCI: introduce pc...
105
106
107
108
109
110
111
  	/* Don't touch ioapic devices already enabled by firmware */
  	if (class == PCI_CLASS_SYSTEM_PIC) {
  		u16 command;
  		pci_read_config_word(dev, PCI_COMMAND, &command);
  		if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
  			return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

6841ec681   Yinghai Lu   PCI: introduce pc...
113
114
  	pdev_sort_resources(dev, head);
  }
231862796   Satoru Takeuchi   PCI: assign ioapi...
115

fc075e1da   Ram Pai   PCI: introduce re...
116
117
118
119
120
121
  static inline void reset_resource(struct resource *res)
  {
  	res->start = 0;
  	res->end = 0;
  	res->flags = 0;
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
122
  /**
9e8bf93a7   Ram Pai   PCI: code and com...
123
   * reassign_resources_sorted() - satisfy any additional resource requests
c8adf9a3e   Ram Pai   PCI: pre-allocate...
124
   *
9e8bf93a7   Ram Pai   PCI: code and com...
125
   * @realloc_head : head of the list tracking requests requiring additional
c8adf9a3e   Ram Pai   PCI: pre-allocate...
126
127
128
129
   *             resources
   * @head     : head of the list tracking requests with allocated
   *             resources
   *
9e8bf93a7   Ram Pai   PCI: code and com...
130
   * Walk through each element of the realloc_head and try to procure
c8adf9a3e   Ram Pai   PCI: pre-allocate...
131
132
133
   * additional resources for the element, provided the element
   * is in the head list.
   */
9e8bf93a7   Ram Pai   PCI: code and com...
134
  static void reassign_resources_sorted(struct resource_list_x *realloc_head,
c8adf9a3e   Ram Pai   PCI: pre-allocate...
135
  		struct resource_list *head)
6841ec681   Yinghai Lu   PCI: introduce pc...
136
137
  {
  	struct resource *res;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
138
139
140
  	struct resource_list_x *list, *tmp, *prev;
  	struct resource_list *hlist;
  	resource_size_t add_size;
6841ec681   Yinghai Lu   PCI: introduce pc...
141
  	int idx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

9e8bf93a7   Ram Pai   PCI: code and com...
143
144
  	prev = realloc_head;
  	for (list = realloc_head->next; list;) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  		res = list->res;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
146
147
148
149
150
151
152
153
154
155
156
157
  		/* skip resource that has been reset */
  		if (!res->flags)
  			goto out;
  
  		/* skip this resource if not found in head list */
  		for (hlist = head->next; hlist && hlist->res != res;
  				hlist = hlist->next);
  		if (!hlist) { /* just skip */
  			prev = list;
  			list = list->next;
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  		idx = res - &list->dev->resource[0];
c8adf9a3e   Ram Pai   PCI: pre-allocate...
159
  		add_size=list->add_size;
2bbc69422   Ram Pai   PCI : ability to ...
160
  		if (!resource_size(res)) {
0a2daa1cf   Ram Pai   PCI: make cardbus...
161
  			res->start = list->start;
2bbc69422   Ram Pai   PCI : ability to ...
162
163
  			res->end = res->start + add_size - 1;
  			if(pci_assign_resource(list->dev, idx))
c8adf9a3e   Ram Pai   PCI: pre-allocate...
164
  				reset_resource(res);
2bbc69422   Ram Pai   PCI : ability to ...
165
166
167
168
169
170
171
  		} else {
  			resource_size_t align = list->min_align;
  			res->flags |= list->flags & (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
  			if (pci_reassign_resource(list->dev, idx, add_size, align))
  				dev_printk(KERN_DEBUG, &list->dev->dev, "failed to add optional resources res=%pR
  ",
  							res);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  		}
  out:
  		tmp = list;
  		prev->next = list = list->next;
  		kfree(tmp);
  	}
  }
  
  /**
   * assign_requested_resources_sorted() - satisfy resource requests
   *
   * @head : head of the list tracking requests for resources
   * @failed_list : head of the list tracking requests that could
   *		not be allocated
   *
   * Satisfy resource requests of each element in the list. Add
   * requests that could not satisfied to the failed_list.
   */
  static void assign_requested_resources_sorted(struct resource_list *head,
  				 struct resource_list_x *fail_head)
  {
  	struct resource *res;
  	struct resource_list *list;
  	int idx;
9a928660c   Yinghai Lu   pci: don't reassi...
196

c8adf9a3e   Ram Pai   PCI: pre-allocate...
197
198
199
200
  	for (list = head->next; list; list = list->next) {
  		res = list->res;
  		idx = res - &list->dev->resource[0];
  		if (resource_size(res) && pci_assign_resource(list->dev, idx)) {
9a928660c   Yinghai Lu   pci: don't reassi...
201
202
203
204
205
206
207
208
209
  			if (fail_head && !pci_is_root_bus(list->dev->bus)) {
  				/*
  				 * if the failed res is for ROM BAR, and it will
  				 * be enabled later, don't add it to the list
  				 */
  				if (!((idx == PCI_ROM_RESOURCE) &&
  				      (!(res->flags & IORESOURCE_ROM_ENABLE))))
  					add_to_failed_list(fail_head, list->dev, res);
  			}
fc075e1da   Ram Pai   PCI: introduce re...
210
  			reset_resource(res);
542df5de5   Rajesh Shah   [PATCH] acpi brid...
211
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
  	}
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
214
  static void __assign_resources_sorted(struct resource_list *head,
9e8bf93a7   Ram Pai   PCI: code and com...
215
  				 struct resource_list_x *realloc_head,
c8adf9a3e   Ram Pai   PCI: pre-allocate...
216
217
218
219
  				 struct resource_list_x *fail_head)
  {
  	/* Satisfy the must-have resource requests */
  	assign_requested_resources_sorted(head, fail_head);
0a2daa1cf   Ram Pai   PCI: make cardbus...
220
  	/* Try to satisfy any additional optional resource
c8adf9a3e   Ram Pai   PCI: pre-allocate...
221
  		requests */
9e8bf93a7   Ram Pai   PCI: code and com...
222
223
  	if (realloc_head)
  		reassign_resources_sorted(realloc_head, head);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
224
225
  	free_list(resource_list, head);
  }
6841ec681   Yinghai Lu   PCI: introduce pc...
226
227
228
229
230
231
232
  static void pdev_assign_resources_sorted(struct pci_dev *dev,
  				 struct resource_list_x *fail_head)
  {
  	struct resource_list head;
  
  	head.next = NULL;
  	__dev_sort_resources(dev, &head);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
233
  	__assign_resources_sorted(&head, NULL, fail_head);
6841ec681   Yinghai Lu   PCI: introduce pc...
234
235
236
237
  
  }
  
  static void pbus_assign_resources_sorted(const struct pci_bus *bus,
9e8bf93a7   Ram Pai   PCI: code and com...
238
  					 struct resource_list_x *realloc_head,
6841ec681   Yinghai Lu   PCI: introduce pc...
239
240
241
242
243
244
245
246
  					 struct resource_list_x *fail_head)
  {
  	struct pci_dev *dev;
  	struct resource_list head;
  
  	head.next = NULL;
  	list_for_each_entry(dev, &bus->devices, bus_list)
  		__dev_sort_resources(dev, &head);
9e8bf93a7   Ram Pai   PCI: code and com...
247
  	__assign_resources_sorted(&head, realloc_head, fail_head);
6841ec681   Yinghai Lu   PCI: introduce pc...
248
  }
b3743fa44   Dominik Brodowski   [PATCH] yenta: sh...
249
  void pci_setup_cardbus(struct pci_bus *bus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  {
  	struct pci_dev *bridge = bus->self;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
252
  	struct resource *res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  	struct pci_bus_region region;
865df576e   Bjorn Helgaas   PCI: improve disc...
254
255
256
  	dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]
  ",
  		 bus->secondary, bus->subordinate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
258
259
260
  	res = bus->resource[0];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_IO) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
  		/*
  		 * The IO resource is allocated a range twice as large as it
  		 * would normally need.  This allows us to set both IO regs.
  		 */
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
265
266
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
270
271
  		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
  					region.start);
  		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
  					region.end);
  	}
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
272
273
274
275
276
  	res = bus->resource[1];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_IO) {
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
  		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
  					region.start);
  		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
  					region.end);
  	}
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
282
283
284
285
286
  	res = bus->resource[2];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_MEM) {
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
290
291
  		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
  					region.start);
  		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
  					region.end);
  	}
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
292
293
294
295
296
  	res = bus->resource[3];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_MEM) {
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
300
301
302
  		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
  					region.start);
  		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
  					region.end);
  	}
  }
b3743fa44   Dominik Brodowski   [PATCH] yenta: sh...
303
  EXPORT_SYMBOL(pci_setup_cardbus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
309
310
311
312
313
314
315
  
  /* Initialize bridges with base/limit values we have collected.
     PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
     requires that if there is no I/O ports or memory behind the
     bridge, corresponding range must be turned off by writing base
     value greater than limit to the bridge's base/limit registers.
  
     Note: care must be taken when updating I/O base/limit registers
     of bridges which support 32-bit I/O. This update requires two
     config space writes, so it's quite possible that an I/O window of
     the bridge will have some undesirable address (e.g. 0) after the
     first write. Ditto 64-bit prefetchable MMIO.  */
7cc5997d1   Yinghai Lu   PCI: separate pci...
316
  static void pci_setup_bridge_io(struct pci_bus *bus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
  {
  	struct pci_dev *bridge = bus->self;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
319
  	struct resource *res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  	struct pci_bus_region region;
7cc5997d1   Yinghai Lu   PCI: separate pci...
321
  	u32 l, io_upper16;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  
  	/* Set up the top and bottom of the PCI I/O segment for this bus. */
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
324
325
326
  	res = bus->resource[0];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_IO) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
332
  		pci_read_config_dword(bridge, PCI_IO_BASE, &l);
  		l &= 0xffff0000;
  		l |= (region.start >> 8) & 0x00f0;
  		l |= region.end & 0xf000;
  		/* Set up upper 16 bits of I/O base/limit. */
  		io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
333
334
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
7cc5997d1   Yinghai Lu   PCI: separate pci...
335
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
  		/* Clear upper 16 bits of I/O base/limit. */
  		io_upper16 = 0;
  		l = 0x00f0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
344
345
  	}
  	/* Temporarily disable the I/O range before updating PCI_IO_BASE. */
  	pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
  	/* Update lower 16 bits of I/O base/limit. */
  	pci_write_config_dword(bridge, PCI_IO_BASE, l);
  	/* Update upper 16 bits of I/O base/limit. */
  	pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);
7cc5997d1   Yinghai Lu   PCI: separate pci...
346
347
348
349
350
351
352
353
  }
  
  static void pci_setup_bridge_mmio(struct pci_bus *bus)
  {
  	struct pci_dev *bridge = bus->self;
  	struct resource *res;
  	struct pci_bus_region region;
  	u32 l;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354

7cc5997d1   Yinghai Lu   PCI: separate pci...
355
  	/* Set up the top and bottom of the PCI Memory segment for this bus. */
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
356
357
358
  	res = bus->resource[1];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_MEM) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
  		l = (region.start >> 16) & 0xfff0;
  		l |= region.end & 0xfff00000;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
361
362
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
7cc5997d1   Yinghai Lu   PCI: separate pci...
363
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
  		l = 0x0000fff0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
  	}
  	pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
7cc5997d1   Yinghai Lu   PCI: separate pci...
367
368
369
370
371
372
373
374
  }
  
  static void pci_setup_bridge_mmio_pref(struct pci_bus *bus)
  {
  	struct pci_dev *bridge = bus->self;
  	struct resource *res;
  	struct pci_bus_region region;
  	u32 l, bu, lu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
  
  	/* Clear out the upper 32 bits of PREF limit.
  	   If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
  	   disables PREF range, which is ok. */
  	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
  
  	/* Set up PREF base/limit. */
c40a22e0c   Benjamin Herrenschmidt   PCI: Fix bus reso...
382
  	bu = lu = 0;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
383
384
385
  	res = bus->resource[2];
  	pcibios_resource_to_bus(bridge, &region, res);
  	if (res->flags & IORESOURCE_PREFETCH) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  		l = (region.start >> 16) & 0xfff0;
  		l |= region.end & 0xfff00000;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
388
  		if (res->flags & IORESOURCE_MEM_64) {
1f82de10d   Yinghai Lu   PCI/x86: don't as...
389
390
  			bu = upper_32_bits(region.start);
  			lu = upper_32_bits(region.end);
1f82de10d   Yinghai Lu   PCI/x86: don't as...
391
  		}
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
392
393
  		dev_info(&bridge->dev, "  bridge window %pR
  ", res);
7cc5997d1   Yinghai Lu   PCI: separate pci...
394
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  		l = 0x0000fff0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
  	}
  	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
59353ea30   Alex Williamson   PCI: Always set p...
398
399
400
  	/* Set the upper 32 bits of PREF base & limit. */
  	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
  	pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
7cc5997d1   Yinghai Lu   PCI: separate pci...
401
402
403
404
405
  }
  
  static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
  {
  	struct pci_dev *bridge = bus->self;
7cc5997d1   Yinghai Lu   PCI: separate pci...
406
407
408
409
410
411
412
413
414
415
416
417
  	dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]
  ",
  		 bus->secondary, bus->subordinate);
  
  	if (type & IORESOURCE_IO)
  		pci_setup_bridge_io(bus);
  
  	if (type & IORESOURCE_MEM)
  		pci_setup_bridge_mmio(bus);
  
  	if (type & IORESOURCE_PREFETCH)
  		pci_setup_bridge_mmio_pref(bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
420
  
  	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
  }
e24442733   Benjamin Herrenschmidt   PCI: Make pci_set...
421
  void pci_setup_bridge(struct pci_bus *bus)
7cc5997d1   Yinghai Lu   PCI: separate pci...
422
423
424
425
426
427
  {
  	unsigned long type = IORESOURCE_IO | IORESOURCE_MEM |
  				  IORESOURCE_PREFETCH;
  
  	__pci_setup_bridge(bus, type);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
  /* Check whether the bridge supports optional I/O and
     prefetchable memory ranges. If not, the respective
     base/limit registers must be read-only and read as 0. */
96bde06a2   Sam Ravnborg   pci: do not mark ...
431
  static void pci_bridge_check_ranges(struct pci_bus *bus)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  {
  	u16 io;
  	u32 pmem;
  	struct pci_dev *bridge = bus->self;
  	struct resource *b_res;
  
  	b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
  	b_res[1].flags |= IORESOURCE_MEM;
  
  	pci_read_config_word(bridge, PCI_IO_BASE, &io);
  	if (!io) {
  		pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
  		pci_read_config_word(bridge, PCI_IO_BASE, &io);
   		pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
   	}
   	if (io)
  		b_res[0].flags |= IORESOURCE_IO;
  	/*  DECchip 21050 pass 2 errata: the bridge may miss an address
  	    disconnect boundary by one PCI data phase.
  	    Workaround: do not use prefetching on this device. */
  	if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)
  		return;
  	pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
  	if (!pmem) {
  		pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE,
  					       0xfff0fff0);
  		pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);
  		pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);
  	}
1f82de10d   Yinghai Lu   PCI/x86: don't as...
461
  	if (pmem) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
995861055   Yinghai Lu   PCI: set PCI_PREF...
463
464
  		if ((pmem & PCI_PREF_RANGE_TYPE_MASK) ==
  		    PCI_PREF_RANGE_TYPE_64) {
1f82de10d   Yinghai Lu   PCI/x86: don't as...
465
  			b_res[2].flags |= IORESOURCE_MEM_64;
995861055   Yinghai Lu   PCI: set PCI_PREF...
466
467
  			b_res[2].flags |= PCI_PREF_RANGE_TYPE_64;
  		}
1f82de10d   Yinghai Lu   PCI/x86: don't as...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  	}
  
  	/* double check if bridge does support 64 bit pref */
  	if (b_res[2].flags & IORESOURCE_MEM_64) {
  		u32 mem_base_hi, tmp;
  		pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32,
  					 &mem_base_hi);
  		pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
  					       0xffffffff);
  		pci_read_config_dword(bridge, PCI_PREF_BASE_UPPER32, &tmp);
  		if (!tmp)
  			b_res[2].flags &= ~IORESOURCE_MEM_64;
  		pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32,
  				       mem_base_hi);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
485
486
487
488
  }
  
  /* Helper function for sizing routines: find first available
     bus resource of a given type. Note: we intentionally skip
     the bus resources which have already been assigned (that is,
     have non-NULL parent resource). */
96bde06a2   Sam Ravnborg   pci: do not mark ...
489
  static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
492
493
494
  {
  	int i;
  	struct resource *r;
  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
  				  IORESOURCE_PREFETCH;
89a74eccc   Bjorn Helgaas   PCI: add pci_bus_...
495
  	pci_bus_for_each_resource(bus, r, i) {
299de0343   Ivan Kokshaysky   [PATCH] PCI: pci_...
496
497
  		if (r == &ioport_resource || r == &iomem_resource)
  			continue;
55a109847   Jesse Barnes   Revert "PCI: get ...
498
499
  		if (r && (r->flags & type_mask) == type && !r->parent)
  			return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
  	}
  	return NULL;
  }
13583b165   Ram Pai   PCI: refactor io ...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  static resource_size_t calculate_iosize(resource_size_t size,
  		resource_size_t min_size,
  		resource_size_t size1,
  		resource_size_t old_size,
  		resource_size_t align)
  {
  	if (size < min_size)
  		size = min_size;
  	if (old_size == 1 )
  		old_size = 0;
  	/* To be fixed in 2.5: we should have sort of HAVE_ISA
  	   flag in the struct pci_bus. */
  #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
  	size = (size & 0xff) + ((size & ~0xffUL) << 2);
  #endif
  	size = ALIGN(size + size1, align);
  	if (size < old_size)
  		size = old_size;
  	return size;
  }
  
  static resource_size_t calculate_memsize(resource_size_t size,
  		resource_size_t min_size,
  		resource_size_t size1,
  		resource_size_t old_size,
  		resource_size_t align)
  {
  	if (size < min_size)
  		size = min_size;
  	if (old_size == 1 )
  		old_size = 0;
  	if (size < old_size)
  		size = old_size;
  	size = ALIGN(size + size1, align);
  	return size;
  }
9e8bf93a7   Ram Pai   PCI: code and com...
539
  static resource_size_t get_res_add_size(struct resource_list_x *realloc_head,
be768912a   Yinghai Lu   PCI: honor child ...
540
541
542
  					struct resource *res)
  {
  	struct resource_list_x *list;
9e8bf93a7   Ram Pai   PCI: code and com...
543
544
  	/* check if it is in realloc_head list */
  	for (list = realloc_head->next; list && list->res != res;
be768912a   Yinghai Lu   PCI: honor child ...
545
546
547
548
549
550
  			list = list->next);
  	if (list)
  		return list->add_size;
  
  	return 0;
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
551
552
553
554
555
556
  /**
   * pbus_size_io() - size the io window of a given bus
   *
   * @bus : the bus
   * @min_size : the minimum io window that must to be allocated
   * @add_size : additional optional io window
9e8bf93a7   Ram Pai   PCI: code and com...
557
   * @realloc_head : track the additional io window on this list
c8adf9a3e   Ram Pai   PCI: pre-allocate...
558
559
560
561
562
563
564
   *
   * Sizing the IO windows of the PCI-PCI bridge is trivial,
   * since these windows have 4K granularity and the IO ranges
   * of non-bridge PCI devices are limited to 256 bytes.
   * We must be careful with the ISA aliasing though.
   */
  static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
9e8bf93a7   Ram Pai   PCI: code and com...
565
  		resource_size_t add_size, struct resource_list_x *realloc_head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
568
  {
  	struct pci_dev *dev;
  	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
569
  	unsigned long size = 0, size0 = 0, size1 = 0;
be768912a   Yinghai Lu   PCI: honor child ...
570
  	resource_size_t children_add_size = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
575
576
577
578
579
580
581
582
583
  
  	if (!b_res)
   		return;
  
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		int i;
  
  		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
  			struct resource *r = &dev->resource[i];
  			unsigned long r_size;
  
  			if (r->parent || !(r->flags & IORESOURCE_IO))
  				continue;
022edd86d   Zhao, Yu   PCI: use resource...
584
  			r_size = resource_size(r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
589
590
  
  			if (r_size < 0x400)
  				/* Might be re-aligned for ISA */
  				size += r_size;
  			else
  				size1 += r_size;
be768912a   Yinghai Lu   PCI: honor child ...
591

9e8bf93a7   Ram Pai   PCI: code and com...
592
593
  			if (realloc_head)
  				children_add_size += get_res_add_size(realloc_head, r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
  		}
  	}
c8adf9a3e   Ram Pai   PCI: pre-allocate...
596
597
  	size0 = calculate_iosize(size, min_size, size1,
  			resource_size(b_res), 4096);
be768912a   Yinghai Lu   PCI: honor child ...
598
599
  	if (children_add_size > add_size)
  		add_size = children_add_size;
9e8bf93a7   Ram Pai   PCI: code and com...
600
  	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
c8adf9a3e   Ram Pai   PCI: pre-allocate...
601
  		calculate_iosize(size, min_size+add_size, size1,
13583b165   Ram Pai   PCI: refactor io ...
602
  			resource_size(b_res), 4096);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
603
  	if (!size0 && !size1) {
865df576e   Bjorn Helgaas   PCI: improve disc...
604
605
606
607
608
  		if (b_res->start || b_res->end)
  			dev_info(&bus->self->dev, "disabling bridge window "
  				 "%pR to [bus %02x-%02x] (unused)
  ", b_res,
  				 bus->secondary, bus->subordinate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
611
612
613
  		b_res->flags = 0;
  		return;
  	}
  	/* Alignment of the IO window is always 4K */
  	b_res->start = 4096;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
614
  	b_res->end = b_res->start + size0 - 1;
884525655   Ivan Kokshaysky   PCI: clean up res...
615
  	b_res->flags |= IORESOURCE_STARTALIGN;
9e8bf93a7   Ram Pai   PCI: code and com...
616
617
  	if (size1 > size0 && realloc_head)
  		add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
619
620
621
622
623
624
  /**
   * pbus_size_mem() - size the memory window of a given bus
   *
   * @bus : the bus
   * @min_size : the minimum memory window that must to be allocated
   * @add_size : additional optional memory window
9e8bf93a7   Ram Pai   PCI: code and com...
625
   * @realloc_head : track the additional memory window on this list
c8adf9a3e   Ram Pai   PCI: pre-allocate...
626
627
628
629
   *
   * Calculate the size of the bus and minimal alignment which
   * guarantees that all child resources fit in this size.
   */
28760489a   Eric W. Biederman   PCI: pcie: Ensure...
630
  static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
c8adf9a3e   Ram Pai   PCI: pre-allocate...
631
632
  			 unsigned long type, resource_size_t min_size,
  			resource_size_t add_size,
9e8bf93a7   Ram Pai   PCI: code and com...
633
  			struct resource_list_x *realloc_head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
  {
  	struct pci_dev *dev;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
636
  	resource_size_t min_align, align, size, size0, size1;
c40a22e0c   Benjamin Herrenschmidt   PCI: Fix bus reso...
637
  	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
  	int order, max_order;
  	struct resource *b_res = find_free_bus_resource(bus, type);
1f82de10d   Yinghai Lu   PCI/x86: don't as...
640
  	unsigned int mem64_mask = 0;
be768912a   Yinghai Lu   PCI: honor child ...
641
  	resource_size_t children_add_size = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
646
647
648
  
  	if (!b_res)
  		return 0;
  
  	memset(aligns, 0, sizeof(aligns));
  	max_order = 0;
  	size = 0;
1f82de10d   Yinghai Lu   PCI/x86: don't as...
649
650
  	mem64_mask = b_res->flags & IORESOURCE_MEM_64;
  	b_res->flags &= ~IORESOURCE_MEM_64;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		int i;
1f82de10d   Yinghai Lu   PCI/x86: don't as...
653

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
  		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
  			struct resource *r = &dev->resource[i];
c40a22e0c   Benjamin Herrenschmidt   PCI: Fix bus reso...
656
  			resource_size_t r_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
  
  			if (r->parent || (r->flags & mask) != type)
  				continue;
022edd86d   Zhao, Yu   PCI: use resource...
660
  			r_size = resource_size(r);
2aceefcbd   Yinghai Lu   PCI: make SRIOV r...
661
662
  #ifdef CONFIG_PCI_IOV
  			/* put SRIOV requested res to the optional list */
9e8bf93a7   Ram Pai   PCI: code and com...
663
  			if (realloc_head && i >= PCI_IOV_RESOURCES &&
2aceefcbd   Yinghai Lu   PCI: make SRIOV r...
664
665
  					i <= PCI_IOV_RESOURCE_END) {
  				r->end = r->start - 1;
9e8bf93a7   Ram Pai   PCI: code and com...
666
  				add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */);
2aceefcbd   Yinghai Lu   PCI: make SRIOV r...
667
668
669
670
  				children_add_size += r_size;
  				continue;
  			}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
  			/* For bridges size != alignment */
6faf17f6f   Chris Wright   PCI SR-IOV: corre...
672
  			align = pci_resource_alignment(dev, r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
  			order = __ffs(align) - 20;
  			if (order > 11) {
865df576e   Bjorn Helgaas   PCI: improve disc...
675
676
677
678
  				dev_warn(&dev->dev, "disabling BAR %d: %pR "
  					 "(bad alignment %#llx)
  ", i, r,
  					 (unsigned long long) align);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
683
684
685
686
687
688
689
690
  				r->flags = 0;
  				continue;
  			}
  			size += r_size;
  			if (order < 0)
  				order = 0;
  			/* Exclude ranges with size > align from
  			   calculation of the alignment. */
  			if (r_size == align)
  				aligns[order] += align;
  			if (order > max_order)
  				max_order = order;
1f82de10d   Yinghai Lu   PCI/x86: don't as...
691
  			mem64_mask &= r->flags & IORESOURCE_MEM_64;
be768912a   Yinghai Lu   PCI: honor child ...
692

9e8bf93a7   Ram Pai   PCI: code and com...
693
694
  			if (realloc_head)
  				children_add_size += get_res_add_size(realloc_head, r);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
696
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
699
  	align = 0;
  	min_align = 0;
  	for (order = 0; order <= max_order; order++) {
8308c54d7   Jeremy Fitzhardinge   generic: redefine...
700
701
702
  		resource_size_t align1 = 1;
  
  		align1 <<= (order + 20);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
  		if (!align)
  			min_align = align1;
6f6f8c2f4   Milind Arun Choudhary   PCI: ROUND_UP mac...
705
  		else if (ALIGN(align + min_align, min_align) < align1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
708
  			min_align = align1 >> 1;
  		align += aligns[order];
  	}
b42282e5a   Linus Torvalds   pci: fix PCI bus ...
709
  	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
be768912a   Yinghai Lu   PCI: honor child ...
710
711
  	if (children_add_size > add_size)
  		add_size = children_add_size;
9e8bf93a7   Ram Pai   PCI: code and com...
712
  	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
c8adf9a3e   Ram Pai   PCI: pre-allocate...
713
  		calculate_memsize(size, min_size+add_size, 0,
b42282e5a   Linus Torvalds   pci: fix PCI bus ...
714
  				resource_size(b_res), min_align);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
715
  	if (!size0 && !size1) {
865df576e   Bjorn Helgaas   PCI: improve disc...
716
717
718
719
720
  		if (b_res->start || b_res->end)
  			dev_info(&bus->self->dev, "disabling bridge window "
  				 "%pR to [bus %02x-%02x] (unused)
  ", b_res,
  				 bus->secondary, bus->subordinate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
722
723
724
  		b_res->flags = 0;
  		return 1;
  	}
  	b_res->start = min_align;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
725
726
  	b_res->end = size0 + min_align - 1;
  	b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
9e8bf93a7   Ram Pai   PCI: code and com...
727
728
  	if (size1 > size0 && realloc_head)
  		add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
729
730
  	return 1;
  }
0a2daa1cf   Ram Pai   PCI: make cardbus...
731
732
733
734
735
736
737
738
739
740
  unsigned long pci_cardbus_resource_alignment(struct resource *res)
  {
  	if (res->flags & IORESOURCE_IO)
  		return pci_cardbus_io_size;
  	if (res->flags & IORESOURCE_MEM)
  		return pci_cardbus_mem_size;
  	return 0;
  }
  
  static void pci_bus_size_cardbus(struct pci_bus *bus,
9e8bf93a7   Ram Pai   PCI: code and com...
741
  			struct resource_list_x *realloc_head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
746
747
748
749
750
  {
  	struct pci_dev *bridge = bus->self;
  	struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
  	u16 ctrl;
  
  	/*
  	 * Reserve some resources for CardBus.  We reserve
  	 * a fixed amount of bus space for CardBus bridges.
  	 */
934b7024f   Linus Torvalds   Fix cardbus resou...
751
  	b_res[0].start = 0;
934b7024f   Linus Torvalds   Fix cardbus resou...
752
  	b_res[0].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
9e8bf93a7   Ram Pai   PCI: code and com...
753
754
  	if (realloc_head)
  		add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size, 0 /* dont care */);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755

934b7024f   Linus Torvalds   Fix cardbus resou...
756
  	b_res[1].start = 0;
934b7024f   Linus Torvalds   Fix cardbus resou...
757
  	b_res[1].flags |= IORESOURCE_IO | IORESOURCE_SIZEALIGN;
9e8bf93a7   Ram Pai   PCI: code and com...
758
759
  	if (realloc_head)
  		add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size, 0 /* dont care */);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
  
  	/*
  	 * Check whether prefetchable memory is supported
  	 * by this bridge.
  	 */
  	pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
  	if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
  		ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
  		pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
  		pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
  	}
  
  	/*
  	 * If we have prefetchable memory support, allocate
  	 * two regions.  Otherwise, allocate one region of
  	 * twice the size.
  	 */
  	if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
934b7024f   Linus Torvalds   Fix cardbus resou...
778
  		b_res[2].start = 0;
934b7024f   Linus Torvalds   Fix cardbus resou...
779
  		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_SIZEALIGN;
9e8bf93a7   Ram Pai   PCI: code and com...
780
781
  		if (realloc_head)
  			add_to_list(realloc_head, bridge, b_res+2, pci_cardbus_mem_size, 0 /* dont care */);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782

934b7024f   Linus Torvalds   Fix cardbus resou...
783
  		b_res[3].start = 0;
934b7024f   Linus Torvalds   Fix cardbus resou...
784
  		b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
9e8bf93a7   Ram Pai   PCI: code and com...
785
786
  		if (realloc_head)
  			add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size, 0 /* dont care */);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787
  	} else {
934b7024f   Linus Torvalds   Fix cardbus resou...
788
  		b_res[3].start = 0;
934b7024f   Linus Torvalds   Fix cardbus resou...
789
  		b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_SIZEALIGN;
9e8bf93a7   Ram Pai   PCI: code and com...
790
791
  		if (realloc_head)
  			add_to_list(realloc_head, bridge, b_res+3, pci_cardbus_mem_size * 2, 0 /* dont care */);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
  	}
0a2daa1cf   Ram Pai   PCI: make cardbus...
793
794
795
796
797
798
799
  
  	/* set the size of the resource to zero, so that the resource does not
  	 * get assigned during required-resource allocation cycle but gets assigned
  	 * during the optional-resource allocation cycle.
   	 */
  	b_res[0].start = b_res[1].start = b_res[2].start = b_res[3].start = 1;
  	b_res[0].end = b_res[1].end = b_res[2].end = b_res[3].end = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
801
  void __ref __pci_bus_size_bridges(struct pci_bus *bus,
9e8bf93a7   Ram Pai   PCI: code and com...
802
  			struct resource_list_x *realloc_head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
805
  {
  	struct pci_dev *dev;
  	unsigned long mask, prefmask;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
806
  	resource_size_t additional_mem_size = 0, additional_io_size = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
810
811
812
813
814
  
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		struct pci_bus *b = dev->subordinate;
  		if (!b)
  			continue;
  
  		switch (dev->class >> 8) {
  		case PCI_CLASS_BRIDGE_CARDBUS:
9e8bf93a7   Ram Pai   PCI: code and com...
815
  			pci_bus_size_cardbus(b, realloc_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
817
818
819
  			break;
  
  		case PCI_CLASS_BRIDGE_PCI:
  		default:
9e8bf93a7   Ram Pai   PCI: code and com...
820
  			__pci_bus_size_bridges(b, realloc_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  			break;
  		}
  	}
  
  	/* The root bus? */
  	if (!bus->self)
  		return;
  
  	switch (bus->self->class >> 8) {
  	case PCI_CLASS_BRIDGE_CARDBUS:
  		/* don't size cardbuses yet. */
  		break;
  
  	case PCI_CLASS_BRIDGE_PCI:
  		pci_bridge_check_ranges(bus);
28760489a   Eric W. Biederman   PCI: pcie: Ensure...
836
  		if (bus->self->is_hotplug_bridge) {
c8adf9a3e   Ram Pai   PCI: pre-allocate...
837
838
  			additional_io_size  = pci_hotplug_io_size;
  			additional_mem_size = pci_hotplug_mem_size;
28760489a   Eric W. Biederman   PCI: pcie: Ensure...
839
  		}
c8adf9a3e   Ram Pai   PCI: pre-allocate...
840
841
842
  		/*
  		 * Follow thru
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  	default:
9e8bf93a7   Ram Pai   PCI: code and com...
844
  		pbus_size_io(bus, 0, additional_io_size, realloc_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
847
848
849
850
851
  		/* If the bridge supports prefetchable range, size it
  		   separately. If it doesn't, or its prefetchable window
  		   has already been allocated by arch code, try
  		   non-prefetchable range for both types of PCI memory
  		   resources. */
  		mask = IORESOURCE_MEM;
  		prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
9e8bf93a7   Ram Pai   PCI: code and com...
852
  		if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, realloc_head))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  			mask = prefmask; /* Success, size non-prefetch only. */
28760489a   Eric W. Biederman   PCI: pcie: Ensure...
854
  		else
c8adf9a3e   Ram Pai   PCI: pre-allocate...
855
  			additional_mem_size += additional_mem_size;
9e8bf93a7   Ram Pai   PCI: code and com...
856
  		pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, realloc_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
858
859
  		break;
  	}
  }
c8adf9a3e   Ram Pai   PCI: pre-allocate...
860
861
862
863
864
  
  void __ref pci_bus_size_bridges(struct pci_bus *bus)
  {
  	__pci_bus_size_bridges(bus, NULL);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
  EXPORT_SYMBOL(pci_bus_size_bridges);
568ddef87   Yinghai Lu   PCI: add failed_l...
866
  static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
9e8bf93a7   Ram Pai   PCI: code and com...
867
  					 struct resource_list_x *realloc_head,
568ddef87   Yinghai Lu   PCI: add failed_l...
868
  					 struct resource_list_x *fail_head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
870
871
  {
  	struct pci_bus *b;
  	struct pci_dev *dev;
9e8bf93a7   Ram Pai   PCI: code and com...
872
  	pbus_assign_resources_sorted(bus, realloc_head, fail_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
875
876
877
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		b = dev->subordinate;
  		if (!b)
  			continue;
9e8bf93a7   Ram Pai   PCI: code and com...
878
  		__pci_bus_assign_resources(b, realloc_head, fail_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
  
  		switch (dev->class >> 8) {
  		case PCI_CLASS_BRIDGE_PCI:
6841ec681   Yinghai Lu   PCI: introduce pc...
882
883
  			if (!pci_is_enabled(dev))
  				pci_setup_bridge(b);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
885
886
887
888
889
890
  			break;
  
  		case PCI_CLASS_BRIDGE_CARDBUS:
  			pci_setup_cardbus(b);
  			break;
  
  		default:
80ccba118   Bjorn Helgaas   PCI: use dev_prin...
891
892
893
  			dev_info(&dev->dev, "not setting up bridge for bus "
  				 "%04x:%02x
  ", pci_domain_nr(b), b->number);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
896
897
  			break;
  		}
  	}
  }
568ddef87   Yinghai Lu   PCI: add failed_l...
898
899
900
  
  void __ref pci_bus_assign_resources(const struct pci_bus *bus)
  {
c8adf9a3e   Ram Pai   PCI: pre-allocate...
901
  	__pci_bus_assign_resources(bus, NULL, NULL);
568ddef87   Yinghai Lu   PCI: add failed_l...
902
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  EXPORT_SYMBOL(pci_bus_assign_resources);
6841ec681   Yinghai Lu   PCI: introduce pc...
904
905
906
907
908
909
910
911
912
913
  static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
  					 struct resource_list_x *fail_head)
  {
  	struct pci_bus *b;
  
  	pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head);
  
  	b = bridge->subordinate;
  	if (!b)
  		return;
c8adf9a3e   Ram Pai   PCI: pre-allocate...
914
  	__pci_bus_assign_resources(b, NULL, fail_head);
6841ec681   Yinghai Lu   PCI: introduce pc...
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
  
  	switch (bridge->class >> 8) {
  	case PCI_CLASS_BRIDGE_PCI:
  		pci_setup_bridge(b);
  		break;
  
  	case PCI_CLASS_BRIDGE_CARDBUS:
  		pci_setup_cardbus(b);
  		break;
  
  	default:
  		dev_info(&bridge->dev, "not setting up bridge for bus "
  			 "%04x:%02x
  ", pci_domain_nr(b), b->number);
  		break;
  	}
  }
5009b4602   Yinghai Lu   PCI: add pci_brid...
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  static void pci_bridge_release_resources(struct pci_bus *bus,
  					  unsigned long type)
  {
  	int idx;
  	bool changed = false;
  	struct pci_dev *dev;
  	struct resource *r;
  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
  				  IORESOURCE_PREFETCH;
  
  	dev = bus->self;
  	for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END;
  	     idx++) {
  		r = &dev->resource[idx];
  		if ((r->flags & type_mask) != type)
  			continue;
  		if (!r->parent)
  			continue;
  		/*
  		 * if there are children under that, we should release them
  		 *  all
  		 */
  		release_child_resources(r);
  		if (!release_resource(r)) {
  			dev_printk(KERN_DEBUG, &dev->dev,
  				 "resource %d %pR released
  ", idx, r);
  			/* keep the old size */
  			r->end = resource_size(r) - 1;
  			r->start = 0;
  			r->flags = 0;
  			changed = true;
  		}
  	}
  
  	if (changed) {
  		/* avoiding touch the one without PREF */
  		if (type & IORESOURCE_PREFETCH)
  			type = IORESOURCE_PREFETCH;
  		__pci_setup_bridge(bus, type);
  	}
  }
  
  enum release_type {
  	leaf_only,
  	whole_subtree,
  };
  /*
   * try to release pci bridge resources that is from leaf bridge,
   * so we can allocate big new one later
   */
  static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus,
  						   unsigned long type,
  						   enum release_type rel_type)
  {
  	struct pci_dev *dev;
  	bool is_leaf_bridge = true;
  
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		struct pci_bus *b = dev->subordinate;
  		if (!b)
  			continue;
  
  		is_leaf_bridge = false;
  
  		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
  			continue;
  
  		if (rel_type == whole_subtree)
  			pci_bus_release_bridge_resources(b, type,
  						 whole_subtree);
  	}
  
  	if (pci_is_root_bus(bus))
  		return;
  
  	if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI)
  		return;
  
  	if ((rel_type == whole_subtree) || is_leaf_bridge)
  		pci_bridge_release_resources(bus, type);
  }
76fbc263f   Yinghai Lu   pci: debug extra ...
1014
1015
  static void pci_bus_dump_res(struct pci_bus *bus)
  {
89a74eccc   Bjorn Helgaas   PCI: add pci_bus_...
1016
1017
  	struct resource *res;
  	int i;
7c9342b8d   Yinghai Lu   PCI: don't dump r...
1018

89a74eccc   Bjorn Helgaas   PCI: add pci_bus_...
1019
  	pci_bus_for_each_resource(bus, res, i) {
7c9342b8d   Yinghai Lu   PCI: don't dump r...
1020
  		if (!res || !res->end || !res->flags)
76fbc263f   Yinghai Lu   pci: debug extra ...
1021
                          continue;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
1022
1023
  		dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR
  ", i, res);
76fbc263f   Yinghai Lu   pci: debug extra ...
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
          }
  }
  
  static void pci_bus_dump_resources(struct pci_bus *bus)
  {
  	struct pci_bus *b;
  	struct pci_dev *dev;
  
  
  	pci_bus_dump_res(bus);
  
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		b = dev->subordinate;
  		if (!b)
  			continue;
  
  		pci_bus_dump_resources(b);
  	}
  }
da7822e5a   Yinghai Lu   PCI: update bridg...
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
  static int __init pci_bus_get_depth(struct pci_bus *bus)
  {
  	int depth = 0;
  	struct pci_dev *dev;
  
  	list_for_each_entry(dev, &bus->devices, bus_list) {
  		int ret;
  		struct pci_bus *b = dev->subordinate;
  		if (!b)
  			continue;
  
  		ret = pci_bus_get_depth(b);
  		if (ret + 1 > depth)
  			depth = ret + 1;
  	}
  
  	return depth;
  }
  static int __init pci_get_max_depth(void)
  {
  	int depth = 0;
  	struct pci_bus *bus;
  
  	list_for_each_entry(bus, &pci_root_buses, node) {
  		int ret;
  
  		ret = pci_bus_get_depth(bus);
  		if (ret > depth)
  			depth = ret;
  	}
  
  	return depth;
  }
f483d3923   Ram Pai   PCI: conditional ...
1076

da7822e5a   Yinghai Lu   PCI: update bridg...
1077
1078
1079
1080
1081
  /*
   * first try will not touch pci bridge res
   * second  and later try will clear small leaf bridge res
   * will stop till to the max  deepth if can not find good one
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
1083
1084
1085
  void __init
  pci_assign_unassigned_resources(void)
  {
  	struct pci_bus *bus;
9e8bf93a7   Ram Pai   PCI: code and com...
1086
  	struct resource_list_x realloc_list; /* list of resources that
c8adf9a3e   Ram Pai   PCI: pre-allocate...
1087
  					want additional resources */
da7822e5a   Yinghai Lu   PCI: update bridg...
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  	int tried_times = 0;
  	enum release_type rel_type = leaf_only;
  	struct resource_list_x head, *list;
  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
  				  IORESOURCE_PREFETCH;
  	unsigned long failed_type;
  	int max_depth = pci_get_max_depth();
  	int pci_try_num;
  
  
  	head.next = NULL;
9e8bf93a7   Ram Pai   PCI: code and com...
1099
  	realloc_list.next = NULL;
da7822e5a   Yinghai Lu   PCI: update bridg...
1100
1101
1102
1103
1104
1105
1106
  
  	pci_try_num = max_depth + 1;
  	printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d
  ",
  		 max_depth, pci_try_num);
  
  again:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
1108
  	/* Depth first, calculate sizes and alignments of all
  	   subordinate buses. */
da7822e5a   Yinghai Lu   PCI: update bridg...
1109
  	list_for_each_entry(bus, &pci_root_buses, node)
9e8bf93a7   Ram Pai   PCI: code and com...
1110
  		__pci_bus_size_bridges(bus, &realloc_list);
c8adf9a3e   Ram Pai   PCI: pre-allocate...
1111

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  	/* Depth last, allocate resources and update the hardware. */
da7822e5a   Yinghai Lu   PCI: update bridg...
1113
  	list_for_each_entry(bus, &pci_root_buses, node)
9e8bf93a7   Ram Pai   PCI: code and com...
1114
1115
  		__pci_bus_assign_resources(bus, &realloc_list, &head);
  	BUG_ON(realloc_list.next);
da7822e5a   Yinghai Lu   PCI: update bridg...
1116
1117
1118
1119
1120
  	tried_times++;
  
  	/* any device complain? */
  	if (!head.next)
  		goto enable_and_dump;
f483d3923   Ram Pai   PCI: conditional ...
1121
1122
1123
1124
1125
1126
  
  	/* don't realloc if asked to do so */
  	if (!pci_realloc_enabled()) {
  		free_list(resource_list_x, &head);
  		goto enable_and_dump;
  	}
da7822e5a   Yinghai Lu   PCI: update bridg...
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
  	failed_type = 0;
  	for (list = head.next; list;) {
  		failed_type |= list->flags;
  		list = list->next;
  	}
  	/*
  	 * io port are tight, don't try extra
  	 * or if reach the limit, don't want to try more
  	 */
  	failed_type &= type_mask;
  	if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
  		free_list(resource_list_x, &head);
  		goto enable_and_dump;
  	}
  
  	printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res
  ",
  			 tried_times + 1);
  
  	/* third times and later will not check if it is leaf */
  	if ((tried_times + 1) > 2)
  		rel_type = whole_subtree;
  
  	/*
  	 * Try to release leaf bridge's resources that doesn't fit resource of
  	 * child device under that bridge
  	 */
  	for (list = head.next; list;) {
  		bus = list->dev->bus;
  		pci_bus_release_bridge_resources(bus, list->flags & type_mask,
  						  rel_type);
  		list = list->next;
  	}
  	/* restore size and flags */
  	for (list = head.next; list;) {
  		struct resource *res = list->res;
  
  		res->start = list->start;
  		res->end = list->end;
  		res->flags = list->flags;
  		if (list->dev->subordinate)
  			res->flags = 0;
  
  		list = list->next;
  	}
  	free_list(resource_list_x, &head);
  
  	goto again;
  
  enable_and_dump:
  	/* Depth last, update the hardware. */
  	list_for_each_entry(bus, &pci_root_buses, node)
  		pci_enable_bridges(bus);
76fbc263f   Yinghai Lu   pci: debug extra ...
1180
1181
  
  	/* dump the resource on buses */
da7822e5a   Yinghai Lu   PCI: update bridg...
1182
  	list_for_each_entry(bus, &pci_root_buses, node)
76fbc263f   Yinghai Lu   pci: debug extra ...
1183
  		pci_bus_dump_resources(bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  }
6841ec681   Yinghai Lu   PCI: introduce pc...
1185
1186
1187
1188
  
  void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
  {
  	struct pci_bus *parent = bridge->subordinate;
32180e402   Yinghai Lu   PCI: pciehp: seco...
1189
1190
  	int tried_times = 0;
  	struct resource_list_x head, *list;
6841ec681   Yinghai Lu   PCI: introduce pc...
1191
  	int retval;
32180e402   Yinghai Lu   PCI: pciehp: seco...
1192
1193
1194
1195
  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
  				  IORESOURCE_PREFETCH;
  
  	head.next = NULL;
6841ec681   Yinghai Lu   PCI: introduce pc...
1196

32180e402   Yinghai Lu   PCI: pciehp: seco...
1197
  again:
6841ec681   Yinghai Lu   PCI: introduce pc...
1198
  	pci_bus_size_bridges(parent);
32180e402   Yinghai Lu   PCI: pciehp: seco...
1199
  	__pci_bridge_assign_resources(bridge, &head);
32180e402   Yinghai Lu   PCI: pciehp: seco...
1200
1201
1202
1203
  
  	tried_times++;
  
  	if (!head.next)
3f579c340   Yinghai Lu   PCI hotplug: make...
1204
  		goto enable_all;
32180e402   Yinghai Lu   PCI: pciehp: seco...
1205
1206
1207
  
  	if (tried_times >= 2) {
  		/* still fail, don't need to try more */
094732a52   Ram Pai   PCI: data structu...
1208
  		free_list(resource_list_x, &head);
3f579c340   Yinghai Lu   PCI hotplug: make...
1209
  		goto enable_all;
32180e402   Yinghai Lu   PCI: pciehp: seco...
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
  	}
  
  	printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res
  ",
  			 tried_times + 1);
  
  	/*
  	 * Try to release leaf bridge's resources that doesn't fit resource of
  	 * child device under that bridge
  	 */
  	for (list = head.next; list;) {
  		struct pci_bus *bus = list->dev->bus;
  		unsigned long flags = list->flags;
  
  		pci_bus_release_bridge_resources(bus, flags & type_mask,
  						 whole_subtree);
  		list = list->next;
  	}
  	/* restore size and flags */
  	for (list = head.next; list;) {
  		struct resource *res = list->res;
  
  		res->start = list->start;
  		res->end = list->end;
  		res->flags = list->flags;
  		if (list->dev->subordinate)
  			res->flags = 0;
  
  		list = list->next;
  	}
094732a52   Ram Pai   PCI: data structu...
1240
  	free_list(resource_list_x, &head);
32180e402   Yinghai Lu   PCI: pciehp: seco...
1241
1242
  
  	goto again;
3f579c340   Yinghai Lu   PCI hotplug: make...
1243
1244
1245
1246
1247
  
  enable_all:
  	retval = pci_reenable_device(bridge);
  	pci_set_master(bridge);
  	pci_enable_bridges(parent);
6841ec681   Yinghai Lu   PCI: introduce pc...
1248
1249
  }
  EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);