[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <200809261540.31443.bjorn.helgaas@hp.com>
Date: Fri, 26 Sep 2008 15:40:30 -0600
From: Bjorn Helgaas <bjorn.helgaas@...com>
To: Frans Pop <elendil@...net.nl>
Cc: Rene Herman <rene.herman@...access.nl>,
linux-kernel@...r.kernel.org, Rene Herman <rene.herman@...il.com>,
Ingo Molnar <mingo@...e.hu>,
Thomas Gleixner <tglx@...utronix.de>,
Jesse Barnes <jbarnes@...tuousgeek.org>,
Matthew Wilcox <matthew@....cx>,
Benjamin Herrenschmidt <benh@...nel.crashing.org>,
"Rafael J. Wysocki" <rjw@...k.pl>, bugme-daemon@...zilla.kernel.org
Subject: [Bug #11550] pnp: Huge number of "io resource overlap" messages
http://bugzilla.kernel.org/show_bug.cgi?id=11550
On Saturday 20 September 2008 05:56:24 pm Bjorn Helgaas wrote:
> > > On Tuesday 09 September 2008 12:31:09 pm Rene Herman wrote:
> > > > On 09-09-08 19:40, Bjorn Helgaas wrote:
> > > > > If the PCI device isn't fully initialized, it doesn't seem right to
> > > > > check it for resource conflicts. But I don't know how to tell
> > > > > that.
> > > >
> > > > His pci_resource_start() values are 0. How about just checking for
> > > > that?
> ...
> I am still not 100% comfortable with this because I think we really
> want to know whether the BAR value is zero, not whether the CPU
> address is zero, and pci_resource_start() gives us the CPU address.
>
> Bus and CPU addresses are currently identical on x86, but I expect
> that will change someday. They're already different on ia64 and
> some other architectures.
The problem seems to be that Frans has some PCI devices that are not
configured by the BIOS, and their BARs contain zero. A PNP quirk
checks for overlaps of PCI devices and PNP devices, and those zero-
valued BARs of course conflict with the PNP motherboard devices that
describe legacy hardware.
Here's another approach based on section 3.5 of the PCI Firmware spec.
It says:
Since not all devices may be configured prior to the operating
system handoff, the operating system needs to know whether a
specific BAR register has been configured by firmware. The operating
system makes the determination by checking the I/O Enable, and
Memory Enable bits in the device's command register, and Expansion
ROM BAR enable bits. If the enable bit is set, then the corresponding
resource register has been configured.
So instead of checking whether the BAR contains zero, the patch below
checks the I/O, Mem, and ROM BAR enable bits to determine whether a
BAR is enabled.
Frans, I'm sorry to trouble you again, but could you test this and
make sure it takes care of the "resource overlap" messages you saw?
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 1a5fc83..26195c3 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -26,6 +26,28 @@
#include "pci.h"
+int pci_resource_enabled(struct pci_dev *dev, int bar)
+{
+ u16 command = 0;
+ u32 addr = 0;
+
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+
+ if (pci_resource_flags(dev, bar) & IORESOURCE_IO)
+ return command & PCI_COMMAND_IO;
+
+ if (command & PCI_COMMAND_MEMORY) {
+ if (bar == PCI_ROM_RESOURCE) {
+ pci_read_config_dword(dev, dev->rom_base_reg, &addr);
+ return addr & PCI_ROM_ADDRESS_ENABLE;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
{
struct pci_bus_region region;
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 0bdf9b8..ef5ed99 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -247,6 +247,9 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
unsigned int type;
+ if (!pci_resource_enabled(pdev, i))
+ continue;
+
type = pci_resource_flags(pdev, i) &
(IORESOURCE_IO | IORESOURCE_MEM);
if (!type || pci_resource_len(pdev, i) == 0)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c0e1400..28ec520 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -796,6 +796,8 @@ static inline int pci_proc_domain(struct pci_bus *bus)
}
#endif /* CONFIG_PCI_DOMAINS */
+extern int pci_resource_enabled(struct pci_dev *dev, int bar);
+
#else /* CONFIG_PCI is not enabled */
/*
@@ -976,6 +978,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
unsigned int devfn)
{ return NULL; }
+static inline int pci_resource_enabled(struct pci_dev *dev, int bar)
+{ return 0; }
+
#endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists