PCI: add failed_list to pci_bus_assign_resources
This allows us to track failed allocations for later re-trying with reallocation. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Reviewed-by: Alex Chiang <achiang@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
5009b46025
commit
568ddef873
|
@ -27,7 +27,52 @@
|
|||
#include <linux/slab.h>
|
||||
#include "pci.h"
|
||||
|
||||
static void pbus_assign_resources_sorted(const struct pci_bus *bus)
|
||||
struct resource_list_x {
|
||||
struct resource_list_x *next;
|
||||
struct resource *res;
|
||||
struct pci_dev *dev;
|
||||
resource_size_t start;
|
||||
resource_size_t end;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
static void add_to_failed_list(struct resource_list_x *head,
|
||||
struct pci_dev *dev, struct resource *res)
|
||||
{
|
||||
struct resource_list_x *list = head;
|
||||
struct resource_list_x *ln = list->next;
|
||||
struct resource_list_x *tmp;
|
||||
|
||||
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp) {
|
||||
pr_warning("add_to_failed_list: kmalloc() failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tmp->next = ln;
|
||||
tmp->res = res;
|
||||
tmp->dev = dev;
|
||||
tmp->start = res->start;
|
||||
tmp->end = res->end;
|
||||
tmp->flags = res->flags;
|
||||
list->next = tmp;
|
||||
}
|
||||
|
||||
static void free_failed_list(struct resource_list_x *head)
|
||||
{
|
||||
struct resource_list_x *list, *tmp;
|
||||
|
||||
for (list = head->next; list;) {
|
||||
tmp = list;
|
||||
list = list->next;
|
||||
kfree(tmp);
|
||||
}
|
||||
|
||||
head->next = NULL;
|
||||
}
|
||||
|
||||
static void pbus_assign_resources_sorted(const struct pci_bus *bus,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct resource *res;
|
||||
|
@ -58,6 +103,8 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
|
|||
res = list->res;
|
||||
idx = res - &list->dev->resource[0];
|
||||
if (pci_assign_resource(list->dev, idx)) {
|
||||
if (fail_head && !pci_is_root_bus(list->dev->bus))
|
||||
add_to_failed_list(fail_head, list->dev, res);
|
||||
res->start = 0;
|
||||
res->end = 0;
|
||||
res->flags = 0;
|
||||
|
@ -572,19 +619,20 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_bus_size_bridges);
|
||||
|
||||
void __ref pci_bus_assign_resources(const struct pci_bus *bus)
|
||||
static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
||||
struct resource_list_x *fail_head)
|
||||
{
|
||||
struct pci_bus *b;
|
||||
struct pci_dev *dev;
|
||||
|
||||
pbus_assign_resources_sorted(bus);
|
||||
pbus_assign_resources_sorted(bus, fail_head);
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
b = dev->subordinate;
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
pci_bus_assign_resources(b);
|
||||
__pci_bus_assign_resources(b, fail_head);
|
||||
|
||||
switch (dev->class >> 8) {
|
||||
case PCI_CLASS_BRIDGE_PCI:
|
||||
|
@ -602,6 +650,11 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __ref pci_bus_assign_resources(const struct pci_bus *bus)
|
||||
{
|
||||
__pci_bus_assign_resources(bus, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_bus_assign_resources);
|
||||
|
||||
static void pci_bridge_release_resources(struct pci_bus *bus,
|
||||
|
|
Loading…
Reference in New Issue