Add a wrap of resource_alignment() so it can handle device specific resource alignment. Cc: Jesse Barnes <jbarnes@xxxxxxxxxxxxxxxx> Cc: Randy Dunlap <randy.dunlap@xxxxxxxxxx> Cc: Grant Grundler <grundler@xxxxxxxxxxxxxxxx> Cc: Alex Chiang <achiang@xxxxxx> Cc: Matthew Wilcox <matthew@xxxxxx> Cc: Roland Dreier <rdreier@xxxxxxxxx> Cc: Greg KH <greg@xxxxxxxxx> Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx> --- drivers/pci/pci.c | 20 ++++++++++++++++++++ drivers/pci/pci.h | 1 + drivers/pci/setup-bus.c | 4 ++-- drivers/pci/setup-res.c | 7 ++++--- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 40284dc..a9b554e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1904,6 +1904,26 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags) return bars; } +/** + * pci_resource_alignment - get a PCI BAR resource alignment + * @dev: the PCI device + * @resno: the resource number + * + * Returns alignment size on success, or 0 on error. + */ +int pci_resource_alignment(struct pci_dev *dev, int resno) +{ + resource_size_t align; + struct resource *res = dev->resource + resno; + + align = resource_alignment(res); + if (align) + return align; + + dev_err(&dev->dev, "alignment: invalid resource #%d\n", resno); + return 0; +} + static void __devinit pci_no_domains(void) { #ifdef CONFIG_PCI_DOMAINS diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fbbc6ad..baa3d23 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -166,6 +166,7 @@ enum pci_bar_type { extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct resource *res, unsigned int reg); +extern int pci_resource_alignment(struct pci_dev *dev, int resno); extern void pci_enable_ari(struct pci_dev *dev); /** * pci_ari_enabled - query ARI forwarding status diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ea979f2..90a9c0a 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,6 +25,7 @@ #include <linux/ioport.h> #include <linux/cache.h> #include <linux/slab.h> +#include "pci.h" static void pbus_assign_resources_sorted(struct pci_bus *bus) @@ -351,8 +352,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long if (r->parent || (r->flags & mask) != type) continue; r_size = resource_size(r); - /* For bridges size != alignment */ - align = resource_alignment(r); + align = pci_resource_alignment(dev, i); order = __ffs(align) - 20; if (order > 11) { dev_warn(&dev->dev, "BAR %d bad alignment %llx: " diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index b7ca679..88a9c70 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -133,7 +133,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) size = resource_size(res); min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - align = resource_alignment(res); + align = pci_resource_alignment(dev, resno); if (!align) { dev_err(&dev->dev, "BAR %d: can't allocate resource (bogus " "alignment) %pR flags %#lx\n", @@ -224,7 +224,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) if (!(r->flags) || r->parent) continue; - r_align = resource_alignment(r); + r_align = pci_resource_alignment(dev, i); if (!r_align) { dev_warn(&dev->dev, "BAR %d: bogus alignment " "%pR flags %#lx\n", @@ -236,7 +236,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) struct resource_list *ln = list->next; if (ln) - align = resource_alignment(ln->res); + align = pci_resource_alignment(ln->dev, + ln->res - ln->dev->resource); if (r_align > align) { tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); -- 1.5.6.4 -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html