diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1181d24d2b44f623c8fa250c133eebf03bacf8bc..426e31bcfd46bcf49a85bddb528f9499c358a4cf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -5792,6 +5792,16 @@ static void nvidia_ion_ahci_fixup(struct pci_dev *pdev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup); +static void rom_bar_overlap_defect(struct pci_dev *dev) +{ + pci_info(dev, "working around ROM BAR overlap defect\n"); + dev->rom_bar_overlap = 1; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1533, rom_bar_overlap_defect); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1536, rom_bar_overlap_defect); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1537, rom_bar_overlap_defect); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1538, rom_bar_overlap_defect); + /* * On Alibaba yitian710 Soc, the Hardware does always clear pcie config space * and some key registers between resetting the secondary bus. This results in diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c33624ea42f8019d4b6687518c3c196549119b46..c53f1348ab65807bf70cd231da665f7d66dafe37 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -824,11 +824,9 @@ static resource_size_t calculate_memsize(resource_size_t size, size = min_size; if (old_size == 1) old_size = 0; - if (size < old_size) - size = old_size; - size = ALIGN(max(size, add_size) + children_add_size, align); - return size; + size = max(size, add_size) + children_add_size; + return ALIGN(max(size, old_size), align); } resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus, diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 875d50c16f19d0565c6970e8e38f7a7f63dd1070..b492e67c3d871747ec73d69dbb1dc1d1fc774dca 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -75,12 +75,16 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno) * as zero when disabled, so don't update ROM BARs unless * they're enabled. See * https://lore.kernel.org/r/43147B3D.1030309@vc.cvut.cz/ + * But we must update ROM BAR for buggy devices where even a + * disabled ROM can conflict with other BARs. */ - if (!(res->flags & IORESOURCE_ROM_ENABLE)) + if (!(res->flags & IORESOURCE_ROM_ENABLE) && + !dev->rom_bar_overlap) return; reg = dev->rom_base_reg; - new |= PCI_ROM_ADDRESS_ENABLE; + if (res->flags & IORESOURCE_ROM_ENABLE) + new |= PCI_ROM_ADDRESS_ENABLE; } else return; diff --git a/include/linux/pci.h b/include/linux/pci.h index 9c79cf6a61422e2b0e6de8479038feb92f7698ec..7e365da2faebf9899b81414d36d4a28b3abb6df5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -465,6 +465,7 @@ struct pci_dev { unsigned int link_active_reporting:1;/* Device capable of reporting link active */ unsigned int no_vf_scan:1; /* Don't scan for VFs after IOV enablement */ unsigned int no_command_memory:1; /* No PCI_COMMAND_MEMORY */ + unsigned int rom_bar_overlap:1; /* ROM BAR disable broken */ unsigned int broken_bus_reset:1; /* Abnormal bus reset */ unsigned int enable_vpp:1; /* Change the sequence of operation lights */ pci_dev_flags_t dev_flags;