aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/quirks.c
diff options
context:
space:
mode:
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