Commit 865df576 authored by Bjorn Helgaas's avatar Bjorn Helgaas Committed by Jesse Barnes
Browse files

PCI: improve discovery/configuration messages



This makes PCI resource management messages more consistent and adds a few
new messages to aid debugging.

Whenever we assign resources to a device, update a BAR, or change a
bridge aperture, it's worth noting it.

Signed-off-by: default avatarBjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 0207c356
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -129,7 +129,9 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
					continue;
					continue;
				if (!r->start ||
				if (!r->start ||
				    pci_claim_resource(dev, idx) < 0) {
				    pci_claim_resource(dev, idx) < 0) {
					dev_info(&dev->dev, "BAR %d: can't allocate %pR\n", idx, r);
					dev_info(&dev->dev,
						 "can't reserve window %pR\n",
						 r);
					/*
					/*
					 * Something is wrong with the region.
					 * Something is wrong with the region.
					 * Invalidate the resource to prevent
					 * Invalidate the resource to prevent
@@ -165,10 +167,11 @@ static void __init pcibios_allocate_resources(int pass)
				disabled = !(command & PCI_COMMAND_MEMORY);
				disabled = !(command & PCI_COMMAND_MEMORY);
			if (pass == disabled) {
			if (pass == disabled) {
				dev_dbg(&dev->dev,
				dev_dbg(&dev->dev,
					"BAR %d: claiming %pr (d=%d, p=%d)\n",
					"BAR %d: reserving %pr (d=%d, p=%d)\n",
					idx, r, disabled, pass);
					idx, r, disabled, pass);
				if (pci_claim_resource(dev, idx) < 0) {
				if (pci_claim_resource(dev, idx) < 0) {
					dev_info(&dev->dev, "BAR %d: can't claim %pR\n", idx, r);
					dev_info(&dev->dev,
						 "can't reserve %pR\n", r);
					/* We'll assign a new address later */
					/* We'll assign a new address later */
					r->end -= r->start;
					r->end -= r->start;
					r->start = 0;
					r->start = 0;
+1 −1
Original line number Original line Diff line number Diff line
@@ -2575,7 +2575,7 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
			return reg;
			return reg;
	}
	}


	dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno);
	dev_err(&dev->dev, "BAR %d: invalid resource\n", resno);
	return 0;
	return 0;
}
}


+9 −4
Original line number Original line Diff line number Diff line
@@ -226,7 +226,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
			goto fail;
			goto fail;


		if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
		if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
			dev_err(&dev->dev, "can't handle 64-bit BAR\n");
			dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
				pos);
			goto fail;
			goto fail;
		}
		}


@@ -294,8 +295,11 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
	if (pci_is_root_bus(child))	/* It's a host bus, nothing to read */
	if (pci_is_root_bus(child))	/* It's a host bus, nothing to read */
		return;
		return;


	dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
		 child->secondary, child->subordinate,
		 dev->transparent ? " (subtractive decode)": "");

	if (dev->transparent) {
	if (dev->transparent) {
		dev_info(&dev->dev, "transparent bridge\n");
		for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
		for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
			child->resource[i] = child->parent->resource[i - 3];
			child->resource[i] = child->parent->resource[i - 3];
	}
	}
@@ -645,13 +649,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
		    (child->number > bus->subordinate) ||
		    (child->number > bus->subordinate) ||
		    (child->number < bus->number) ||
		    (child->number < bus->number) ||
		    (child->subordinate < bus->number)) {
		    (child->subordinate < bus->number)) {
			pr_debug("PCI: Bus #%02x (-#%02x) is %s "
			dev_info(&child->dev, "[bus %02x-%02x] %s "
				"hidden behind%s bridge #%02x (-#%02x)\n",
				"hidden behind%s bridge %s [bus %02x-%02x]\n",
				child->number, child->subordinate,
				child->number, child->subordinate,
				(bus->number > child->subordinate &&
				(bus->number > child->subordinate &&
				 bus->subordinate < child->number) ?
				 bus->subordinate < child->number) ?
					"wholly" : "partially",
					"wholly" : "partially",
				bus->self->transparent ? " transparent" : "",
				bus->self->transparent ? " transparent" : "",
				dev_name(&bus->dev),
				bus->number, bus->subordinate);
				bus->number, bus->subordinate);
		}
		}
		bus = bus->parent;
		bus = bus->parent;
+15 −6
Original line number Original line Diff line number Diff line
@@ -74,8 +74,8 @@ void pci_setup_cardbus(struct pci_bus *bus)
	struct resource *res;
	struct resource *res;
	struct pci_bus_region region;
	struct pci_bus_region region;


	dev_info(&bridge->dev, "CardBus bridge, secondary bus %04x:%02x\n",
	dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
		 pci_domain_nr(bus), bus->number);
		 bus->secondary, bus->subordinate);


	res = bus->resource[0];
	res = bus->resource[0];
	pcibios_resource_to_bus(bridge, &region, res);
	pcibios_resource_to_bus(bridge, &region, res);
@@ -145,8 +145,8 @@ static void pci_setup_bridge(struct pci_bus *bus)
	if (pci_is_enabled(bridge))
	if (pci_is_enabled(bridge))
		return;
		return;


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


	/* Set up the top and bottom of the PCI I/O segment for this bus. */
	/* Set up the top and bottom of the PCI I/O segment for this bus. */
	res = bus->resource[0];
	res = bus->resource[0];
@@ -338,6 +338,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
#endif
#endif
	size = ALIGN(size + size1, 4096);
	size = ALIGN(size + size1, 4096);
	if (!size) {
	if (!size) {
		if (b_res->start || b_res->end)
			dev_info(&bus->self->dev, "disabling bridge window "
				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
				 bus->secondary, bus->subordinate);
		b_res->flags = 0;
		b_res->flags = 0;
		return;
		return;
	}
	}
@@ -383,8 +387,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
			align = pci_resource_alignment(dev, r);
			align = pci_resource_alignment(dev, r);
			order = __ffs(align) - 20;
			order = __ffs(align) - 20;
			if (order > 11) {
			if (order > 11) {
				dev_warn(&dev->dev, "BAR %d: bad alignment %llx: "
				dev_warn(&dev->dev, "disabling BAR %d: %pR "
					 "%pR\n", i, (unsigned long long)align, r);
					 "(bad alignment %#llx)\n", i, r,
					 (unsigned long long) align);
				r->flags = 0;
				r->flags = 0;
				continue;
				continue;
			}
			}
@@ -418,6 +423,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
	}
	}
	size = ALIGN(size, min_align);
	size = ALIGN(size, min_align);
	if (!size) {
	if (!size) {
		if (b_res->start || b_res->end)
			dev_info(&bus->self->dev, "disabling bridge window "
				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
				 bus->secondary, bus->subordinate);
		b_res->flags = 0;
		b_res->flags = 0;
		return 1;
		return 1;
	}
	}
+32 −28
Original line number Original line Diff line number Diff line
@@ -51,12 +51,6 @@ void pci_update_resource(struct pci_dev *dev, int resno)


	pcibios_resource_to_bus(dev, &region, res);
	pcibios_resource_to_bus(dev, &region, res);


	dev_dbg(&dev->dev, "BAR %d: got res %pR bus [%#llx-%#llx] "
		"flags %#lx\n", resno, res,
		 (unsigned long long)region.start,
		 (unsigned long long)region.end,
		 (unsigned long)res->flags);

	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
	if (res->flags & IORESOURCE_IO)
	if (res->flags & IORESOURCE_IO)
		mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
		mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
@@ -91,7 +85,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)
		}
		}
	}
	}
	res->flags &= ~IORESOURCE_UNSET;
	res->flags &= ~IORESOURCE_UNSET;
	dev_dbg(&dev->dev, "BAR %d: moved to %pR (bus addr [%#llx-%#llx])\n",
	dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx]\n",
		 resno, res, (unsigned long long)region.start,
		 resno, res, (unsigned long long)region.start,
		 (unsigned long long)region.end);
		 (unsigned long long)region.end);
}
}
@@ -103,19 +97,16 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
	int err;
	int err;


	root = pci_find_parent_resource(dev, res);
	root = pci_find_parent_resource(dev, res);
	if (!root) {
		dev_err(&dev->dev, "no compatible bridge window for %pR\n",
			res);
		return -EINVAL;
	}


	err = -EINVAL;
	if (root != NULL)
	err = request_resource(root, res);
	err = request_resource(root, res);

	if (err)
	if (err) {
		dev_err(&dev->dev,
		const char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
			"address space collision: %pR already in use\n", res);
		dev_err(&dev->dev, "BAR %d: %s of %s %pR\n",
			resource,
			root ? "address space collision on" :
				"no parent found for",
			dtype, res);
	}


	return err;
	return err;
}
}
@@ -124,7 +115,7 @@ EXPORT_SYMBOL(pci_claim_resource);
#ifdef CONFIG_PCI_QUIRKS
#ifdef CONFIG_PCI_QUIRKS
void pci_disable_bridge_window(struct pci_dev *dev)
void pci_disable_bridge_window(struct pci_dev *dev)
{
{
	dev_dbg(&dev->dev, "Disabling bridge window.\n");
	dev_info(&dev->dev, "disabling bridge mem windows\n");


	/* MMIO Base/Limit */
	/* MMIO Base/Limit */
	pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
	pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
@@ -165,6 +156,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,


	if (!ret) {
	if (!ret) {
		res->flags &= ~IORESOURCE_STARTALIGN;
		res->flags &= ~IORESOURCE_STARTALIGN;
		dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
		if (resno < PCI_BRIDGE_RESOURCES)
		if (resno < PCI_BRIDGE_RESOURCES)
			pci_update_resource(dev, resno);
			pci_update_resource(dev, resno);
	}
	}
@@ -178,10 +170,11 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
	resource_size_t align;
	resource_size_t align;
	struct pci_bus *bus;
	struct pci_bus *bus;
	int ret;
	int ret;
	char *type;


	align = pci_resource_alignment(dev, res);
	align = pci_resource_alignment(dev, res);
	if (!align) {
	if (!align) {
		dev_info(&dev->dev, "BAR %d: can't allocate %pR "
		dev_info(&dev->dev, "BAR %d: can't assign %pR "
			 "(bogus alignment)\n", resno, res);
			 "(bogus alignment)\n", resno, res);
		return -EINVAL;
		return -EINVAL;
	}
	}
@@ -197,9 +190,20 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
		break;
		break;
	}
	}


	if (ret)
	if (ret) {
		dev_info(&dev->dev, "BAR %d: can't allocate %pR\n",
		if (res->flags & IORESOURCE_MEM)
			 resno, res);
			if (res->flags & IORESOURCE_PREFETCH)
				type = "mem pref";
			else
				type = "mem";
		else if (res->flags & IORESOURCE_IO)
			type = "io";
		else
			type = "unknown";
		dev_info(&dev->dev,
			 "BAR %d: can't assign %s (size %#llx)\n",
			 resno, type, (unsigned long long) resource_size(res));
	}


	return ret;
	return ret;
}
}
@@ -272,8 +276,8 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
			continue;
			continue;


		if (!r->parent) {
		if (!r->parent) {
			dev_err(&dev->dev, "device not available because of "
			dev_err(&dev->dev, "device not available "
				"BAR %d %pR collisions\n", i, r);
				"(can't reserve %pR)\n", r);
			return -EINVAL;
			return -EINVAL;
		}
		}