diff options
Diffstat (limited to 'drivers/pci/setup-res.c')
| -rw-r--r-- | drivers/pci/setup-res.c | 32 |
1 files changed, 32 insertions, 0 deletions
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); |
