setup-bus.c 40.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
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>
28
#include "pci.h"
Linus Torvalds's avatar
Linus Torvalds committed
29

30
31
struct pci_dev_resource {
	struct list_head list;
32
33
	struct resource *res;
	struct pci_dev *dev;
34
35
	resource_size_t start;
	resource_size_t end;
36
	resource_size_t add_size;
37
	resource_size_t min_align;
38
39
40
	unsigned long flags;
};

41
42
43
44
45
46
47
48
49
static void free_list(struct list_head *head)
{
	struct pci_dev_resource *dev_res, *tmp;

	list_for_each_entry_safe(dev_res, tmp, head, list) {
		list_del(&dev_res->list);
		kfree(dev_res);
	}
}
50

51
52
53
54
55
56
57
58
59
/**
 * 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
 */
60
static int add_to_list(struct list_head *head,
61
		 struct pci_dev *dev, struct resource *res,
62
		 resource_size_t add_size, resource_size_t min_align)
63
{
64
	struct pci_dev_resource *tmp;
65

66
	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
67
	if (!tmp) {
68
		pr_warning("add_to_list: kmalloc() failed!\n");
69
		return -ENOMEM;
70
71
72
73
74
75
76
	}

	tmp->res = res;
	tmp->dev = dev;
	tmp->start = res->start;
	tmp->end = res->end;
	tmp->flags = res->flags;
77
	tmp->add_size = add_size;
78
	tmp->min_align = min_align;
79
80

	list_add(&tmp->list, head);
81
82

	return 0;
83
84
}

85
static void remove_from_list(struct list_head *head,
86
87
				 struct resource *res)
{
88
	struct pci_dev_resource *dev_res, *tmp;
89

90
91
92
93
	list_for_each_entry_safe(dev_res, tmp, head, list) {
		if (dev_res->res == res) {
			list_del(&dev_res->list);
			kfree(dev_res);
94
			break;
95
96
97
98
		}
	}
}

99
static resource_size_t get_res_add_size(struct list_head *head,
100
101
					struct resource *res)
{
102
	struct pci_dev_resource *dev_res;
103

104
105
	list_for_each_entry(dev_res, head, list) {
		if (dev_res->res == res) {
106
107
			int idx = res - &dev_res->dev->resource[0];

108
			dev_printk(KERN_DEBUG, &dev_res->dev->dev,
109
110
				 "res[%d]=%pR get_res_add_size add_size %llx\n",
				 idx, dev_res->res,
111
				 (unsigned long long)dev_res->add_size);
112

113
			return dev_res->add_size;
114
		}
115
	}
116
117
118
119

	return 0;
}

120
/* Sort resources by alignment */
121
static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
122
123
124
125
126
{
	int i;

	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
		struct resource *r;
127
		struct pci_dev_resource *dev_res, *tmp;
128
		resource_size_t r_align;
129
		struct list_head *n;
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

		r = &dev->resource[i];

		if (r->flags & IORESOURCE_PCI_FIXED)
			continue;

		if (!(r->flags) || r->parent)
			continue;

		r_align = pci_resource_alignment(dev, r);
		if (!r_align) {
			dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
				 i, r);
			continue;
		}

146
147
148
149
150
151
152
153
154
155
156
157
158
159
		tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
		if (!tmp)
			panic("pdev_sort_resources(): "
			      "kmalloc() failed!\n");
		tmp->res = r;
		tmp->dev = dev;

		/* fallback is smallest one or list is empty*/
		n = head;
		list_for_each_entry(dev_res, head, list) {
			resource_size_t align;

			align = pci_resource_alignment(dev_res->dev,
							 dev_res->res);
160
161

			if (r_align > align) {
162
				n = &dev_res->list;
163
164
165
				break;
			}
		}
166
167
		/* Insert it just before n*/
		list_add_tail(&tmp->list, n);
168
169
170
	}
}

171
static void __dev_sort_resources(struct pci_dev *dev,
172
				 struct list_head *head)
Linus Torvalds's avatar
Linus Torvalds committed
173
{
174
	u16 class = dev->class >> 8;
Linus Torvalds's avatar
Linus Torvalds committed
175

176
177
178
	/* Don't touch classless devices or host bridges or ioapics.  */
	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
		return;
Linus Torvalds's avatar
Linus Torvalds committed
179

180
181
182
183
184
185
186
	/* 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;
	}
Linus Torvalds's avatar
Linus Torvalds committed
187

188
189
	pdev_sort_resources(dev, head);
}
190

Ram Pai's avatar
Ram Pai committed
191
192
193
194
195
196
197
static inline void reset_resource(struct resource *res)
{
	res->start = 0;
	res->end = 0;
	res->flags = 0;
}

198
/**
Ram Pai's avatar
Ram Pai committed
199
 * reassign_resources_sorted() - satisfy any additional resource requests
200
 *
Ram Pai's avatar
Ram Pai committed
201
 * @realloc_head : head of the list tracking requests requiring additional
202
203
204
205
 *             resources
 * @head     : head of the list tracking requests with allocated
 *             resources
 *
Ram Pai's avatar
Ram Pai committed
206
 * Walk through each element of the realloc_head and try to procure
207
208
209
 * additional resources for the element, provided the element
 * is in the head list.
 */
210
211
static void reassign_resources_sorted(struct list_head *realloc_head,
		struct list_head *head)
212
213
{
	struct resource *res;
214
	struct pci_dev_resource *add_res, *tmp;
215
	struct pci_dev_resource *dev_res;
216
	resource_size_t add_size;
217
	int idx;
Linus Torvalds's avatar
Linus Torvalds committed
218

219
	list_for_each_entry_safe(add_res, tmp, realloc_head, list) {
220
221
		bool found_match = false;

222
		res = add_res->res;
223
224
225
226
227
		/* skip resource that has been reset */
		if (!res->flags)
			goto out;

		/* skip this resource if not found in head list */
228
229
230
231
232
		list_for_each_entry(dev_res, head, list) {
			if (dev_res->res == res) {
				found_match = true;
				break;
			}
233
		}
234
235
		if (!found_match)/* just skip */
			continue;
236

237
238
		idx = res - &add_res->dev->resource[0];
		add_size = add_res->add_size;
239
		if (!resource_size(res)) {
240
			res->start = add_res->start;
241
			res->end = res->start + add_size - 1;
242
			if (pci_assign_resource(add_res->dev, idx))
243
				reset_resource(res);
244
		} else {
245
246
			resource_size_t align = add_res->min_align;
			res->flags |= add_res->flags &
247
				 (IORESOURCE_STARTALIGN|IORESOURCE_SIZEALIGN);
248
			if (pci_reassign_resource(add_res->dev, idx,
249
						  add_size, align))
250
				dev_printk(KERN_DEBUG, &add_res->dev->dev,
251
252
253
					   "failed to add %llx res[%d]=%pR\n",
					   (unsigned long long)add_size,
					   idx, res);
254
255
		}
out:
256
257
		list_del(&add_res->list);
		kfree(add_res);
258
259
260
261
262
263
264
265
266
267
268
269
270
	}
}

/**
 * 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.
 */
271
272
static void assign_requested_resources_sorted(struct list_head *head,
				 struct list_head *fail_head)
273
274
{
	struct resource *res;
275
	struct pci_dev_resource *dev_res;
276
	int idx;
277

278
279
280
281
282
283
	list_for_each_entry(dev_res, head, list) {
		res = dev_res->res;
		idx = res - &dev_res->dev->resource[0];
		if (resource_size(res) &&
		    pci_assign_resource(dev_res->dev, idx)) {
			if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) {
284
285
286
287
288
289
				/*
				 * 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))))
Yinghai Lu's avatar
Yinghai Lu committed
290
291
292
293
					add_to_list(fail_head,
						    dev_res->dev, res,
						    0 /* dont care */,
						    0 /* dont care */);
294
			}
Ram Pai's avatar
Ram Pai committed
295
			reset_resource(res);
296
		}
Linus Torvalds's avatar
Linus Torvalds committed
297
298
299
	}
}

300
301
302
static void __assign_resources_sorted(struct list_head *head,
				 struct list_head *realloc_head,
				 struct list_head *fail_head)
303
{
304
305
306
307
308
309
310
311
312
	/*
	 * Should not assign requested resources at first.
	 *   they could be adjacent, so later reassign can not reallocate
	 *   them one by one in parent resource window.
	 * Try to assign requested + add_size at begining
	 *  if could do that, could get out early.
	 *  if could not do that, we still try to assign requested at first,
	 *    then try to reassign add_size for some resources.
	 */
313
314
	LIST_HEAD(save_head);
	LIST_HEAD(local_fail_head);
315
	struct pci_dev_resource *save_res;
316
	struct pci_dev_resource *dev_res;
317
318

	/* Check if optional add_size is there */
319
	if (!realloc_head || list_empty(realloc_head))
320
321
322
		goto requested_and_reassign;

	/* Save original start, end, flags etc at first */
323
324
	list_for_each_entry(dev_res, head, list) {
		if (add_to_list(&save_head, dev_res->dev, dev_res->res, 0, 0)) {
325
			free_list(&save_head);
326
327
			goto requested_and_reassign;
		}
328
	}
329
330

	/* Update res in head list with add_size in realloc_head list */
331
332
333
	list_for_each_entry(dev_res, head, list)
		dev_res->res->end += get_res_add_size(realloc_head,
							dev_res->res);
334
335
336
337
338

	/* Try updated head list with add_size added */
	assign_requested_resources_sorted(head, &local_fail_head);

	/* all assigned with add_size ? */
339
	if (list_empty(&local_fail_head)) {
340
		/* Remove head list from realloc_head list */
341
342
		list_for_each_entry(dev_res, head, list)
			remove_from_list(realloc_head, dev_res->res);
343
344
		free_list(&save_head);
		free_list(head);
345
346
347
		return;
	}

348
	free_list(&local_fail_head);
349
	/* Release assigned resource */
350
351
352
	list_for_each_entry(dev_res, head, list)
		if (dev_res->res->parent)
			release_resource(dev_res->res);
353
	/* Restore start/end/flags from saved list */
354
355
	list_for_each_entry(save_res, &save_head, list) {
		struct resource *res = save_res->res;
356

357
358
359
		res->start = save_res->start;
		res->end = save_res->end;
		res->flags = save_res->flags;
360
	}
361
	free_list(&save_head);
362
363

requested_and_reassign:
364
365
366
	/* Satisfy the must-have resource requests */
	assign_requested_resources_sorted(head, fail_head);

367
	/* Try to satisfy any additional optional resource
368
		requests */
Ram Pai's avatar
Ram Pai committed
369
370
	if (realloc_head)
		reassign_resources_sorted(realloc_head, head);
371
	free_list(head);
372
373
}

374
static void pdev_assign_resources_sorted(struct pci_dev *dev,
375
376
				 struct list_head *add_head,
				 struct list_head *fail_head)
377
{
378
	LIST_HEAD(head);
379
380

	__dev_sort_resources(dev, &head);
381
	__assign_resources_sorted(&head, add_head, fail_head);
382
383
384
385

}

static void pbus_assign_resources_sorted(const struct pci_bus *bus,
386
387
					 struct list_head *realloc_head,
					 struct list_head *fail_head)
388
389
{
	struct pci_dev *dev;
390
	LIST_HEAD(head);
391
392
393
394

	list_for_each_entry(dev, &bus->devices, bus_list)
		__dev_sort_resources(dev, &head);

Ram Pai's avatar
Ram Pai committed
395
	__assign_resources_sorted(&head, realloc_head, fail_head);
396
397
}

398
void pci_setup_cardbus(struct pci_bus *bus)
Linus Torvalds's avatar
Linus Torvalds committed
399
400
{
	struct pci_dev *bridge = bus->self;
401
	struct resource *res;
Linus Torvalds's avatar
Linus Torvalds committed
402
403
	struct pci_bus_region region;

404
405
	dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
		 bus->secondary, bus->subordinate);
Linus Torvalds's avatar
Linus Torvalds committed
406

407
408
409
	res = bus->resource[0];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_IO) {
Linus Torvalds's avatar
Linus Torvalds committed
410
411
412
413
		/*
		 * The IO resource is allocated a range twice as large as it
		 * would normally need.  This allows us to set both IO regs.
		 */
414
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
Linus Torvalds's avatar
Linus Torvalds committed
415
416
417
418
419
420
		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
					region.start);
		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
					region.end);
	}

421
422
423
424
	res = bus->resource[1];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_IO) {
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
Linus Torvalds's avatar
Linus Torvalds committed
425
426
427
428
429
430
		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
					region.start);
		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
					region.end);
	}

431
432
433
434
	res = bus->resource[2];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_MEM) {
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
Linus Torvalds's avatar
Linus Torvalds committed
435
436
437
438
439
440
		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
					region.start);
		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
					region.end);
	}

441
442
443
444
	res = bus->resource[3];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_MEM) {
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
Linus Torvalds's avatar
Linus Torvalds committed
445
446
447
448
449
450
		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
					region.start);
		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
					region.end);
	}
}
451
EXPORT_SYMBOL(pci_setup_cardbus);
Linus Torvalds's avatar
Linus Torvalds committed
452
453
454
455
456
457
458
459
460
461
462
463

/* 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.  */
464
static void pci_setup_bridge_io(struct pci_bus *bus)
Linus Torvalds's avatar
Linus Torvalds committed
465
466
{
	struct pci_dev *bridge = bus->self;
467
	struct resource *res;
Linus Torvalds's avatar
Linus Torvalds committed
468
	struct pci_bus_region region;
469
	u32 l, io_upper16;
Linus Torvalds's avatar
Linus Torvalds committed
470
471

	/* Set up the top and bottom of the PCI I/O segment for this bus. */
472
473
474
	res = bus->resource[0];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_IO) {
Linus Torvalds's avatar
Linus Torvalds committed
475
476
477
478
479
480
		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);
481
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
482
	} else {
Linus Torvalds's avatar
Linus Torvalds committed
483
484
485
486
487
488
489
490
491
492
		/* Clear upper 16 bits of I/O base/limit. */
		io_upper16 = 0;
		l = 0x00f0;
	}
	/* 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);
493
494
495
496
497
498
499
500
}

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;
Linus Torvalds's avatar
Linus Torvalds committed
501

502
	/* Set up the top and bottom of the PCI Memory segment for this bus. */
503
504
505
	res = bus->resource[1];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_MEM) {
Linus Torvalds's avatar
Linus Torvalds committed
506
507
		l = (region.start >> 16) & 0xfff0;
		l |= region.end & 0xfff00000;
508
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
509
	} else {
Linus Torvalds's avatar
Linus Torvalds committed
510
511
512
		l = 0x0000fff0;
	}
	pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
513
514
515
516
517
518
519
520
}

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;
Linus Torvalds's avatar
Linus Torvalds committed
521
522
523
524
525
526
527

	/* 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. */
528
	bu = lu = 0;
529
530
531
	res = bus->resource[2];
	pcibios_resource_to_bus(bridge, &region, res);
	if (res->flags & IORESOURCE_PREFETCH) {
Linus Torvalds's avatar
Linus Torvalds committed
532
533
		l = (region.start >> 16) & 0xfff0;
		l |= region.end & 0xfff00000;
534
		if (res->flags & IORESOURCE_MEM_64) {
535
536
537
			bu = upper_32_bits(region.start);
			lu = upper_32_bits(region.end);
		}
538
		dev_info(&bridge->dev, "  bridge window %pR\n", res);
539
	} else {
Linus Torvalds's avatar
Linus Torvalds committed
540
541
542
543
		l = 0x0000fff0;
	}
	pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);

544
545
546
	/* 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);
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
}

static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
{
	struct pci_dev *bridge = bus->self;

	dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
		 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);
Linus Torvalds's avatar
Linus Torvalds committed
564
565
566
567

	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
}

568
void pci_setup_bridge(struct pci_bus *bus)
569
570
571
572
573
574
575
{
	unsigned long type = IORESOURCE_IO | IORESOURCE_MEM |
				  IORESOURCE_PREFETCH;

	__pci_setup_bridge(bus, type);
}

Linus Torvalds's avatar
Linus Torvalds committed
576
577
578
/* 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. */
579
static void pci_bridge_check_ranges(struct pci_bus *bus)
Linus Torvalds's avatar
Linus Torvalds committed
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
{
	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);
	}
609
	if (pmem) {
Linus Torvalds's avatar
Linus Torvalds committed
610
		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
611
612
		if ((pmem & PCI_PREF_RANGE_TYPE_MASK) ==
		    PCI_PREF_RANGE_TYPE_64) {
613
			b_res[2].flags |= IORESOURCE_MEM_64;
614
615
			b_res[2].flags |= PCI_PREF_RANGE_TYPE_64;
		}
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
	}

	/* 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);
	}
Linus Torvalds's avatar
Linus Torvalds committed
631
632
633
634
635
636
}

/* 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). */
637
static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type)
Linus Torvalds's avatar
Linus Torvalds committed
638
639
640
641
642
643
{
	int i;
	struct resource *r;
	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
				  IORESOURCE_PREFETCH;

644
	pci_bus_for_each_resource(bus, r, i) {
645
646
		if (r == &ioport_resource || r == &iomem_resource)
			continue;
647
648
		if (r && (r->flags & type_mask) == type && !r->parent)
			return r;
Linus Torvalds's avatar
Linus Torvalds committed
649
650
651
652
	}
	return NULL;
}

653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
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;
}

690
691
692
693
694
695
/**
 * 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
Ram Pai's avatar
Ram Pai committed
696
 * @realloc_head : track the additional io window on this list
697
698
699
700
701
702
703
 *
 * 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,
704
		resource_size_t add_size, struct list_head *realloc_head)
Linus Torvalds's avatar
Linus Torvalds committed
705
706
707
{
	struct pci_dev *dev;
	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
708
	unsigned long size = 0, size0 = 0, size1 = 0;
709
	resource_size_t children_add_size = 0;
Linus Torvalds's avatar
Linus Torvalds committed
710
711
712
713
714
715
716
717
718
719
720
721
722

	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;
723
			r_size = resource_size(r);
Linus Torvalds's avatar
Linus Torvalds committed
724
725
726
727
728
729

			if (r_size < 0x400)
				/* Might be re-aligned for ISA */
				size += r_size;
			else
				size1 += r_size;
730

Ram Pai's avatar
Ram Pai committed
731
732
			if (realloc_head)
				children_add_size += get_res_add_size(realloc_head, r);
Linus Torvalds's avatar
Linus Torvalds committed
733
734
		}
	}
735
736
	size0 = calculate_iosize(size, min_size, size1,
			resource_size(b_res), 4096);
737
738
	if (children_add_size > add_size)
		add_size = children_add_size;
Ram Pai's avatar
Ram Pai committed
739
	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
Yinghai Lu's avatar
Yinghai Lu committed
740
		calculate_iosize(size, min_size, add_size + size1,
741
			resource_size(b_res), 4096);
742
	if (!size0 && !size1) {
743
744
745
746
		if (b_res->start || b_res->end)
			dev_info(&bus->self->dev, "disabling bridge window "
				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
				 bus->secondary, bus->subordinate);
Linus Torvalds's avatar
Linus Torvalds committed
747
748
749
750
751
		b_res->flags = 0;
		return;
	}
	/* Alignment of the IO window is always 4K */
	b_res->start = 4096;
752
	b_res->end = b_res->start + size0 - 1;
753
	b_res->flags |= IORESOURCE_STARTALIGN;
754
	if (size1 > size0 && realloc_head) {
Ram Pai's avatar
Ram Pai committed
755
		add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
756
757
758
759
		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
				 "%pR to [bus %02x-%02x] add_size %lx\n", b_res,
				 bus->secondary, bus->subordinate, size1-size0);
	}
Linus Torvalds's avatar
Linus Torvalds committed
760
761
}

762
763
764
765
766
767
/**
 * 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
Ram Pai's avatar
Ram Pai committed
768
 * @realloc_head : track the additional memory window on this list
769
770
771
772
 *
 * Calculate the size of the bus and minimal alignment which
 * guarantees that all child resources fit in this size.
 */
773
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
774
775
			 unsigned long type, resource_size_t min_size,
			resource_size_t add_size,
776
			struct list_head *realloc_head)
Linus Torvalds's avatar
Linus Torvalds committed
777
778
{
	struct pci_dev *dev;
779
	resource_size_t min_align, align, size, size0, size1;
780
	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
Linus Torvalds's avatar
Linus Torvalds committed
781
782
	int order, max_order;
	struct resource *b_res = find_free_bus_resource(bus, type);
783
	unsigned int mem64_mask = 0;
784
	resource_size_t children_add_size = 0;
Linus Torvalds's avatar
Linus Torvalds committed
785
786
787
788
789
790
791
792

	if (!b_res)
		return 0;

	memset(aligns, 0, sizeof(aligns));
	max_order = 0;
	size = 0;

793
794
795
	mem64_mask = b_res->flags & IORESOURCE_MEM_64;
	b_res->flags &= ~IORESOURCE_MEM_64;

Linus Torvalds's avatar
Linus Torvalds committed
796
797
	list_for_each_entry(dev, &bus->devices, bus_list) {
		int i;
798

Linus Torvalds's avatar
Linus Torvalds committed
799
800
		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
			struct resource *r = &dev->resource[i];
801
			resource_size_t r_size;
Linus Torvalds's avatar
Linus Torvalds committed
802
803
804

			if (r->parent || (r->flags & mask) != type)
				continue;
805
			r_size = resource_size(r);
806
807
#ifdef CONFIG_PCI_IOV
			/* put SRIOV requested res to the optional list */
Ram Pai's avatar
Ram Pai committed
808
			if (realloc_head && i >= PCI_IOV_RESOURCES &&
809
810
					i <= PCI_IOV_RESOURCE_END) {
				r->end = r->start - 1;
Ram Pai's avatar
Ram Pai committed
811
				add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */);
812
813
814
815
				children_add_size += r_size;
				continue;
			}
#endif
Linus Torvalds's avatar
Linus Torvalds committed
816
			/* For bridges size != alignment */
817
			align = pci_resource_alignment(dev, r);
Linus Torvalds's avatar
Linus Torvalds committed
818
819
			order = __ffs(align) - 20;
			if (order > 11) {
820
821
822
				dev_warn(&dev->dev, "disabling BAR %d: %pR "
					 "(bad alignment %#llx)\n", i, r,
					 (unsigned long long) align);
Linus Torvalds's avatar
Linus Torvalds committed
823
824
825
826
827
828
829
830
831
832
833
834
				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;
835
			mem64_mask &= r->flags & IORESOURCE_MEM_64;
836

Ram Pai's avatar
Ram Pai committed
837
838
			if (realloc_head)
				children_add_size += get_res_add_size(realloc_head, r);
Linus Torvalds's avatar
Linus Torvalds committed
839
840
841
842
843
		}
	}
	align = 0;
	min_align = 0;
	for (order = 0; order <= max_order; order++) {
844
845
846
847
		resource_size_t align1 = 1;

		align1 <<= (order + 20);

Linus Torvalds's avatar
Linus Torvalds committed
848
849
		if (!align)
			min_align = align1;
850
		else if (ALIGN(align + min_align, min_align) < align1)
Linus Torvalds's avatar
Linus Torvalds committed
851
852
853
			min_align = align1 >> 1;
		align += aligns[order];
	}
854
	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
855
856
	if (children_add_size > add_size)
		add_size = children_add_size;
Ram Pai's avatar
Ram Pai committed
857
	size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
Yinghai Lu's avatar
Yinghai Lu committed
858
		calculate_memsize(size, min_size, add_size,
859
				resource_size(b_res), min_align);
860
	if (!size0 && !size1) {
861
862
863
864
		if (b_res->start || b_res->end)
			dev_info(&bus->self->dev, "disabling bridge window "
				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
				 bus->secondary, bus->subordinate);
Linus Torvalds's avatar
Linus Torvalds committed
865
866
867
868
		b_res->flags = 0;
		return 1;
	}
	b_res->start = min_align;
869
870
	b_res->end = size0 + min_align - 1;
	b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
871
	if (size1 > size0 && realloc_head) {
Ram Pai's avatar
Ram Pai committed
872
		add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
873
874
875
876
		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
				 "%pR to [bus %02x-%02x] add_size %llx\n", b_res,
				 bus->secondary, bus->subordinate, (unsigned long long)size1-size0);
	}
Linus Torvalds's avatar
Linus Torvalds committed
877
878
879
	return 1;
}

880
881
882
883
884
885
886
887
888
889
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,
890
			struct list_head *realloc_head)
Linus Torvalds's avatar
Linus Torvalds committed
891
892
893
{
	struct pci_dev *bridge = bus->self;
	struct resource *b_res = &bridge->resource[PCI_BRIDGE_RESOURCES];
894
	resource_size_t b_res_3_size = pci_cardbus_mem_size * 2;
Linus Torvalds's avatar
Linus Torvalds committed
895
896
	u16 ctrl;

897
898
	if (b_res[0].parent)
		goto handle_b_res_1;
Linus Torvalds's avatar
Linus Torvalds committed
899
900
901
902
	/*
	 * Reserve some resources for CardBus.  We reserve
	 * a fixed amount of bus space for CardBus bridges.
	 */
903
904
905
906
907
908
909
910
	b_res[0].start = pci_cardbus_io_size;
	b_res[0].end = b_res[0].start + pci_cardbus_io_size - 1;
	b_res[0].flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
	if (realloc_head) {
		b_res[0].end -= pci_cardbus_io_size;
		add_to_list(realloc_head, bridge, b_res, pci_cardbus_io_size,
				pci_cardbus_io_size);
	}
Linus Torvalds's avatar
Linus Torvalds committed
911

912
913
914
handle_b_res_1:
	if (b_res[1].parent)
		goto handle_b_res_2;
915
916
917
918
919
920
921
922
	b_res[1].start = pci_cardbus_io_size;
	b_res[1].end = b_res[1].start + pci_cardbus_io_size - 1;
	b_res[1].flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
	if (realloc_head) {
		b_res[1].end -= pci_cardbus_io_size;
		add_to_list(realloc_head, bridge, b_res+1, pci_cardbus_io_size,
				 pci_cardbus_io_size);
	}
Linus Torvalds's avatar
Linus Torvalds committed
923

924
handle_b_res_2:
925
926
927
928
929
930
931
932
	/* MEM1 must not be pref mmio */
	pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
	if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
		ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
		pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
		pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
	}

Linus Torvalds's avatar
Linus Torvalds committed
933
934
935
936
937
938
939
940
941
942
943
	/*
	 * 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);
	}

944
945
	if (b_res[2].parent)
		goto handle_b_res_3;
Linus Torvalds's avatar
Linus Torvalds committed
946
947
948
949
950
951
	/*
	 * 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) {
952
953
954
955
956
957
958
959
960
961
962
963
964
965
		b_res[2].start = pci_cardbus_mem_size;
		b_res[2].end = b_res[2].start + pci_cardbus_mem_size - 1;
		b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH |
				  IORESOURCE_STARTALIGN;
		if (realloc_head) {
			b_res[2].end -= pci_cardbus_mem_size;
			add_to_list(realloc_head, bridge, b_res+2,
				 pci_cardbus_mem_size, pci_cardbus_mem_size);
		}

		/* reduce that to half */
		b_res_3_size = pci_cardbus_mem_size;
	}

966
967
968
handle_b_res_3:
	if (b_res[3].parent)
		goto handle_done;
969
970
971
972
973
974
975
976
	b_res[3].start = pci_cardbus_mem_size;
	b_res[3].end = b_res[3].start + b_res_3_size - 1;
	b_res[3].flags |= IORESOURCE_MEM | IORESOURCE_STARTALIGN;
	if (realloc_head) {
		b_res[3].end -= b_res_3_size;
		add_to_list(realloc_head, bridge, b_res+3, b_res_3_size,
				 pci_cardbus_mem_size);
	}
977
978
979

handle_done:
	;
Linus Torvalds's avatar
Linus Torvalds committed
980
981
}

982
void __ref __pci_bus_size_bridges(struct pci_bus *bus,
983
			struct list_head *realloc_head)
Linus Torvalds's avatar
Linus Torvalds committed
984
985
986
{
	struct pci_dev *dev;
	unsigned long mask, prefmask;
987
	resource_size_t additional_mem_size = 0, additional_io_size = 0;
Linus Torvalds's avatar
Linus Torvalds committed
988
989
990
991
992
993
994
995

	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:
Ram Pai's avatar
Ram Pai committed
996
			pci_bus_size_cardbus(b, realloc_head);
Linus Torvalds's avatar
Linus Torvalds committed
997
998
999
1000
			break;

		case PCI_CLASS_BRIDGE_PCI:
		default: