PCI: Use pci_release_resource() instead of release_resource()

A few places in setup-bus.c call release_resource() directly and end up
duplicating functionality from pci_release_resource() such as parent check,
logging, and clearing the resource. Worse yet, the way the resource is
cleared is inconsistent between different sites.

Convert release_resource() calls into pci_release_resource() to remove code
duplication. This will also make the resource start, end, and flags
behavior consistent, i.e., start address is cleared, and only
IORESOURCE_UNSET is asserted for the resource.

While at it, eliminate the unnecessary initialization of idx variable in
pci_bridge_release_resources().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20250829131113.36754-9-ilpo.jarvinen@linux.intel.com
This commit is contained in:
Ilpo Järvinen 2025-08-29 16:10:57 +03:00 committed by Bjorn Helgaas
parent b15f45ab65
commit 3baeae3603
3 changed files with 23 additions and 36 deletions

View File

@ -473,8 +473,6 @@ static void __assign_resources_sorted(struct list_head *head,
struct pci_dev_resource *dev_res, *tmp_res, *dev_res2; struct pci_dev_resource *dev_res, *tmp_res, *dev_res2;
struct resource *res; struct resource *res;
struct pci_dev *dev; struct pci_dev *dev;
const char *res_name;
int idx;
unsigned long fail_type; unsigned long fail_type;
resource_size_t add_align, align; resource_size_t add_align, align;
@ -582,14 +580,7 @@ static void __assign_resources_sorted(struct list_head *head,
res = dev_res->res; res = dev_res->res;
dev = dev_res->dev; dev = dev_res->dev;
if (!res->parent) pci_release_resource(dev, pci_resource_num(dev, res));
continue;
idx = pci_resource_num(dev, res);
res_name = pci_resource_name(dev, idx);
pci_dbg(dev, "%s %pR: releasing\n", res_name, res);
release_resource(res);
restore_dev_resource(dev_res); restore_dev_resource(dev_res);
} }
/* Restore start/end/flags from saved list */ /* Restore start/end/flags from saved list */
@ -1732,7 +1723,7 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
struct resource *r; struct resource *r;
unsigned int old_flags; unsigned int old_flags;
struct resource *b_res; struct resource *b_res;
int idx = 1; int idx, ret;
b_res = &dev->resource[PCI_BRIDGE_RESOURCES]; b_res = &dev->resource[PCI_BRIDGE_RESOURCES];
@ -1766,21 +1757,18 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
/* If there are children, release them all */ /* If there are children, release them all */
release_child_resources(r); release_child_resources(r);
if (!release_resource(r)) {
type = old_flags = r->flags & PCI_RES_TYPE_MASK;
pci_info(dev, "resource %d %pR released\n",
PCI_BRIDGE_RESOURCES + idx, r);
/* Keep the old size */
resource_set_range(r, 0, resource_size(r));
r->flags = 0;
/* Avoiding touch the one without PREF */ type = old_flags = r->flags & PCI_RES_TYPE_MASK;
if (type & IORESOURCE_PREFETCH) ret = pci_release_resource(dev, PCI_BRIDGE_RESOURCES + idx);
type = IORESOURCE_PREFETCH; if (ret)
__pci_setup_bridge(bus, type); return;
/* For next child res under same bridge */
r->flags = old_flags; /* Avoiding touch the one without PREF */
} if (type & IORESOURCE_PREFETCH)
type = IORESOURCE_PREFETCH;
__pci_setup_bridge(bus, type);
/* For next child res under same bridge */
r->flags = old_flags;
} }
enum release_type { enum release_type {
@ -2425,7 +2413,6 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCE_END; for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCE_END;
i++) { i++) {
struct resource *res = &bridge->resource[i]; struct resource *res = &bridge->resource[i];
const char *res_name = pci_resource_name(bridge, i);
if ((res->flags ^ type) & PCI_RES_TYPE_MASK) if ((res->flags ^ type) & PCI_RES_TYPE_MASK)
continue; continue;
@ -2438,12 +2425,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
if (ret) if (ret)
goto cleanup; goto cleanup;
pci_info(bridge, "%s %pR: releasing\n", res_name, res); pci_release_resource(bridge, i);
if (res->parent)
release_resource(res);
res->start = 0;
res->end = 0;
break; break;
} }
if (i == PCI_BRIDGE_RESOURCE_END) if (i == PCI_BRIDGE_RESOURCE_END)

View File

@ -406,20 +406,25 @@ int pci_reassign_resource(struct pci_dev *dev, int resno,
return 0; return 0;
} }
void pci_release_resource(struct pci_dev *dev, int resno) int pci_release_resource(struct pci_dev *dev, int resno)
{ {
struct resource *res = pci_resource_n(dev, resno); struct resource *res = pci_resource_n(dev, resno);
const char *res_name = pci_resource_name(dev, resno); const char *res_name = pci_resource_name(dev, resno);
int ret;
if (!res->parent) if (!res->parent)
return; return 0;
pci_info(dev, "%s %pR: releasing\n", res_name, res); pci_info(dev, "%s %pR: releasing\n", res_name, res);
release_resource(res); ret = release_resource(res);
if (ret)
return ret;
res->end = resource_size(res) - 1; res->end = resource_size(res) - 1;
res->start = 0; res->start = 0;
res->flags |= IORESOURCE_UNSET; res->flags |= IORESOURCE_UNSET;
return 0;
} }
EXPORT_SYMBOL(pci_release_resource); EXPORT_SYMBOL(pci_release_resource);

View File

@ -1417,7 +1417,7 @@ void pci_reset_secondary_bus(struct pci_dev *dev);
void pcibios_reset_secondary_bus(struct pci_dev *dev); void pcibios_reset_secondary_bus(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno); void pci_update_resource(struct pci_dev *dev, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_assign_resource(struct pci_dev *dev, int i);
void pci_release_resource(struct pci_dev *dev, int resno); int pci_release_resource(struct pci_dev *dev, int resno);
static inline int pci_rebar_bytes_to_size(u64 bytes) static inline int pci_rebar_bytes_to_size(u64 bytes)
{ {
bytes = roundup_pow_of_two(bytes); bytes = roundup_pow_of_two(bytes);