diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-07-18 18:05:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-07-18 18:05:22 -0400 |
commit | 2044f2282d7558c765270d78e19dbdcf6190ca71 (patch) | |
tree | 03b2c4d211fa8e7e2ef8c489d28a16442f030d57 | |
parent | bea9a6d239cb2aa2ced4dcb0a05e1827ce61fa3d (diff) | |
parent | 58c84eda07560a6b75b03e8d3b26d6eddfc14011 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
PCI: fall back to original BIOS BAR addresses
-rw-r--r-- | arch/x86/pci/i386.c | 1 | ||||
-rw-r--r-- | drivers/pci/setup-res.c | 32 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
3 files changed, 34 insertions, 0 deletions
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 6fdb3ec30c31..55253095be84 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
@@ -184,6 +184,7 @@ static void __init pcibios_allocate_resources(int pass) | |||
184 | idx, r, disabled, pass); | 184 | idx, r, disabled, pass); |
185 | if (pci_claim_resource(dev, idx) < 0) { | 185 | if (pci_claim_resource(dev, idx) < 0) { |
186 | /* We'll assign a new address later */ | 186 | /* We'll assign a new address later */ |
187 | dev->fw_addr[idx] = r->start; | ||
187 | r->end -= r->start; | 188 | r->end -= r->start; |
188 | r->start = 0; | 189 | r->start = 0; |
189 | } | 190 | } |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 92379e2d37e7..2aaa13150de3 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
@@ -156,6 +156,38 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, | |||
156 | pcibios_align_resource, dev); | 156 | pcibios_align_resource, dev); |
157 | } | 157 | } |
158 | 158 | ||
159 | if (ret < 0 && dev->fw_addr[resno]) { | ||
160 | struct resource *root, *conflict; | ||
161 | resource_size_t start, end; | ||
162 | |||
163 | /* | ||
164 | * If we failed to assign anything, let's try the address | ||
165 | * where firmware left it. That at least has a chance of | ||
166 | * working, which is better than just leaving it disabled. | ||
167 | */ | ||
168 | |||
169 | if (res->flags & IORESOURCE_IO) | ||
170 | root = &ioport_resource; | ||
171 | else | ||
172 | root = &iomem_resource; | ||
173 | |||
174 | start = res->start; | ||
175 | end = res->end; | ||
176 | res->start = dev->fw_addr[resno]; | ||
177 | res->end = res->start + size - 1; | ||
178 | dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n", | ||
179 | resno, res); | ||
180 | conflict = request_resource_conflict(root, res); | ||
181 | if (conflict) { | ||
182 | dev_info(&dev->dev, | ||
183 | "BAR %d: %pR conflicts with %s %pR\n", resno, | ||
184 | res, conflict->name, conflict); | ||
185 | res->start = start; | ||
186 | res->end = end; | ||
187 | } else | ||
188 | ret = 0; | ||
189 | } | ||
190 | |||
159 | if (!ret) { | 191 | if (!ret) { |
160 | res->flags &= ~IORESOURCE_STARTALIGN; | 192 | res->flags &= ~IORESOURCE_STARTALIGN; |
161 | dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); | 193 | dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 7cb00845f150..f26fda76b87f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -288,6 +288,7 @@ struct pci_dev { | |||
288 | */ | 288 | */ |
289 | unsigned int irq; | 289 | unsigned int irq; |
290 | struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ | 290 | struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ |
291 | resource_size_t fw_addr[DEVICE_COUNT_RESOURCE]; /* FW-assigned addr */ | ||
291 | 292 | ||
292 | /* These fields are used by common fixups */ | 293 | /* These fields are used by common fixups */ |
293 | unsigned int transparent:1; /* Transparent PCI bridge */ | 294 | unsigned int transparent:1; /* Transparent PCI bridge */ |