mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
PCI: Pass bridge window to pci_bus_release_bridge_resources()
pci_bus_release_bridge_resources() takes type, which is converted into a bridge window resource in pci_bridge_release_resources(). Find out the correct bridge window for resource whose assignment failed. Pass that bridge window to pci_bus_release_bridge_resources() instead of passing the type. When recursing to subordinate, check which bridge windows have to be released and recurse for each. For now, use pbus_select_window_for_type() instead of pbus_select_window() because non-bridge window resources still have their flags reset which destroys the type information from the struct resource. The struct pci_dev_resource holds a copy of the flags which are used instead. 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-24-ilpo.jarvinen@linux.intel.com
This commit is contained in:
parent
ebbebd8873
commit
159fbfd041
|
|
@ -1800,51 +1800,24 @@ static void __pci_bridge_assign_resources(const struct pci_dev *bridge,
|
|||
}
|
||||
|
||||
static void pci_bridge_release_resources(struct pci_bus *bus,
|
||||
unsigned long type)
|
||||
struct resource *b_win)
|
||||
{
|
||||
struct pci_dev *dev = bus->self;
|
||||
struct resource *r;
|
||||
struct resource *b_res;
|
||||
int idx, ret;
|
||||
|
||||
b_res = &dev->resource[PCI_BRIDGE_RESOURCES];
|
||||
|
||||
/*
|
||||
* 1. If IO port assignment fails, release bridge IO port.
|
||||
* 2. If non pref MMIO assignment fails, release bridge nonpref MMIO.
|
||||
* 3. If 64bit pref MMIO assignment fails, and bridge pref is 64bit,
|
||||
* release bridge pref MMIO.
|
||||
* 4. If pref MMIO assignment fails, and bridge pref is 32bit,
|
||||
* release bridge pref MMIO.
|
||||
* 5. If pref MMIO assignment fails, and bridge pref is not
|
||||
* assigned, release bridge nonpref MMIO.
|
||||
*/
|
||||
if (type & IORESOURCE_IO)
|
||||
idx = 0;
|
||||
else if (!(type & IORESOURCE_PREFETCH))
|
||||
idx = 1;
|
||||
else if ((type & IORESOURCE_MEM_64) &&
|
||||
(b_res[2].flags & IORESOURCE_MEM_64))
|
||||
idx = 2;
|
||||
else if (!(b_res[2].flags & IORESOURCE_MEM_64) &&
|
||||
(b_res[2].flags & IORESOURCE_PREFETCH))
|
||||
idx = 2;
|
||||
else
|
||||
idx = 1;
|
||||
|
||||
r = &b_res[idx];
|
||||
|
||||
if (!r->parent)
|
||||
if (!b_win->parent)
|
||||
return;
|
||||
|
||||
/* If there are children, release them all */
|
||||
release_child_resources(r);
|
||||
idx = pci_resource_num(dev, b_win);
|
||||
|
||||
ret = pci_release_resource(dev, PCI_BRIDGE_RESOURCES + idx);
|
||||
/* If there are children, release them all */
|
||||
release_child_resources(b_win);
|
||||
|
||||
ret = pci_release_resource(dev, idx);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
pci_setup_one_bridge_window(dev, PCI_BRIDGE_RESOURCES + idx);
|
||||
pci_setup_one_bridge_window(dev, idx);
|
||||
}
|
||||
|
||||
enum release_type {
|
||||
|
|
@ -1857,7 +1830,7 @@ enum release_type {
|
|||
* a larger window later.
|
||||
*/
|
||||
static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
||||
unsigned long type,
|
||||
struct resource *b_win,
|
||||
enum release_type rel_type)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
|
@ -1865,6 +1838,8 @@ static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
|||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
struct pci_bus *b = dev->subordinate;
|
||||
struct resource *res;
|
||||
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
|
|
@ -1873,9 +1848,15 @@ static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
|||
if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
||||
continue;
|
||||
|
||||
if (rel_type == whole_subtree)
|
||||
pci_bus_release_bridge_resources(b, type,
|
||||
whole_subtree);
|
||||
if (rel_type != whole_subtree)
|
||||
continue;
|
||||
|
||||
pci_bus_for_each_resource(b, res) {
|
||||
if (res->parent != b_win)
|
||||
continue;
|
||||
|
||||
pci_bus_release_bridge_resources(b, res, whole_subtree);
|
||||
}
|
||||
}
|
||||
|
||||
if (pci_is_root_bus(bus))
|
||||
|
|
@ -1885,7 +1866,7 @@ static void pci_bus_release_bridge_resources(struct pci_bus *bus,
|
|||
return;
|
||||
|
||||
if ((rel_type == whole_subtree) || is_leaf_bridge)
|
||||
pci_bridge_release_resources(bus, type);
|
||||
pci_bridge_release_resources(bus, b_win);
|
||||
}
|
||||
|
||||
static void pci_bus_dump_res(struct pci_bus *bus)
|
||||
|
|
@ -2282,9 +2263,13 @@ static void pci_prepare_next_assign_round(struct list_head *fail_head,
|
|||
* enough to contain child device resources.
|
||||
*/
|
||||
list_for_each_entry(fail_res, fail_head, list) {
|
||||
pci_bus_release_bridge_resources(fail_res->dev->bus,
|
||||
fail_res->flags & PCI_RES_TYPE_MASK,
|
||||
rel_type);
|
||||
struct pci_bus *bus = fail_res->dev->bus;
|
||||
struct resource *b_win;
|
||||
|
||||
b_win = pbus_select_window_for_type(bus, fail_res->flags);
|
||||
if (!b_win)
|
||||
continue;
|
||||
pci_bus_release_bridge_resources(bus, b_win, rel_type);
|
||||
}
|
||||
|
||||
/* Restore size and flags */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user