mirror of https://gitee.com/openkylin/linux.git
PCI / ACPI: Use boot-time resource allocation rules during hotplug
On x86 platforms, the kernel respects PCI resource assignments from the BIOS and only reassigns resources for unassigned BARs at boot time. However, with the ACPI-based hotplug (acpiphp), it ignores the BIOS' PCI resource assignments completely and reassigns all resources by itself. This causes differences in PCI resource allocation between boot time and runtime hotplug to occur, which is generally undesirable and sometimes actively breaks things. Namely, if there are enough resources, reassigning all PCI resources during runtime hotplug should work, but it may fail if the resources are constrained. This may happen, for instance, when some PCI devices with huge MMIO BARs are involved in the runtime hotplug operations, because the current PCI MMIO alignment algorithm may waste huge chunks of MMIO address space in those cases. On the Alexander's Sony VAIO VPCZ23A4R the BIOS allocates limited MMIO resources for the dock station which contains a device (graphics adapter) with a 256MB MMIO BAR. An attempt to reassign that during runtime hotplug causes the dock station MMIO window to be exhausted and acpiphp fails to allocate resources for the majority of devices on the dock station as a result. To prevent that from happening, modify acpiphp to follow the boot time resources allocation behavior so that the BIOS' resource assignments are respected during runtime hotplug too. [rjw: Changelog] References: https://bugzilla.kernel.org/show_bug.cgi?id=56531 Reported-and-tested-by: Alexander E. Patrakov <patrakov@gmail.com> Tested-by: Illya Klymov <xanf@xanf.me> Signed-off-by: Jiang Liu <jiang.liu@huawei.com> Acked-by: Yinghai Lu <yinghai@kernel.org> Cc: 3.9+ <stable@vger.kernel.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
94add0f824
commit
d66ecb7220
|
@ -670,6 +670,7 @@ static int __ref enable_device(struct acpiphp_slot *slot)
|
|||
struct pci_bus *bus = slot->bridge->pci_bus;
|
||||
struct acpiphp_func *func;
|
||||
int num, max, pass;
|
||||
LIST_HEAD(add_list);
|
||||
|
||||
if (slot->flags & SLOT_ENABLED)
|
||||
goto err_exit;
|
||||
|
@ -694,13 +695,15 @@ static int __ref enable_device(struct acpiphp_slot *slot)
|
|||
max = pci_scan_bridge(bus, dev, max, pass);
|
||||
if (pass && dev->subordinate) {
|
||||
check_hotplug_bridge(slot, dev);
|
||||
pci_bus_size_bridges(dev->subordinate);
|
||||
pcibios_resource_survey_bus(dev->subordinate);
|
||||
__pci_bus_size_bridges(dev->subordinate,
|
||||
&add_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pci_bus_assign_resources(bus);
|
||||
__pci_bus_assign_resources(bus, &add_list, NULL);
|
||||
acpiphp_sanitize_bus(bus);
|
||||
acpiphp_set_hpp_values(bus);
|
||||
acpiphp_set_acpi_region(slot);
|
||||
|
|
|
@ -202,6 +202,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
struct resource *res, unsigned int reg);
|
||||
int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);
|
||||
void pci_configure_ari(struct pci_dev *dev);
|
||||
void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
struct list_head *realloc_head);
|
||||
void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
||||
struct list_head *realloc_head,
|
||||
struct list_head *fail_head);
|
||||
|
||||
/**
|
||||
* pci_ari_enabled - query ARI forwarding status
|
||||
|
|
|
@ -1044,7 +1044,7 @@ static void pci_bus_size_cardbus(struct pci_bus *bus,
|
|||
;
|
||||
}
|
||||
|
||||
static void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
void __ref __pci_bus_size_bridges(struct pci_bus *bus,
|
||||
struct list_head *realloc_head)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
@ -1115,9 +1115,9 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_bus_size_bridges);
|
||||
|
||||
static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
||||
struct list_head *realloc_head,
|
||||
struct list_head *fail_head)
|
||||
void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
|
||||
struct list_head *realloc_head,
|
||||
struct list_head *fail_head)
|
||||
{
|
||||
struct pci_bus *b;
|
||||
struct pci_dev *dev;
|
||||
|
|
Loading…
Reference in New Issue