pci_bus_for_each_resource, transparent bridges and rsrc_nonstatic.c

Dominik Brodowski linux at dominikbrodowski.net
Tue Mar 30 02:51:11 EDT 2010


> Avoiding this kind of collision only requires that you identify the
> range you want to avoid; it has nothing to do with whether a bridge
> window is &iomem_resource or &ioport_resource or whether it is
> subtractively decoded. 

Well, it's actually not only a range I want to avoid, it's _anything_ which
is not made available exclusively for the secondary PCI bus. It seems to me
that such secondary PCI buses are usually well enumerated, all resource
users well known PCI devices etc.

> Here's a topology where I think you would want to pay attention to the
> subtractively decoded window forwarded to bus 01:
> 
>   host bridge window [io  0x4000-0x4fff] to bus 00
>     00:00.0 PCI bridge to bus 01 (subtractive decode mode)
>       01:00.0 CardBus bridge to bus 02

Exactly.

> As an aside, even if the BIOS provided perfect ACPI resource
> information, Linux would happily ignore almost all of it, since the
> Linux/ACPI core doesn't even look at those resource descriptions, and
> while PNPACPI does evaluate _CRS methods, it never puts any of the
> information in the resource trees.  It's only when a driver claims a
> device and reserves its resources that those resources become visible to
> the rest of the system.  So it's all well and good to acknowledge that
> BIOSes often have bugs, but we're on pretty shaky ground in Linux, too.

Thanks for the clarification.

From: Dominik Brodowski <linux at dominikbrodowski.net>
Date: Mon, 29 Mar 2010 21:40:35 +0200
Subject: [PATCH] pcmcia: do not autoadd root PCI bus resources

On the PCI root bus on the x86 architecture, the risk of hitting
some strange system devices is too high: If a driver isn't loaded,
the resources are not claimed; even if a driver is loaded, it
may not request all resources or even the wrong one. We can neither
trust the rest of the kernel nor ACPI/PNP and CRS parsing to get it
right.

Therefore, explicitly spell out what safeguards we provide, and add
a safeguard to only use resources which are set up exclusively for
the secondary PCI bus (non-subtractive mode): the risk of hitting
system devices is quite low, as they usually aren't connected to
the secondary PCI bus.

CC: Jesse Barnes <jbarnes at virtuousgeek.org>
CC: Bjorn Helgaas <bjorn.helgaas at hp.com>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>

diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 39c89e1..bfb2774 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -930,23 +930,42 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 		return -ENODEV;
 
 #if defined(CONFIG_X86)
-	/* If this is the root bus, the risk of hitting
-	 * some strange system devices which aren't protected
-	 * by either ACPI resource tables or properly requested
-	 * resources is too big. Therefore, don't do auto-adding
-	 * of resources at the moment.
+	/* If this is the root bus, the risk of hitting some strange
+	 * system devices is too high: If a driver isn't loaded, the
+	 * resources are not claimed; even if a driver is loaded, it
+	 * may not request all resources or even the wrong one. We
+	 * can neither trust the rest of the kernel nor ACPI/PNP and
+	 * CRS parsing to get it right. Therefore, use several
+	 * safeguards:
+	 *
+	 * - Do not auto-add resources if the CardBus bridge is on 
+	 *   the PCI root bus
+	 *
+	 * - Avoid any I/O ports < 0x100.
+	 *
+	 * - On PCI-PCI bridges, only use resources which are set up
+	 *   exclusively for the secondary PCI bus: the risk of hitting
+	 *   system devices is quite low, as they usually aren't
+	 *   connected to the secondary PCI bus.
 	 */
 	if (s->cb_dev->bus->number == 0)
 		return -EINVAL;
-#endif
 
+	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
+		res = s->cb_dev->bus->resource[i];
+#else
 	pci_bus_for_each_resource(s->cb_dev->bus, res, i) {
+#endif
 		if (!res)
 			continue;
 
 		if (res->flags & IORESOURCE_IO) {
+			/* safeguard against the root resource, where the
+			 * risk of hitting any other device would be too
+			 * high */
 			if (res == &ioport_resource)
 				continue;
+
 			dev_printk(KERN_INFO, &s->cb_dev->dev,
 				   "pcmcia: parent PCI bridge window: %pR\n",
 				   res);
@@ -956,8 +975,12 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 		}
 
 		if (res->flags & IORESOURCE_MEM) {
+			/* safeguard against the root resource, where the
+			 * risk of hitting any other device would be too
+			 * high */
 			if (res == &iomem_resource)
 				continue;
+
 			dev_printk(KERN_INFO, &s->cb_dev->dev,
 				   "pcmcia: parent PCI bridge window: %pR\n",
 				   res);



More information about the linux-pcmcia mailing list