summaryrefslogtreecommitdiff
path: root/drivers/pci/setup-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r--drivers/pci/setup-bus.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ef1c82d2e58e..b0b146757943 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -252,9 +252,14 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
res = add_res->res;
dev = add_res->dev;
+ idx = pci_resource_num(dev, res);
- /* Skip resource that has been reset */
- if (!res->flags)
+ /*
+ * Skip resource that failed the earlier assignment and is
+ * not optional as it would just fail again.
+ */
+ if (!res->parent && resource_size(res) &&
+ !pci_resource_is_optional(dev, idx))
goto out;
/* Skip this resource if not found in head list */
@@ -267,7 +272,6 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
if (!found_match) /* Just skip */
continue;
- idx = pci_resource_num(dev, res);
res_name = pci_resource_name(dev, idx);
add_size = add_res->add_size;
align = add_res->min_align;
@@ -277,7 +281,6 @@ static void reassign_resources_sorted(struct list_head *realloc_head,
pci_dbg(dev,
"%s %pR: ignoring failure in optional allocation\n",
res_name, res);
- reset_resource(res);
}
} else {
res->flags |= add_res->flags &
@@ -332,7 +335,6 @@ static void assign_requested_resources_sorted(struct list_head *head,
0 /* don't care */,
0 /* don't care */);
}
- reset_resource(res);
}
}
}
@@ -518,13 +520,34 @@ static void __assign_resources_sorted(struct list_head *head,
requested_and_reassign:
/* Satisfy the must-have resource requests */
- assign_requested_resources_sorted(head, fail_head);
+ assign_requested_resources_sorted(head, NULL);
/* Try to satisfy any additional optional resource requests */
if (!list_empty(realloc_head))
reassign_resources_sorted(realloc_head, head);
out:
+ /* Reset any failed resource, cannot use fail_head as it can be NULL. */
+ list_for_each_entry(dev_res, head, list) {
+ res = dev_res->res;
+ dev = dev_res->dev;
+
+ if (res->parent)
+ continue;
+
+ /*
+ * If the failed resource is a ROM BAR and it will
+ * be enabled later, don't add it to the list.
+ */
+ if (fail_head && !pci_resource_is_disabled_rom(res, idx)) {
+ add_to_list(fail_head, dev, res,
+ 0 /* don't care */,
+ 0 /* don't care */);
+ }
+
+ reset_resource(res);
+ }
+
free_list(head);
}