Skip to content

Commit

Permalink
PCI: Perform reset_resource() and build fail list in sync
Browse files Browse the repository at this point in the history
Resetting a resource is problematic as it prevents attempting to allocate
the resource later, unless something in between restores the resource.
Similarly, if fail_head does not contain all resources that were reset,
those resources cannot be restored later.

The entire reset/restore cycle adds complexity and leaving resources in the
reset state causes issues to other code such as for checks done in
pci_enable_resources(). Take a small step towards not resetting resources
by delaying reset until the end of resource assignment and build failure
list (fail_head) in sync with the reset to avoid leaving behind resources
that cannot be restored (for the case where the caller provides fail_head
in the first place to allow restore somewhere in the callchain, as is not
all callers pass non-NULL fail_head).

Leave the Expansion ROM check temporarily in place while building the
failure list until an upcoming change that reworks optional resource
handling.

Ideally, whole resource reset could be removed but doing that in one step
would be non-tractable due to complexity of all related code.

Link: https://lore.kernel.org/r/20241216175632.4175-25-ilpo.jarvinen@linux.intel.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Xiaochun Lee <lixc17@lenovo.com>
  • Loading branch information
Ilpo Järvinen authored and Bjorn Helgaas committed Feb 18, 2025
1 parent e89df6d commit 96336ec
Showing 1 changed file with 29 additions and 6 deletions.
35 changes: 29 additions & 6 deletions drivers/pci/setup-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
Expand All @@ -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 &
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 96336ec

Please sign in to comment.