Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32180e40 authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes
Browse files

PCI: pciehp: second try to get big range for pcie devices



Handle the case where the slot bridge that doesn't get a pre-allocated
resource big enough to handle its child resources..  For example pcie
devices need 256M, but the bridge only gets 2M preallocated.

Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 9789ac97
Loading
Loading
Loading
Loading
+50 −1
Original line number Original line Diff line number Diff line
@@ -964,12 +964,61 @@ enable_and_dump:
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
{
{
	struct pci_bus *parent = bridge->subordinate;
	struct pci_bus *parent = bridge->subordinate;
	int tried_times = 0;
	struct resource_list_x head, *list;
	int retval;
	int retval;
	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
				  IORESOURCE_PREFETCH;

	head.next = NULL;


again:
	pci_bus_size_bridges(parent);
	pci_bus_size_bridges(parent);
	__pci_bridge_assign_resources(bridge, NULL);
	__pci_bridge_assign_resources(bridge, &head);
	retval = pci_reenable_device(bridge);
	retval = pci_reenable_device(bridge);
	pci_set_master(bridge);
	pci_set_master(bridge);
	pci_enable_bridges(parent);
	pci_enable_bridges(parent);

	tried_times++;

	if (!head.next)
		return;

	if (tried_times >= 2) {
		/* still fail, don't need to try more */
		free_failed_list(&head);
		return;
	}

	printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
			 tried_times + 1);

	/*
	 * Try to release leaf bridge's resources that doesn't fit resource of
	 * child device under that bridge
	 */
	for (list = head.next; list;) {
		struct pci_bus *bus = list->dev->bus;
		unsigned long flags = list->flags;

		pci_bus_release_bridge_resources(bus, flags & type_mask,
						 whole_subtree);
		list = list->next;
	}
	/* restore size and flags */
	for (list = head.next; list;) {
		struct resource *res = list->res;

		res->start = list->start;
		res->end = list->end;
		res->flags = list->flags;
		if (list->dev->subordinate)
			res->flags = 0;

		list = list->next;
	}
	free_failed_list(&head);

	goto again;
}
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);