mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 09:14:19 +08:00
a2b36ffbf5
This reverts commit4c5e242d3e
. Prior to4c5e242d3e
("x86/PCI: Clip only host bridge windows for E820 regions"), E820 regions did not affect PCI host bridge windows. We only looked at E820 regions and avoided them when allocating new MMIO space. If firmware PCI bridge window and BAR assignments used E820 regions, we left them alone. After4c5e242d3e
, we removed E820 regions from the PCI host bridge windows before looking at BARs, so firmware assignments in E820 regions looked like errors, and we moved things around to fit in the space left (if any) after removing the E820 regions. This unnecessary BAR reassignment broke several machines. Guilherme reported that Steam Deck fails to boot after4c5e242d3e
. We clipped the window that contained most 32-bit BARs: BIOS-e820: [mem 0x00000000a0000000-0x00000000a00fffff] reserved acpi PNP0A08:00: clipped [mem 0x80000000-0xf7ffffff window] to [mem 0xa0100000-0xf7ffffff window] for e820 entry [mem 0xa0000000-0xa00fffff] which forced us to reassign all those BARs, for example, this NVMe BAR: pci 0000:00:01.2: PCI bridge to [bus 01] pci 0000:00:01.2: bridge window [mem 0x80600000-0x806fffff] pci 0000:01:00.0: BAR 0: [mem 0x80600000-0x80603fff 64bit] pci 0000:00:01.2: can't claim window [mem 0x80600000-0x806fffff]: no compatible bridge window pci 0000:01:00.0: can't claim BAR 0 [mem 0x80600000-0x80603fff 64bit]: no compatible bridge window pci 0000:00:01.2: bridge window: assigned [mem 0xa0100000-0xa01fffff] pci 0000:01:00.0: BAR 0: assigned [mem 0xa0100000-0xa0103fff 64bit] All the reassignments were successful, so the devices should have been functional at the new addresses, but some were not. Andy reported a similar failure on an Intel MID platform. Benjamin reported a similar failure on a VMWare Fusion VM. Note: this is not a clean revert; this revert keeps the later change to make the clipping dependent on a new pci_use_e820 bool, moving the checking of this bool to arch_remove_reservations(). [bhelgaas: commit log, add more reporters and testers] BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216109 Reported-by: Guilherme G. Piccoli <gpiccoli@igalia.com> Reported-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reported-by: Benjamin Coddington <bcodding@redhat.com> Reported-by: Jongman Heo <jongman.heo@gmail.com> Fixes:4c5e242d3e
("x86/PCI: Clip only host bridge windows for E820 regions") Link: https://lore.kernel.org/r/20220612144325.85366-1-hdegoede@redhat.com Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com> Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
65 lines
1.5 KiB
C
65 lines
1.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/ioport.h>
|
|
#include <linux/printk.h>
|
|
#include <asm/e820/api.h>
|
|
#include <asm/pci_x86.h>
|
|
|
|
static void resource_clip(struct resource *res, resource_size_t start,
|
|
resource_size_t end)
|
|
{
|
|
resource_size_t low = 0, high = 0;
|
|
|
|
if (res->end < start || res->start > end)
|
|
return; /* no conflict */
|
|
|
|
if (res->start < start)
|
|
low = start - res->start;
|
|
|
|
if (res->end > end)
|
|
high = res->end - end;
|
|
|
|
/* Keep the area above or below the conflict, whichever is larger */
|
|
if (low > high)
|
|
res->end = start - 1;
|
|
else
|
|
res->start = end + 1;
|
|
}
|
|
|
|
static void remove_e820_regions(struct resource *avail)
|
|
{
|
|
int i;
|
|
struct e820_entry *entry;
|
|
u64 e820_start, e820_end;
|
|
struct resource orig = *avail;
|
|
|
|
if (!pci_use_e820)
|
|
return;
|
|
|
|
for (i = 0; i < e820_table->nr_entries; i++) {
|
|
entry = &e820_table->entries[i];
|
|
e820_start = entry->addr;
|
|
e820_end = entry->addr + entry->size - 1;
|
|
|
|
resource_clip(avail, e820_start, e820_end);
|
|
if (orig.start != avail->start || orig.end != avail->end) {
|
|
pr_info("clipped %pR to %pR for e820 entry [mem %#010Lx-%#010Lx]\n",
|
|
&orig, avail, e820_start, e820_end);
|
|
orig = *avail;
|
|
}
|
|
}
|
|
}
|
|
|
|
void arch_remove_reservations(struct resource *avail)
|
|
{
|
|
/*
|
|
* Trim out BIOS area (high 2MB) and E820 regions. We do not remove
|
|
* the low 1MB unconditionally, as this area is needed for some ISA
|
|
* cards requiring a memory range, e.g. the i82365 PCMCIA controller.
|
|
*/
|
|
if (avail->flags & IORESOURCE_MEM) {
|
|
resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
|
|
|
|
remove_e820_regions(avail);
|
|
}
|
|
}
|