aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-07-09 21:55:29 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-07-09 21:55:29 -0400
commitfd591341102ba5eb9e517d3889e7566fa45e021e (patch)
treee4e658bac28fe3626c9507a459d648d14a007b5e
parent2b28ae1912e5ce5bb0527e352ae6ff04e76183d1 (diff)
PCI: support sizing P2P bridge I/O windows with 1K granularity
Some bridges support I/O windows with 1K alignment, not just the 4K alignment defined by the PCI spec. For example, see the IOBL_ADR register and the EN1K bit in the CNF register in the Intel 82870P2 (P64H2). This patch adds support for sizing the window in 1K increments based on the requirements of downstream devices. [bhelgaas: changelog, comment] Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/setup-bus.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index dad5425f1f09..eb0293e23e48 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -706,7 +706,7 @@ static resource_size_t calculate_memsize(resource_size_t size,
706 * @realloc_head : track the additional io window on this list 706 * @realloc_head : track the additional io window on this list
707 * 707 *
708 * Sizing the IO windows of the PCI-PCI bridge is trivial, 708 * Sizing the IO windows of the PCI-PCI bridge is trivial,
709 * since these windows have 4K granularity and the IO ranges 709 * since these windows have 1K or 4K granularity and the IO ranges
710 * of non-bridge PCI devices are limited to 256 bytes. 710 * of non-bridge PCI devices are limited to 256 bytes.
711 * We must be careful with the ISA aliasing though. 711 * We must be careful with the ISA aliasing though.
712 */ 712 */
@@ -717,10 +717,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
717 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); 717 struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
718 unsigned long size = 0, size0 = 0, size1 = 0; 718 unsigned long size = 0, size0 = 0, size1 = 0;
719 resource_size_t children_add_size = 0; 719 resource_size_t children_add_size = 0;
720 resource_size_t min_align = 4096, align;
720 721
721 if (!b_res) 722 if (!b_res)
722 return; 723 return;
723 724
725 /*
726 * Per spec, I/O windows are 4K-aligned, but some bridges have an
727 * extension to support 1K alignment.
728 */
729 if (bus->self->io_window_1k)
730 min_align = 1024;
724 list_for_each_entry(dev, &bus->devices, bus_list) { 731 list_for_each_entry(dev, &bus->devices, bus_list) {
725 int i; 732 int i;
726 733
@@ -738,17 +745,25 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
738 else 745 else
739 size1 += r_size; 746 size1 += r_size;
740 747
748 align = pci_resource_alignment(dev, r);
749 if (align > min_align)
750 min_align = align;
751
741 if (realloc_head) 752 if (realloc_head)
742 children_add_size += get_res_add_size(realloc_head, r); 753 children_add_size += get_res_add_size(realloc_head, r);
743 } 754 }
744 } 755 }
756
757 if (min_align > 4096)
758 min_align = 4096;
759
745 size0 = calculate_iosize(size, min_size, size1, 760 size0 = calculate_iosize(size, min_size, size1,
746 resource_size(b_res), 4096); 761 resource_size(b_res), min_align);
747 if (children_add_size > add_size) 762 if (children_add_size > add_size)
748 add_size = children_add_size; 763 add_size = children_add_size;
749 size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 : 764 size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
750 calculate_iosize(size, min_size, add_size + size1, 765 calculate_iosize(size, min_size, add_size + size1,
751 resource_size(b_res), 4096); 766 resource_size(b_res), min_align);
752 if (!size0 && !size1) { 767 if (!size0 && !size1) {
753 if (b_res->start || b_res->end) 768 if (b_res->start || b_res->end)
754 dev_info(&bus->self->dev, "disabling bridge window " 769 dev_info(&bus->self->dev, "disabling bridge window "
@@ -757,12 +772,13 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
757 b_res->flags = 0; 772 b_res->flags = 0;
758 return; 773 return;
759 } 774 }
760 /* Alignment of the IO window is always 4K */ 775
761 b_res->start = 4096; 776 b_res->start = min_align;
762 b_res->end = b_res->start + size0 - 1; 777 b_res->end = b_res->start + size0 - 1;
763 b_res->flags |= IORESOURCE_STARTALIGN; 778 b_res->flags |= IORESOURCE_STARTALIGN;
764 if (size1 > size0 && realloc_head) { 779 if (size1 > size0 && realloc_head) {
765 add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096); 780 add_to_list(realloc_head, bus->self, b_res, size1-size0,
781 min_align);
766 dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " 782 dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
767 "%pR to [bus %02x-%02x] add_size %lx\n", b_res, 783 "%pR to [bus %02x-%02x] add_size %lx\n", b_res,
768 bus->secondary, bus->subordinate, size1-size0); 784 bus->secondary, bus->subordinate, size1-size0);