pci_bus_for_each_resource, transparent bridges and rsrc_nonstatic.c

Dominik Brodowski linux at dominikbrodowski.net
Tue Mar 23 11:13:01 EDT 2010


On Tue, Mar 23, 2010 at 12:28:00AM +0100, Dominik Brodowski wrote:
> On Mon, Mar 22, 2010 at 04:11:33PM -0700, Bjorn Helgaas wrote:
> > > (1) The root PCI bus has _CRS I/O 0000-0cf7; 0d00-ffff "produced";
> > > 
> > >     the (transparent) PCI-PCI bridge offers, as bus resources, to
> > >     downstream users 0x4000-0x4fff plus everything else because of
> > >     subtractive decoding;
> > > 
> > >     there is a yenta-style PCI-CardBus/PCMCIA bridge below this
> > >     PCI-PCI bridge.
> > > 
> > > (2) There are some I/O ports which react rather unfriendly to being read or
> > >     written. Let's assume they're at 0x100-0x10f; and let's also assume that
> > >     the BIOS writers forgot to mention them at all in the ACPI _CRS
> > >     settings; no other part of the kernel knows about it.
> > > 
> > > 0000-0cf7 : PCI Bus 0000:00
> > > ...
> > >   00f0-00ff : fpu
> > >   0170-0177 : 0000:00:1f.2
> > > 
> > > 
> > > (3) A PCMCIA card is inserted. It needs an I/O port resource of size 8. The
> > >     PCMCIA subsystem looks in its own resource database which I/O ports it
> > >     may use; there, it finds not only 0x4000-0x4fff but (with a small
> > >     exception) 0x0000-0xffff; as 0x0000-0x00ff are already assigned, it
> > >     happily assigns the first free area -- 0x100-0x108 -- to the PCMCIA
> > >     card.
> > > 
> > > 0000-0cf7 : PCI Bus 0000:00
> > > ...
> > >   00f0-00ff : fpu
> > >   0100-0108 : pcmcia0.0
> > >   0170-0177 : 0000:00:1f.2
> > > 
> > > (4) The PCMCIA card and the PCMCIA driver are set up to work with an IO
> > >     resource at 0x100-0x108. As soon as they attempt to use this resource,
> > >     bad things happen (lockups, etc.) because of the reasons spelled out at
> > >     (2).
> > 
> > We'd have exactly the same situation if we assigned I/O port 0x100
> > to a PCI device.  Why can't we use the same strategy PCI uses to
> > avoid it?
> 
> Well, PCI devices have three advantages:
> 
> - they can more easily be "enumerated" (and their resource needs reflected)
>   by ACPI or the BIOS.
> 
> - they usually don't conflict with ISA-style hardware(?)
> 
> - they usually work happily with any (even high) I/O ports.
> 
> > > => It is only an issue if the ACPI resource descriptions are incomplete. It
> > > is worse for PCMCIA because it happily assigns resources below 0x1000, where
> > > such system/platform devices usually listen to. And usecrs worsens the
> > > situation also in another regard: on my own laptop (a pre-2008 model),
> > > pci=use_crs makes the PCI-PCI bridge to be marked as "transparent", while
> > > pci=nocrs means the PCI-PCI bridge is assumed to be "non-transparent".
> > 
> > Sorry to be slow again...  The pci=use_crs and pci=nocrs options only
> > affect the PCI host bridge; they don't affect PCI-PCI bridges at all,
> > except that they change the set of resources available for subtractive-
> > decode PCI-PCI bridges to forward.  (Strictly speaking, they don't
> > affect the *behavior* of the PCI-PCI bridges, they only affect our
> > *idea* of what they're doing.)
> > 
> > I'm thinking of the code in pci_setup_device() where we set dev->transparent
> > based on the bridge's class code.  Obviously, you must be thinking
> > of something else.
> > 
> > My intention was that on pre-2008 systems like your laptop, my patches
> > would not change any behavior at all, unless you boot with "pci=use_crs".
> > Are you seeing an unexpected change on your system?
> 
> No, that's excactly what I'm seeing here. On pre-2008 system, the behavior
> is still the same; no unexpected change; all fine unless I boot with
> "pci=use_crs".
> 
> In contrast, on post-2008 systems like Komuros system, we now trust to
> ACPI report _all_ resource users. If ACPI gets this right, I don't see a
> real problem (but I might add a safety check to avoid any I/O ports < 0x0100
> anyway). The remaining question: can we safely trust BIOS authors to get it
> right?

From: Dominik Brodowski <linux at dominikbrodowski.net>
Date: Tue, 23 Mar 2010 16:05:00 +0100
Subject: [PATCH] pcmcia: do not use ioports < 0x100 on x86

On x86 systems using ACPI _CRS information -- now the default for
post-2008 systems -- the PCI root bus no longer pretends to be
offering the root ioport_resource. To avoid accidentally hitting
some platform / system device, use only I/O ports >= 0x100 for
PCMCIA devices on x86.

Also, use %pR, while we're there.

Reported-by: Komuro <komurojun-mbn at nifty.com>
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 4663b3f..7ae5b0f 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -864,13 +864,21 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 			continue;
 
 		if (res->flags & IORESOURCE_IO) {
+
+#if defined(CONFIG_X86)
+			/* on x86, avoid anything < 0x100 for it is often
+			 * used for legacy platform devices
+			 */
+			if (res->start < 0x100)
+				res->start = 0x100;
+			if (res->start >= res->end)
+				continue;
+#endif
+
 			if (res == &ioport_resource)
 				continue;
-			dev_printk(KERN_INFO, &s->cb_dev->dev,
-				   "pcmcia: parent PCI bridge I/O "
-				   "window: 0x%llx - 0x%llx\n",
-				   (unsigned long long)res->start,
-				   (unsigned long long)res->end);
+			dev_info(&s->cb_dev->dev, "pcmcia: parent PCI bridge "
+				"window: %pR\n", res);
 			if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
 				done |= IORESOURCE_IO;
 
@@ -879,11 +887,8 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 		if (res->flags & IORESOURCE_MEM) {
 			if (res == &iomem_resource)
 				continue;
-			dev_printk(KERN_INFO, &s->cb_dev->dev,
-				   "pcmcia: parent PCI bridge Memory "
-				   "window: 0x%llx - 0x%llx\n",
-				   (unsigned long long)res->start,
-				   (unsigned long long)res->end);
+			dev_info(&s->cb_dev->dev, "pcmcia: parent PCI bridge "
+				"window: %pR\n", res);
 			if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
 				done |= IORESOURCE_MEM;
 		}



More information about the linux-pcmcia mailing list