lkml.org 
[lkml]   [2010]   [Jan]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 02/11] pci: add failed_list to record failed one for pci_bus_assign_resources
    so later we can try to assign resource those failed devices again.

    -v2: store start, end, flags aside. so could keep res cleared when assign
    failed. and make following assignment of its children do not go wild
    -v3: update comments

    Signed-off-by: Yinghai Lu <yinghai@kernel.org>
    ---
    drivers/pci/setup-bus.c | 66 ++++++++++++++++++++++++++++++++++++++++++++---
    1 files changed, 62 insertions(+), 4 deletions(-)

    diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
    index 7a18428..fa9f4e2 100644
    --- a/drivers/pci/setup-bus.c
    +++ b/drivers/pci/setup-bus.c
    @@ -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,13 @@ 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)) {
    + /*
    + * device need to keep flags and size
    + * for next try
    + */
    + add_to_failed_list(fail_head, list->dev, res);
    + }
    res->start = 0;
    res->end = 0;
    res->flags = 0;
    @@ -572,19 +624,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 +655,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,
    --
    1.6.4.2


    \
     
     \ /
      Last update: 2010-01-16 12:15    [W:7.945 / U:1.440 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site