Skip to content

Commit

Permalink
PCI: support sizing P2P bridge I/O windows with 1K granularity
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yinghai Lu authored and Bjorn Helgaas committed Jul 10, 2012
1 parent 2b28ae1 commit fd59134
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions drivers/pci/setup-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ static resource_size_t calculate_memsize(resource_size_t size,
* @realloc_head : track the additional io window on this list
*
* Sizing the IO windows of the PCI-PCI bridge is trivial,
* since these windows have 4K granularity and the IO ranges
* since these windows have 1K or 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.
*/
Expand All @@ -717,10 +717,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
unsigned long size = 0, size0 = 0, size1 = 0;
resource_size_t children_add_size = 0;
resource_size_t min_align = 4096, align;

if (!b_res)
return;

/*
* Per spec, I/O windows are 4K-aligned, but some bridges have an
* extension to support 1K alignment.
*/
if (bus->self->io_window_1k)
min_align = 1024;
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;

Expand All @@ -738,17 +745,25 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
else
size1 += r_size;

align = pci_resource_alignment(dev, r);
if (align > min_align)
min_align = align;

if (realloc_head)
children_add_size += get_res_add_size(realloc_head, r);
}
}

if (min_align > 4096)
min_align = 4096;

size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), 4096);
resource_size(b_res), min_align);
if (children_add_size > add_size)
add_size = children_add_size;
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
calculate_iosize(size, min_size, add_size + size1,
resource_size(b_res), 4096);
resource_size(b_res), min_align);
if (!size0 && !size1) {
if (b_res->start || b_res->end)
dev_info(&bus->self->dev, "disabling bridge window "
Expand All @@ -757,12 +772,13 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
b_res->flags = 0;
return;
}
/* Alignment of the IO window is always 4K */
b_res->start = 4096;

b_res->start = min_align;
b_res->end = b_res->start + size0 - 1;
b_res->flags |= IORESOURCE_STARTALIGN;
if (size1 > size0 && realloc_head) {
add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
add_to_list(realloc_head, bus->self, b_res, size1-size0,
min_align);
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);
Expand Down

0 comments on commit fd59134

Please sign in to comment.