Commit be768912 authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes

PCI: honor child buses add_size in hot plug configuration

git commit c8adf9a3
    "PCI: pre-allocate additional resources to devices only after
	successful allocation of essential resources."

fails to take into consideration the optional-resources needed by children
devices while calculating the optional-resource needed by the bridge.

This can be a problem on some setup. For example, if a hotplug bridge has 8
children hotplug bridges, the bridge should have enough resources to accomodate
the hotplug requirements for each of its children hotplug bridges.  Currently
this is not the case.

This patch fixes the problem.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Reviewed-by: default avatarRam Pai <linuxram@us.ibm.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent b03e7495
...@@ -540,6 +540,20 @@ static resource_size_t calculate_memsize(resource_size_t size, ...@@ -540,6 +540,20 @@ static resource_size_t calculate_memsize(resource_size_t size,
return size; return size;
} }
static resource_size_t get_res_add_size(struct resource_list_x *add_head,
struct resource *res)
{
struct resource_list_x *list;
/* check if it is in add_head list */
for (list = add_head->next; list && list->res != res;
list = list->next);
if (list)
return list->add_size;
return 0;
}
/** /**
* pbus_size_io() - size the io window of a given bus * pbus_size_io() - size the io window of a given bus
* *
...@@ -559,6 +573,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -559,6 +573,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
struct pci_dev *dev; struct pci_dev *dev;
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
unsigned long size = 0, size0 = 0, size1 = 0; unsigned long size = 0, size0 = 0, size1 = 0;
resource_size_t children_add_size = 0;
if (!b_res) if (!b_res)
return; return;
...@@ -579,10 +594,15 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -579,10 +594,15 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
size += r_size; size += r_size;
else else
size1 += r_size; size1 += r_size;
if (add_head)
children_add_size += get_res_add_size(add_head, r);
} }
} }
size0 = calculate_iosize(size, min_size, size1, size0 = calculate_iosize(size, min_size, size1,
resource_size(b_res), 4096); resource_size(b_res), 4096);
if (children_add_size > add_size)
add_size = children_add_size;
size1 = (!add_head || (add_head && !add_size)) ? size0 : size1 = (!add_head || (add_head && !add_size)) ? size0 :
calculate_iosize(size, min_size+add_size, size1, calculate_iosize(size, min_size+add_size, size1,
resource_size(b_res), 4096); resource_size(b_res), 4096);
...@@ -624,6 +644,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -624,6 +644,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
int order, max_order; int order, max_order;
struct resource *b_res = find_free_bus_resource(bus, type); struct resource *b_res = find_free_bus_resource(bus, type);
unsigned int mem64_mask = 0; unsigned int mem64_mask = 0;
resource_size_t children_add_size = 0;
if (!b_res) if (!b_res)
return 0; return 0;
...@@ -665,6 +686,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -665,6 +686,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (order > max_order) if (order > max_order)
max_order = order; max_order = order;
mem64_mask &= r->flags & IORESOURCE_MEM_64; mem64_mask &= r->flags & IORESOURCE_MEM_64;
if (add_head)
children_add_size += get_res_add_size(add_head, r);
} }
} }
align = 0; align = 0;
...@@ -681,6 +705,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -681,6 +705,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
align += aligns[order]; align += aligns[order];
} }
size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align); size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
if (children_add_size > add_size)
add_size = children_add_size;
size1 = (!add_head || (add_head && !add_size)) ? size0 : size1 = (!add_head || (add_head && !add_size)) ? size0 :
calculate_memsize(size, min_size+add_size, 0, calculate_memsize(size, min_size+add_size, 0,
resource_size(b_res), min_align); resource_size(b_res), min_align);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment