]> git.ipfire.org Git - thirdparty/pciutils.git/commitdiff
Update margin_hw.c
authorAmit Kumar <akamit91@hotmail.com>
Thu, 27 Nov 2025 08:39:56 +0000 (14:09 +0530)
committerMartin Mareš <mj@ucw.cz>
Sun, 28 Dec 2025 20:22:22 +0000 (21:22 +0100)
pcilmr: Fix incorrect device pair detection in margin_find_pair()

When finding the parent bridge of an endpoint device, margin_find_pair()
was reading PCI_SECONDARY_BUS (offset 0x19) from all devices in the
system without checking if they are actually bridge devices.

For non-bridge devices (header type 0), offset 0x19 contains arbitrary
data that could coincidentally match the target device's bus number,
causing the function to return an incorrect device as the downstream port.

This resulted in the misleading error:
  "Looks like you don't have enough privileges to access Device
   Configuration Space."

The error occurred because the incorrectly selected device (e.g., a SATA
controller) doesn't have a PCIe Express capability, causing pci_find_cap()
to correctly return NULL.

Fix by adding a margin_port_is_down(p) check before reading
PCI_SECONDARY_BUS. This ensures we only examine actual PCIe bridge
devices (Root Ports or Switch Downstream Ports) when searching for
the parent bridge.

Example failure case:
  - Target: 0000:60:00.0 (NVMe device, bus 0x60)
  - Actual parent: 0000:5d:02.0 (PCIe switch downstream port)
  - Incorrectly matched: 0000:00:18.0 (SATA controller with 0x60 at offset 0x19)

After fix, correctly identifies 0000:5d:02.0 as the downstream port.

lmr/margin_hw.c

index e10e36f6b767636999a5fc3b4914037a330859eb..c6785f16c5f2c7c9eece7951c54cf7e9e8b2941a 100644 (file)
@@ -68,8 +68,8 @@ margin_find_pair(struct pci_access *pacc, struct pci_dev *dev, struct pci_dev **
           *up_port = p;
           return true;
         }
-      else if (!given_down && pci_read_byte(p, PCI_SECONDARY_BUS) == dev->bus
-               && dev->domain == p->domain)
+      else if (!given_down && dev->domain == p->domain && margin_port_is_down(p)
+               && pci_read_byte(p, PCI_SECONDARY_BUS) == dev->bus)
         {
           *down_port = p;
           *up_port = dev;