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.
*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;