|
@@ -156,6 +156,38 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
|
|
pcibios_align_resource, dev);
|
|
|
}
|
|
|
|
|
|
+ if (ret < 0 && dev->fw_addr[resno]) {
|
|
|
+ struct resource *root, *conflict;
|
|
|
+ resource_size_t start, end;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we failed to assign anything, let's try the address
|
|
|
+ * where firmware left it. That at least has a chance of
|
|
|
+ * working, which is better than just leaving it disabled.
|
|
|
+ */
|
|
|
+
|
|
|
+ if (res->flags & IORESOURCE_IO)
|
|
|
+ root = &ioport_resource;
|
|
|
+ else
|
|
|
+ root = &iomem_resource;
|
|
|
+
|
|
|
+ start = res->start;
|
|
|
+ end = res->end;
|
|
|
+ res->start = dev->fw_addr[resno];
|
|
|
+ res->end = res->start + size - 1;
|
|
|
+ dev_info(&dev->dev, "BAR %d: trying firmware assignment %pR\n",
|
|
|
+ resno, res);
|
|
|
+ conflict = request_resource_conflict(root, res);
|
|
|
+ if (conflict) {
|
|
|
+ dev_info(&dev->dev,
|
|
|
+ "BAR %d: %pR conflicts with %s %pR\n", resno,
|
|
|
+ res, conflict->name, conflict);
|
|
|
+ res->start = start;
|
|
|
+ res->end = end;
|
|
|
+ } else
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+
|
|
|
if (!ret) {
|
|
|
res->flags &= ~IORESOURCE_STARTALIGN;
|
|
|
dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
|