aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/quirks.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2008-03-11 17:24:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-03-12 15:39:36 -0400
commit0509ad5e1a7d9220f09edd5be114bf3bd51a7023 (patch)
tree41c02d01032da129ae82137591d48ecd7369662f /drivers/pnp/quirks.c
parente0aca2330b59752193877da49c6e6b07df78690a (diff)
PNP: disable PNP motherboard resources that overlap PCI BARs
Some BIOSes have PNP motherboard devices with resources that partially overlap PCI BARs. The PNP system driver claims these motherboard resources, which prevents the normal PCI driver from requesting them later. This patch disables the PNP resources that conflict with PCI BARs so they won't be claimed by the PNP system driver. Of course, this only works if PCI devices have already been enumerated. Currently this is the case because PCI devices are discovered before any PNP init via this path: acpi_pci_root_init() -> acpi_pci_root_add() -> pci_acpi_scan_root() -> pci_scan_bus_parented() -> pci_scan_child_bus() -> ... Avuton Olrich tested this and confirmed that it fixes his ALSA sound card (see http://lkml.org/lkml/2008/1/27/168). References: https://bugzilla.redhat.com/show_bug.cgi?id=280641 https://bugzilla.redhat.com/show_bug.cgi?id=313491 http://lkml.org/lkml/2008/1/9/449 http://thread.gmane.org/gmane.linux.acpi.devel/27312 http://lkml.org/lkml/2008/1/27/168 Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/pnp/quirks.c')
-rw-r--r--drivers/pnp/quirks.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index e903b8c2b1fa..37993206ae5d 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -108,6 +108,77 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
108 "pnp: SB audio device quirk - increasing port range\n"); 108 "pnp: SB audio device quirk - increasing port range\n");
109} 109}
110 110
111
112#include <linux/pci.h>
113
114static void quirk_system_pci_resources(struct pnp_dev *dev)
115{
116 struct pci_dev *pdev = NULL;
117 resource_size_t pnp_start, pnp_end, pci_start, pci_end;
118 int i, j;
119
120 /*
121 * Some BIOSes have PNP motherboard devices with resources that
122 * partially overlap PCI BARs. The PNP system driver claims these
123 * motherboard resources, which prevents the normal PCI driver from
124 * requesting them later.
125 *
126 * This patch disables the PNP resources that conflict with PCI BARs
127 * so they won't be claimed by the PNP system driver.
128 */
129 for_each_pci_dev(pdev) {
130 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
131 if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM) ||
132 pci_resource_len(pdev, i) == 0)
133 continue;
134
135 pci_start = pci_resource_start(pdev, i);
136 pci_end = pci_resource_end(pdev, i);
137 for (j = 0; j < PNP_MAX_MEM; j++) {
138 if (!pnp_mem_valid(dev, j) ||
139 pnp_mem_len(dev, j) == 0)
140 continue;
141
142 pnp_start = pnp_mem_start(dev, j);
143 pnp_end = pnp_mem_end(dev, j);
144
145 /*
146 * If the PNP region doesn't overlap the PCI
147 * region at all, there's no problem.
148 */
149 if (pnp_end < pci_start || pnp_start > pci_end)
150 continue;
151
152 /*
153 * If the PNP region completely encloses (or is
154 * at least as large as) the PCI region, that's
155 * also OK. For example, this happens when the
156 * PNP device describes a bridge with PCI
157 * behind it.
158 */
159 if (pnp_start <= pci_start &&
160 pnp_end >= pci_end)
161 continue;
162
163 /*
164 * Otherwise, the PNP region overlaps *part* of
165 * the PCI region, and that might prevent a PCI
166 * driver from requesting its resources.
167 */
168 dev_warn(&dev->dev, "mem resource "
169 "(0x%llx-0x%llx) overlaps %s BAR %d "
170 "(0x%llx-0x%llx), disabling\n",
171 (unsigned long long) pnp_start,
172 (unsigned long long) pnp_end,
173 pci_name(pdev), i,
174 (unsigned long long) pci_start,
175 (unsigned long long) pci_end);
176 pnp_mem_flags(dev, j) = 0;
177 }
178 }
179 }
180}
181
111/* 182/*
112 * PnP Quirks 183 * PnP Quirks
113 * Cards or devices that need some tweaking due to incomplete resource info 184 * Cards or devices that need some tweaking due to incomplete resource info
@@ -128,6 +199,8 @@ static struct pnp_fixup pnp_fixups[] = {
128 {"CTL0043", quirk_sb16audio_resources}, 199 {"CTL0043", quirk_sb16audio_resources},
129 {"CTL0044", quirk_sb16audio_resources}, 200 {"CTL0044", quirk_sb16audio_resources},
130 {"CTL0045", quirk_sb16audio_resources}, 201 {"CTL0045", quirk_sb16audio_resources},
202 {"PNP0c01", quirk_system_pci_resources},
203 {"PNP0c02", quirk_system_pci_resources},
131 {""} 204 {""}
132}; 205};
133 206