Skip to content

Commit 500b55b

Browse files
committed
PCI: Work around Intel I210 ROM BAR overlap defect
Per PCIe r5, sec 7.5.1.2.4, a device must not claim accesses to its Expansion ROM unless both the Memory Space Enable and the Expansion ROM Enable bit are set. But apparently some Intel I210 NICs don't work correctly if the ROM BAR overlaps another BAR, even if the Expansion ROM is disabled. Michael reported that on a Kontron SMARC-sAL28 ARM64 system with U-Boot v2021.01-rc3, the ROM BAR overlaps BAR 3, and networking doesn't work at all: BAR 0: 0x40000000 (32-bit, non-prefetchable) [size=1M] BAR 3: 0x40200000 (32-bit, non-prefetchable) [size=16K] ROM: 0x40200000 (disabled) [size=1M] NETDEV WATCHDOG: enP2p1s0 (igb): transmit queue 0 timed out Hardware name: Kontron SMARC-sAL28 (Single PHY) on SMARC Eval 2.0 carrier (DT) igb 0002:01:00.0 enP2p1s0: Reset adapter Previously, pci_std_update_resource() wrote the assigned ROM address to the BAR only when the ROM was enabled. This meant that the I210 ROM BAR could be left with an address assigned by firmware, which might overlap with other BARs. Quirk these I210 devices so pci_std_update_resource() always writes the assigned address to the ROM BAR, whether or not the ROM is enabled. Link: https://lore.kernel.org/r/20211223163754.GA1267351@bhelgaas Link: https://lore.kernel.org/r/20201230185317.30915-1-michael@walle.cc Link: https://bugzilla.kernel.org/show_bug.cgi?id=211105 Reported-by: Michael Walle <michael@walle.cc> Tested-by: Michael Walle <michael@walle.cc> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
1 parent fa55b7d commit 500b55b

3 files changed

Lines changed: 17 additions & 2 deletions

File tree

drivers/pci/quirks.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5857,3 +5857,13 @@ static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
58575857
pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
58585858
}
58595859
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);
5860+
5861+
static void rom_bar_overlap_defect(struct pci_dev *dev)
5862+
{
5863+
pci_info(dev, "working around ROM BAR overlap defect\n");
5864+
dev->rom_bar_overlap = 1;
5865+
}
5866+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1533, rom_bar_overlap_defect);
5867+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1536, rom_bar_overlap_defect);
5868+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1537, rom_bar_overlap_defect);
5869+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1538, rom_bar_overlap_defect);

drivers/pci/setup-res.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,16 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno)
7575
* as zero when disabled, so don't update ROM BARs unless
7676
* they're enabled. See
7777
* https://lore.kernel.org/r/43147B3D.1030309@vc.cvut.cz/
78+
* But we must update ROM BAR for buggy devices where even a
79+
* disabled ROM can conflict with other BARs.
7880
*/
79-
if (!(res->flags & IORESOURCE_ROM_ENABLE))
81+
if (!(res->flags & IORESOURCE_ROM_ENABLE) &&
82+
!dev->rom_bar_overlap)
8083
return;
8184

8285
reg = dev->rom_base_reg;
83-
new |= PCI_ROM_ADDRESS_ENABLE;
86+
if (res->flags & IORESOURCE_ROM_ENABLE)
87+
new |= PCI_ROM_ADDRESS_ENABLE;
8488
} else
8589
return;
8690

include/linux/pci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ struct pci_dev {
455455
unsigned int link_active_reporting:1;/* Device capable of reporting link active */
456456
unsigned int no_vf_scan:1; /* Don't scan for VFs after IOV enablement */
457457
unsigned int no_command_memory:1; /* No PCI_COMMAND_MEMORY */
458+
unsigned int rom_bar_overlap:1; /* ROM BAR disable broken */
458459
pci_dev_flags_t dev_flags;
459460
atomic_t enable_cnt; /* pci_enable_device has been called */
460461

0 commit comments

Comments
 (0)