diff mbox series

PCI: Fix BAR resizing when VF BARs are assigned

Message ID 20241112134225.9837-1-ilpo.jarvinen@linux.intel.com (mailing list archive)
State New
Headers show
Series PCI: Fix BAR resizing when VF BARs are assigned | expand

Commit Message

Ilpo Järvinen Nov. 12, 2024, 1:42 p.m. UTC
__resource_resize_store() attempts to release all resources of the
device before attempting the resize. The loop, however, only covers
standard BARs (< PCI_STD_NUM_BARS). If a device has VF BARs that are
assigned, pci_reassign_bridge_resources() finds the bridge window still
has some assigned child resources and returns -NOENT which makes
pci_resize_resource() to detect an error and abort the resize.

Similarly, an assigned Expansion ROM resource prevents the resize.

Change the release loop to cover both the VF BARs and Expansion ROM
which allows the resize operation to release the bridge windows and
attempt to assigned them again with the different size.

As __resource_resize_store() checks first that no driver is bound to
the PCI device before resizing is allowed, SR-IOV cannot be enabled
during resize so it is safe to release also the IOV resources.

Fixes: 8bb705e3e79d ("PCI: Add pci_resize_resource() for resizing BARs")
Reported-by: Michał Winiarski <michal.winiarski@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
 drivers/pci/pci-sysfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Ilpo Järvinen Nov. 12, 2024, 2:28 p.m. UTC | #1
On Tue, 12 Nov 2024, Christian König wrote:

> Am 12.11.24 um 14:42 schrieb Ilpo Järvinen:
> 
> __resource_resize_store() attempts to release all resources of the
> device before attempting the resize. The loop, however, only covers
> standard BARs (< PCI_STD_NUM_BARS). If a device has VF BARs that are
> assigned, pci_reassign_bridge_resources() finds the bridge window still
> has some assigned child resources and returns -NOENT which makes
> pci_resize_resource() to detect an error and abort the resize.
> 
> 
> Looks good in general, but a couple of comments.
> 
> Similarly, an assigned Expansion ROM resource prevents the resize.
> 
> 
> Expansion ROMs were intentionally left untouched by the initial patch since those are
> usually 32bit resources and the resize was implemented only for 64bit BARs.
> 
> Change the release loop to cover both the VF BARs and Expansion ROM
> which allows the resize operation to release the bridge windows and
> attempt to assigned them again with the different size.
> 
> 
> I'm not sure if Expansion ROMs should be touched here. Those are 32bit resources
> usually and notoriously broken in the ACPI tables.
>
> What I've seen multiple times that after releasing them you can't move nor assign
> them again to their original position.
> 
> Background is that some ACPI table denotes the location of the ROM as reserved and we
> only accept the Expansion ROM at that location because of a quirk (which is of course
> not applied when you resize).
> 
> On the other hand do we have use cases for resizing 32bit BARs? So far we resized
> those only by accident.

Thanks for taking a look!

This is not about resizing 32bit BARs.

Is that somehow enforced so they cannot end up into the same bridge 
window? Because we can only resize a bridge window if we release all its 
child resources.

> As __resource_resize_store() checks first that no driver is bound to
> the PCI device before resizing is allowed, SR-IOV cannot be enabled
> during resize so it is safe to release also the IOV resources.
> 
> Fixes: 8bb705e3e79d ("PCI: Add pci_resize_resource() for resizing BARs")
> 
> 
> The code in question was added by 91fa127794ac ("PCI: Expose PCIe Resizable BAR
> support via sysfs").

Oh right. I don't know why I ended up picking that other commit (sure, I 
was also looking that other diff but maybe it was just a copy-paste 
error).
Ilpo Järvinen Nov. 12, 2024, 4:16 p.m. UTC | #2
On Tue, 12 Nov 2024, Christian König wrote:

> Am 12.11.24 um 15:28 schrieb Ilpo Järvinen:
> 
> On Tue, 12 Nov 2024, Christian König wrote:
> 
> Am 12.11.24 um 14:42 schrieb Ilpo Järvinen:
> 
> __resource_resize_store() attempts to release all resources of the
> device before attempting the resize. The loop, however, only covers
> standard BARs (< PCI_STD_NUM_BARS). If a device has VF BARs that are
> assigned, pci_reassign_bridge_resources() finds the bridge window still
> has some assigned child resources and returns -NOENT which makes
> pci_resize_resource() to detect an error and abort the resize.
> 
> 
> Looks good in general, but a couple of comments.
> 
> Similarly, an assigned Expansion ROM resource prevents the resize.
> 
> 
> Expansion ROMs were intentionally left untouched by the initial patch since those are
> usually 32bit resources and the resize was implemented only for 64bit BARs.
> 
> Change the release loop to cover both the VF BARs and Expansion ROM
> which allows the resize operation to release the bridge windows and
> attempt to assigned them again with the different size.
> 
> 
> I'm not sure if Expansion ROMs should be touched here. Those are 32bit resources
> usually and notoriously broken in the ACPI tables.
> 
> What I've seen multiple times that after releasing them you can't move nor assign
> them again to their original position.
> 
> Background is that some ACPI table denotes the location of the ROM as reserved and we
> only accept the Expansion ROM at that location because of a quirk (which is of course
> not applied when you resize).
> 
> On the other hand do we have use cases for resizing 32bit BARs? So far we resized
> those only by accident.
> 
> Thanks for taking a look!
> 
> This is not about resizing 32bit BARs.
> 
> Is that somehow enforced so they cannot end up into the same bridge 
> window? Because we can only resize a bridge window if we release all its 
> child resources.
> 
> 
> Good question, I'm not 100% sure either.
> 
> IIRC the PCI subsystem has a fallback which tries to squeeze 64bit BARs into 32bit
> windows of bridges if nothing else works.

Yes, as far as I understand the code, that can happen.

> But the PCI subsystem never does that the other way around. Simply because a 32bit
> BAR doesn't necessary work in a 64bit window.
>
> So you should never need to free up a 32bit BAR to resize and/or move a 64bit BAR
> because that operation should move the 64bit BAR into the 64bit window anyway.

I fail to follow your logic here. Why exactly the 64bit resizable BAR 
couldn't end up into a bridge window that is shared with Expansion ROM 
(and perhaps other 32-bit resources) consider the fallbacks? And why 
couldn't the resize be attempted there?

> That we only free up resources with the same flags is taken care of this code here:
> 
>                 if (pci_resource_len(pdev, i) &&
>                     pci_resource_flags(pdev, i) == flags)
>                         pci_release_resource(pdev, i);
> 
> The flags should contain IORESOURCE_MEM_64 for 64bit BARs. So we most likely don't
> need a special handling for Expansion ROMs or 32bit BARs.

Most likely true, neither would get released and the resize ends up 
failing.

However, now that you brought it up, I question if that flags check there 
is correct at all. I think it would simply want to check if the resource 
to be resized shares the bridge window with the i'th resource? Do you 
agree? (And that check has nothing to do with 32/64bit.)

This is far from the only inconsistency I've come across while recently 
trying to address a number of issues in the resource fitting and 
assignment logic. I'm slowly trying to come into understanding of mess 
this ->flags and resource fitting & allocation is and hopefully 
eventually make it something that is actually tractable (yeah, wish me 
luck :-/).

So I don't want to accept "we most likely don't need a special handling 
for Expansion ROMs or 32bit BARs" just because it happens to work, I'd 
want that check to make sense too.

It would always be possible to explicitly do something if we detect 
Expansion ROM resource that is assigned (and perhaps not disabled?) but 
even then, preventing resize from proceeding just because something bad 
might happen to the Expansion ROM seems a bit big hammer to me (but 
could certainly e.g. print a warning if that gets attempted for ROM).
diff mbox series

Patch

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5d0f4db1cab7..80b01087d3ef 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1440,7 +1440,7 @@  static ssize_t __resource_resize_store(struct device *dev, int n,
 
 	pci_remove_resource_files(pdev);
 
-	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
+	for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
 		if (pci_resource_len(pdev, i) &&
 		    pci_resource_flags(pdev, i) == flags)
 			pci_release_resource(pdev, i);