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

Commit 6841ec68 authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes
Browse files

PCI: introduce pci_assign_unassigned_bridge_resources



For use by pciehp.

pci_setup_bridge() will not check enabled for the slot bridge, otherwise
update res is not updated to bridge BAR.  That is, bridge is already
enabled for port service.

Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Reviewed-by: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 977d17bb
Loading
Loading
Loading
Loading
+89 −27
Original line number Diff line number Diff line
@@ -71,35 +71,34 @@ static void free_failed_list(struct resource_list_x *head)
	head->next = NULL;
}

static void pbus_assign_resources_sorted(const struct pci_bus *bus,
					 struct resource_list_x *fail_head)
static void __dev_sort_resources(struct pci_dev *dev,
				 struct resource_list *head)
{
	struct pci_dev *dev;
	struct resource *res;
	struct resource_list head, *list, *tmp;
	int idx;

	head.next = NULL;
	list_for_each_entry(dev, &bus->devices, bus_list) {
	u16 class = dev->class >> 8;

	/* Don't touch classless devices or host bridges or ioapics.  */
		if (class == PCI_CLASS_NOT_DEFINED ||
		    class == PCI_CLASS_BRIDGE_HOST)
			continue;
	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
		return;

	/* Don't touch ioapic devices already enabled by firmware */
	if (class == PCI_CLASS_SYSTEM_PIC) {
		u16 command;
		pci_read_config_word(dev, PCI_COMMAND, &command);
		if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
				continue;
			return;
	}

		pdev_sort_resources(dev, &head);
	pdev_sort_resources(dev, head);
}

	for (list = head.next; list;) {
static void __assign_resources_sorted(struct resource_list *head,
				 struct resource_list_x *fail_head)
{
	struct resource *res;
	struct resource_list *list, *tmp;
	int idx;

	for (list = head->next; list;) {
		res = list->res;
		idx = res - &list->dev->resource[0];
		if (pci_assign_resource(list->dev, idx)) {
@@ -115,6 +114,30 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
	}
}

static void pdev_assign_resources_sorted(struct pci_dev *dev,
				 struct resource_list_x *fail_head)
{
	struct resource_list head;

	head.next = NULL;
	__dev_sort_resources(dev, &head);
	__assign_resources_sorted(&head, fail_head);

}

static void pbus_assign_resources_sorted(const struct pci_bus *bus,
					 struct resource_list_x *fail_head)
{
	struct pci_dev *dev;
	struct resource_list head;

	head.next = NULL;
	list_for_each_entry(dev, &bus->devices, bus_list)
		__dev_sort_resources(dev, &head);

	__assign_resources_sorted(&head, fail_head);
}

void pci_setup_cardbus(struct pci_bus *bus)
{
	struct pci_dev *bridge = bus->self;
@@ -273,9 +296,6 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
{
	struct pci_dev *bridge = bus->self;

	if (pci_is_enabled(bridge))
		return;

	dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
		 bus->secondary, bus->subordinate);

@@ -646,6 +666,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,

		switch (dev->class >> 8) {
		case PCI_CLASS_BRIDGE_PCI:
			if (!pci_is_enabled(dev))
				pci_setup_bridge(b);
			break;

@@ -667,6 +688,34 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_bus_assign_resources);

static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
					 struct resource_list_x *fail_head)
{
	struct pci_bus *b;

	pdev_assign_resources_sorted((struct pci_dev *)bridge, fail_head);

	b = bridge->subordinate;
	if (!b)
		return;

	__pci_bus_assign_resources(b, fail_head);

	switch (bridge->class >> 8) {
	case PCI_CLASS_BRIDGE_PCI:
		pci_setup_bridge(b);
		break;

	case PCI_CLASS_BRIDGE_CARDBUS:
		pci_setup_cardbus(b);
		break;

	default:
		dev_info(&bridge->dev, "not setting up bridge for bus "
			 "%04x:%02x\n", pci_domain_nr(b), b->number);
		break;
	}
}
static void pci_bridge_release_resources(struct pci_bus *bus,
					  unsigned long type)
{
@@ -911,3 +960,16 @@ enable_and_dump:
		pci_bus_dump_resources(bus);
	}
}

void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
{
	struct pci_bus *parent = bridge->subordinate;
	int retval;

	pci_bus_size_bridges(parent);
	__pci_bridge_assign_resources(bridge, NULL);
	retval = pci_reenable_device(bridge);
	pci_set_master(bridge);
	pci_enable_bridges(parent);
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
+1 −0
Original line number Diff line number Diff line
@@ -801,6 +801,7 @@ void pci_bus_assign_resources(const struct pci_bus *bus);
void pci_bus_size_bridges(struct pci_bus *bus);
int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void);
void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
void pdev_enable_device(struct pci_dev *);
void pdev_sort_resources(struct pci_dev *, struct resource_list *);
int pci_enable_resources(struct pci_dev *, int mask);