sparclinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/24] PCI: Bridge window selection improvements
@ 2025-08-22 14:55 Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 01/24] m68k/PCI: Use pci_enable_resources() in pcibios_enable_device() Ilpo Järvinen
                   ` (25 more replies)
  0 siblings, 26 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński
  Cc: linux-kernel, Michał Winiarski, linuxppc-dev,
	Ilpo Järvinen

This series is based on top of the three resource fitting and
assignment algorithm fixes (v3).

PCI resource fitting and assignment code needs to find the bridge
window a resource belongs to in multiple places, yet, no common
function for that exists. Thus, each site has its own version of
the decision, each with their own corner cases, misbehaviors, and
some resulting in complex interfaces between internal functions.

This series tries to rectify the situation by adding two new functions
to select the bridge window. To support these functions, bridge windows
must always contain their type information in flags which requires
modifying the flags behavior for bridge window resources.

I've hit problems related to zeroed resource flags so many times by now
that I've already lost count which has highlighted over and over again
that clearing type information is not a good idea. As also proven by
some changes of this series, retaining the flags for bridge windows
ended up fixing existing issues (although kernel ended up recovering
from the worst problem graciously and the other just results in dormant
code).

This series only changes resource flags behavior for bridge windows.
The sensible direction is to make a similar change for the other
resources as well eventually but making that change involves more
uncertainty and is not strictly necessary yet. Driver code outside of
PCI core could have assumptions about the flags, whereas bridge windows
are mostly internal to PCI core code (or should be, sane endpoint
drivers shouldn't be messing with the bridge windows). Thus, limiting
the flags behavior changes to bridge windows for now is safer than
attempting full behavioral change in a single step.


I've tried to look out for any trouble that code under arch/ could
cause after the flags start to behave differently and therefore ended
up consolidating arch/ code to use pci_enable_resources(). My
impression is that strictly speaking only the MIPS code would break
similar to PCI core's copy of pci_enable_resources(), the others were
much more lax in checking so they'd likely keep working but
consolidation seemed still the best approach there as the enable checks
seemed diverging for no apparent reason.

Most sites are converted by this change. There are three known places
that are not yet converted:

  - fail_type based logic in __assign_resources_sorted():
    I'm expecting to cover this along with the resizable BAR
    changes as I need to change the fallback logic anyway (one
    of the motivators what got me started with this series,
    I need an easy way to acquire the bridge window during
    retries/fallbacks if maximum sized BARs do not fit, which
    is what this series provides).

  - Failure detection after BAR resize: Keeps using the type
    based heuristic for failure detection. It isn't very clear how
    to decide which assignment failures should be counted and which
    not. There could be pre-existing failures that keep happening
    that end up blocking BAR resize but that's no worse than behavior
    before this series. How to identify the relevant failures does
    not look straightforward given the current structures. This
    clearly needs more thought before coding any solution.

  - resource assignment itself: This is a very complex change
    due to bus and kernel resources abstractions and might not be
    realistic any time soon.

I'd have wanted to also get rid of pci_bridge_check_ranges() that
(re)adds type information which seemed now unnecessary. It turns out,
however, that root windows still require so it will have to wait for
now.

This change has been tested on a large number of machine I've access to
which come with heterogeneous PCI configurations. Some resources
retained their original addresses now also with pci=realloc because
this series fixed the unnecessary release(+assign) of those resources.
Other than that, nothing worth of note from that testing.


My test coverage is x86 centric unfortunately so I'd appreciate if
somebody with access to non-x86 archs takes the effort to test this
series.

Info for potential testers:

Usually, it's enough to gather lspci -vvv pre and post the series, and
use diff to see whether the resources remained the same and also check
that the same drivers are still bound to the devices to confirm that
devices got properly enabled (also shown by lspci -vvv). I normally
test both with and without pci=realloc. In case of a trouble, besides
lspci -vvv output, providing pre and post dmesg and /proc/iomem
contents would be helpful, please take the dmesg with dyndbg="file
drivers/pci/*.c +p" on the kernel cmdline.

Ilpo Järvinen (24):
  m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
  sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
  MIPS: PCI: Use pci_enable_resources()
  PCI: Move find_bus_resource_of_type() earlier
  PCI: Refactor find_bus_resource_of_type() logic checks
  PCI: Always claim bridge window before its setup
  PCI: Disable non-claimed bridge window
  PCI: Use pci_release_resource() instead of release_resource()
  PCI: Enable bridge even if bridge window fails to assign
  PCI: Preserve bridge window resource type flags
  PCI: Add defines for bridge window indexing
  PCI: Add bridge window selection functions
  PCI: Fix finding bridge window in pci_reassign_bridge_resources()
  PCI: Warn if bridge window cannot be released when resizing BAR
  PCI: Use pbus_select_window() during BAR resize
  PCI: Use pbus_select_window_for_type() during IO window sizing
  PCI: Rename resource variable from r to res
  PCI: Use pbus_select_window() in space available checker
  PCI: Use pbus_select_window_for_type() during mem window sizing
  PCI: Refactor distributing available memory to use loops
  PCI: Refactor remove_dev_resources() to use pbus_select_window()
  PCI: Add pci_setup_one_bridge_window()
  PCI: Pass bridge window to pci_bus_release_bridge_resources()
  PCI: Alter misleading recursion to pci_bus_release_bridge_resources()

 arch/m68k/kernel/pcibios.c   |  39 +-
 arch/mips/pci/pci-legacy.c   |  38 +-
 arch/sparc/kernel/leon_pci.c |  27 --
 arch/sparc/kernel/pci.c      |  27 --
 arch/sparc/kernel/pcic.c     |  27 --
 drivers/pci/bus.c            |   3 +
 drivers/pci/pci-sysfs.c      |  27 +-
 drivers/pci/pci.h            |   8 +-
 drivers/pci/probe.c          |  35 +-
 drivers/pci/setup-bus.c      | 798 ++++++++++++++++++-----------------
 drivers/pci/setup-res.c      |  46 +-
 include/linux/pci.h          |   5 +-
 12 files changed, 504 insertions(+), 576 deletions(-)


base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
prerequisite-patch-id: 801e8dd3aa9847d4945cb7d8958574a6006004ab
prerequisite-patch-id: 0233311f04e3ea013676b6cc00626410bbe11e41
prerequisite-patch-id: 9841faf37d56c1acf1167559613e862ef62e509d
-- 
2.39.5


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/24] m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 02/24] sparc/PCI: Remove pcibios_enable_device() as they do nothing extra Ilpo Järvinen
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

m68k has a resource enable (check) loop in its pcibios_enable_device()
which for some reason differs from pci_enable_resources(). This could
lead to inconsistencies in behavior, especially now as
pci_enable_resources() and the bridge window resource flags behavior
are going to be altered by upcoming changes.

The check for !r->start && r->end is already covered by the more
generic checks done in pci_enable_resources().

The entire pcibios_enable_device() suspiciously looks copy-paste from
some other arch as also indicated by the preceding comment. However,
it also enables PCI_COMMAND_IO | PCI_COMMAND_MEMORY always for bridges,
it is not clear why that is being done as the commit e93a6bbeb5a5
("m68k: common PCI support definitions and code") introducing this
code states: "Nothing specific to any PCI implementation in any m68k
class CPU hardware yet".

Replace the resource enable loop with a call to pci_enable_resources()
and adjust the Command Register afterwards as it's unclear if that is
necessary or not so keep it for now.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 arch/m68k/kernel/pcibios.c | 39 +++++++++++---------------------------
 1 file changed, 11 insertions(+), 28 deletions(-)

diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c
index 9504eb19d73a..e6ab3f9ff5d8 100644
--- a/arch/m68k/kernel/pcibios.c
+++ b/arch/m68k/kernel/pcibios.c
@@ -44,41 +44,24 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
  */
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	struct resource *r;
 	u16 cmd, newcmd;
-	int idx;
+	int ret;
 
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	newcmd = cmd;
-
-	for (idx = 0; idx < 6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1 << idx)))
-			continue;
-
-		r = dev->resource + idx;
-		if (!r->start && r->end) {
-			pr_err("PCI: Device %s not available because of resource collisions\n",
-				pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			newcmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			newcmd |= PCI_COMMAND_MEMORY;
-	}
+	ret = pci_enable_resources(dev, mask);
+	if (ret < 0)
+		return ret;
 
 	/*
 	 * Bridges (eg, cardbus bridges) need to be fully enabled
 	 */
-	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 		newcmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
-
-	if (newcmd != cmd) {
-		pr_info("PCI: enabling device %s (0x%04x -> 0x%04x)\n",
-			pci_name(dev), cmd, newcmd);
-		pci_write_config_word(dev, PCI_COMMAND, newcmd);
+		if (newcmd != cmd) {
+			pr_info("PCI: enabling bridge %s (0x%04x -> 0x%04x)\n",
+				pci_name(dev), cmd, newcmd);
+			pci_write_config_word(dev, PCI_COMMAND, newcmd);
+		}
 	}
 	return 0;
 }
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/24] sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 01/24] m68k/PCI: Use pci_enable_resources() in pcibios_enable_device() Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 03/24] MIPS: PCI: Use pci_enable_resources() Ilpo Järvinen
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Under arch/sparc/ there are multiple copies of pcibios_enable_device()
but none of those seem to do anything extra beyond what
pci_enable_resources() is supposed to do. These functions could lead to
inconsistencies in behavior, especially now as pci_enable_resources()
and the bridge window resource flags behavior are going to be altered
by upcoming changes.

Remove all pcibios_enable_device() from arch/sparc/ so that PCI core
can simply call into pci_enable_resources() instead using it's __weak
version of pcibios_enable_device().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 arch/sparc/kernel/leon_pci.c | 27 ---------------------------
 arch/sparc/kernel/pci.c      | 27 ---------------------------
 arch/sparc/kernel/pcic.c     | 27 ---------------------------
 3 files changed, 81 deletions(-)

diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 8de6646e9ce8..10934dfa987a 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -60,30 +60,3 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 	pci_assign_unassigned_resources();
 	pci_bus_add_devices(root_bus);
 }
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	struct resource *res;
-	u16 cmd, oldcmd;
-	int i;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	oldcmd = cmd;
-
-	pci_dev_for_each_resource(dev, res, i) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<i)))
-			continue;
-
-		if (res->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (res->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	if (cmd != oldcmd) {
-		pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index ddac216a2aff..a9448088e762 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -722,33 +722,6 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
 	return bus;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	struct resource *res;
-	u16 cmd, oldcmd;
-	int i;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	oldcmd = cmd;
-
-	pci_dev_for_each_resource(dev, res, i) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<i)))
-			continue;
-
-		if (res->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (res->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	if (cmd != oldcmd) {
-		pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
 /* Platform support for /proc/bus/pci/X/Y mmap()s. */
 int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)
 {
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 25fe0a061732..3d54ad5656a4 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -641,33 +641,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 	}
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	struct resource *res;
-	u16 cmd, oldcmd;
-	int i;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	oldcmd = cmd;
-
-	pci_dev_for_each_resource(dev, res, i) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<i)))
-			continue;
-
-		if (res->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (res->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	if (cmd != oldcmd) {
-		pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
 /* Makes compiler happy */
 static volatile int pcic_timer_dummy;
 
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/24] MIPS: PCI: Use pci_enable_resources()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 01/24] m68k/PCI: Use pci_enable_resources() in pcibios_enable_device() Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 02/24] sparc/PCI: Remove pcibios_enable_device() as they do nothing extra Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-28  6:57   ` Thomas Bogendoerfer
  2025-08-22 14:55 ` [PATCH 04/24] PCI: Move find_bus_resource_of_type() earlier Ilpo Järvinen
                   ` (22 subsequent siblings)
  25 siblings, 1 reply; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

pci-legacy.c under MIPS has a copy of pci_enable_resources() named as
pcibios_enable_resources(). Having own copy of same functionality could
lead to inconsistencies in behavior, especially now as
pci_enable_resources() and the bridge window resource flags behavior
are going to be altered by upcoming changes.

The check for !r->start && r->end is already covered by the more
generic checks done in pci_enable_resources().

Call pci_enable_resources() from MIPS's pcibios_enable_device() and
remove pcibios_enable_resources().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 arch/mips/pci/pci-legacy.c | 38 ++------------------------------------
 1 file changed, 2 insertions(+), 36 deletions(-)

diff --git a/arch/mips/pci/pci-legacy.c b/arch/mips/pci/pci-legacy.c
index 66898fd182dc..d04b7c1294b6 100644
--- a/arch/mips/pci/pci-legacy.c
+++ b/arch/mips/pci/pci-legacy.c
@@ -249,45 +249,11 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-static int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	pci_dev_for_each_resource(dev, r, idx) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<idx)))
-			continue;
-
-		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-			continue;
-		if ((idx == PCI_ROM_RESOURCE) &&
-				(!(r->flags & IORESOURCE_ROM_ENABLE)))
-			continue;
-		if (!r->start && r->end) {
-			pci_err(dev,
-				"can't enable device: resource collisions\n");
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		pci_info(dev, "enabling device (%04x -> %04x)\n", old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	int err = pcibios_enable_resources(dev, mask);
+	int err;
 
+	err = pci_enable_resources(dev, mask);
 	if (err < 0)
 		return err;
 
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/24] PCI: Move find_bus_resource_of_type() earlier
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (2 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 03/24] MIPS: PCI: Use pci_enable_resources() Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 05/24] PCI: Refactor find_bus_resource_of_type() logic checks Ilpo Järvinen
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Move find_bus_resource_of_type() earlier in setup-bus.c to be able to
call it in upcoming changes.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 56 ++++++++++++++++++++---------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index def29506700e..4097d8703b8f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -140,6 +140,34 @@ static void restore_dev_resource(struct pci_dev_resource *dev_res)
 	res->flags = dev_res->flags;
 }
 
+/*
+ * Helper function for sizing routines.  Assigned resources have non-NULL
+ * parent resource.
+ *
+ * Return first unassigned resource of the correct type.  If there is none,
+ * return first assigned resource of the correct type.  If none of the
+ * above, return NULL.
+ *
+ * Returning an assigned resource of the correct type allows the caller to
+ * distinguish between already assigned and no resource of the correct type.
+ */
+static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
+						  unsigned long type_mask,
+						  unsigned long type)
+{
+	struct resource *r, *r_assigned = NULL;
+
+	pci_bus_for_each_resource(bus, r) {
+		if (r == &ioport_resource || r == &iomem_resource)
+			continue;
+		if (r && (r->flags & type_mask) == type && !r->parent)
+			return r;
+		if (r && (r->flags & type_mask) == type && !r_assigned)
+			r_assigned = r;
+	}
+	return r_assigned;
+}
+
 static bool pdev_resources_assignable(struct pci_dev *dev)
 {
 	u16 class = dev->class >> 8, command;
@@ -876,34 +904,6 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
 	}
 }
 
-/*
- * Helper function for sizing routines.  Assigned resources have non-NULL
- * parent resource.
- *
- * Return first unassigned resource of the correct type.  If there is none,
- * return first assigned resource of the correct type.  If none of the
- * above, return NULL.
- *
- * Returning an assigned resource of the correct type allows the caller to
- * distinguish between already assigned and no resource of the correct type.
- */
-static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
-						  unsigned long type_mask,
-						  unsigned long type)
-{
-	struct resource *r, *r_assigned = NULL;
-
-	pci_bus_for_each_resource(bus, r) {
-		if (r == &ioport_resource || r == &iomem_resource)
-			continue;
-		if (r && (r->flags & type_mask) == type && !r->parent)
-			return r;
-		if (r && (r->flags & type_mask) == type && !r_assigned)
-			r_assigned = r;
-	}
-	return r_assigned;
-}
-
 static resource_size_t calculate_iosize(resource_size_t size,
 					resource_size_t min_size,
 					resource_size_t size1,
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/24] PCI: Refactor find_bus_resource_of_type() logic checks
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (3 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 04/24] PCI: Move find_bus_resource_of_type() earlier Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 06/24] PCI: Always claim bridge window before its setup Ilpo Järvinen
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

The logic checks can be simplified in find_bus_resource_of_type() by
reordering them.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 4097d8703b8f..c5fc4e2825be 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -158,11 +158,15 @@ static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
 	struct resource *r, *r_assigned = NULL;
 
 	pci_bus_for_each_resource(bus, r) {
-		if (r == &ioport_resource || r == &iomem_resource)
+		if (!r || r == &ioport_resource || r == &iomem_resource)
 			continue;
-		if (r && (r->flags & type_mask) == type && !r->parent)
+
+		if ((r->flags & type_mask) != type)
+			continue;
+
+		if (!r->parent)
 			return r;
-		if (r && (r->flags & type_mask) == type && !r_assigned)
+		if (!r_assigned)
 			r_assigned = r;
 	}
 	return r_assigned;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/24] PCI: Always claim bridge window before its setup
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (4 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 05/24] PCI: Refactor find_bus_resource_of_type() logic checks Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 07/24] PCI: Disable non-claimed bridge window Ilpo Järvinen
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

When the claim of a resource fails for the full range in
pci_claim_bridge_resource(), clipping the resource to a smaller size is
attempted. If the clipping successful, the new bridge window is
programmed and only as the last step the code attempts to claim the
resource again. The order of the last two steps is slightly illogical
and inconsistent with the assignment call chains.

If claiming the bridge window after clipping fails, the bridge window
that was setup is left in place.

Rework the logic such that the bridge window is claimed before calling
the relevant bridge setup function. This make the behavior consistent
with resource fitting call chains that always assign the bridge window
before programming it.

If claiming the bridge window fails, the clipped bridge window is no
longer setup but pci_claim_bridge_resource() returns without writing
the bridge window at all.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index c5fc4e2825be..b477f68b236c 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -857,9 +857,16 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
 	if ((bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
 		return 0;
 
+	if (i > PCI_BRIDGE_PREF_MEM_WINDOW)
+		return -EINVAL;
+
+	/* Try to clip the resource and claim the smaller window */
 	if (!pci_bus_clip_resource(bridge, i))
 		return -EINVAL;	/* Clipping didn't change anything */
 
+	if (!pci_claim_resource(bridge, i))
+		return -EINVAL;
+
 	switch (i) {
 	case PCI_BRIDGE_IO_WINDOW:
 		pci_setup_bridge_io(bridge);
@@ -874,10 +881,7 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
 		return -EINVAL;
 	}
 
-	if (pci_claim_resource(bridge, i) == 0)
-		return 0;	/* Claimed a smaller window */
-
-	return -EINVAL;
+	return 0;
 }
 
 /*
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/24] PCI: Disable non-claimed bridge window
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (5 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 06/24] PCI: Always claim bridge window before its setup Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 08/24] PCI: Use pci_release_resource() instead of release_resource() Ilpo Järvinen
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

If clipping or claiming the bridge window fails, the bridge window is
left into a state that does not match with the kernel's view on what
the bridge window is.

Disable the bridge window by writing the magic disable value into the
Base and Limit Registers if clipping or claiming failed. To detect if
claiming the resource was successful, add res->parent checks into the
bridge setup functions.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index b477f68b236c..6bdc1af887da 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -660,7 +660,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 	res = bus->resource[0];
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_IO) {
+	if (res->parent && res->flags & IORESOURCE_IO) {
 		/*
 		 * The IO resource is allocated a range twice as large as it
 		 * would normally need.  This allows us to set both IO regs.
@@ -674,7 +674,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 	res = bus->resource[1];
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_IO) {
+	if (res->parent && res->flags & IORESOURCE_IO) {
 		pci_info(bridge, "  bridge window %pR\n", res);
 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
 					region.start);
@@ -684,7 +684,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 	res = bus->resource[2];
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_MEM) {
+	if (res->parent && res->flags & IORESOURCE_MEM) {
 		pci_info(bridge, "  bridge window %pR\n", res);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
 					region.start);
@@ -694,7 +694,7 @@ void pci_setup_cardbus(struct pci_bus *bus)
 
 	res = bus->resource[3];
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_MEM) {
+	if (res->parent && res->flags & IORESOURCE_MEM) {
 		pci_info(bridge, "  bridge window %pR\n", res);
 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
 					region.start);
@@ -735,7 +735,7 @@ static void pci_setup_bridge_io(struct pci_dev *bridge)
 	res = &bridge->resource[PCI_BRIDGE_IO_WINDOW];
 	res_name = pci_resource_name(bridge, PCI_BRIDGE_IO_WINDOW);
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_IO) {
+	if (res->parent && res->flags & IORESOURCE_IO) {
 		pci_read_config_word(bridge, PCI_IO_BASE, &l);
 		io_base_lo = (region.start >> 8) & io_mask;
 		io_limit_lo = (region.end >> 8) & io_mask;
@@ -767,7 +767,7 @@ static void pci_setup_bridge_mmio(struct pci_dev *bridge)
 	res = &bridge->resource[PCI_BRIDGE_MEM_WINDOW];
 	res_name = pci_resource_name(bridge, PCI_BRIDGE_MEM_WINDOW);
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_MEM) {
+	if (res->parent && res->flags & IORESOURCE_MEM) {
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
 		pci_info(bridge, "  %s %pR\n", res_name, res);
@@ -796,7 +796,7 @@ static void pci_setup_bridge_mmio_pref(struct pci_dev *bridge)
 	res = &bridge->resource[PCI_BRIDGE_PREF_MEM_WINDOW];
 	res_name = pci_resource_name(bridge, PCI_BRIDGE_PREF_MEM_WINDOW);
 	pcibios_resource_to_bus(bridge->bus, &region, res);
-	if (res->flags & IORESOURCE_PREFETCH) {
+	if (res->parent && res->flags & IORESOURCE_PREFETCH) {
 		l = (region.start >> 16) & 0xfff0;
 		l |= region.end & 0xfff00000;
 		if (res->flags & IORESOURCE_MEM_64) {
@@ -848,6 +848,8 @@ static void pci_setup_bridge(struct pci_bus *bus)
 
 int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
 {
+	int ret = -EINVAL;
+
 	if (i < PCI_BRIDGE_RESOURCES || i > PCI_BRIDGE_RESOURCE_END)
 		return 0;
 
@@ -861,11 +863,8 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
 		return -EINVAL;
 
 	/* Try to clip the resource and claim the smaller window */
-	if (!pci_bus_clip_resource(bridge, i))
-		return -EINVAL;	/* Clipping didn't change anything */
-
-	if (!pci_claim_resource(bridge, i))
-		return -EINVAL;
+	if (pci_bus_clip_resource(bridge, i))
+		ret = pci_claim_resource(bridge, i);
 
 	switch (i) {
 	case PCI_BRIDGE_IO_WINDOW:
@@ -881,7 +880,7 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
 		return -EINVAL;
 	}
 
-	return 0;
+	return ret;
 }
 
 /*
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/24] PCI: Use pci_release_resource() instead of release_resource()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (6 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 07/24] PCI: Disable non-claimed bridge window Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 09/24] PCI: Enable bridge even if bridge window fails to assign Ilpo Järvinen
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

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. The will also make the resource start, end, and flags
behavior consistent, ie., 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>
---
 drivers/pci/setup-bus.c | 46 +++++++++++++----------------------------
 drivers/pci/setup-res.c | 11 +++++++---
 include/linux/pci.h     |  2 +-
 3 files changed, 23 insertions(+), 36 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6bdc1af887da..b62465665abc 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -473,8 +473,6 @@ static void __assign_resources_sorted(struct list_head *head,
 	struct pci_dev_resource *dev_res, *tmp_res, *dev_res2;
 	struct resource *res;
 	struct pci_dev *dev;
-	const char *res_name;
-	int idx;
 	unsigned long fail_type;
 	resource_size_t add_align, align;
 
@@ -582,14 +580,7 @@ static void __assign_resources_sorted(struct list_head *head,
 		res = dev_res->res;
 		dev = dev_res->dev;
 
-		if (!res->parent)
-			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);
+		pci_release_resource(dev, pci_resource_num(dev, res));
 		restore_dev_resource(dev_res);
 	}
 	/* Restore start/end/flags from saved list */
@@ -1732,7 +1723,7 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
 	struct resource *r;
 	unsigned int old_flags;
 	struct resource *b_res;
-	int idx = 1;
+	int idx, ret;
 
 	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 */
 	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 */
-		if (type & IORESOURCE_PREFETCH)
-			type = IORESOURCE_PREFETCH;
-		__pci_setup_bridge(bus, type);
-		/* For next child res under same bridge */
-		r->flags = old_flags;
-	}
+	type = old_flags = r->flags & PCI_RES_TYPE_MASK;
+	ret = pci_release_resource(dev, PCI_BRIDGE_RESOURCES + idx);
+	if (ret)
+		return;
+
+	/* 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 {
@@ -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;
 		     i++) {
 			struct resource *res = &bridge->resource[i];
-			const char *res_name = pci_resource_name(bridge, i);
 
 			if ((res->flags ^ type) & PCI_RES_TYPE_MASK)
 				continue;
@@ -2438,12 +2425,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
 			if (ret)
 				goto cleanup;
 
-			pci_info(bridge, "%s %pR: releasing\n", res_name, res);
-
-			if (res->parent)
-				release_resource(res);
-			res->start = 0;
-			res->end = 0;
+			pci_release_resource(bridge, i);
 			break;
 		}
 		if (i == PCI_BRIDGE_RESOURCE_END)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index d2b3ed51e880..0468c058b598 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -406,20 +406,25 @@ int pci_reassign_resource(struct pci_dev *dev, int resno,
 	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);
 	const char *res_name = pci_resource_name(dev, resno);
+	int ret;
 
 	if (!res->parent)
-		return;
+		return 0;
 
 	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->start = 0;
 	res->flags |= IORESOURCE_UNSET;
+
+	return 0;
 }
 EXPORT_SYMBOL(pci_release_resource);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 59876de13860..275df4058767 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1417,7 +1417,7 @@ void pci_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);
 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)
 {
 	bytes = roundup_pow_of_two(bytes);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/24] PCI: Enable bridge even if bridge window fails to assign
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (7 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 08/24] PCI: Use pci_release_resource() instead of release_resource() Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 10/24] PCI: Preserve bridge window resource type flags Ilpo Järvinen
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

A normal PCI bridge has multiple bridge windows and not all of them are
always required by devices underneath the bridge. If Root Port or
bridge does not have a device underneath, no bridge windows get
assigned. Yet, pci_enable_resources() is set to fail indiscriminantly
on any resource assignment failure if the resource is not known to be
optional.

In practice, the code in pci_enable_resources() is currently largely
dormant. The kernel sets resource flags to zero for any unused bridge
window and resets flags to zero in case of an resource assignment
failure, which short-circuits pci_enable_resources() because of this
check:

	if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
		continue;

However, an upcoming change to resource flags will alter how bridge
window flags resource flags behave activating these long dormants
checks in pci_enable_resources().

While complex logic could be built to selectively enable a bridge only
under some conditions, a few versions of such logic were tried during
development of this change and none of them worked satisfactorily.
Thus, I just gave up and decided to enable any bridge regardless of the
bridge windows as there seems to be no clear benefit from not enabling
it but a major downside as pcieport will not be probed for the bridge
if it's not enabled.

Therefore, change pci_enable_resources() to not check if bridge window
resources remain unassigned. Resource assignment failures are pretty
noisy already so there is no need to log that for bridge windows in
pci_enable_resources().

Ignoring bridge window failures hopefully prevents an obvious sources
of regressions when the upcoming change that no longer clears resource
flags for bridge windows is enacted. I've hit this problem even during
my own testing on multiple occassions so I expect it to be a quite
common problem.

This can always be revisited later if somebody thinks the enable check
for bridges is not strict enough, but expect a mind-boggling number of
regressions from such a change.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-res.c | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 0468c058b598..4e0e60256f04 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -527,22 +527,26 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
 		if (pci_resource_is_optional(dev, i))
 			continue;
 
-		if (r->flags & IORESOURCE_UNSET) {
-			pci_err(dev, "%s %pR: not assigned; can't enable device\n",
-				r_name, r);
-			return -EINVAL;
+		if (i < PCI_BRIDGE_RESOURCES) {
+			if (r->flags & IORESOURCE_UNSET) {
+				pci_err(dev, "%s %pR: not assigned; can't enable device\n",
+					r_name, r);
+				return -EINVAL;
+			}
+
+			if (!r->parent) {
+				pci_err(dev, "%s %pR: not claimed; can't enable device\n",
+					r_name, r);
+				return -EINVAL;
+			}
 		}
 
-		if (!r->parent) {
-			pci_err(dev, "%s %pR: not claimed; can't enable device\n",
-				r_name, r);
-			return -EINVAL;
+		if (r->parent) {
+			if (r->flags & IORESOURCE_IO)
+				cmd |= PCI_COMMAND_IO;
+			if (r->flags & IORESOURCE_MEM)
+				cmd |= PCI_COMMAND_MEMORY;
 		}
-
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
 	}
 
 	if (cmd != old_cmd) {
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/24] PCI: Preserve bridge window resource type flags
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (8 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 09/24] PCI: Enable bridge even if bridge window fails to assign Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 11/24] PCI: Add defines for bridge window indexing Ilpo Järvinen
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

When a bridge window is found unused or fails to assign, the flags of
the associated resource are cleared. Clearing flags is problematic as
it also removes the type information of the resource which is needed
later.

Thus, always preserve the bridge window type flags and use
IORESOURCE_UNSET and IORESOURCE_DISABLED to indicate the status of the
bridge window. Also, when initializing resources, make sure all valid
bridge windows do get their type flags set.

Change various places that relied on resource flags being cleared to
check for IORESOURCE_UNSET and IORESOURCE_DISABLED to allow bridge
window resource to retain their type flags. Add
pdev_resource_assignable() and pdev_resource_should_fit() helpers to
filter out disabled bridge windows during resource fitting, the latter
combines more common checks into the helper.

When reading the bridge windows from the registers, instead of leaving
the resource flags cleared for bridge windows that are not enabled,
always setup the flags and set IORESOURCE_UNSET | IORESOURCE_DISABLED
as needed.

When resource fitting or assignment fails for a bridge window resource,
or the bridge window is not needed, mark the resource with
IORESOURCE_UNSET or IORESOURCE_DISABLED, respectively.

Use dummy zero resource in resource_show() for backwards compatibility
as lspci will otherwise misrepresent disabled bridge windows.

This change ended up fixing an issue which too highlights the
importance of keeping the resource type flags intact:

At the end of __assign_resources_sorted(), reset_resource() is called,
previously clearing the flags. Later, pci_prepare_next_assign_round()
attempted to release bridge resources using
pci_bus_release_bridge_resources() that calls into
pci_bridge_release_resources() that assumes type flags are still
present. As type flags were cleared, IORESOURCE_MEM_64 was not set
leading to resources under an incorrect bridge window to be released
(idx = 1 instead of idx = 2). While the assignments performed later
covered this problem so that the wrongly released resources got
assigned in the end, it was still causing extra release+assign pairs.

There are other reasons why the resource flags should be retained in
upcoming changes too.

Removing the flag reset for non-bridge window resource is left as
future work, in part because it has a much higher regression potential
due to pci_enable_resources() that will start to work also for those
resources then and due to what endpoint drivers might assume about
resources.

Despite the Fixes tag, backporting this (at least any time soon) is
highly discouraged. The issue fixed is borderline cosmetic as the later
assignments normally cover the problem entirely. Also there might be
non-obvious dependencies.

Fixes: 5b28541552ef ("PCI: Restrict 64-bit prefetchable bridge windows to 64-bit resources")
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/bus.c       |  3 ++
 drivers/pci/pci-sysfs.c |  7 ++++
 drivers/pci/probe.c     | 25 +++++++++---
 drivers/pci/setup-bus.c | 88 ++++++++++++++++++++++++++---------------
 drivers/pci/setup-res.c |  3 ++
 5 files changed, 89 insertions(+), 37 deletions(-)

diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index b77fd30bbfd9..58b5388423ee 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -204,6 +204,9 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
 		if (!r)
 			continue;
 
+		if (r->flags & (IORESOURCE_UNSET|IORESOURCE_DISABLED))
+			continue;
+
 		/* type_mask must match */
 		if ((res->flags ^ r->flags) & type_mask)
 			continue;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5eea14c1f7f5..162a5241c7f7 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -177,6 +177,13 @@ static ssize_t resource_show(struct device *dev, struct device_attribute *attr,
 
 	for (i = 0; i < max; i++) {
 		struct resource *res =  &pci_dev->resource[i];
+		struct resource zerores = {};
+
+		/* For backwards compatibility */
+		if (i >= PCI_BRIDGE_RESOURCES && i <= PCI_BRIDGE_RESOURCE_END &&
+		    res->flags & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
+			res = &zerores;
+
 		pci_resource_to_user(pci_dev, i, res, &start, &end);
 		len += sysfs_emit_at(buf, len, "0x%016llx 0x%016llx 0x%016llx\n",
 				     (unsigned long long)start,
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f41128f91ca7..f31d27c7708a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -419,13 +419,17 @@ static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res,
 		limit |= ((unsigned long) io_limit_hi << 16);
 	}
 
+	res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+
 	if (base <= limit) {
-		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
 		region.start = base;
 		region.end = limit + io_granularity - 1;
 		pcibios_bus_to_resource(dev->bus, res, &region);
 		if (log)
 			pci_info(dev, "  bridge window %pR\n", res);
+	} else {
+		resource_set_range(res, 0, 0);
+		res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
 	}
 }
 
@@ -440,13 +444,18 @@ static void pci_read_bridge_mmio(struct pci_dev *dev, struct resource *res,
 	pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
 	base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
 	limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+
+	res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
+
 	if (base <= limit) {
-		res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
 		region.start = base;
 		region.end = limit + 0xfffff;
 		pcibios_bus_to_resource(dev->bus, res, &region);
 		if (log)
 			pci_info(dev, "  bridge window %pR\n", res);
+	} else {
+		resource_set_range(res, 0, 0);
+		res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
 	}
 }
 
@@ -489,16 +498,20 @@ static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res,
 		return;
 	}
 
+	res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) | IORESOURCE_MEM |
+		     IORESOURCE_PREFETCH;
+	if (res->flags & PCI_PREF_RANGE_TYPE_64)
+		res->flags |= IORESOURCE_MEM_64;
+
 	if (base <= limit) {
-		res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
-					 IORESOURCE_MEM | IORESOURCE_PREFETCH;
-		if (res->flags & PCI_PREF_RANGE_TYPE_64)
-			res->flags |= IORESOURCE_MEM_64;
 		region.start = base;
 		region.end = limit + 0xfffff;
 		pcibios_bus_to_resource(dev->bus, res, &region);
 		if (log)
 			pci_info(dev, "  bridge window %pR\n", res);
+	} else {
+		resource_set_range(res, 0, 0);
+		res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
 	}
 }
 
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index b62465665abc..223f0e025407 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -190,6 +190,31 @@ static bool pdev_resources_assignable(struct pci_dev *dev)
 	return true;
 }
 
+static bool pdev_resource_assignable(struct pci_dev *dev, struct resource *res)
+{
+	int idx = pci_resource_num(dev, res);
+
+	if (!res->flags)
+		return false;
+
+	if (idx >= PCI_BRIDGE_RESOURCES && idx <= PCI_BRIDGE_RESOURCE_END &&
+	    res->flags & IORESOURCE_DISABLED)
+		return false;
+
+	return true;
+}
+
+static bool pdev_resource_should_fit(struct pci_dev *dev, struct resource *res)
+{
+	if (res->parent)
+		return false;
+
+	if (res->flags & IORESOURCE_PCI_FIXED)
+		return false;
+
+	return pdev_resource_assignable(dev, res);
+}
+
 /* Sort resources by alignment */
 static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
 {
@@ -205,10 +230,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)
 		resource_size_t r_align;
 		struct list_head *n;
 
-		if (r->flags & IORESOURCE_PCI_FIXED)
-			continue;
-
-		if (!(r->flags) || r->parent)
+		if (!pdev_resource_should_fit(dev, r))
 			continue;
 
 		r_align = pci_resource_alignment(dev, r);
@@ -257,8 +279,15 @@ bool pci_resource_is_optional(const struct pci_dev *dev, int resno)
 	return false;
 }
 
-static inline void reset_resource(struct resource *res)
+static inline void reset_resource(struct pci_dev *dev, struct resource *res)
 {
+	int idx = pci_resource_num(dev, res);
+
+	if (idx >= PCI_BRIDGE_RESOURCES && idx <= PCI_BRIDGE_RESOURCE_END) {
+		res->flags |= IORESOURCE_UNSET;
+		return;
+	}
+
 	res->start = 0;
 	res->end = 0;
 	res->flags = 0;
@@ -610,7 +639,7 @@ static void __assign_resources_sorted(struct list_head *head,
 				    0 /* don't care */);
 		}
 
-		reset_resource(res);
+		reset_resource(dev, res);
 	}
 
 	free_list(head);
@@ -1014,8 +1043,11 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 
 			if (r->parent || !(r->flags & IORESOURCE_IO))
 				continue;
-			r_size = resource_size(r);
 
+			if (!pdev_resource_assignable(dev, r))
+				continue;
+
+			r_size = resource_size(r);
 			if (r_size < SZ_1K)
 				/* Might be re-aligned for ISA */
 				size += r_size;
@@ -1034,6 +1066,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 	size0 = calculate_iosize(size, min_size, size1, 0, 0,
 			resource_size(b_res), min_align);
 
+	if (size0)
+		b_res->flags &= ~IORESOURCE_DISABLED;
+
 	size1 = size0;
 	if (realloc_head && (add_size > 0 || children_add_size > 0)) {
 		size1 = calculate_iosize(size, min_size, size1, add_size,
@@ -1045,13 +1080,14 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 		if (bus->self && (b_res->start || b_res->end))
 			pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n",
 				 b_res, &bus->busn_res);
-		b_res->flags = 0;
+		b_res->flags |= IORESOURCE_DISABLED;
 		return;
 	}
 
 	resource_set_range(b_res, min_align, size0);
 	b_res->flags |= IORESOURCE_STARTALIGN;
 	if (bus->self && size1 > size0 && realloc_head) {
+		b_res->flags &= ~IORESOURCE_DISABLED;
 		add_to_list(realloc_head, bus->self, b_res, size1-size0,
 			    min_align);
 		pci_info(bus->self, "bridge window %pR to %pR add_size %llx\n",
@@ -1198,11 +1234,13 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			const char *r_name = pci_resource_name(dev, i);
 			resource_size_t r_size;
 
-			if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) ||
-			    !pdev_resources_assignable(dev) ||
-			    ((r->flags & mask) != type &&
-			     (r->flags & mask) != type2 &&
-			     (r->flags & mask) != type3))
+			if (!pdev_resources_assignable(dev) ||
+			    !pdev_resource_should_fit(dev, r))
+				continue;
+
+			if ((r->flags & mask) != type &&
+			    (r->flags & mask) != type2 &&
+			    (r->flags & mask) != type3)
 				continue;
 			r_size = resource_size(r);
 
@@ -1253,6 +1291,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 	min_align = max(min_align, win_align);
 	size0 = calculate_memsize(size, min_size, 0, 0, resource_size(b_res), min_align);
 
+	if (size0)
+		b_res->flags &= ~IORESOURCE_DISABLED;
+
 	if (bus->self && size0 &&
 	    !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type,
 					   size0, min_align)) {
@@ -1287,13 +1328,14 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 		if (bus->self && (b_res->start || b_res->end))
 			pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n",
 				 b_res, &bus->busn_res);
-		b_res->flags = 0;
+		b_res->flags |= IORESOURCE_DISABLED;
 		return 0;
 	}
 
 	resource_set_range(b_res, min_align, size0);
 	b_res->flags |= IORESOURCE_STARTALIGN;
 	if (bus->self && size1 > size0 && realloc_head) {
+		b_res->flags &= ~IORESOURCE_DISABLED;
 		add_to_list(realloc_head, bus->self, b_res, size1-size0, add_align);
 		pci_info(bus->self, "bridge window %pR to %pR add_size %llx add_align %llx\n",
 			   b_res, &bus->busn_res,
@@ -1721,7 +1763,6 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
 {
 	struct pci_dev *dev = bus->self;
 	struct resource *r;
-	unsigned int old_flags;
 	struct resource *b_res;
 	int idx, ret;
 
@@ -1758,7 +1799,6 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
 	/* If there are children, release them all */
 	release_child_resources(r);
 
-	type = old_flags = r->flags & PCI_RES_TYPE_MASK;
 	ret = pci_release_resource(dev, PCI_BRIDGE_RESOURCES + idx);
 	if (ret)
 		return;
@@ -1767,8 +1807,6 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
 	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 {
@@ -2246,21 +2284,9 @@ static void pci_prepare_next_assign_round(struct list_head *fail_head,
 	}
 
 	/* Restore size and flags */
-	list_for_each_entry(fail_res, fail_head, list) {
-		struct resource *res = fail_res->res;
-		struct pci_dev *dev = fail_res->dev;
-		int idx = pci_resource_num(dev, res);
-
+	list_for_each_entry(fail_res, fail_head, list)
 		restore_dev_resource(fail_res);
 
-		if (!pci_is_bridge(dev))
-			continue;
-
-		if (idx >= PCI_BRIDGE_RESOURCES &&
-		    idx <= PCI_BRIDGE_RESOURCE_END)
-			res->flags = 0;
-	}
-
 	free_list(fail_head);
 }
 
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 4e0e60256f04..21f77e5c647c 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -359,6 +359,9 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
 
 	res->flags &= ~IORESOURCE_UNSET;
 	res->flags &= ~IORESOURCE_STARTALIGN;
+	if (resno >= PCI_BRIDGE_RESOURCES && resno <= PCI_BRIDGE_RESOURCE_END)
+		res->flags &= ~IORESOURCE_DISABLED;
+
 	pci_info(dev, "%s %pR: assigned\n", res_name, res);
 	if (resno < PCI_BRIDGE_RESOURCES)
 		pci_update_resource(dev, resno);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/24] PCI: Add defines for bridge window indexing
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (9 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 10/24] PCI: Preserve bridge window resource type flags Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 12/24] PCI: Add bridge window selection functions Ilpo Järvinen
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

include/linux/pci.h provides PCI_BRIDGE_{IO,MEM,PREF_MEM}_WINDOW
defines, however, they're based on the resource array indexing in the
pci_dev struct. The struct pci_bus also has pointers to those same
resource but they start from zeroth index.

Add PCI_BUS_BRIDGE_{IO,MEM,PREF_MEM}_WINDOW defines to get rid of
literal indexing.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/pci.h   |  4 ++++
 drivers/pci/probe.c | 10 +++++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 34f65d69662e..1dc8a8066761 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -81,6 +81,10 @@ struct pcie_tlp_log;
 #define PCIE_MSG_CODE_DEASSERT_INTC	0x26
 #define PCIE_MSG_CODE_DEASSERT_INTD	0x27
 
+#define PCI_BUS_BRIDGE_IO_WINDOW	0
+#define PCI_BUS_BRIDGE_MEM_WINDOW	1
+#define PCI_BUS_BRIDGE_PREF_MEM_WINDOW	2
+
 extern const unsigned char pcie_link_speed[];
 extern bool pci_early_dump;
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f31d27c7708a..eaeb66bec433 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -598,9 +598,13 @@ void pci_read_bridge_bases(struct pci_bus *child)
 	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
 		child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
 
-	pci_read_bridge_io(child->self, child->resource[0], false);
-	pci_read_bridge_mmio(child->self, child->resource[1], false);
-	pci_read_bridge_mmio_pref(child->self, child->resource[2], false);
+	pci_read_bridge_io(child->self,
+			   child->resource[PCI_BUS_BRIDGE_IO_WINDOW], false);
+	pci_read_bridge_mmio(child->self,
+			     child->resource[PCI_BUS_BRIDGE_MEM_WINDOW], false);
+	pci_read_bridge_mmio_pref(child->self,
+				  child->resource[PCI_BUS_BRIDGE_PREF_MEM_WINDOW],
+				  false);
 
 	if (!dev->transparent)
 		return;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/24] PCI: Add bridge window selection functions
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (10 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 11/24] PCI: Add defines for bridge window indexing Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 13/24] PCI: Fix finding bridge window in pci_reassign_bridge_resources() Ilpo Järvinen
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Various places in the PCI core code make independently a decision into
which bridge window a child resource should be placed to. It is hard to
see whether these decisions always end up into agreement, especially in
the corner cases, and in some places it requires complex logic to pass
multiple resource types and/or bridge windows around.

Add pbus_select_window() and pbus_select_window_for_type() for case
where the former cannot be used so that eventually the same helper can
be used to select the bridge window everywhere. Using the same function
ensures the selected bridge window remains always the same and it can
be easily recalculated in-situ allowing simplifying the interfaces
between internal functions in upcoming changes.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/pci.h       |   2 +
 drivers/pci/setup-bus.c | 101 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 1dc8a8066761..cbd40f05c39c 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -385,6 +385,8 @@ static inline int pci_resource_num(const struct pci_dev *dev,
 	return resno;
 }
 
+struct resource *pbus_select_window(struct pci_bus *bus,
+				    const struct resource *res);
 void pci_reassigndev_resource_alignment(struct pci_dev *dev);
 void pci_disable_bridge_window(struct pci_dev *dev);
 struct pci_bus *pci_bus_get(struct pci_bus *bus);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 223f0e025407..0c0872b85762 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -172,6 +172,107 @@ static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
 	return r_assigned;
 }
 
+/**
+ * pbus_select_window_for_type - Select bridge window for a resource type
+ * @bus: PCI bus
+ * @type: Resource type (resource flags can be passed as is)
+ *
+ * Selects the bridge window based on a resource @type.
+ *
+ * For memory resources, the selection is done as follows:
+ *
+ * Any non-prefetchable resource is put into the non-prefetchable window.
+ *
+ * If there is no prefetchable MMIO window, put all memory resources into the
+ * non-prefetchable window.
+ *
+ * If there's a 64-bit prefetchable MMIO window, put all 64-bit prefetchable
+ * resources into it and place 32-bit prefetchable memory into the
+ * non-prefetchable window.
+ *
+ * Otherwise, put all prefetchable resources into the prefetchable window.
+ *
+ * Return: the bridge window resource or NULL if no bridge window is found.
+ */
+static struct resource *pbus_select_window_for_type(struct pci_bus *bus,
+						    unsigned long type)
+{
+	int iores_type = type & IORESOURCE_TYPE_BITS;	/* w/o 64bit & pref */
+	struct resource *mmio, *mmio_pref, *win;
+
+	type &= PCI_RES_TYPE_MASK;			/* with 64bit & pref */
+
+	if ((iores_type != IORESOURCE_IO) && (iores_type != IORESOURCE_MEM))
+		return NULL;
+
+	if (pci_is_root_bus(bus)) {
+		win = find_bus_resource_of_type(bus, type, type);
+		if (win)
+			return win;
+
+		type &= ~IORESOURCE_MEM_64;
+		win = find_bus_resource_of_type(bus, type, type);
+		if (win)
+			return win;
+
+		type &= ~IORESOURCE_PREFETCH;
+		return find_bus_resource_of_type(bus, type, type);
+	}
+
+	switch (iores_type) {
+	case IORESOURCE_IO:
+		return pci_bus_resource_n(bus, PCI_BUS_BRIDGE_IO_WINDOW);
+
+	case IORESOURCE_MEM:
+		mmio = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_MEM_WINDOW);
+		mmio_pref = pci_bus_resource_n(bus, PCI_BUS_BRIDGE_PREF_MEM_WINDOW);
+
+		if (!(type & IORESOURCE_PREFETCH) ||
+		    !(mmio_pref->flags & IORESOURCE_MEM))
+			return mmio;
+
+		if ((type & IORESOURCE_MEM_64) ||
+		    !(mmio_pref->flags & IORESOURCE_MEM_64))
+			return mmio_pref;
+
+		return mmio;
+	default:
+		return NULL;
+	}
+}
+
+/**
+ * pbus_select_window - Select bridge window for a resource
+ * @bus: PCI bus
+ * @res: Resource
+ *
+ * Selects the bridge window for @res. If the resource is already assigned,
+ * the current bridge window is returned.
+ *
+ * For memory resources, the selection is done as follows:
+ *
+ * Any non-prefetchable resource is put into the non-prefetchable window.
+ *
+ * If there is no prefetchable MMIO window, put all memory resources into the
+ * non-prefetchable window.
+ *
+ * If there's a 64-bit prefetchable MMIO window, put all 64-bit prefetchable
+ * resources into it and place 32-bit prefetchable memory into the
+ * non-prefetchable window.
+ *
+ * Otherwise, put all prefetchable resources into the prefetchable window.
+ *
+ * Return: the bridge window resource or NULL if no bridge window is found.
+ */
+struct resource *pbus_select_window(struct pci_bus *bus,
+				    const struct resource *res)
+{
+	if (res->parent)
+		return res->parent;
+
+	return pbus_select_window_for_type(bus, res->flags);
+}
+
 static bool pdev_resources_assignable(struct pci_dev *dev)
 {
 	u16 class = dev->class >> 8, command;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/24] PCI: Fix finding bridge window in pci_reassign_bridge_resources()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (11 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 12/24] PCI: Add bridge window selection functions Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 14/24] PCI: Warn if bridge window cannot be released when resizing BAR Ilpo Järvinen
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

pci_reassign_bridge_resources() walks upwards in the PCI bus hierarchy,
locates the relevant bridge window on each level using flags check, and
attempts to release the bridge window. The flags-based check is fragile
due to various fallbacks bridge window selection logic might use. As
such, the algorithm might not locate the correct bridge window.

Refactor pci_reassign_bridge_resources() to determine the correct
bridge window using pbus_select_window() that contains logic to handle
all fallback cases correctly. Change function prefix to pbus as it now
inputs struct bus and resource for which to locate the bridge window.

The main purpose of this change is to make bridge window selection
logic consistent across the entire PCI core (one step at a time). While
this technically also fixes the commit 8bb705e3e79d ("PCI: Add
pci_resize_resource() for resizing BARs") making the bridge window walk
algorithm more robust, The normal setup having a 64-bit resizable BAR
underneath bridge(s) with 64-bit prefetchable windows does not need to
use any fallbacks. As such, the practical impact is low (requiring BAR
resize use case and a non-typical bridge device).

The way to detect if unrelated resource failed again is left to use the
type based approximation which should not behave worse than before.

Fixes: 8bb705e3e79d ("PCI: Add pci_resize_resource() for resizing BARs")
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/pci.h       |  2 +-
 drivers/pci/setup-bus.c | 40 ++++++++++++++++++++--------------------
 drivers/pci/setup-res.c |  2 +-
 3 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index cbd40f05c39c..0d96a9141227 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -334,7 +334,7 @@ struct device *pci_get_host_bridge_device(struct pci_dev *dev);
 void pci_put_host_bridge_device(struct device *dev);
 
 unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
-int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type);
+int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *res);
 int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
 
 int pci_configure_extended_tags(struct pci_dev *dev, void *ign);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 0c0872b85762..5ef6362b5166 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2521,10 +2521,17 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
 }
 EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
 
-int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
+/*
+ * Walk to the root hub, find the bridge window relevant for @res and
+ * releasing it when possible. If the bridge window contains assigned
+ * resources, it cannot be released.
+ */
+int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *res)
 {
+	unsigned long type = res->flags;
 	struct pci_dev_resource *dev_res;
-	struct pci_dev *next;
+	struct pci_dev *bridge;
+	const char *res_name;
 	LIST_HEAD(saved);
 	LIST_HEAD(added);
 	LIST_HEAD(failed);
@@ -2533,33 +2540,26 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
 
 	down_read(&pci_bus_sem);
 
-	/* Walk to the root hub, releasing bridge BARs when possible */
-	next = bridge;
-	do {
-		bridge = next;
-		for (i = PCI_BRIDGE_RESOURCES; i < PCI_BRIDGE_RESOURCE_END;
-		     i++) {
-			struct resource *res = &bridge->resource[i];
-
-			if ((res->flags ^ type) & PCI_RES_TYPE_MASK)
-				continue;
+	while (!pci_is_root_bus(bus)) {
+		bridge = bus->self;
+		res = pbus_select_window(bus, res);
+		if (!res)
+			break;
 
-			/* Ignore BARs which are still in use */
-			if (res->child)
-				continue;
+		i = pci_resource_num(bridge, res);
+		res_name = pci_resource_name(bridge, i);
 
+		/* Ignore BARs which are still in use */
+		if (!res->child) {
 			ret = add_to_list(&saved, bridge, res, 0, 0);
 			if (ret)
 				goto cleanup;
 
 			pci_release_resource(bridge, i);
-			break;
 		}
-		if (i == PCI_BRIDGE_RESOURCE_END)
-			break;
 
-		next = bridge->bus ? bridge->bus->self : NULL;
-	} while (next);
+		bus = bus->parent;
+	}
 
 	if (list_empty(&saved)) {
 		up_read(&pci_bus_sem);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 21f77e5c647c..c3ba4ccecd43 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -496,7 +496,7 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size)
 
 	/* Check if the new config works by trying to assign everything. */
 	if (dev->bus->self) {
-		ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
+		ret = pbus_reassign_bridge_resources(dev->bus, res);
 		if (ret)
 			goto error_resize;
 	}
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/24] PCI: Warn if bridge window cannot be released when resizing BAR
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (12 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 13/24] PCI: Fix finding bridge window in pci_reassign_bridge_resources() Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 15/24] PCI: Use pbus_select_window() during BAR resize Ilpo Järvinen
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

BAR resizing calls to pci_reassign_bridge_resources() that attempts to
release any upstream bridge window to allow them to accommodate the new
BAR size. The release can only be performed if there are no other child
resources for the bridge window. The code just silently continues when
this condition is detects.

Add pci_warn() to inform user that a bridge window could not be
released because of child resources. As too small bridge window is
often the reason why the BAR resize cannot succeed, this warning will
help to pinpoint to the cause.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 5ef6362b5166..55289cd58e2c 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2556,6 +2556,10 @@ int pbus_reassign_bridge_resources(struct pci_bus *bus, struct resource *res)
 				goto cleanup;
 
 			pci_release_resource(bridge, i);
+		} else {
+			pci_warn(bridge,
+				 "%s %pR: was not released (still contains assigned resources)\n",
+				 res_name, res);
 		}
 
 		bus = bus->parent;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/24] PCI: Use pbus_select_window() during BAR resize
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (13 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 14/24] PCI: Warn if bridge window cannot be released when resizing BAR Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 16/24] PCI: Use pbus_select_window_for_type() during IO window sizing Ilpo Järvinen
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Prior to a BAR resize, __resource_resize_store() loops through the
normal resources of the PCI device and releases those that match to the
flags of the BAR to be resized. This is necessary to allow resizing
also the upstream bridge window as only childless bridge windows can be
resized.

While the flags check (mostly) works (if corner cases are ignored), the
more straightforward way is to check if the resources share the bridge
window. Change __resource_resize_store() to do the check using
pbus_select_window().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/pci-sysfs.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 162a5241c7f7..ce3923c4aa80 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1562,13 +1562,19 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
 				       const char *buf, size_t count)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
-	unsigned long size, flags;
+	struct pci_bus *bus = pdev->bus;
+	struct resource *b_win, *res;
+	unsigned long size;
 	int ret, i;
 	u16 cmd;
 
 	if (kstrtoul(buf, 0, &size) < 0)
 		return -EINVAL;
 
+	b_win = pbus_select_window(bus, pci_resource_n(pdev, n));
+	if (!b_win)
+		return -EINVAL;
+
 	device_lock(dev);
 	if (dev->driver || pci_num_vf(pdev)) {
 		ret = -EBUSY;
@@ -1588,19 +1594,19 @@ static ssize_t __resource_resize_store(struct device *dev, int n,
 	pci_write_config_word(pdev, PCI_COMMAND,
 			      cmd & ~PCI_COMMAND_MEMORY);
 
-	flags = pci_resource_flags(pdev, n);
-
 	pci_remove_resource_files(pdev);
 
-	for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
-		if (pci_resource_len(pdev, i) &&
-		    pci_resource_flags(pdev, i) == flags)
+	pci_dev_for_each_resource(pdev, res, i) {
+		if (i >= PCI_BRIDGE_RESOURCES)
+			break;
+
+		if (b_win == pbus_select_window(bus, res))
 			pci_release_resource(pdev, i);
 	}
 
 	ret = pci_resize_resource(pdev, n, size);
 
-	pci_assign_unassigned_bus_resources(pdev->bus);
+	pci_assign_unassigned_bus_resources(bus);
 
 	if (pci_create_resource_files(pdev))
 		pci_warn(pdev, "Failed to recreate resource files after BAR resizing\n");
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 16/24] PCI: Use pbus_select_window_for_type() during IO window sizing
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (14 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 15/24] PCI: Use pbus_select_window() during BAR resize Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 17/24] PCI: Rename resource variable from r to res Ilpo Järvinen
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Convert pbus_size_io() to use pbus_select_window_for_type().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 55289cd58e2c..3f2776f7a1b2 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1122,8 +1122,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
 			 struct list_head *realloc_head)
 {
 	struct pci_dev *dev;
-	struct resource *b_res = find_bus_resource_of_type(bus, IORESOURCE_IO,
-							   IORESOURCE_IO);
+	struct resource *b_res = pbus_select_window_for_type(bus, IORESOURCE_IO);
 	resource_size_t size = 0, size0 = 0, size1 = 0;
 	resource_size_t children_add_size = 0;
 	resource_size_t min_align, align;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 17/24] PCI: Rename resource variable from r to res
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (15 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 16/24] PCI: Use pbus_select_window_for_type() during IO window sizing Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:55 ` [PATCH 18/24] PCI: Use pbus_select_window() in space available checker Ilpo Järvinen
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Resource is going to be passed in as argument aften an upcoming change.
Rename the struct resource variable from "r" to "res" to avoid using
one letter variable name in a function argument.

This rename is made separately to reduce churn in the upcoming change.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 3f2776f7a1b2..dac0f0f0360b 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1241,24 +1241,24 @@ static bool pbus_upstream_space_available(struct pci_bus *bus, unsigned long mas
 		.align = align,
 	};
 	struct pci_bus *downstream = bus;
-	struct resource *r;
+	struct resource *res;
 
 	while ((bus = bus->parent)) {
 		if (pci_is_root_bus(bus))
 			break;
 
-		pci_bus_for_each_resource(bus, r) {
-			if (!r || !r->parent || (r->flags & mask) != type)
+		pci_bus_for_each_resource(bus, res) {
+			if (!res || !res->parent || (res->flags & mask) != type)
 				continue;
 
-			if (resource_size(r) >= size) {
+			if (resource_size(res) >= size) {
 				struct resource gap = {};
 
-				if (find_resource_space(r, &gap, size, &constraint) == 0) {
+				if (find_resource_space(res, &gap, size, &constraint) == 0) {
 					gap.flags = type;
 					pci_dbg(bus->self,
 						"Assigned bridge window %pR to %pR free space at %pR\n",
-						r, &bus->busn_res, &gap);
+						res, &bus->busn_res, &gap);
 					return true;
 				}
 			}
@@ -1266,7 +1266,7 @@ static bool pbus_upstream_space_available(struct pci_bus *bus, unsigned long mas
 			if (bus->self) {
 				pci_info(bus->self,
 					 "Assigned bridge window %pR to %pR cannot fit 0x%llx required for %s bridging to %pR\n",
-					 r, &bus->busn_res,
+					 res, &bus->busn_res,
 					 (unsigned long long)size,
 					 pci_name(downstream->self),
 					 &downstream->busn_res);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 18/24] PCI: Use pbus_select_window() in space available checker
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (16 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 17/24] PCI: Rename resource variable from r to res Ilpo Järvinen
@ 2025-08-22 14:55 ` Ilpo Järvinen
  2025-08-22 14:56 ` [PATCH 19/24] PCI: Use pbus_select_window_for_type() during mem window sizing Ilpo Järvinen
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:55 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

pbus_upstream_space_available() figures out the upstream bridge window
resources on its own. Migrate it to use pbus_select_window().

Note, pbus_select_window() -> pbus_select_window_for_type() calls
find_bus_resource_of_type() for root bus, which does not do parent
check similar to what pbus_upstream_space_available() did earlier, but
the difference does not matter because pbus_upstream_space_available()
itself stops when it encounters the root bus.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 63 ++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index dac0f0f0360b..281ca5c73c97 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1221,19 +1221,20 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
 /**
  * pbus_upstream_space_available - Check no upstream resource limits allocation
  * @bus:	The bus
- * @mask:	Mask the resource flag, then compare it with type
- * @type:	The type of resource from bridge
+ * @res:	The resource to help to pick the correct bridge window
  * @size:	The size required from the bridge window
  * @align:	Required alignment for the resource
  *
  * Checks that @size can fit inside the upstream bridge resources that are
- * already assigned.
+ * already assigned. @res (its type) is used to select to correct upstream
+ * bridge window.
  *
  * Return: %true if enough space is available on all assigned upstream
  * resources.
  */
-static bool pbus_upstream_space_available(struct pci_bus *bus, unsigned long mask,
-					  unsigned long type, resource_size_t size,
+static bool pbus_upstream_space_available(struct pci_bus *bus,
+					  struct resource *res,
+					  resource_size_t size,
 					  resource_size_t align)
 {
 	struct resource_constraint constraint = {
@@ -1241,39 +1242,39 @@ static bool pbus_upstream_space_available(struct pci_bus *bus, unsigned long mas
 		.align = align,
 	};
 	struct pci_bus *downstream = bus;
-	struct resource *res;
 
 	while ((bus = bus->parent)) {
 		if (pci_is_root_bus(bus))
 			break;
 
-		pci_bus_for_each_resource(bus, res) {
-			if (!res || !res->parent || (res->flags & mask) != type)
-				continue;
-
-			if (resource_size(res) >= size) {
-				struct resource gap = {};
+		res = pbus_select_window(bus, res);
+		if (!res)
+			return false;
+		if (!res->parent)
+			continue;
 
-				if (find_resource_space(res, &gap, size, &constraint) == 0) {
-					gap.flags = type;
-					pci_dbg(bus->self,
-						"Assigned bridge window %pR to %pR free space at %pR\n",
-						res, &bus->busn_res, &gap);
-					return true;
-				}
-			}
+		if (resource_size(res) >= size) {
+			struct resource gap = {};
 
-			if (bus->self) {
-				pci_info(bus->self,
-					 "Assigned bridge window %pR to %pR cannot fit 0x%llx required for %s bridging to %pR\n",
-					 res, &bus->busn_res,
-					 (unsigned long long)size,
-					 pci_name(downstream->self),
-					 &downstream->busn_res);
+			if (find_resource_space(res, &gap, size, &constraint) == 0) {
+				gap.flags = res->flags;
+				pci_dbg(bus->self,
+					"Assigned bridge window %pR to %pR free space at %pR\n",
+					res, &bus->busn_res, &gap);
+				return true;
 			}
+		}
 
-			return false;
+		if (bus->self) {
+			pci_info(bus->self,
+				 "Assigned bridge window %pR to %pR cannot fit 0x%llx required for %s bridging to %pR\n",
+				 res, &bus->busn_res,
+				 (unsigned long long)size,
+				 pci_name(downstream->self),
+				 &downstream->busn_res);
 		}
+
+		return false;
 	}
 
 	return true;
@@ -1395,8 +1396,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 		b_res->flags &= ~IORESOURCE_DISABLED;
 
 	if (bus->self && size0 &&
-	    !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type,
-					   size0, min_align)) {
+	    !pbus_upstream_space_available(bus, b_res, size0, min_align)) {
 		relaxed_align = 1ULL << (max_order + __ffs(SZ_1M));
 		relaxed_align = max(relaxed_align, win_align);
 		min_align = min(min_align, relaxed_align);
@@ -1411,8 +1411,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 					  resource_size(b_res), add_align);
 
 		if (bus->self && size1 &&
-		    !pbus_upstream_space_available(bus, mask | IORESOURCE_PREFETCH, type,
-						   size1, add_align)) {
+		    !pbus_upstream_space_available(bus, b_res, size1, add_align)) {
 			relaxed_align = 1ULL << (max_order + __ffs(SZ_1M));
 			relaxed_align = max(relaxed_align, win_align);
 			min_align = min(min_align, relaxed_align);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 19/24] PCI: Use pbus_select_window_for_type() during mem window sizing
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (17 preceding siblings ...)
  2025-08-22 14:55 ` [PATCH 18/24] PCI: Use pbus_select_window() in space available checker Ilpo Järvinen
@ 2025-08-22 14:56 ` Ilpo Järvinen
  2025-08-22 14:56 ` [PATCH 20/24] PCI: Refactor distributing available memory to use loops Ilpo Järvinen
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:56 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

__pci_bus_size_bridges() goes to great lengths of helping
pbus_size_mem() in which types it should put into a particular bridge
window, requiring passing up to three resource type into
pbus_size_mem().

Instead of having complex logic __pci_bus_size_bridges() and a
non-straightforward interface between those functions, use
pbus_select_window_for_type() and pbus_select_window() to find the
correct bridge window and compare if the resources belong to that
window.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 111 +++++++++-------------------------------
 1 file changed, 24 insertions(+), 87 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 281ca5c73c97..28133a9c5f51 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1284,24 +1284,22 @@ static bool pbus_upstream_space_available(struct pci_bus *bus,
  * pbus_size_mem() - Size the memory window of a given bus
  *
  * @bus:		The bus
- * @mask:		Mask the resource flag, then compare it with type
- * @type:		The type of free resource from bridge
- * @type2:		Second match type
- * @type3:		Third match type
+ * @type:		The type of bridge resource
  * @min_size:		The minimum memory window that must be allocated
  * @add_size:		Additional optional memory window
  * @realloc_head:	Track the additional memory window on this list
  *
- * Calculate the size of the bus and minimal alignment which guarantees
- * that all child resources fit in this size.
+ * Calculate the size of the bus resource for @type and minimal alignment
+ * which guarantees that all child resources fit in this size.
  *
- * Return -ENOSPC if there's no available bus resource of the desired
- * type.  Otherwise, set the bus resource start/end to indicate the
- * required size, add things to realloc_head (if supplied), and return 0.
+ * Sets the bus resource start/end to indicate the required size if there an
+ * available unassigned bus resource of the desired @type.
+ *
+ * Adds optional resource requests to the @realloc_head list if it is
+ * supplied.
  */
-static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
-			 unsigned long type, unsigned long type2,
-			 unsigned long type3, resource_size_t min_size,
+static void pbus_size_mem(struct pci_bus *bus, unsigned long type,
+			 resource_size_t min_size,
 			 resource_size_t add_size,
 			 struct list_head *realloc_head)
 {
@@ -1309,19 +1307,18 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 	resource_size_t min_align, win_align, align, size, size0, size1 = 0;
 	resource_size_t aligns[28]; /* Alignments from 1MB to 128TB */
 	int order, max_order;
-	struct resource *b_res = find_bus_resource_of_type(bus,
-					mask | IORESOURCE_PREFETCH, type);
+	struct resource *b_res = pbus_select_window_for_type(bus, type);
 	resource_size_t children_add_size = 0;
 	resource_size_t children_add_align = 0;
 	resource_size_t add_align = 0;
 	resource_size_t relaxed_align;
 
 	if (!b_res)
-		return -ENOSPC;
+		return;
 
 	/* If resource is already assigned, nothing more to do */
 	if (b_res->parent)
-		return 0;
+		return;
 
 	memset(aligns, 0, sizeof(aligns));
 	max_order = 0;
@@ -1338,11 +1335,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			if (!pdev_resources_assignable(dev) ||
 			    !pdev_resource_should_fit(dev, r))
 				continue;
-
-			if ((r->flags & mask) != type &&
-			    (r->flags & mask) != type2 &&
-			    (r->flags & mask) != type3)
+			if (b_res != pbus_select_window(bus, r))
 				continue;
+
 			r_size = resource_size(r);
 
 			/* Put SRIOV requested res to the optional list */
@@ -1428,7 +1423,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			pci_info(bus->self, "disabling bridge window %pR to %pR (unused)\n",
 				 b_res, &bus->busn_res);
 		b_res->flags |= IORESOURCE_DISABLED;
-		return 0;
+		return;
 	}
 
 	resource_set_range(b_res, min_align, size0);
@@ -1441,7 +1436,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			   (unsigned long long) (size1 - size0),
 			   (unsigned long long) add_align);
 	}
-	return 0;
 }
 
 unsigned long pci_cardbus_resource_alignment(struct resource *res)
@@ -1546,12 +1540,11 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,
 void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
 {
 	struct pci_dev *dev;
-	unsigned long mask, prefmask, type2 = 0, type3 = 0;
 	resource_size_t additional_io_size = 0, additional_mmio_size = 0,
 			additional_mmio_pref_size = 0;
 	struct resource *pref;
 	struct pci_host_bridge *host;
-	int hdr_type, ret;
+	int hdr_type;
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		struct pci_bus *b = dev->subordinate;
@@ -1601,71 +1594,15 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)
 		pbus_size_io(bus, realloc_head ? 0 : additional_io_size,
 			     additional_io_size, realloc_head);
 
-		/*
-		 * If there's a 64-bit prefetchable MMIO window, compute
-		 * the size required to put all 64-bit prefetchable
-		 * resources in it.
-		 */
-		mask = IORESOURCE_MEM;
-		prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-		if (pref && (pref->flags & IORESOURCE_MEM_64)) {
-			prefmask |= IORESOURCE_MEM_64;
-			ret = pbus_size_mem(bus, prefmask, prefmask,
-				prefmask, prefmask,
-				realloc_head ? 0 : additional_mmio_pref_size,
-				additional_mmio_pref_size, realloc_head);
-
-			/*
-			 * If successful, all non-prefetchable resources
-			 * and any 32-bit prefetchable resources will go in
-			 * the non-prefetchable window.
-			 */
-			if (ret == 0) {
-				mask = prefmask;
-				type2 = prefmask & ~IORESOURCE_MEM_64;
-				type3 = prefmask & ~IORESOURCE_PREFETCH;
-			}
-		}
-
-		/*
-		 * If there is no 64-bit prefetchable window, compute the
-		 * size required to put all prefetchable resources in the
-		 * 32-bit prefetchable window (if there is one).
-		 */
-		if (!type2) {
-			prefmask &= ~IORESOURCE_MEM_64;
-			ret = pbus_size_mem(bus, prefmask, prefmask,
-				prefmask, prefmask,
-				realloc_head ? 0 : additional_mmio_pref_size,
-				additional_mmio_pref_size, realloc_head);
-
-			/*
-			 * If successful, only non-prefetchable resources
-			 * will go in the non-prefetchable window.
-			 */
-			if (ret == 0)
-				mask = prefmask;
-			else
-				additional_mmio_size += additional_mmio_pref_size;
-
-			type2 = type3 = IORESOURCE_MEM;
+		if (pref) {
+			pbus_size_mem(bus,
+				      IORESOURCE_MEM | IORESOURCE_PREFETCH |
+				      (pref->flags & IORESOURCE_MEM_64),
+				      realloc_head ? 0 : additional_mmio_pref_size,
+				      additional_mmio_pref_size, realloc_head);
 		}
 
-		/*
-		 * Compute the size required to put everything else in the
-		 * non-prefetchable window. This includes:
-		 *
-		 *   - all non-prefetchable resources
-		 *   - 32-bit prefetchable resources if there's a 64-bit
-		 *     prefetchable window or no prefetchable window at all
-		 *   - 64-bit prefetchable resources if there's no prefetchable
-		 *     window at all
-		 *
-		 * Note that the strategy in __pci_assign_resource() must match
-		 * that used here. Specifically, we cannot put a 32-bit
-		 * prefetchable resource in a 64-bit prefetchable window.
-		 */
-		pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
+		pbus_size_mem(bus, IORESOURCE_MEM,
 			      realloc_head ? 0 : additional_mmio_size,
 			      additional_mmio_size, realloc_head);
 		break;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 20/24] PCI: Refactor distributing available memory to use loops
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (18 preceding siblings ...)
  2025-08-22 14:56 ` [PATCH 19/24] PCI: Use pbus_select_window_for_type() during mem window sizing Ilpo Järvinen
@ 2025-08-22 14:56 ` Ilpo Järvinen
  2025-08-22 14:56 ` [PATCH 21/24] PCI: Refactor remove_dev_resources() to use pbus_select_window() Ilpo Järvinen
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:56 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

pci_bus_distribute_available_resources() and
pci_bridge_distribute_available_resources() retain bridge window
resources and related data needed for distributing the available window
in independent variables for io, memory, and prefetchable memory
windows. The code is essentially the same for all of them and therefore
repeated three times with different variable names.

Refactor pci_bus_distribute_available_resources() to take an array.
This is complicated slightly by the function taking advantage of
passing the struct as value, which cannot be done for arrays in C.
Therefore, copy the data into a local array in the stack in the first
loop.

Variable names are (hopefully) improved slightly as well.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 162 ++++++++++++++++++----------------------
 include/linux/pci.h     |   3 +-
 2 files changed, 74 insertions(+), 91 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 28133a9c5f51..ee2f2c78d8c9 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2058,15 +2058,16 @@ static void remove_dev_resource(struct resource *avail, struct pci_dev *dev,
 	avail->start = min(avail->start + tmp, avail->end + 1);
 }
 
-static void remove_dev_resources(struct pci_dev *dev, struct resource *io,
-				 struct resource *mmio,
-				 struct resource *mmio_pref)
+static void remove_dev_resources(struct pci_dev *dev,
+				 struct resource available[PCI_P2P_BRIDGE_RESOURCE_NUM])
 {
+	struct resource *mmio_pref = &available[PCI_BUS_BRIDGE_PREF_MEM_WINDOW];
 	struct resource *res;
 
 	pci_dev_for_each_resource(dev, res) {
 		if (resource_type(res) == IORESOURCE_IO) {
-			remove_dev_resource(io, dev, res);
+			remove_dev_resource(&available[PCI_BUS_BRIDGE_IO_WINDOW],
+					    dev, res);
 		} else if (resource_type(res) == IORESOURCE_MEM) {
 
 			/*
@@ -2080,10 +2081,13 @@ static void remove_dev_resources(struct pci_dev *dev, struct resource *io,
 			 */
 			if ((res->flags & IORESOURCE_PREFETCH) &&
 			    ((res->flags & IORESOURCE_MEM_64) ==
-			     (mmio_pref->flags & IORESOURCE_MEM_64)))
-				remove_dev_resource(mmio_pref, dev, res);
-			else
-				remove_dev_resource(mmio, dev, res);
+			     (mmio_pref->flags & IORESOURCE_MEM_64))) {
+				remove_dev_resource(&available[PCI_BUS_BRIDGE_PREF_MEM_WINDOW],
+						    dev, res);
+			} else {
+				remove_dev_resource(&available[PCI_BUS_BRIDGE_MEM_WINDOW],
+						    dev, res);
+			}
 		}
 	}
 }
@@ -2098,45 +2102,39 @@ static void remove_dev_resources(struct pci_dev *dev, struct resource *io,
  * shared with the bridges.
  */
 static void pci_bus_distribute_available_resources(struct pci_bus *bus,
-					    struct list_head *add_list,
-					    struct resource io,
-					    struct resource mmio,
-					    struct resource mmio_pref)
+		    struct list_head *add_list,
+		    struct resource available_in[PCI_P2P_BRIDGE_RESOURCE_NUM])
 {
+	struct resource available[PCI_P2P_BRIDGE_RESOURCE_NUM];
 	unsigned int normal_bridges = 0, hotplug_bridges = 0;
-	struct resource *io_res, *mmio_res, *mmio_pref_res;
 	struct pci_dev *dev, *bridge = bus->self;
-	resource_size_t io_per_b, mmio_per_b, mmio_pref_per_b, align;
+	resource_size_t per_bridge[PCI_P2P_BRIDGE_RESOURCE_NUM];
+	resource_size_t align;
+	int i;
 
-	io_res = &bridge->resource[PCI_BRIDGE_IO_WINDOW];
-	mmio_res = &bridge->resource[PCI_BRIDGE_MEM_WINDOW];
-	mmio_pref_res = &bridge->resource[PCI_BRIDGE_PREF_MEM_WINDOW];
+	for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++) {
+		struct resource *res = pci_bus_resource_n(bus, i);
 
-	/*
-	 * The alignment of this bridge is yet to be considered, hence it must
-	 * be done now before extending its bridge window.
-	 */
-	align = pci_resource_alignment(bridge, io_res);
-	if (!io_res->parent && align)
-		io.start = min(ALIGN(io.start, align), io.end + 1);
-
-	align = pci_resource_alignment(bridge, mmio_res);
-	if (!mmio_res->parent && align)
-		mmio.start = min(ALIGN(mmio.start, align), mmio.end + 1);
+		available[i] = available_in[i];
 
-	align = pci_resource_alignment(bridge, mmio_pref_res);
-	if (!mmio_pref_res->parent && align)
-		mmio_pref.start = min(ALIGN(mmio_pref.start, align),
-			mmio_pref.end + 1);
+		/*
+		 * The alignment of this bridge is yet to be considered,
+		 * hence it must be done now before extending its bridge
+		 * window.
+		 */
+		align = pci_resource_alignment(bridge, res);
+		if (!res->parent && align)
+			available[i].start = min(ALIGN(available[i].start, align),
+						 available[i].end + 1);
 
-	/*
-	 * Now that we have adjusted for alignment, update the bridge window
-	 * resources to fill as much remaining resource space as possible.
-	 */
-	adjust_bridge_window(bridge, io_res, add_list, resource_size(&io));
-	adjust_bridge_window(bridge, mmio_res, add_list, resource_size(&mmio));
-	adjust_bridge_window(bridge, mmio_pref_res, add_list,
-			     resource_size(&mmio_pref));
+		/*
+		 * Now that we have adjusted for alignment, update the
+		 * bridge window resources to fill as much remaining
+		 * resource space as possible.
+		 */
+		adjust_bridge_window(bridge, res, add_list,
+				     resource_size(&available[i]));
+	}
 
 	/*
 	 * Calculate how many hotplug bridges and normal bridges there
@@ -2160,7 +2158,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
 	 */
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if (!dev->is_virtfn)
-			remove_dev_resources(dev, &io, &mmio, &mmio_pref);
+			remove_dev_resources(dev, available);
 	}
 
 	/*
@@ -2172,16 +2170,9 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
 	 * split between non-hotplug bridges. This is to allow possible
 	 * hotplug bridges below them to get the extra space as well.
 	 */
-	if (hotplug_bridges) {
-		io_per_b = div64_ul(resource_size(&io), hotplug_bridges);
-		mmio_per_b = div64_ul(resource_size(&mmio), hotplug_bridges);
-		mmio_pref_per_b = div64_ul(resource_size(&mmio_pref),
-					   hotplug_bridges);
-	} else {
-		io_per_b = div64_ul(resource_size(&io), normal_bridges);
-		mmio_per_b = div64_ul(resource_size(&mmio), normal_bridges);
-		mmio_pref_per_b = div64_ul(resource_size(&mmio_pref),
-					   normal_bridges);
+	for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++) {
+		per_bridge[i] = div64_ul(resource_size(&available[i]),
+					 hotplug_bridges ?: normal_bridges);
 	}
 
 	for_each_pci_bridge(dev, bus) {
@@ -2194,49 +2185,41 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
 		if (hotplug_bridges && !dev->is_hotplug_bridge)
 			continue;
 
-		res = &dev->resource[PCI_BRIDGE_IO_WINDOW];
+		for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++) {
+			res = pci_bus_resource_n(bus, i);
 
-		/*
-		 * Make sure the split resource space is properly aligned
-		 * for bridge windows (align it down to avoid going above
-		 * what is available).
-		 */
-		align = pci_resource_alignment(dev, res);
-		resource_set_size(&io, ALIGN_DOWN_IF_NONZERO(io_per_b, align));
-
-		/*
-		 * The x_per_b holds the extra resource space that can be
-		 * added for each bridge but there is the minimal already
-		 * reserved as well so adjust x.start down accordingly to
-		 * cover the whole space.
-		 */
-		io.start -= resource_size(res);
-
-		res = &dev->resource[PCI_BRIDGE_MEM_WINDOW];
-		align = pci_resource_alignment(dev, res);
-		resource_set_size(&mmio,
-				  ALIGN_DOWN_IF_NONZERO(mmio_per_b,align));
-		mmio.start -= resource_size(res);
+			/*
+			 * Make sure the split resource space is properly
+			 * aligned for bridge windows (align it down to
+			 * avoid going above what is available).
+			 */
+			align = pci_resource_alignment(dev, res);
+			resource_set_size(&available[i],
+					  ALIGN_DOWN_IF_NONZERO(per_bridge[i],
+								align));
 
-		res = &dev->resource[PCI_BRIDGE_PREF_MEM_WINDOW];
-		align = pci_resource_alignment(dev, res);
-		resource_set_size(&mmio_pref,
-				  ALIGN_DOWN_IF_NONZERO(mmio_pref_per_b, align));
-		mmio_pref.start -= resource_size(res);
+			/*
+			 * The per_bridge holds the extra resource space
+			 * that can be added for each bridge but there is
+			 * the minimal already reserved as well so adjust
+			 * x.start down accordingly to cover the whole
+			 * space.
+			 */
+			available[i].start -= resource_size(res);
+		}
 
-		pci_bus_distribute_available_resources(b, add_list, io, mmio,
-						       mmio_pref);
+		pci_bus_distribute_available_resources(b, add_list, available);
 
-		io.start += io.end + 1;
-		mmio.start += mmio.end + 1;
-		mmio_pref.start += mmio_pref.end + 1;
+		for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++)
+			available[i].start += available[i].end + 1;
 	}
 }
 
 static void pci_bridge_distribute_available_resources(struct pci_dev *bridge,
 						      struct list_head *add_list)
 {
-	struct resource available_io, available_mmio, available_mmio_pref;
+	struct resource *res, available[PCI_P2P_BRIDGE_RESOURCE_NUM];
+	unsigned int i;
 
 	if (!bridge->is_hotplug_bridge)
 		return;
@@ -2244,14 +2227,13 @@ static void pci_bridge_distribute_available_resources(struct pci_dev *bridge,
 	pci_dbg(bridge, "distributing available resources\n");
 
 	/* Take the initial extra resources from the hotplug port */
-	available_io = bridge->resource[PCI_BRIDGE_IO_WINDOW];
-	available_mmio = bridge->resource[PCI_BRIDGE_MEM_WINDOW];
-	available_mmio_pref = bridge->resource[PCI_BRIDGE_PREF_MEM_WINDOW];
+	for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++) {
+		res = pci_resource_n(bridge, PCI_BRIDGE_RESOURCES + i);
+		available[i] = *res;
+	}
 
 	pci_bus_distribute_available_resources(bridge->subordinate,
-					       add_list, available_io,
-					       available_mmio,
-					       available_mmio_pref);
+					       add_list, available);
 }
 
 static bool pci_bridge_resources_not_assigned(struct pci_dev *dev)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 275df4058767..723e9cede69d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -119,7 +119,8 @@ enum {
 #define PCI_CB_BRIDGE_MEM_1_WINDOW	(PCI_BRIDGE_RESOURCES + 3)
 
 /* Total number of bridge resources for P2P and CardBus */
-#define PCI_BRIDGE_RESOURCE_NUM 4
+#define PCI_P2P_BRIDGE_RESOURCE_NUM	3
+#define PCI_BRIDGE_RESOURCE_NUM		4
 
 	/* Resources assigned to buses behind the bridge */
 	PCI_BRIDGE_RESOURCES,
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 21/24] PCI: Refactor remove_dev_resources() to use pbus_select_window()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (19 preceding siblings ...)
  2025-08-22 14:56 ` [PATCH 20/24] PCI: Refactor distributing available memory to use loops Ilpo Järvinen
@ 2025-08-22 14:56 ` Ilpo Järvinen
  2025-08-22 14:56 ` [PATCH 22/24] PCI: Add pci_setup_one_bridge_window() Ilpo Järvinen
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:56 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Convert remove_dev_resources() to use pbus_select_window(). As
'available' is not the real resources, the index has to be adjusted as
only bridge resource counterparts are present in the 'available' array.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 34 +++++++++-------------------------
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ee2f2c78d8c9..ece533181ff1 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2061,34 +2061,18 @@ static void remove_dev_resource(struct resource *avail, struct pci_dev *dev,
 static void remove_dev_resources(struct pci_dev *dev,
 				 struct resource available[PCI_P2P_BRIDGE_RESOURCE_NUM])
 {
-	struct resource *mmio_pref = &available[PCI_BUS_BRIDGE_PREF_MEM_WINDOW];
-	struct resource *res;
+	struct resource *res, *b_win;
+	int idx;
 
 	pci_dev_for_each_resource(dev, res) {
-		if (resource_type(res) == IORESOURCE_IO) {
-			remove_dev_resource(&available[PCI_BUS_BRIDGE_IO_WINDOW],
-					    dev, res);
-		} else if (resource_type(res) == IORESOURCE_MEM) {
+		b_win = pbus_select_window(dev->bus, res);
+		if (!b_win)
+			continue;
 
-			/*
-			 * Make sure prefetchable memory is reduced from
-			 * the correct resource. Specifically we put 32-bit
-			 * prefetchable memory in non-prefetchable window
-			 * if there is a 64-bit prefetchable window.
-			 *
-			 * See comments in __pci_bus_size_bridges() for
-			 * more information.
-			 */
-			if ((res->flags & IORESOURCE_PREFETCH) &&
-			    ((res->flags & IORESOURCE_MEM_64) ==
-			     (mmio_pref->flags & IORESOURCE_MEM_64))) {
-				remove_dev_resource(&available[PCI_BUS_BRIDGE_PREF_MEM_WINDOW],
-						    dev, res);
-			} else {
-				remove_dev_resource(&available[PCI_BUS_BRIDGE_MEM_WINDOW],
-						    dev, res);
-			}
-		}
+		idx = pci_resource_num(dev->bus->self, b_win);
+		idx -= PCI_BRIDGE_RESOURCES;
+
+		remove_dev_resource(&available[idx], dev, res);
 	}
 }
 
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 22/24] PCI: Add pci_setup_one_bridge_window()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (20 preceding siblings ...)
  2025-08-22 14:56 ` [PATCH 21/24] PCI: Refactor remove_dev_resources() to use pbus_select_window() Ilpo Järvinen
@ 2025-08-22 14:56 ` Ilpo Järvinen
  2025-08-22 14:56 ` [PATCH 23/24] PCI: Pass bridge window to pci_bus_release_bridge_resources() Ilpo Järvinen
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:56 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

pci_bridge_release_resources() contains a resource type hack to work
around the unsuitable __pci_setup_bridge() interface. Extract the
switch statement that picks the correct bridge window setup function
from pci_claim_bridge_resource() into pci_setup_one_bridge_window() and
use it also in pci_bridge_release_resources().

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 36 +++++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ece533181ff1..f5b0274bde0a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -953,6 +953,23 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
 	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
 
+static void pci_setup_one_bridge_window(struct pci_dev *bridge, int resno)
+{
+	switch (resno) {
+	case PCI_BRIDGE_IO_WINDOW:
+		pci_setup_bridge_io(bridge);
+		break;
+	case PCI_BRIDGE_MEM_WINDOW:
+		pci_setup_bridge_mmio(bridge);
+		break;
+	case PCI_BRIDGE_PREF_MEM_WINDOW:
+		pci_setup_bridge_mmio_pref(bridge);
+		break;
+	default:
+		return;
+	}
+}
+
 void __weak pcibios_setup_bridge(struct pci_bus *bus, unsigned long type)
 {
 }
@@ -987,19 +1004,7 @@ int pci_claim_bridge_resource(struct pci_dev *bridge, int i)
 	if (pci_bus_clip_resource(bridge, i))
 		ret = pci_claim_resource(bridge, i);
 
-	switch (i) {
-	case PCI_BRIDGE_IO_WINDOW:
-		pci_setup_bridge_io(bridge);
-		break;
-	case PCI_BRIDGE_MEM_WINDOW:
-		pci_setup_bridge_mmio(bridge);
-		break;
-	case PCI_BRIDGE_PREF_MEM_WINDOW:
-		pci_setup_bridge_mmio_pref(bridge);
-		break;
-	default:
-		return -EINVAL;
-	}
+	pci_setup_one_bridge_window(bridge, i);
 
 	return ret;
 }
@@ -1839,10 +1844,7 @@ static void pci_bridge_release_resources(struct pci_bus *bus,
 	if (ret)
 		return;
 
-	/* Avoiding touch the one without PREF */
-	if (type & IORESOURCE_PREFETCH)
-		type = IORESOURCE_PREFETCH;
-	__pci_setup_bridge(bus, type);
+	pci_setup_one_bridge_window(dev, PCI_BRIDGE_RESOURCES + idx);
 }
 
 enum release_type {
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 23/24] PCI: Pass bridge window to pci_bus_release_bridge_resources()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (21 preceding siblings ...)
  2025-08-22 14:56 ` [PATCH 22/24] PCI: Add pci_setup_one_bridge_window() Ilpo Järvinen
@ 2025-08-22 14:56 ` Ilpo Järvinen
  2025-08-22 14:56 ` [PATCH 24/24] PCI: Alter misleading recursion " Ilpo Järvinen
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:56 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

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>
---
 drivers/pci/setup-bus.c | 69 ++++++++++++++++-------------------------
 1 file changed, 27 insertions(+), 42 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index f5b0274bde0a..9c69a84f2b23 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -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;
 
+	idx = pci_resource_num(dev, b_win);
+
 	/* If there are children, release them all */
-	release_child_resources(r);
+	release_child_resources(b_win);
 
-	ret = pci_release_resource(dev, PCI_BRIDGE_RESOURCES + idx);
+	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 */
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 24/24] PCI: Alter misleading recursion to pci_bus_release_bridge_resources()
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (22 preceding siblings ...)
  2025-08-22 14:56 ` [PATCH 23/24] PCI: Pass bridge window to pci_bus_release_bridge_resources() Ilpo Järvinen
@ 2025-08-22 14:56 ` Ilpo Järvinen
  2025-08-22 15:04 ` [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
  2025-08-27 22:36 ` Bjorn Helgaas
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 14:56 UTC (permalink / raw)
  To: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel
  Cc: Michał Winiarski, linuxppc-dev, Ilpo Järvinen

Recursing into pci_bus_release_bridge_resources() should not alter
rel_type because it makes no sense to change the release type within
the recursion call chain. A literal "whole_subtree" is passed into the
recursion instead of "rel_type" parameter which is misleading as the
release type should remain the same throughout the entire operation.

This is not a correctness issue because of the preceding if () that
only allows the recursion to happen if rel_type is "whole_subtree".
Still, replace the non-intuitive parameter with direct passing of
"rel_type".

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/setup-bus.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 9c69a84f2b23..0fbdb031bc3d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1855,7 +1855,7 @@ static void pci_bus_release_bridge_resources(struct pci_bus *bus,
 			if (res->parent != b_win)
 				continue;
 
-			pci_bus_release_bridge_resources(b, res, whole_subtree);
+			pci_bus_release_bridge_resources(b, res, rel_type);
 		}
 	}
 
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/24] PCI: Bridge window selection improvements
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (23 preceding siblings ...)
  2025-08-22 14:56 ` [PATCH 24/24] PCI: Alter misleading recursion " Ilpo Järvinen
@ 2025-08-22 15:04 ` Ilpo Järvinen
  2025-08-27 22:36 ` Bjorn Helgaas
  25 siblings, 0 replies; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-22 15:04 UTC (permalink / raw)
  To: linux-pci
  Cc: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, LKML,
	Michał Winiarski, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 7513 bytes --]

On Fri, 22 Aug 2025, Ilpo Järvinen wrote:

> This series is based on top of the three resource fitting and
> assignment algorithm fixes (v3).

I realized I didn't include a link to those patches. It's this series: 

https://lore.kernel.org/linux-pci/20250822123359.16305-1-ilpo.jarvinen@linux.intel.com/

I'm sorry about the extra hassle.

-- 
 i.

> PCI resource fitting and assignment code needs to find the bridge
> window a resource belongs to in multiple places, yet, no common
> function for that exists. Thus, each site has its own version of
> the decision, each with their own corner cases, misbehaviors, and
> some resulting in complex interfaces between internal functions.
> 
> This series tries to rectify the situation by adding two new functions
> to select the bridge window. To support these functions, bridge windows
> must always contain their type information in flags which requires
> modifying the flags behavior for bridge window resources.
> 
> I've hit problems related to zeroed resource flags so many times by now
> that I've already lost count which has highlighted over and over again
> that clearing type information is not a good idea. As also proven by
> some changes of this series, retaining the flags for bridge windows
> ended up fixing existing issues (although kernel ended up recovering
> from the worst problem graciously and the other just results in dormant
> code).
> 
> This series only changes resource flags behavior for bridge windows.
> The sensible direction is to make a similar change for the other
> resources as well eventually but making that change involves more
> uncertainty and is not strictly necessary yet. Driver code outside of
> PCI core could have assumptions about the flags, whereas bridge windows
> are mostly internal to PCI core code (or should be, sane endpoint
> drivers shouldn't be messing with the bridge windows). Thus, limiting
> the flags behavior changes to bridge windows for now is safer than
> attempting full behavioral change in a single step.
> 
> 
> I've tried to look out for any trouble that code under arch/ could
> cause after the flags start to behave differently and therefore ended
> up consolidating arch/ code to use pci_enable_resources(). My
> impression is that strictly speaking only the MIPS code would break
> similar to PCI core's copy of pci_enable_resources(), the others were
> much more lax in checking so they'd likely keep working but
> consolidation seemed still the best approach there as the enable checks
> seemed diverging for no apparent reason.
> 
> Most sites are converted by this change. There are three known places
> that are not yet converted:
> 
>   - fail_type based logic in __assign_resources_sorted():
>     I'm expecting to cover this along with the resizable BAR
>     changes as I need to change the fallback logic anyway (one
>     of the motivators what got me started with this series,
>     I need an easy way to acquire the bridge window during
>     retries/fallbacks if maximum sized BARs do not fit, which
>     is what this series provides).
> 
>   - Failure detection after BAR resize: Keeps using the type
>     based heuristic for failure detection. It isn't very clear how
>     to decide which assignment failures should be counted and which
>     not. There could be pre-existing failures that keep happening
>     that end up blocking BAR resize but that's no worse than behavior
>     before this series. How to identify the relevant failures does
>     not look straightforward given the current structures. This
>     clearly needs more thought before coding any solution.
> 
>   - resource assignment itself: This is a very complex change
>     due to bus and kernel resources abstractions and might not be
>     realistic any time soon.
> 
> I'd have wanted to also get rid of pci_bridge_check_ranges() that
> (re)adds type information which seemed now unnecessary. It turns out,
> however, that root windows still require so it will have to wait for
> now.
> 
> This change has been tested on a large number of machine I've access to
> which come with heterogeneous PCI configurations. Some resources
> retained their original addresses now also with pci=realloc because
> this series fixed the unnecessary release(+assign) of those resources.
> Other than that, nothing worth of note from that testing.
> 
> 
> My test coverage is x86 centric unfortunately so I'd appreciate if
> somebody with access to non-x86 archs takes the effort to test this
> series.
> 
> Info for potential testers:
> 
> Usually, it's enough to gather lspci -vvv pre and post the series, and
> use diff to see whether the resources remained the same and also check
> that the same drivers are still bound to the devices to confirm that
> devices got properly enabled (also shown by lspci -vvv). I normally
> test both with and without pci=realloc. In case of a trouble, besides
> lspci -vvv output, providing pre and post dmesg and /proc/iomem
> contents would be helpful, please take the dmesg with dyndbg="file
> drivers/pci/*.c +p" on the kernel cmdline.
> 
> Ilpo Järvinen (24):
>   m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
>   sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
>   MIPS: PCI: Use pci_enable_resources()
>   PCI: Move find_bus_resource_of_type() earlier
>   PCI: Refactor find_bus_resource_of_type() logic checks
>   PCI: Always claim bridge window before its setup
>   PCI: Disable non-claimed bridge window
>   PCI: Use pci_release_resource() instead of release_resource()
>   PCI: Enable bridge even if bridge window fails to assign
>   PCI: Preserve bridge window resource type flags
>   PCI: Add defines for bridge window indexing
>   PCI: Add bridge window selection functions
>   PCI: Fix finding bridge window in pci_reassign_bridge_resources()
>   PCI: Warn if bridge window cannot be released when resizing BAR
>   PCI: Use pbus_select_window() during BAR resize
>   PCI: Use pbus_select_window_for_type() during IO window sizing
>   PCI: Rename resource variable from r to res
>   PCI: Use pbus_select_window() in space available checker
>   PCI: Use pbus_select_window_for_type() during mem window sizing
>   PCI: Refactor distributing available memory to use loops
>   PCI: Refactor remove_dev_resources() to use pbus_select_window()
>   PCI: Add pci_setup_one_bridge_window()
>   PCI: Pass bridge window to pci_bus_release_bridge_resources()
>   PCI: Alter misleading recursion to pci_bus_release_bridge_resources()
> 
>  arch/m68k/kernel/pcibios.c   |  39 +-
>  arch/mips/pci/pci-legacy.c   |  38 +-
>  arch/sparc/kernel/leon_pci.c |  27 --
>  arch/sparc/kernel/pci.c      |  27 --
>  arch/sparc/kernel/pcic.c     |  27 --
>  drivers/pci/bus.c            |   3 +
>  drivers/pci/pci-sysfs.c      |  27 +-
>  drivers/pci/pci.h            |   8 +-
>  drivers/pci/probe.c          |  35 +-
>  drivers/pci/setup-bus.c      | 798 ++++++++++++++++++-----------------
>  drivers/pci/setup-res.c      |  46 +-
>  include/linux/pci.h          |   5 +-
>  12 files changed, 504 insertions(+), 576 deletions(-)
> 
> 
> base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
> prerequisite-patch-id: 801e8dd3aa9847d4945cb7d8958574a6006004ab
> prerequisite-patch-id: 0233311f04e3ea013676b6cc00626410bbe11e41
> prerequisite-patch-id: 9841faf37d56c1acf1167559613e862ef62e509d
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/24] PCI: Bridge window selection improvements
  2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
                   ` (24 preceding siblings ...)
  2025-08-22 15:04 ` [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
@ 2025-08-27 22:36 ` Bjorn Helgaas
  2025-08-28 16:47   ` Ilpo Järvinen
  2025-09-01  8:38   ` Geert Uytterhoeven
  25 siblings, 2 replies; 31+ messages in thread
From: Bjorn Helgaas @ 2025-08-27 22:36 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel,
	Michał Winiarski, linuxppc-dev

On Fri, Aug 22, 2025 at 05:55:41PM +0300, Ilpo Järvinen wrote:
> This series is based on top of the three resource fitting and
> assignment algorithm fixes (v3).
> 
> PCI resource fitting and assignment code needs to find the bridge
> window a resource belongs to in multiple places, yet, no common
> function for that exists. Thus, each site has its own version of
> the decision, each with their own corner cases, misbehaviors, and
> some resulting in complex interfaces between internal functions.
> ...

> I've tried to look out for any trouble that code under arch/ could
> cause after the flags start to behave differently and therefore ended
> up consolidating arch/ code to use pci_enable_resources(). My
> impression is that strictly speaking only the MIPS code would break
> similar to PCI core's copy of pci_enable_resources(), the others were
> much more lax in checking so they'd likely keep working but
> consolidation seemed still the best approach there as the enable checks
> seemed diverging for no apparent reason.
> ...

>   m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
>   sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
>   MIPS: PCI: Use pci_enable_resources()
> ...

>  arch/m68k/kernel/pcibios.c   |  39 +-
>  arch/mips/pci/pci-legacy.c   |  38 +-
>  arch/sparc/kernel/leon_pci.c |  27 --
>  arch/sparc/kernel/pci.c      |  27 --
>  arch/sparc/kernel/pcic.c     |  27 --
> ...

I love the fact that you're doing so much cleanup.  Thanks for all the
work in this!

Obviously all this code is quite sensitive, so I put it on
pci/resource to get more exposure in -next.  If it turns out that we
trip over things or just don't feel comfortable yet for v6.18, we can
always defer this part until the next cycle.

I will also watch for acks from the m68k, mips, and sparc maintainers
for those pieces.

Bjorn

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 03/24] MIPS: PCI: Use pci_enable_resources()
  2025-08-22 14:55 ` [PATCH 03/24] MIPS: PCI: Use pci_enable_resources() Ilpo Järvinen
@ 2025-08-28  6:57   ` Thomas Bogendoerfer
  0 siblings, 0 replies; 31+ messages in thread
From: Thomas Bogendoerfer @ 2025-08-28  6:57 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Christian König, Yinghai Lu, Igor Mammedov,
	Rafael J . Wysocki, Jonathan Cameron, Lorenzo Pieralisi,
	Krzysztof Wilczyński, linux-kernel, Michał Winiarski,
	linuxppc-dev

On Fri, Aug 22, 2025 at 05:55:44PM +0300, Ilpo Järvinen wrote:
> pci-legacy.c under MIPS has a copy of pci_enable_resources() named as
> pcibios_enable_resources(). Having own copy of same functionality could
> lead to inconsistencies in behavior, especially now as
> pci_enable_resources() and the bridge window resource flags behavior
> are going to be altered by upcoming changes.
> 
> The check for !r->start && r->end is already covered by the more
> generic checks done in pci_enable_resources().
> 
> Call pci_enable_resources() from MIPS's pcibios_enable_device() and
> remove pcibios_enable_resources().
> 
> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> ---
>  arch/mips/pci/pci-legacy.c | 38 ++------------------------------------
>  1 file changed, 2 insertions(+), 36 deletions(-)

Acked-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/24] PCI: Bridge window selection improvements
  2025-08-27 22:36 ` Bjorn Helgaas
@ 2025-08-28 16:47   ` Ilpo Järvinen
  2025-08-28 17:31     ` Bjorn Helgaas
  2025-09-01  8:38   ` Geert Uytterhoeven
  1 sibling, 1 reply; 31+ messages in thread
From: Ilpo Järvinen @ 2025-08-28 16:47 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, LKML,
	Michał Winiarski, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 2845 bytes --]

On Wed, 27 Aug 2025, Bjorn Helgaas wrote:

> On Fri, Aug 22, 2025 at 05:55:41PM +0300, Ilpo Järvinen wrote:
> > This series is based on top of the three resource fitting and
> > assignment algorithm fixes (v3).
> > 
> > PCI resource fitting and assignment code needs to find the bridge
> > window a resource belongs to in multiple places, yet, no common
> > function for that exists. Thus, each site has its own version of
> > the decision, each with their own corner cases, misbehaviors, and
> > some resulting in complex interfaces between internal functions.
> > ...
> 
> > I've tried to look out for any trouble that code under arch/ could
> > cause after the flags start to behave differently and therefore ended
> > up consolidating arch/ code to use pci_enable_resources(). My
> > impression is that strictly speaking only the MIPS code would break
> > similar to PCI core's copy of pci_enable_resources(), the others were
> > much more lax in checking so they'd likely keep working but
> > consolidation seemed still the best approach there as the enable checks
> > seemed diverging for no apparent reason.
> > ...
> 
> >   m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
> >   sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
> >   MIPS: PCI: Use pci_enable_resources()
> > ...
> 
> >  arch/m68k/kernel/pcibios.c   |  39 +-
> >  arch/mips/pci/pci-legacy.c   |  38 +-
> >  arch/sparc/kernel/leon_pci.c |  27 --
> >  arch/sparc/kernel/pci.c      |  27 --
> >  arch/sparc/kernel/pcic.c     |  27 --
> > ...
> 
> I love the fact that you're doing so much cleanup.  Thanks for all the
> work in this!
>
> Obviously all this code is quite sensitive, so I put it on
> pci/resource to get more exposure in -next.

Thanks. I really appreciate the opportunity to have it in next for extra 
testing as my testing, while relatively extensive, still has its limits.

I'll need to do minor corrections into a few intermediate patches though 
to ensure bisectability, we really want to make this as bisectable as 
possible. In other words, I've found 2 relatively small issues in them 
which won't change the end result when the whole series is complete and 
fixed some small grammar errors in the changelogs.

I see you made some corrections so I'm not sure what's the best course of 
action here to update them. Should I just send v2 normally and you deal 
with your changes while replacing v1 with v2?

> If it turns out that we
> trip over things or just don't feel comfortable yet for v6.18, we can
> always defer this part until the next cycle.

I agree, and really please don't hesitate to postpone if it turns out 
necessary.

> I will also watch for acks from the m68k, mips, and sparc maintainers
> for those pieces.
> 
> Bjorn
> 

-- 
 i.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/24] PCI: Bridge window selection improvements
  2025-08-28 16:47   ` Ilpo Järvinen
@ 2025-08-28 17:31     ` Bjorn Helgaas
  0 siblings, 0 replies; 31+ messages in thread
From: Bjorn Helgaas @ 2025-08-28 17:31 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Andreas Larsson, Bjorn Helgaas, David S. Miller,
	Geert Uytterhoeven, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, LKML,
	Michał Winiarski, linuxppc-dev

On Thu, Aug 28, 2025 at 07:47:06PM +0300, Ilpo Järvinen wrote:
> On Wed, 27 Aug 2025, Bjorn Helgaas wrote:
> > On Fri, Aug 22, 2025 at 05:55:41PM +0300, Ilpo Järvinen wrote:
> > > This series is based on top of the three resource fitting and
> > > assignment algorithm fixes (v3).
> > > 
> > > PCI resource fitting and assignment code needs to find the bridge
> > > window a resource belongs to in multiple places, yet, no common
> > > function for that exists. Thus, each site has its own version of
> > > the decision, each with their own corner cases, misbehaviors, and
> > > some resulting in complex interfaces between internal functions.
> > > ...

> I'll need to do minor corrections into a few intermediate patches though 
> to ensure bisectability, we really want to make this as bisectable as 
> possible. In other words, I've found 2 relatively small issues in them 
> which won't change the end result when the whole series is complete and 
> fixed some small grammar errors in the changelogs.
> 
> I see you made some corrections so I'm not sure what's the best course of 
> action here to update them. Should I just send v2 normally and you deal 
> with your changes while replacing v1 with v2?

That would work for me.  Or if you picked the patches from
pci/resource and posted a v2 based on them, that would be even easier
for me.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 00/24] PCI: Bridge window selection improvements
  2025-08-27 22:36 ` Bjorn Helgaas
  2025-08-28 16:47   ` Ilpo Järvinen
@ 2025-09-01  8:38   ` Geert Uytterhoeven
  1 sibling, 0 replies; 31+ messages in thread
From: Geert Uytterhoeven @ 2025-09-01  8:38 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Ilpo Järvinen, Andreas Larsson, Bjorn Helgaas,
	David S. Miller, linux-m68k, linux-mips, linux-pci, sparclinux,
	Thomas Bogendoerfer, Christian König, Yinghai Lu,
	Igor Mammedov, Rafael J . Wysocki, Jonathan Cameron,
	Lorenzo Pieralisi, Krzysztof Wilczyński, linux-kernel,
	Michał Winiarski, linuxppc-dev, Greg Ungerer

CC Greg

On Thu, 28 Aug 2025 at 00:36, Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Fri, Aug 22, 2025 at 05:55:41PM +0300, Ilpo Järvinen wrote:
> > This series is based on top of the three resource fitting and
> > assignment algorithm fixes (v3).
> >
> > PCI resource fitting and assignment code needs to find the bridge
> > window a resource belongs to in multiple places, yet, no common
> > function for that exists. Thus, each site has its own version of
> > the decision, each with their own corner cases, misbehaviors, and
> > some resulting in complex interfaces between internal functions.
> > ...
>
> > I've tried to look out for any trouble that code under arch/ could
> > cause after the flags start to behave differently and therefore ended
> > up consolidating arch/ code to use pci_enable_resources(). My
> > impression is that strictly speaking only the MIPS code would break
> > similar to PCI core's copy of pci_enable_resources(), the others were
> > much more lax in checking so they'd likely keep working but
> > consolidation seemed still the best approach there as the enable checks
> > seemed diverging for no apparent reason.
> > ...
>
> >   m68k/PCI: Use pci_enable_resources() in pcibios_enable_device()
> >   sparc/PCI: Remove pcibios_enable_device() as they do nothing extra
> >   MIPS: PCI: Use pci_enable_resources()
> > ...
>
> >  arch/m68k/kernel/pcibios.c   |  39 +-
> >  arch/mips/pci/pci-legacy.c   |  38 +-
> >  arch/sparc/kernel/leon_pci.c |  27 --
> >  arch/sparc/kernel/pci.c      |  27 --
> >  arch/sparc/kernel/pcic.c     |  27 --
> > ...
>
> I love the fact that you're doing so much cleanup.  Thanks for all the
> work in this!
>
> Obviously all this code is quite sensitive, so I put it on
> pci/resource to get more exposure in -next.  If it turns out that we
> trip over things or just don't feel comfortable yet for v6.18, we can
> always defer this part until the next cycle.
>
> I will also watch for acks from the m68k, mips, and sparc maintainers
> for those pieces.

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2025-09-01  8:39 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-22 14:55 [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 01/24] m68k/PCI: Use pci_enable_resources() in pcibios_enable_device() Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 02/24] sparc/PCI: Remove pcibios_enable_device() as they do nothing extra Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 03/24] MIPS: PCI: Use pci_enable_resources() Ilpo Järvinen
2025-08-28  6:57   ` Thomas Bogendoerfer
2025-08-22 14:55 ` [PATCH 04/24] PCI: Move find_bus_resource_of_type() earlier Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 05/24] PCI: Refactor find_bus_resource_of_type() logic checks Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 06/24] PCI: Always claim bridge window before its setup Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 07/24] PCI: Disable non-claimed bridge window Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 08/24] PCI: Use pci_release_resource() instead of release_resource() Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 09/24] PCI: Enable bridge even if bridge window fails to assign Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 10/24] PCI: Preserve bridge window resource type flags Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 11/24] PCI: Add defines for bridge window indexing Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 12/24] PCI: Add bridge window selection functions Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 13/24] PCI: Fix finding bridge window in pci_reassign_bridge_resources() Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 14/24] PCI: Warn if bridge window cannot be released when resizing BAR Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 15/24] PCI: Use pbus_select_window() during BAR resize Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 16/24] PCI: Use pbus_select_window_for_type() during IO window sizing Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 17/24] PCI: Rename resource variable from r to res Ilpo Järvinen
2025-08-22 14:55 ` [PATCH 18/24] PCI: Use pbus_select_window() in space available checker Ilpo Järvinen
2025-08-22 14:56 ` [PATCH 19/24] PCI: Use pbus_select_window_for_type() during mem window sizing Ilpo Järvinen
2025-08-22 14:56 ` [PATCH 20/24] PCI: Refactor distributing available memory to use loops Ilpo Järvinen
2025-08-22 14:56 ` [PATCH 21/24] PCI: Refactor remove_dev_resources() to use pbus_select_window() Ilpo Järvinen
2025-08-22 14:56 ` [PATCH 22/24] PCI: Add pci_setup_one_bridge_window() Ilpo Järvinen
2025-08-22 14:56 ` [PATCH 23/24] PCI: Pass bridge window to pci_bus_release_bridge_resources() Ilpo Järvinen
2025-08-22 14:56 ` [PATCH 24/24] PCI: Alter misleading recursion " Ilpo Järvinen
2025-08-22 15:04 ` [PATCH 00/24] PCI: Bridge window selection improvements Ilpo Järvinen
2025-08-27 22:36 ` Bjorn Helgaas
2025-08-28 16:47   ` Ilpo Järvinen
2025-08-28 17:31     ` Bjorn Helgaas
2025-09-01  8:38   ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).