diff options
Diffstat (limited to 'drivers/pci/setup-res.c')
-rw-r--r-- | drivers/pci/setup-res.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index bad509e40fb..7d35cdf4579 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -137,10 +137,16 @@ int pci_assign_resource(struct pci_dev *dev, int resno) size = res->end - res->start + 1; min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - /* The bridge resources are special, as their - size != alignment. Sizing routines return - required alignment in the "start" field. */ - align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; + + align = resource_alignment(res); + if (!align) { + printk(KERN_ERR "PCI: Cannot allocate resource (bogus " + "alignment) %d [%llx:%llx] (flags %lx) of %s\n", + resno, (unsigned long long)res->start, + (unsigned long long)res->end, res->flags, + pci_name(dev)); + return -EINVAL; + } /* First, try exact prefetching match.. */ ret = pci_bus_alloc_resource(bus, res, size, align, min, @@ -164,8 +170,10 @@ int pci_assign_resource(struct pci_dev *dev, int resno) res->flags & IORESOURCE_IO ? "I/O" : "mem", resno, (unsigned long long)size, (unsigned long long)res->start, pci_name(dev)); - } else if (resno < PCI_BRIDGE_RESOURCES) { - pci_update_resource(dev, res, resno); + } else { + res->flags &= ~IORESOURCE_STARTALIGN; + if (resno < PCI_BRIDGE_RESOURCES) + pci_update_resource(dev, res, resno); } return ret; @@ -226,29 +234,25 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) if (r->flags & IORESOURCE_PCI_FIXED) continue; - r_align = r->end - r->start; - if (!(r->flags) || r->parent) continue; + + r_align = resource_alignment(r); if (!r_align) { - printk(KERN_WARNING "PCI: Ignore bogus resource %d " - "[%llx:%llx] of %s\n", + printk(KERN_WARNING "PCI: bogus alignment of resource " + "%d [%llx:%llx] (flags %lx) of %s\n", i, (unsigned long long)r->start, - (unsigned long long)r->end, pci_name(dev)); + (unsigned long long)r->end, r->flags, + pci_name(dev)); continue; } - r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start; for (list = head; ; list = list->next) { resource_size_t align = 0; struct resource_list *ln = list->next; - int idx; - if (ln) { - idx = ln->res - &ln->dev->resource[0]; - align = (idx < PCI_BRIDGE_RESOURCES) ? - ln->res->end - ln->res->start + 1 : - ln->res->start; - } + if (ln) + align = resource_alignment(ln->res); + if (r_align > align) { tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) |