From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Ville Syrjälä" <ville.syrjala@linux.intel.com>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Sasha Levin" <sashal@kernel.org>
Subject: [PATCH 6.6.y 1/2] PCI: Fix Resizable BAR restore order
Date: Tue, 29 Sep 2026 20:20:19 -0400 [thread overview]
Message-ID: <20260930002020.2934016-1-sashal@kernel.org> (raw)
In-Reply-To: <2026092923-escalator-elephant-9055@gregkh>
From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
[ Upstream commit 5528fd38f230c906fcebb202cc94fbb8ed8f122a ]
The commit 337b1b566db0 ("PCI: Fix restoring BARs on BAR resize rollback
path") changed BAR resize to layer rebar code and resource setup/restore
code cleanly. Unfortunately, it did not consider how the value of the BAR
Size field impacts the read-only bits in the Base Address Register (PCIe7
spec, sec. 7.8.6.3). That is, it very much matters in which order the BAR
Size and Base Address Register are restored.
Post-337b1b566db0 ("PCI: Fix restoring BARs on BAR resize rollback path")
during BAR resize rollback, pci_do_resource_release_and_resize() attempts
to restore the old address to the BAR that was resized, but it can fail to
setup the address correctly if the address has low bits set that collide
with the bits that are still read-only. As a result, kernel's resource and
BAR will be out-of-sync.
Fix this by restoring BAR Size before rolling back the resource changes and
restoring the BAR.
Fixes: 337b1b566db0 ("PCI: Fix restoring BARs on BAR resize rollback path")
Reported-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://lore.kernel.org/linux-pci/aW_w1oFQCzUxGYtu@intel.com/
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260121131417.9582-3-ilpo.jarvinen@linux.intel.com
[6.12 dependency preparation for d58384c22739848efe14b34e9586e4f1242f33c0:
Keep the existing memory-decoding and supported-size checks in rebar.c.
Move BAR size programming and rollback into the resource release helper,
so the old size is restored before restoring BAR addresses.
Use the assigned parent window to select resources for release, retaining
the old flags-based selection when the resized BAR has no parent. Provide
file-local macro mappings for the follow-up's bridge reassignment and
resource assignment checks; no functions are added.
Retain the upstream pre-target pci_bus_sem placement to allow the target
to apply without conflicts. This preparatory dependency must be applied
together with d58384c22739848efe14b34e9586e4f1242f33c0, which takes the lock
before releasing resources and assigns released BARs on root buses.]
Stable-dep-of: d58384c22739 ("PCI: Fix BAR resize for devices on a root bus")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pci/rebar.c | 19 +------------------
drivers/pci/setup-bus.c | 39 ++++++++++++++++++++++++++++++++-------
2 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/drivers/pci/rebar.c b/drivers/pci/rebar.c
index 920ef3ab4bda3..d5e432d084e51 100644
--- a/drivers/pci/rebar.c
+++ b/drivers/pci/rebar.c
@@ -177,7 +177,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
int exclude_bars)
{
struct pci_host_bridge *host;
- int old, ret;
u32 sizes;
u16 cmd;
@@ -197,22 +196,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
if (!(sizes & BIT(size)))
return -EINVAL;
- old = pci_rebar_get_current_size(dev, resno);
- if (old < 0)
- return old;
-
- ret = pci_rebar_set_size(dev, resno, size);
- if (ret)
- return ret;
-
- ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
- if (ret)
- goto error_resize;
-
- return 0;
-
-error_resize:
- pci_rebar_set_size(dev, resno, old);
- return ret;
+ return pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
}
EXPORT_SYMBOL(pci_resize_resource);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 98d0038e32ef9..fc752f5ef3f8d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2292,6 +2292,11 @@ static int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long t
return 0;
}
+/* Keep the resize follow-up compatible with the 6.12 resource helpers. */
+#define pbus_reassign_bridge_resources(bus, res, saved) \
+ pci_reassign_bridge_resources((bus)->self, (res)->flags, (saved))
+#define resource_assigned(res) ((res)->parent != NULL)
+
int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size,
int exclude_bars)
{
@@ -2299,12 +2304,20 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
unsigned long flags = res->flags;
struct pci_dev_resource *dev_res;
struct pci_bus *bus = pdev->bus;
- struct resource *r;
+ struct resource *b_win, *r;
LIST_HEAD(saved);
unsigned int i;
- int ret = 0;
+ int old, ret;
- down_read(&pci_bus_sem);
+ b_win = res->parent;
+
+ old = pci_rebar_get_current_size(pdev, resno);
+ if (old < 0)
+ return old;
+
+ ret = pci_rebar_set_size(pdev, resno, size);
+ if (ret)
+ return ret;
pci_dev_for_each_resource(pdev, r, i) {
if (i >= PCI_BRIDGE_RESOURCES)
@@ -2313,7 +2326,10 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
if (exclude_bars & BIT(i))
continue;
- if (!pci_resource_len(pdev, i) || r->flags != flags)
+ if (!pci_resource_len(pdev, i))
+ continue;
+
+ if (b_win ? r->parent != b_win : r->flags != flags)
continue;
ret = add_to_list(&saved, pdev, r, 0, 0);
@@ -2327,7 +2343,8 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
if (!bus->self)
goto out;
- ret = pci_reassign_bridge_resources(bus->self, res->flags, &saved);
+ down_read(&pci_bus_sem);
+ ret = pbus_reassign_bridge_resources(bus, res, &saved);
if (ret)
goto restore;
@@ -2337,14 +2354,22 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
return ret;
restore:
- /* Revert to the old configuration */
+ /*
+ * Revert to the old configuration.
+ *
+ * BAR Size must be restored first because it affects the read-only
+ * bits in BAR (the old address might not be restorable otherwise
+ * due to low address bits).
+ */
+ pci_rebar_set_size(pdev, resno, old);
+
list_for_each_entry(dev_res, &saved, list) {
struct resource *res = dev_res->res;
struct pci_dev *dev = dev_res->dev;
i = res - dev->resource;
- if (res->parent) {
+ if (resource_assigned(res)) {
release_child_resources(res);
pci_release_resource(dev, i);
}
--
2.53.0
next prev parent reply other threads:[~2026-09-30 0:20 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 8:28 FAILED: patch "[PATCH] PCI: Fix BAR resize for devices on a root bus" failed to apply to 6.6-stable tree gregkh
2026-09-30 0:20 ` Sasha Levin [this message]
2026-09-30 0:20 ` [PATCH 6.6.y 2/2] PCI: Fix BAR resize for devices on a root bus Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930002020.2934016-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=bhelgaas@google.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=stable@vger.kernel.org \
--cc=ville.syrjala@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.