diff mbox series

[pciutils,3/4] libpci: Add support for filling bridge resources

Message ID 20211220155448.1233-3-pali@kernel.org
State New
Headers show
Series [pciutils,1/4] lspci: Show 16/32/64 bit width for address ranges behind bridge | expand

Commit Message

Pali Rohár Dec. 20, 2021, 3:54 p.m. UTC
Extend libpci API and ABI to fill bridge resources from sysfs.
---
 lib/access.c   | 20 +++++++++++---------
 lib/caps.c     |  2 +-
 lib/filter.c   |  2 +-
 lib/internal.h |  1 +
 lib/libpci.ver |  5 +++++
 lib/pci.h      |  4 ++++
 lib/sysfs.c    | 48 ++++++++++++++++++++++++++++++++++++++++++------
 7 files changed, 65 insertions(+), 17 deletions(-)

Comments

Martin Mareš Dec. 26, 2021, 10:13 p.m. UTC | #1
Hi!

> +      else if (i < 7+6+4)
> +        {
> +          /*
> +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> +           * the ROM line for configured bridge device (that which had set
> +           * subordinary bus number to non-zero value) are four additional lines
> +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> +           * there is no additional line after the ROM line. If kernel was
> +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> +           * before the first bridge resource line are six additional lines
> +           * which describe IOV resources. Read all remaining lines in resource
> +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> +           * resources behind bridge.
> +           */
> +          lines[i-7].flags = flags;
> +          lines[i-7].base_addr = start;
> +          lines[i-7].size = size;
> +        }
> +    }
> +  if (i == 7+4 || i == 7+6+4)

This looks crazy: is there any other way how to tell what the bridge entries mean?
Checking the number of entries looks very brittle.

				Martin
Pali Rohár Dec. 26, 2021, 10:20 p.m. UTC | #2
On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> Hi!
> 
> > +      else if (i < 7+6+4)
> > +        {
> > +          /*
> > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > +           * the ROM line for configured bridge device (that which had set
> > +           * subordinary bus number to non-zero value) are four additional lines
> > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > +           * there is no additional line after the ROM line. If kernel was
> > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > +           * before the first bridge resource line are six additional lines
> > +           * which describe IOV resources. Read all remaining lines in resource
> > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > +           * resources behind bridge.
> > +           */
> > +          lines[i-7].flags = flags;
> > +          lines[i-7].base_addr = start;
> > +          lines[i-7].size = size;
> > +        }
> > +    }
> > +  if (i == 7+4 || i == 7+6+4)
> 
> This looks crazy: is there any other way how to tell what the bridge entries mean?
> Checking the number of entries looks very brittle.

I do not know any other way. Just for reference, here is a link to the
function resource_show() and DEVICE_COUNT_RESOURCE enum:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94
Pali Rohár Dec. 31, 2021, 10:27 p.m. UTC | #3
On Sunday 26 December 2021 23:20:27 Pali Rohár wrote:
> On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> > Hi!
> > 
> > > +      else if (i < 7+6+4)
> > > +        {
> > > +          /*
> > > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > > +           * the ROM line for configured bridge device (that which had set
> > > +           * subordinary bus number to non-zero value) are four additional lines
> > > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > > +           * there is no additional line after the ROM line. If kernel was
> > > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > > +           * before the first bridge resource line are six additional lines
> > > +           * which describe IOV resources. Read all remaining lines in resource
> > > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > > +           * resources behind bridge.
> > > +           */
> > > +          lines[i-7].flags = flags;
> > > +          lines[i-7].base_addr = start;
> > > +          lines[i-7].size = size;
> > > +        }
> > > +    }
> > > +  if (i == 7+4 || i == 7+6+4)
> > 
> > This looks crazy: is there any other way how to tell what the bridge entries mean?
> > Checking the number of entries looks very brittle.
> 
> I do not know any other way. Just for reference, here is a link to the
> function resource_show() and DEVICE_COUNT_RESOURCE enum:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94

I have also checked flags and there is no indication if resource is
assigned on bridge as BAR or is forwarded behind the bridge.

Bjorn, Krzysztof: any idea if something better than checking number of
entries in "resource" node can be used to determinate type of entry at
specified line in "resource" node?
Bjorn Helgaas Jan. 20, 2022, 8:33 p.m. UTC | #4
On Fri, Dec 31, 2021 at 11:27:48PM +0100, Pali Rohár wrote:
> On Sunday 26 December 2021 23:20:27 Pali Rohár wrote:
> > On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> > > Hi!
> > > 
> > > > +      else if (i < 7+6+4)
> > > > +        {
> > > > +          /*
> > > > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > > > +           * the ROM line for configured bridge device (that which had set
> > > > +           * subordinary bus number to non-zero value) are four additional lines
> > > > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > > > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > > > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > > > +           * there is no additional line after the ROM line. If kernel was
> > > > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > > > +           * before the first bridge resource line are six additional lines
> > > > +           * which describe IOV resources. Read all remaining lines in resource
> > > > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > > > +           * resources behind bridge.
> > > > +           */
> > > > +          lines[i-7].flags = flags;
> > > > +          lines[i-7].base_addr = start;
> > > > +          lines[i-7].size = size;
> > > > +        }
> > > > +    }
> > > > +  if (i == 7+4 || i == 7+6+4)
> > > 
> > > This looks crazy: is there any other way how to tell what the
> > > bridge entries mean?  Checking the number of entries looks very
> > > brittle.
> > 
> > I do not know any other way. Just for reference, here is a link to
> > the function resource_show() and DEVICE_COUNT_RESOURCE enum:
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94
> 
> I have also checked flags and there is no indication if resource is
> assigned on bridge as BAR or is forwarded behind the bridge.
> 
> Bjorn, Krzysztof: any idea if something better than checking number
> of entries in "resource" node can be used to determinate type of
> entry at specified line in "resource" node?

That *is* crazy.  I'm sorry that resource_show() works that way, and
that it gives no clue to identify BAR vs ROM vs IOV BAR vs CB window
vs regular bridge window.

It's conceivable that we could add "io_window" and "mem_window" files
or something similar.

Does this patch fix a problem?  I'm not clear on what the benefit is.

Bjorn
Pali Rohár Jan. 20, 2022, 8:45 p.m. UTC | #5
On Thursday 20 January 2022 14:33:52 Bjorn Helgaas wrote:
> On Fri, Dec 31, 2021 at 11:27:48PM +0100, Pali Rohár wrote:
> > On Sunday 26 December 2021 23:20:27 Pali Rohár wrote:
> > > On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> > > > Hi!
> > > > 
> > > > > +      else if (i < 7+6+4)
> > > > > +        {
> > > > > +          /*
> > > > > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > > > > +           * the ROM line for configured bridge device (that which had set
> > > > > +           * subordinary bus number to non-zero value) are four additional lines
> > > > > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > > > > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > > > > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > > > > +           * there is no additional line after the ROM line. If kernel was
> > > > > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > > > > +           * before the first bridge resource line are six additional lines
> > > > > +           * which describe IOV resources. Read all remaining lines in resource
> > > > > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > > > > +           * resources behind bridge.
> > > > > +           */
> > > > > +          lines[i-7].flags = flags;
> > > > > +          lines[i-7].base_addr = start;
> > > > > +          lines[i-7].size = size;
> > > > > +        }
> > > > > +    }
> > > > > +  if (i == 7+4 || i == 7+6+4)
> > > > 
> > > > This looks crazy: is there any other way how to tell what the
> > > > bridge entries mean?  Checking the number of entries looks very
> > > > brittle.
> > > 
> > > I do not know any other way. Just for reference, here is a link to
> > > the function resource_show() and DEVICE_COUNT_RESOURCE enum:
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94
> > 
> > I have also checked flags and there is no indication if resource is
> > assigned on bridge as BAR or is forwarded behind the bridge.
> > 
> > Bjorn, Krzysztof: any idea if something better than checking number
> > of entries in "resource" node can be used to determinate type of
> > entry at specified line in "resource" node?
> 
> That *is* crazy.  I'm sorry that resource_show() works that way, and
> that it gives no clue to identify BAR vs ROM vs IOV BAR vs CB window
> vs regular bridge window.
> 
> It's conceivable that we could add "io_window" and "mem_window" files
> or something similar.

Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
constant with comment /* forwarded by bridge */
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56

But apparently it is not set for resources behind PCI bridges and
therefore it is not available in column of "resources" sysfs file.

So maybe instead of adding new sysfs files, it would be better way to
implement this flag and export it in flags column of "resources" file
for every row which belongs to resources behind bridges?

But in any case changes in kernel does not help lspci/libpci which is
running on existing (unmodified) kernel.

> Does this patch fix a problem?  I'm not clear on what the benefit is.
> 
> Bjorn

My patch for libpci fixes it, but via counting number of rows in
"resources" sysfs file... which is crazy. But I do not see any other
option how to do it via currently available kernel APIs.
Bjorn Helgaas Jan. 20, 2022, 9:02 p.m. UTC | #6
On Thu, Jan 20, 2022 at 09:45:05PM +0100, Pali Rohár wrote:
> On Thursday 20 January 2022 14:33:52 Bjorn Helgaas wrote:
> > On Fri, Dec 31, 2021 at 11:27:48PM +0100, Pali Rohár wrote:
> > > On Sunday 26 December 2021 23:20:27 Pali Rohár wrote:
> > > > On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> > > > > Hi!
> > > > > 
> > > > > > +      else if (i < 7+6+4)
> > > > > > +        {
> > > > > > +          /*
> > > > > > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > > > > > +           * the ROM line for configured bridge device (that which had set
> > > > > > +           * subordinary bus number to non-zero value) are four additional lines
> > > > > > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > > > > > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > > > > > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > > > > > +           * there is no additional line after the ROM line. If kernel was
> > > > > > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > > > > > +           * before the first bridge resource line are six additional lines
> > > > > > +           * which describe IOV resources. Read all remaining lines in resource
> > > > > > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > > > > > +           * resources behind bridge.
> > > > > > +           */
> > > > > > +          lines[i-7].flags = flags;
> > > > > > +          lines[i-7].base_addr = start;
> > > > > > +          lines[i-7].size = size;
> > > > > > +        }
> > > > > > +    }
> > > > > > +  if (i == 7+4 || i == 7+6+4)
> > > > > 
> > > > > This looks crazy: is there any other way how to tell what the
> > > > > bridge entries mean?  Checking the number of entries looks very
> > > > > brittle.
> > > > 
> > > > I do not know any other way. Just for reference, here is a link to
> > > > the function resource_show() and DEVICE_COUNT_RESOURCE enum:
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94
> > > 
> > > I have also checked flags and there is no indication if resource is
> > > assigned on bridge as BAR or is forwarded behind the bridge.
> > > 
> > > Bjorn, Krzysztof: any idea if something better than checking number
> > > of entries in "resource" node can be used to determinate type of
> > > entry at specified line in "resource" node?
> > 
> > That *is* crazy.  I'm sorry that resource_show() works that way, and
> > that it gives no clue to identify BAR vs ROM vs IOV BAR vs CB window
> > vs regular bridge window.
> > 
> > It's conceivable that we could add "io_window" and "mem_window" files
> > or something similar.
> 
> Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
> constant with comment /* forwarded by bridge */
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56
> 
> But apparently it is not set for resources behind PCI bridges and
> therefore it is not available in column of "resources" sysfs file.
> 
> So maybe instead of adding new sysfs files, it would be better way to
> implement this flag and export it in flags column of "resources" file
> for every row which belongs to resources behind bridges?

I looked at that, too.  Today we only set IORESOURCE_WINDOW for host
bridge windows.  Maybe it could be set for PCI-to-PCI bridge windows,
too.  Would have to audit users to make sure it wouldn't break
anything.

> But in any case changes in kernel does not help lspci/libpci which is
> running on existing (unmodified) kernel.

Of course.

> > Does this patch fix a problem?  I'm not clear on what the benefit is.
> 
> My patch for libpci fixes it, but via counting number of rows in
> "resources" sysfs file... which is crazy. But I do not see any other
> option how to do it via currently available kernel APIs.

The current subject and commit log are:

  libpci: Add support for filling bridge resources

  Extend libpci API and ABI to fill bridge resources from sysfs.

That doesn't give a reason why Martin should include this patch.  Does
it fix a problem?  Does it help lspci show more information?  If so,
what is the difference in output?

Bjorn
Pali Rohár Jan. 20, 2022, 9:19 p.m. UTC | #7
On Thursday 20 January 2022 15:02:12 Bjorn Helgaas wrote:
> On Thu, Jan 20, 2022 at 09:45:05PM +0100, Pali Rohár wrote:
> > On Thursday 20 January 2022 14:33:52 Bjorn Helgaas wrote:
> > > On Fri, Dec 31, 2021 at 11:27:48PM +0100, Pali Rohár wrote:
> > > > On Sunday 26 December 2021 23:20:27 Pali Rohár wrote:
> > > > > On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> > > > > > Hi!
> > > > > > 
> > > > > > > +      else if (i < 7+6+4)
> > > > > > > +        {
> > > > > > > +          /*
> > > > > > > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > > > > > > +           * the ROM line for configured bridge device (that which had set
> > > > > > > +           * subordinary bus number to non-zero value) are four additional lines
> > > > > > > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > > > > > > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > > > > > > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > > > > > > +           * there is no additional line after the ROM line. If kernel was
> > > > > > > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > > > > > > +           * before the first bridge resource line are six additional lines
> > > > > > > +           * which describe IOV resources. Read all remaining lines in resource
> > > > > > > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > > > > > > +           * resources behind bridge.
> > > > > > > +           */
> > > > > > > +          lines[i-7].flags = flags;
> > > > > > > +          lines[i-7].base_addr = start;
> > > > > > > +          lines[i-7].size = size;
> > > > > > > +        }
> > > > > > > +    }
> > > > > > > +  if (i == 7+4 || i == 7+6+4)
> > > > > > 
> > > > > > This looks crazy: is there any other way how to tell what the
> > > > > > bridge entries mean?  Checking the number of entries looks very
> > > > > > brittle.
> > > > > 
> > > > > I do not know any other way. Just for reference, here is a link to
> > > > > the function resource_show() and DEVICE_COUNT_RESOURCE enum:
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94
> > > > 
> > > > I have also checked flags and there is no indication if resource is
> > > > assigned on bridge as BAR or is forwarded behind the bridge.
> > > > 
> > > > Bjorn, Krzysztof: any idea if something better than checking number
> > > > of entries in "resource" node can be used to determinate type of
> > > > entry at specified line in "resource" node?
> > > 
> > > That *is* crazy.  I'm sorry that resource_show() works that way, and
> > > that it gives no clue to identify BAR vs ROM vs IOV BAR vs CB window
> > > vs regular bridge window.
> > > 
> > > It's conceivable that we could add "io_window" and "mem_window" files
> > > or something similar.
> > 
> > Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
> > constant with comment /* forwarded by bridge */
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56
> > 
> > But apparently it is not set for resources behind PCI bridges and
> > therefore it is not available in column of "resources" sysfs file.
> > 
> > So maybe instead of adding new sysfs files, it would be better way to
> > implement this flag and export it in flags column of "resources" file
> > for every row which belongs to resources behind bridges?
> 
> I looked at that, too.  Today we only set IORESOURCE_WINDOW for host
> bridge windows.  Maybe it could be set for PCI-to-PCI bridge windows,
> too.  Would have to audit users to make sure it wouldn't break
> anything.
> 
> > But in any case changes in kernel does not help lspci/libpci which is
> > running on existing (unmodified) kernel.
> 
> Of course.
> 
> > > Does this patch fix a problem?  I'm not clear on what the benefit is.
> > 
> > My patch for libpci fixes it, but via counting number of rows in
> > "resources" sysfs file... which is crazy. But I do not see any other
> > option how to do it via currently available kernel APIs.
> 
> The current subject and commit log are:
> 
>   libpci: Add support for filling bridge resources
> 
>   Extend libpci API and ABI to fill bridge resources from sysfs.
> 
> That doesn't give a reason why Martin should include this patch.  Does
> it fix a problem?  Does it help lspci show more information?  If so,
> what is the difference in output?
> 
> Bjorn

Usage is in patch 4/4. lspci with this change and also with patch 4/4 can
distinguish between states: 1) PCI-to-PCI bridge does not support IO and
2) PCI-to-PCI bridge has enabled IO forwarding range set to 0x0000-0x0fff.
Both these two states have IO_BASE and IO_LIMIT registers set to zeros.
lspci currently decodes IO_BASE=IO_LIMIT=0x00 as IO forwarding range is
enabled and set to range 0x0000-0x0fff.
Pali Rohár Nov. 11, 2022, 8:09 p.m. UTC | #8
On Thursday 20 January 2022 15:02:12 Bjorn Helgaas wrote:
> On Thu, Jan 20, 2022 at 09:45:05PM +0100, Pali Rohár wrote:
> > On Thursday 20 January 2022 14:33:52 Bjorn Helgaas wrote:
> > > On Fri, Dec 31, 2021 at 11:27:48PM +0100, Pali Rohár wrote:
> > > > On Sunday 26 December 2021 23:20:27 Pali Rohár wrote:
> > > > > On Sunday 26 December 2021 23:13:11 Martin Mareš wrote:
> > > > > > Hi!
> > > > > > 
> > > > > > > +      else if (i < 7+6+4)
> > > > > > > +        {
> > > > > > > +          /*
> > > > > > > +           * If kernel was compiled without CONFIG_PCI_IOV option then after
> > > > > > > +           * the ROM line for configured bridge device (that which had set
> > > > > > > +           * subordinary bus number to non-zero value) are four additional lines
> > > > > > > +           * which describe resources behind bridge. For PCI-to-PCI bridges they
> > > > > > > +           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
> > > > > > > +           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
> > > > > > > +           * there is no additional line after the ROM line. If kernel was
> > > > > > > +           * compiled with CONFIG_PCI_IOV option then after the ROM line and
> > > > > > > +           * before the first bridge resource line are six additional lines
> > > > > > > +           * which describe IOV resources. Read all remaining lines in resource
> > > > > > > +           * file and based on the number of remaining lines (0, 4, 6, 10) parse
> > > > > > > +           * resources behind bridge.
> > > > > > > +           */
> > > > > > > +          lines[i-7].flags = flags;
> > > > > > > +          lines[i-7].base_addr = start;
> > > > > > > +          lines[i-7].size = size;
> > > > > > > +        }
> > > > > > > +    }
> > > > > > > +  if (i == 7+4 || i == 7+6+4)
> > > > > > 
> > > > > > This looks crazy: is there any other way how to tell what the
> > > > > > bridge entries mean?  Checking the number of entries looks very
> > > > > > brittle.
> > > > > 
> > > > > I do not know any other way. Just for reference, here is a link to
> > > > > the function resource_show() and DEVICE_COUNT_RESOURCE enum:
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pci/pci-sysfs.c?h=v5.15#n136
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/pci.h?h=v5.15#n94
> > > > 
> > > > I have also checked flags and there is no indication if resource is
> > > > assigned on bridge as BAR or is forwarded behind the bridge.
> > > > 
> > > > Bjorn, Krzysztof: any idea if something better than checking number
> > > > of entries in "resource" node can be used to determinate type of
> > > > entry at specified line in "resource" node?
> > > 
> > > That *is* crazy.  I'm sorry that resource_show() works that way, and
> > > that it gives no clue to identify BAR vs ROM vs IOV BAR vs CB window
> > > vs regular bridge window.
> > > 
> > > It's conceivable that we could add "io_window" and "mem_window" files
> > > or something similar.
> > 
> > Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
> > constant with comment /* forwarded by bridge */
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56
> > 
> > But apparently it is not set for resources behind PCI bridges and
> > therefore it is not available in column of "resources" sysfs file.
> > 
> > So maybe instead of adding new sysfs files, it would be better way to
> > implement this flag and export it in flags column of "resources" file
> > for every row which belongs to resources behind bridges?
> 
> I looked at that, too.  Today we only set IORESOURCE_WINDOW for host
> bridge windows.  Maybe it could be set for PCI-to-PCI bridge windows,
> too.  Would have to audit users to make sure it wouldn't break
> anything.

Hello Bjorn, I would like to remind this older issue. Did you have a time
to audit usage of IORESOURCE_WINDOW? Some flag for resource forwarding
windows in PCI-to-PCI bridges would really help userspace application to
distinguish between IO/MEM BARs an IO/MEM forwarding windows.
Bjorn Helgaas Nov. 11, 2022, 9:05 p.m. UTC | #9
On Fri, Nov 11, 2022 at 09:09:45PM +0100, Pali Rohár wrote:
> On Thursday 20 January 2022 15:02:12 Bjorn Helgaas wrote:
> > On Thu, Jan 20, 2022 at 09:45:05PM +0100, Pali Rohár wrote:

[trimmed material; beginning of thread is at
https://lore.kernel.org/r/20211220155448.1233-3-pali@kernel.org]

> > > Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
> > > constant with comment /* forwarded by bridge */
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56
> > > 
> > > But apparently it is not set for resources behind PCI bridges and
> > > therefore it is not available in column of "resources" sysfs file.
> > > 
> > > So maybe instead of adding new sysfs files, it would be better way to
> > > implement this flag and export it in flags column of "resources" file
> > > for every row which belongs to resources behind bridges?
> > 
> > I looked at that, too.  Today we only set IORESOURCE_WINDOW for host
> > bridge windows.  Maybe it could be set for PCI-to-PCI bridge windows,
> > too.  Would have to audit users to make sure it wouldn't break
> > anything.
> 
> Hello Bjorn, I would like to remind this older issue. Did you have a time
> to audit usage of IORESOURCE_WINDOW? Some flag for resource forwarding
> windows in PCI-to-PCI bridges would really help userspace application to
> distinguish between IO/MEM BARs an IO/MEM forwarding windows.

I had forgotten all about this issue.  IIUC, the ultimate goal here
is to help lspci distinguish between an I/O window that's disabled and
one that's enabled at [io 0x0000-0x0fff].

I have not done the research to see whether it would be safe to set
IORESOURCE_WINDOW for PCI-to-PCI bridge windows.  I'm sorry if I left
the impression that I intended to do that.  I would welcome your help
to do that.

Bjorn
Pali Rohár Nov. 11, 2022, 9:48 p.m. UTC | #10
On Friday 11 November 2022 15:05:55 Bjorn Helgaas wrote:
> On Fri, Nov 11, 2022 at 09:09:45PM +0100, Pali Rohár wrote:
> > On Thursday 20 January 2022 15:02:12 Bjorn Helgaas wrote:
> > > On Thu, Jan 20, 2022 at 09:45:05PM +0100, Pali Rohár wrote:
> 
> [trimmed material; beginning of thread is at
> https://lore.kernel.org/r/20211220155448.1233-3-pali@kernel.org]
> 
> > > > Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
> > > > constant with comment /* forwarded by bridge */
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56
> > > > 
> > > > But apparently it is not set for resources behind PCI bridges and
> > > > therefore it is not available in column of "resources" sysfs file.
> > > > 
> > > > So maybe instead of adding new sysfs files, it would be better way to
> > > > implement this flag and export it in flags column of "resources" file
> > > > for every row which belongs to resources behind bridges?
> > > 
> > > I looked at that, too.  Today we only set IORESOURCE_WINDOW for host
> > > bridge windows.  Maybe it could be set for PCI-to-PCI bridge windows,
> > > too.  Would have to audit users to make sure it wouldn't break
> > > anything.
> > 
> > Hello Bjorn, I would like to remind this older issue. Did you have a time
> > to audit usage of IORESOURCE_WINDOW? Some flag for resource forwarding
> > windows in PCI-to-PCI bridges would really help userspace application to
> > distinguish between IO/MEM BARs an IO/MEM forwarding windows.
> 
> I had forgotten all about this issue.  IIUC, the ultimate goal here
> is to help lspci distinguish between an I/O window that's disabled and
> one that's enabled at [io 0x0000-0x0fff].
> 
> I have not done the research to see whether it would be safe to set
> IORESOURCE_WINDOW for PCI-to-PCI bridge windows.  I'm sorry if I left
> the impression that I intended to do that.  I would welcome your help
> to do that.
> 
> Bjorn

Ok, do you have some resources or other information at which I should
look? I just do not know where to start or what to check for that
research.

I looked into kernel sources and the only places where is code checking
for IORESOURCE_WINDOW is ACPI related: arch/arm64/kernel/pci.c and
drivers/pnp/resource.c. And I do not fully understand how is ACPI
connected with PCI resources at this level. Other places which check
(lib/vsprintf.c and drivers/pnp/interface.c) just use it for
printf-formats.
Bjorn Helgaas Nov. 15, 2022, 10:15 p.m. UTC | #11
On Fri, Nov 11, 2022 at 10:48:16PM +0100, Pali Rohár wrote:
> On Friday 11 November 2022 15:05:55 Bjorn Helgaas wrote:
> > On Fri, Nov 11, 2022 at 09:09:45PM +0100, Pali Rohár wrote:
> > > On Thursday 20 January 2022 15:02:12 Bjorn Helgaas wrote:
> > > > On Thu, Jan 20, 2022 at 09:45:05PM +0100, Pali Rohár wrote:
> > 
> > [trimmed material; beginning of thread is at
> > https://lore.kernel.org/r/20211220155448.1233-3-pali@kernel.org]
> > 
> > > > > Meanwhile I found out that in linux/ioport.h file is IORESOURCE_WINDOW
> > > > > constant with comment /* forwarded by bridge */
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/ioport.h?h=v5.15#n56
> > > > > 
> > > > > But apparently it is not set for resources behind PCI bridges and
> > > > > therefore it is not available in column of "resources" sysfs file.
> > > > > 
> > > > > So maybe instead of adding new sysfs files, it would be better way to
> > > > > implement this flag and export it in flags column of "resources" file
> > > > > for every row which belongs to resources behind bridges?
> > > > 
> > > > I looked at that, too.  Today we only set IORESOURCE_WINDOW for host
> > > > bridge windows.  Maybe it could be set for PCI-to-PCI bridge windows,
> > > > too.  Would have to audit users to make sure it wouldn't break
> > > > anything.
> > > 
> > > Hello Bjorn, I would like to remind this older issue. Did you have a time
> > > to audit usage of IORESOURCE_WINDOW? Some flag for resource forwarding
> > > windows in PCI-to-PCI bridges would really help userspace application to
> > > distinguish between IO/MEM BARs an IO/MEM forwarding windows.
> > 
> > I had forgotten all about this issue.  IIUC, the ultimate goal here
> > is to help lspci distinguish between an I/O window that's disabled and
> > one that's enabled at [io 0x0000-0x0fff].
> > 
> > I have not done the research to see whether it would be safe to set
> > IORESOURCE_WINDOW for PCI-to-PCI bridge windows.  I'm sorry if I left
> > the impression that I intended to do that.  I would welcome your help
> > to do that.
> 
> Ok, do you have some resources or other information at which I should
> look? I just do not know where to start or what to check for that
> research.
> 
> I looked into kernel sources and the only places where is code checking
> for IORESOURCE_WINDOW is ACPI related: arch/arm64/kernel/pci.c and
> drivers/pnp/resource.c. And I do not fully understand how is ACPI
> connected with PCI resources at this level. Other places which check
> (lib/vsprintf.c and drivers/pnp/interface.c) just use it for
> printf-formats.

Yeah, that's the kind of thing I have in mind.  I can't remember if I
had any specific concern.

Bjorn
diff mbox series

Patch

diff --git a/lib/access.c b/lib/access.c
index b257849a685e..a33e067e2389 100644
--- a/lib/access.c
+++ b/lib/access.c
@@ -189,7 +189,7 @@  pci_reset_properties(struct pci_dev *d)
 }
 
 int
-pci_fill_info_v35(struct pci_dev *d, int flags)
+pci_fill_info_v38(struct pci_dev *d, int flags)
 {
   unsigned int uflags = flags;
   if (uflags & PCI_FILL_RESCAN)
@@ -203,19 +203,21 @@  pci_fill_info_v35(struct pci_dev *d, int flags)
 }
 
 /* In version 3.1, pci_fill_info got new flags => versioned alias */
-/* In versions 3.2, 3.3, 3.4 and 3.5, the same has happened */
-STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v35(d, flags));
-DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v35);
+/* In versions 3.2, 3.3, 3.4, 3.5 and 3.8, the same has happened */
+STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v38(d, flags));
+DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v35(struct pci_dev *d, int flags), pci_fill_info_v38);
 SYMBOL_VERSION(pci_fill_info_v30, pci_fill_info@LIBPCI_3.0);
 SYMBOL_VERSION(pci_fill_info_v31, pci_fill_info@LIBPCI_3.1);
 SYMBOL_VERSION(pci_fill_info_v32, pci_fill_info@LIBPCI_3.2);
 SYMBOL_VERSION(pci_fill_info_v33, pci_fill_info@LIBPCI_3.3);
 SYMBOL_VERSION(pci_fill_info_v34, pci_fill_info@LIBPCI_3.4);
-SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@@LIBPCI_3.5);
+SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@LIBPCI_3.5);
+SYMBOL_VERSION(pci_fill_info_v38, pci_fill_info@@LIBPCI_3.8);
 
 void
 pci_setup_cache(struct pci_dev *d, byte *cache, int len)
diff --git a/lib/caps.c b/lib/caps.c
index c3b918059fe1..70a41b836e31 100644
--- a/lib/caps.c
+++ b/lib/caps.c
@@ -129,7 +129,7 @@  pci_find_cap_nr(struct pci_dev *d, unsigned int id, unsigned int type,
   unsigned int target = (cap_number ? *cap_number : 0);
   unsigned int index = 0;
 
-  pci_fill_info_v35(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
+  pci_fill_info_v38(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
 
   for (c=d->first_cap; c; c=c->next)
     {
diff --git a/lib/filter.c b/lib/filter.c
index 573fb2810363..195f813193c4 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -129,7 +129,7 @@  pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d)
     return 0;
   if (f->device >= 0 || f->vendor >= 0)
     {
-      pci_fill_info_v35(d, PCI_FILL_IDENT);
+      pci_fill_info_v38(d, PCI_FILL_IDENT);
       if ((f->device >= 0 && f->device != d->device_id) ||
 	  (f->vendor >= 0 && f->vendor != d->vendor_id))
 	return 0;
diff --git a/lib/internal.h b/lib/internal.h
index 17c27e194a29..4df8dd70c2c6 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -74,6 +74,7 @@  int pci_fill_info_v32(struct pci_dev *, int flags) VERSIONED_ABI;
 int pci_fill_info_v33(struct pci_dev *, int flags) VERSIONED_ABI;
 int pci_fill_info_v34(struct pci_dev *, int flags) VERSIONED_ABI;
 int pci_fill_info_v35(struct pci_dev *, int flags) VERSIONED_ABI;
+int pci_fill_info_v38(struct pci_dev *, int flags) VERSIONED_ABI;
 
 struct pci_property {
   struct pci_property *next;
diff --git a/lib/libpci.ver b/lib/libpci.ver
index e20c3f581c71..73f7fa71e357 100644
--- a/lib/libpci.ver
+++ b/lib/libpci.ver
@@ -82,3 +82,8 @@  LIBPCI_3.7 {
 	global:
 		pci_find_cap_nr;
 };
+
+LIBPCI_3.8 {
+	global:
+		pci_fill_info;
+};
diff --git a/lib/pci.h b/lib/pci.h
index 814247691086..0ec7f211ca24 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -142,6 +142,9 @@  struct pci_dev {
   pciaddr_t flags[6];			/* PCI_IORESOURCE_* flags for regions */
   pciaddr_t rom_flags;			/* PCI_IORESOURCE_* flags for expansion ROM */
   int domain;				/* PCI domain (host bridge) */
+  pciaddr_t bridge_base_addr[4];	/* Bridge base addresses (without flags) */
+  pciaddr_t bridge_size[4];		/* Bridge sizes */
+  pciaddr_t bridge_flags[4];		/* PCI_IORESOURCE_* flags for bridge addresses */
 
   /* Fields used internally */
   struct pci_access *access;
@@ -205,6 +208,7 @@  char *pci_get_string_property(struct pci_dev *d, u32 prop) PCI_ABI;
 #define PCI_FILL_IO_FLAGS	0x1000
 #define PCI_FILL_DT_NODE	0x2000		/* Device tree node */
 #define PCI_FILL_IOMMU_GROUP	0x4000
+#define PCI_FILL_BRIDGE_BASES	0x8000
 #define PCI_FILL_RESCAN		0x00010000
 
 void pci_setup_cache(struct pci_dev *, u8 *cache, int len) PCI_ABI;
diff --git a/lib/sysfs.c b/lib/sysfs.c
index fb6424105e84..7c157a2688ad 100644
--- a/lib/sysfs.c
+++ b/lib/sysfs.c
@@ -148,19 +148,22 @@  sysfs_get_value(struct pci_dev *d, char *object, int mandatory)
     return -1;
 }
 
-static void
+static unsigned int
 sysfs_get_resources(struct pci_dev *d)
 {
   struct pci_access *a = d->access;
   char namebuf[OBJNAMELEN], buf[256];
+  struct { pciaddr_t flags, base_addr, size; } lines[10];
+  unsigned int done;
   FILE *file;
   int i;
 
+  done = 0;
   sysfs_obj_name(d, "resource", namebuf);
   file = fopen(namebuf, "r");
   if (!file)
     a->error("Cannot open %s: %s", namebuf, strerror(errno));
-  for (i = 0; i < 7; i++)
+  for (i = 0; i < 7+6+4+1; i++)
     {
       unsigned long long start, end, size, flags;
       if (!fgets(buf, sizeof(buf), file))
@@ -177,16 +180,50 @@  sysfs_get_resources(struct pci_dev *d)
 	  flags &= PCI_ADDR_FLAG_MASK;
 	  d->base_addr[i] = start | flags;
 	  d->size[i] = size;
+	  done |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
 	}
-      else
+      else if (i == 6)
 	{
 	  d->rom_flags = flags;
 	  flags &= PCI_ADDR_FLAG_MASK;
 	  d->rom_base_addr = start | flags;
 	  d->rom_size = size;
+	  done |= PCI_FILL_ROM_BASE;
 	}
+      else if (i < 7+6+4)
+        {
+          /*
+           * If kernel was compiled without CONFIG_PCI_IOV option then after
+           * the ROM line for configured bridge device (that which had set
+           * subordinary bus number to non-zero value) are four additional lines
+           * which describe resources behind bridge. For PCI-to-PCI bridges they
+           * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
+           * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
+           * there is no additional line after the ROM line. If kernel was
+           * compiled with CONFIG_PCI_IOV option then after the ROM line and
+           * before the first bridge resource line are six additional lines
+           * which describe IOV resources. Read all remaining lines in resource
+           * file and based on the number of remaining lines (0, 4, 6, 10) parse
+           * resources behind bridge.
+           */
+          lines[i-7].flags = flags;
+          lines[i-7].base_addr = start;
+          lines[i-7].size = size;
+        }
+    }
+  if (i == 7+4 || i == 7+6+4)
+    {
+      int offset = (i == 7+6+4) ? 6 : 0;
+      for (i = 0; i < 4; i++)
+        {
+          d->bridge_flags[i] = lines[offset+i].flags;
+          d->bridge_base_addr[i] = lines[offset+i].base_addr;
+          d->bridge_size[i] = lines[offset+i].size;
+        }
+      done |= PCI_FILL_BRIDGE_BASES;
     }
   fclose(file);
+  return done;
 }
 
 static void sysfs_scan(struct pci_access *a)
@@ -316,10 +353,9 @@  sysfs_fill_info(struct pci_dev *d, unsigned int flags)
 	  d->irq = sysfs_get_value(d, "irq", 1);
 	  done |= PCI_FILL_IRQ;
 	}
-      if (flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS))
+      if (flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS | PCI_FILL_BRIDGE_BASES))
 	{
-	  sysfs_get_resources(d);
-	  done |= PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
+	  done |= sysfs_get_resources(d);
 	}
     }