Hi Sebastian,

On Friday, 23 January 2026 12:02:30 CET Sebastian Brzezinka wrote:
> Hi Janusz,
> 
> On Wed Jan 21, 2026 at 12:42 PM CET, Janusz Krzysztofik wrote:
> > Users of Intel discrete graphics adapters are confused with fake
> > information on PCIe link bandwidth (speed and size) of their GPU devices
> > reported by sysfs and userspace tools, including our lsgpu utility.  In
> > order for the lsgpu to show correct link bandwidth information, we need to
> > identify an upstream port of a PCIe bridge that sits on the GPU card and
> > get that information from that port.
> >
> > Since the tool uses our udev based igt_device_scan library for identifying
> > GPU devices and printing their properties and attributes, modifications
> > that we need apply to that library.
> >
> > When scanning for DRM devices and their PCI parents, the lsgpu utility
> > requests collection of all their attributes.  When running in this mode,
> > also try to collect information about upstream ports of PCIe bridges of
> > discrete GPU devices.  Once collected, the lsgpu utility will show that
> > information automatically while listing the devices.
> >
> > While IGT tests are using pciaccess library for processing PCI devices,
> > that library requires careful handling in order to avoid collisions among
> > multiple processes or threads potentially using it.  That protection is
> > implemented in igt_device with help of IGT exit handlers. That requires
> > linking with full igt_core library code, while the lsgpu tool now depends
> > neither on igt_device nor on igt_core.  To keep that independence,
> > implement the new code around libpci.  With that approach, refactoring of
> > IGT use of pciaccess is avoided.
> >
> > Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10753
> > Signed-off-by: Janusz Krzysztofik <[email protected]>
> > ---
> >  lib/igt_device_scan.c | 73 +++++++++++++++++++++++++++++++++++++++++--
> >  lib/meson.build       |  2 ++
> >  meson.build           |  1 +
> >  3 files changed, 74 insertions(+), 2 deletions(-)
> >
> > diff --git a/lib/igt_device_scan.c b/lib/igt_device_scan.c
> > index d3a2ebe8d2..34c7a8131b 100644
> > --- a/lib/igt_device_scan.c
> > +++ b/lib/igt_device_scan.c
> > @@ -36,6 +36,7 @@
> >  #ifdef __linux__
> >  #include <linux/limits.h>
> >  #endif
> > +#include <pci/pci.h>
> >  #include <sys/stat.h>
> >  #include <sys/time.h>
> >  #include <sys/types.h>
> > @@ -909,6 +910,27 @@ static struct igt_device 
> > *igt_device_from_syspath(const char *syspath)
> >     return NULL;
> >  }
> >  
> > +static bool is_pcie_upstream_bridge(struct pci_dev *dev)
> > +{
> > +   struct pci_cap *pcie;
> > +   uint8_t type, dir;
> > +
> > +   type = pci_read_byte(dev, PCI_HEADER_TYPE) & 0x7f;
> > +   if (type != PCI_HEADER_TYPE_BRIDGE)
> > +           return false;
> > +
> > +   pcie = pci_find_cap(dev, PCI_CAP_ID_EXP, PCI_CAP_NORMAL);
> > +   if (!pcie)
> > +           return false;
> > +
> > +   /* GET_REG_MASK macro borrowed from pciutils' internal bitops.h */
> > +#define GET_REG_MASK(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 
> > 1)))
> > +   dir = GET_REG_MASK(pci_read_word(dev, pcie->addr + PCI_EXP_FLAGS), 
> > PCI_EXP_FLAGS_TYPE);
> > +#undef GET_REG_MASK
> Instead of copying the macro, we could just use: 
>       type = ( pci_read_word... & PCI_EXP_FLAGS_TYPE) >> 4. This seems 
> cleaner.

I guess it took you a bit of time to understand how that macro works, so it 
did to me :-).  Then OK, let's use the more clear but correct looking version 
you propose, even if it's not clear to me why they did it that way, less 
clear, more complicated.

> 
> > +
> > +   return dir == PCI_EXP_TYPE_UPSTREAM;
> > +}
> > +
> >  #define RETRIES_GET_PARENT 5
> >  
> >  static struct igt_device *find_or_add_igt_device(struct udev *udev,
> > @@ -948,18 +970,55 @@ static struct igt_device 
> > *find_or_add_igt_device(struct udev *udev,
> >     return idev;
> >  }
> >  
> > +static struct udev_device *get_pcie_upstream_bridge(struct udev *udev,
> > +                                               struct udev_device *dev)
> > +{
> > +   struct pci_access *pacc;
> > +
> > +   pacc = pci_alloc();
> > +   pci_init(pacc);
> > +
> I'm not entirely familiar with this pci library, but is it necessary to 
> initialize it
> for every device? It might be more efficient to do it once in 
> scan_drm_devices.

OK, you've got it.

Thanks,
Janusz



Reply via email to