Skip to content

Commit

Permalink
PCI / ACPI: Use boot-time resource allocation rules during hotplug
Browse files Browse the repository at this point in the history
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 <[email protected]>
Tested-by: Illya Klymov <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
Acked-by: Yinghai Lu <[email protected]>
Cc: 3.9+ <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
Jiang Liu authored and rafaeljw committed Jun 22, 2013
1 parent 94add0f commit d66ecb7
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 6 deletions.
7 changes: 5 additions & 2 deletions drivers/pci/hotplug/acpiphp_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions drivers/pci/setup-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit d66ecb7

Please sign in to comment.