Lines 91-97
static void __dev_sort_resources(struct pci_dev *dev,
Link Here
|
91 |
pdev_sort_resources(dev, head); |
91 |
pdev_sort_resources(dev, head); |
92 |
} |
92 |
} |
93 |
|
93 |
|
94 |
static void __assign_resources_sorted(struct resource_list *head, |
94 |
|
|
|
95 |
static void adjust_resources_sorted(struct resource_list *head) |
96 |
{ |
97 |
struct resource *res; |
98 |
struct resource_list *list, *tmp; |
99 |
int idx, err; |
100 |
|
101 |
for (list = head->next; list;) { |
102 |
res = list->res; |
103 |
idx = res - &list->dev->resource[0]; |
104 |
|
105 |
if (!resource_size(res) && res->add_size) { |
106 |
res->end = res->start + res->add_size - 1; |
107 |
err = pci_assign_resource(list->dev, idx); |
108 |
} else if (res->add_size) { |
109 |
dev_info(&list->dev->dev, |
110 |
"%pR before adjusting resource size=%#llx add_size=%#llx\n", res, |
111 |
resource_size(res), res->add_size); |
112 |
err = adjust_resource(res, res->start, |
113 |
resource_size(res) + res->add_size); |
114 |
dev_info(&list->dev->dev, |
115 |
"%pR after adjusting resource size=%#llx add_size=%#llx error=%d\n", |
116 |
res, resource_size(res), res->add_size, err); |
117 |
} |
118 |
tmp = list; |
119 |
list = list->next; |
120 |
kfree(tmp); |
121 |
} |
122 |
} |
123 |
|
124 |
static void assign_requested_resources_sorted(struct resource_list *head, |
95 |
struct resource_list_x *fail_head) |
125 |
struct resource_list_x *fail_head) |
96 |
{ |
126 |
{ |
97 |
struct resource *res; |
127 |
struct resource *res; |
Lines 102-108
static void __assign_resources_sorted(struct resource_list *head,
Link Here
|
102 |
res = list->res; |
132 |
res = list->res; |
103 |
idx = res - &list->dev->resource[0]; |
133 |
idx = res - &list->dev->resource[0]; |
104 |
|
134 |
|
105 |
if (pci_assign_resource(list->dev, idx)) { |
135 |
if (resource_size(res) && pci_assign_resource(list->dev, idx)) { |
106 |
if (fail_head && !pci_is_root_bus(list->dev->bus)) { |
136 |
if (fail_head && !pci_is_root_bus(list->dev->bus)) { |
107 |
/* |
137 |
/* |
108 |
* if the failed res is for ROM BAR, and it will |
138 |
* if the failed res is for ROM BAR, and it will |
Lines 114-127
static void __assign_resources_sorted(struct resource_list *head,
Link Here
|
114 |
} |
144 |
} |
115 |
res->start = 0; |
145 |
res->start = 0; |
116 |
res->end = 0; |
146 |
res->end = 0; |
|
|
147 |
res->add_size = 0; |
117 |
res->flags = 0; |
148 |
res->flags = 0; |
118 |
} |
149 |
} |
119 |
tmp = list; |
150 |
tmp = list; |
120 |
list = list->next; |
151 |
list = list->next; |
121 |
kfree(tmp); |
|
|
122 |
} |
152 |
} |
123 |
} |
153 |
} |
124 |
|
154 |
|
|
|
155 |
static void __assign_resources_sorted(struct resource_list *head, |
156 |
struct resource_list_x *fail_head) |
157 |
{ |
158 |
/* Satisfy the must-have resource requests */ |
159 |
assign_requested_resources_sorted(head, fail_head); |
160 |
|
161 |
/* Try to satisfy any additional nice-to-have resource |
162 |
requests */ |
163 |
adjust_resources_sorted(head); |
164 |
} |
165 |
|
125 |
static void pdev_assign_resources_sorted(struct pci_dev *dev, |
166 |
static void pdev_assign_resources_sorted(struct pci_dev *dev, |
126 |
struct resource_list_x *fail_head) |
167 |
struct resource_list_x *fail_head) |
127 |
{ |
168 |
{ |
Lines 404-421
static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
Link Here
|
404 |
return NULL; |
445 |
return NULL; |
405 |
} |
446 |
} |
406 |
|
447 |
|
|
|
448 |
static resource_size_t calculate_iosize(resource_size_t size, |
449 |
resource_size_t min_size, |
450 |
resource_size_t size1, |
451 |
resource_size_t old_size, |
452 |
resource_size_t align) |
453 |
{ |
454 |
if (size < min_size) |
455 |
size = min_size; |
456 |
if (old_size == 1 ) |
457 |
old_size = 0; |
458 |
/* To be fixed in 2.5: we should have sort of HAVE_ISA |
459 |
flag in the struct pci_bus. */ |
460 |
#if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
461 |
size = (size & 0xff) + ((size & ~0xffUL) << 2); |
462 |
#endif |
463 |
size = ALIGN(size + size1, align); |
464 |
if (size < old_size) |
465 |
size = old_size; |
466 |
return size; |
467 |
} |
468 |
|
407 |
/* Sizing the IO windows of the PCI-PCI bridge is trivial, |
469 |
/* Sizing the IO windows of the PCI-PCI bridge is trivial, |
408 |
since these windows have 4K granularity and the IO ranges |
470 |
since these windows have 4K granularity and the IO ranges |
409 |
of non-bridge PCI devices are limited to 256 bytes. |
471 |
of non-bridge PCI devices are limited to 256 bytes. |
410 |
We must be careful with the ISA aliasing though. */ |
472 |
We must be careful with the ISA aliasing though. */ |
411 |
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) |
473 |
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, |
|
|
474 |
resource_size_t add_size) |
412 |
{ |
475 |
{ |
413 |
struct pci_dev *dev; |
476 |
struct pci_dev *dev; |
414 |
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
477 |
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
415 |
unsigned long size = 0, size1 = 0, old_size; |
478 |
unsigned long size = 0, size1 = 0; |
416 |
|
479 |
|
417 |
if (!b_res) |
480 |
if (!b_res) { |
|
|
481 |
dev_info(&bus->self->dev, "io am I returning from here " |
482 |
"[bus %02x-%02x] \n", |
483 |
bus->secondary, bus->subordinate); |
418 |
return; |
484 |
return; |
|
|
485 |
} |
419 |
|
486 |
|
420 |
list_for_each_entry(dev, &bus->devices, bus_list) { |
487 |
list_for_each_entry(dev, &bus->devices, bus_list) { |
421 |
int i; |
488 |
int i; |
Lines 435-454
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
Link Here
|
435 |
size1 += r_size; |
502 |
size1 += r_size; |
436 |
} |
503 |
} |
437 |
} |
504 |
} |
438 |
if (size < min_size) |
505 |
|
439 |
size = min_size; |
506 |
size = calculate_iosize(size, min_size, size1, |
440 |
old_size = resource_size(b_res); |
507 |
resource_size(b_res), 4096); |
441 |
if (old_size == 1) |
508 |
if (add_size) |
442 |
old_size = 0; |
509 |
size1 = calculate_iosize(size, min_size+add_size, size1, |
443 |
/* To be fixed in 2.5: we should have sort of HAVE_ISA |
510 |
resource_size(b_res), 4096); |
444 |
flag in the struct pci_bus. */ |
511 |
else |
445 |
#if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
512 |
size1 = size; |
446 |
size = (size & 0xff) + ((size & ~0xffUL) << 2); |
513 |
|
447 |
#endif |
514 |
if (!size && !size1) { |
448 |
size = ALIGN(size + size1, 4096); |
|
|
449 |
if (size < old_size) |
450 |
size = old_size; |
451 |
if (!size) { |
452 |
if (b_res->start || b_res->end) |
515 |
if (b_res->start || b_res->end) |
453 |
dev_info(&bus->self->dev, "disabling bridge window " |
516 |
dev_info(&bus->self->dev, "disabling bridge window " |
454 |
"%pR to [bus %02x-%02x] (unused)\n", b_res, |
517 |
"%pR to [bus %02x-%02x] (unused)\n", b_res, |
Lines 459-481
static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
Link Here
|
459 |
/* Alignment of the IO window is always 4K */ |
522 |
/* Alignment of the IO window is always 4K */ |
460 |
b_res->start = 4096; |
523 |
b_res->start = 4096; |
461 |
b_res->end = b_res->start + size - 1; |
524 |
b_res->end = b_res->start + size - 1; |
|
|
525 |
b_res->add_size = size1-size; |
462 |
b_res->flags |= IORESOURCE_STARTALIGN; |
526 |
b_res->flags |= IORESOURCE_STARTALIGN; |
|
|
527 |
dev_info(&bus->self->dev, "io %pR to [bus %02x-%02x] size=%ld add_size=%#llx\n", b_res, |
528 |
bus->secondary, bus->subordinate, size, b_res->add_size); |
529 |
} |
530 |
|
531 |
|
532 |
static resource_size_t calculate_memsize(resource_size_t size, |
533 |
resource_size_t min_size, |
534 |
resource_size_t size1, |
535 |
resource_size_t old_size, |
536 |
resource_size_t align) |
537 |
{ |
538 |
if (size < min_size) |
539 |
size = min_size; |
540 |
if (old_size == 1 ) |
541 |
old_size = 0; |
542 |
if (size < old_size) |
543 |
size = old_size; |
544 |
size = ALIGN(size + size1, align); |
545 |
return size; |
463 |
} |
546 |
} |
464 |
|
547 |
|
465 |
/* Calculate the size of the bus and minimal alignment which |
548 |
/* Calculate the size of the bus and minimal alignment which |
466 |
guarantees that all child resources fit in this size. */ |
549 |
guarantees that all child resources fit in this size. */ |
467 |
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, |
550 |
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, |
468 |
unsigned long type, resource_size_t min_size) |
551 |
unsigned long type, resource_size_t min_size, |
|
|
552 |
resource_size_t add_size) |
469 |
{ |
553 |
{ |
470 |
struct pci_dev *dev; |
554 |
struct pci_dev *dev; |
471 |
resource_size_t min_align, align, size, old_size; |
555 |
resource_size_t min_align, align, size, size1; |
472 |
resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
556 |
resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
473 |
int order, max_order; |
557 |
int order, max_order; |
474 |
struct resource *b_res = find_free_bus_resource(bus, type); |
558 |
struct resource *b_res = find_free_bus_resource(bus, type); |
475 |
unsigned int mem64_mask = 0; |
559 |
unsigned int mem64_mask = 0; |
476 |
|
560 |
|
477 |
if (!b_res) |
561 |
if (!b_res) { |
|
|
562 |
dev_info(&bus->self->dev, "mem am I returning from here " |
563 |
"[bus %02x-%02x] \n", |
564 |
bus->secondary, bus->subordinate); |
478 |
return 0; |
565 |
return 0; |
|
|
566 |
} |
479 |
|
567 |
|
480 |
memset(aligns, 0, sizeof(aligns)); |
568 |
memset(aligns, 0, sizeof(aligns)); |
481 |
max_order = 0; |
569 |
max_order = 0; |
Lines 516-528
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
Link Here
|
516 |
mem64_mask &= r->flags & IORESOURCE_MEM_64; |
604 |
mem64_mask &= r->flags & IORESOURCE_MEM_64; |
517 |
} |
605 |
} |
518 |
} |
606 |
} |
519 |
if (size < min_size) |
|
|
520 |
size = min_size; |
521 |
old_size = resource_size(b_res); |
522 |
if (old_size == 1) |
523 |
old_size = 0; |
524 |
if (size < old_size) |
525 |
size = old_size; |
526 |
|
607 |
|
527 |
align = 0; |
608 |
align = 0; |
528 |
min_align = 0; |
609 |
min_align = 0; |
Lines 537-544
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
Link Here
|
537 |
min_align = align1 >> 1; |
618 |
min_align = align1 >> 1; |
538 |
align += aligns[order]; |
619 |
align += aligns[order]; |
539 |
} |
620 |
} |
540 |
size = ALIGN(size, min_align); |
621 |
|
541 |
if (!size) { |
622 |
size = calculate_memsize(size, min_size, 0, resource_size(b_res), align); |
|
|
623 |
if (add_size) |
624 |
size1 = calculate_memsize(size, min_size+add_size, 0, resource_size(b_res), align); |
625 |
else |
626 |
size1 = size; |
627 |
|
628 |
if (!size && !size1) { |
542 |
if (b_res->start || b_res->end) |
629 |
if (b_res->start || b_res->end) |
543 |
dev_info(&bus->self->dev, "disabling bridge window " |
630 |
dev_info(&bus->self->dev, "disabling bridge window " |
544 |
"%pR to [bus %02x-%02x] (unused)\n", b_res, |
631 |
"%pR to [bus %02x-%02x] (unused)\n", b_res, |
Lines 548-555
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
Link Here
|
548 |
} |
635 |
} |
549 |
b_res->start = min_align; |
636 |
b_res->start = min_align; |
550 |
b_res->end = size + min_align - 1; |
637 |
b_res->end = size + min_align - 1; |
551 |
b_res->flags |= IORESOURCE_STARTALIGN; |
638 |
b_res->add_size = size1 - size; |
552 |
b_res->flags |= mem64_mask; |
639 |
b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; |
|
|
640 |
dev_info(&bus->self->dev, "mem %pR to [bus %02x-%02x] size=%#llx add_size=%#llx\n", b_res, |
641 |
bus->secondary, bus->subordinate, size, b_res->add_size); |
642 |
|
553 |
return 1; |
643 |
return 1; |
554 |
} |
644 |
} |
555 |
|
645 |
|
Lines 606-612
void __ref pci_bus_size_bridges(struct pci_bus *bus)
Link Here
|
606 |
{ |
696 |
{ |
607 |
struct pci_dev *dev; |
697 |
struct pci_dev *dev; |
608 |
unsigned long mask, prefmask; |
698 |
unsigned long mask, prefmask; |
609 |
resource_size_t min_mem_size = 0, min_io_size = 0; |
699 |
resource_size_t additional_mem_size = 0, additional_io_size = 0; |
610 |
|
700 |
|
611 |
list_for_each_entry(dev, &bus->devices, bus_list) { |
701 |
list_for_each_entry(dev, &bus->devices, bus_list) { |
612 |
struct pci_bus *b = dev->subordinate; |
702 |
struct pci_bus *b = dev->subordinate; |
Lines 637-647
void __ref pci_bus_size_bridges(struct pci_bus *bus)
Link Here
|
637 |
case PCI_CLASS_BRIDGE_PCI: |
727 |
case PCI_CLASS_BRIDGE_PCI: |
638 |
pci_bridge_check_ranges(bus); |
728 |
pci_bridge_check_ranges(bus); |
639 |
if (bus->self->is_hotplug_bridge) { |
729 |
if (bus->self->is_hotplug_bridge) { |
640 |
min_io_size = pci_hotplug_io_size; |
730 |
additional_io_size = pci_hotplug_io_size; |
641 |
min_mem_size = pci_hotplug_mem_size; |
731 |
additional_mem_size = pci_hotplug_mem_size; |
642 |
} |
732 |
} |
643 |
default: |
733 |
default: |
644 |
pbus_size_io(bus, min_io_size); |
734 |
pbus_size_io(bus, 0, additional_io_size); |
645 |
/* If the bridge supports prefetchable range, size it |
735 |
/* If the bridge supports prefetchable range, size it |
646 |
separately. If it doesn't, or its prefetchable window |
736 |
separately. If it doesn't, or its prefetchable window |
647 |
has already been allocated by arch code, try |
737 |
has already been allocated by arch code, try |
Lines 649-659
void __ref pci_bus_size_bridges(struct pci_bus *bus)
Link Here
|
649 |
resources. */ |
739 |
resources. */ |
650 |
mask = IORESOURCE_MEM; |
740 |
mask = IORESOURCE_MEM; |
651 |
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
741 |
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
652 |
if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size)) |
742 |
if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size)) |
653 |
mask = prefmask; /* Success, size non-prefetch only. */ |
743 |
mask = prefmask; /* Success, size non-prefetch only. */ |
654 |
else |
744 |
else |
655 |
min_mem_size += min_mem_size; |
745 |
additional_mem_size += additional_mem_size; |
656 |
pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size); |
746 |
pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size); |
657 |
break; |
747 |
break; |
658 |
} |
748 |
} |
659 |
} |
749 |
} |