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 SR-IOV: correct broken resource alignment calculations

+42 -6
+23
drivers/pci/iov.c
··· 598 598 } 599 599 600 600 /** 601 + * pci_sriov_resource_alignment - get resource alignment for VF BAR 602 + * @dev: the PCI device 603 + * @resno: the resource number 604 + * 605 + * Returns the alignment of the VF BAR found in the SR-IOV capability. 606 + * This is not the same as the resource size which is defined as 607 + * the VF BAR size multiplied by the number of VFs. The alignment 608 + * is just the VF BAR size. 609 + */ 610 + int pci_sriov_resource_alignment(struct pci_dev *dev, int resno) 611 + { 612 + struct resource tmp; 613 + enum pci_bar_type type; 614 + int reg = pci_iov_resource_bar(dev, resno, &type); 615 + 616 + if (!reg) 617 + return 0; 618 + 619 + __pci_read_base(dev, type, &tmp, reg); 620 + return resource_alignment(&tmp); 621 + } 622 + 623 + /** 601 624 * pci_restore_iov_state - restore the state of the IOV capability 602 625 * @dev: the PCI device 603 626 */
+13
drivers/pci/pci.h
··· 243 243 extern void pci_iov_release(struct pci_dev *dev); 244 244 extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, 245 245 enum pci_bar_type *type); 246 + extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno); 246 247 extern void pci_restore_iov_state(struct pci_dev *dev); 247 248 extern int pci_iov_bus_range(struct pci_bus *bus); 248 249 ··· 298 297 return 0; 299 298 } 300 299 #endif /* CONFIG_PCI_IOV */ 300 + 301 + static inline int pci_resource_alignment(struct pci_dev *dev, 302 + struct resource *res) 303 + { 304 + #ifdef CONFIG_PCI_IOV 305 + int resno = res - dev->resource; 306 + 307 + if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) 308 + return pci_sriov_resource_alignment(dev, resno); 309 + #endif 310 + return resource_alignment(res); 311 + } 301 312 302 313 #endif /* DRIVERS_PCI_H */
+2 -2
drivers/pci/setup-bus.c
··· 25 25 #include <linux/ioport.h> 26 26 #include <linux/cache.h> 27 27 #include <linux/slab.h> 28 - 28 + #include "pci.h" 29 29 30 30 static void pbus_assign_resources_sorted(const struct pci_bus *bus) 31 31 { ··· 384 384 continue; 385 385 r_size = resource_size(r); 386 386 /* For bridges size != alignment */ 387 - align = resource_alignment(r); 387 + align = pci_resource_alignment(dev, r); 388 388 order = __ffs(align) - 20; 389 389 if (order > 11) { 390 390 dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
+4 -4
drivers/pci/setup-res.c
··· 144 144 145 145 size = resource_size(res); 146 146 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; 147 - align = resource_alignment(res); 147 + align = pci_resource_alignment(dev, res); 148 148 149 149 /* First, try exact prefetching match.. */ 150 150 ret = pci_bus_alloc_resource(bus, res, size, align, min, ··· 178 178 struct pci_bus *bus; 179 179 int ret; 180 180 181 - align = resource_alignment(res); 181 + align = pci_resource_alignment(dev, res); 182 182 if (!align) { 183 183 dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus " 184 184 "alignment) %pR flags %#lx\n", ··· 259 259 if (!(r->flags) || r->parent) 260 260 continue; 261 261 262 - r_align = resource_alignment(r); 262 + r_align = pci_resource_alignment(dev, r); 263 263 if (!r_align) { 264 264 dev_warn(&dev->dev, "BAR %d: bogus alignment " 265 265 "%pR flags %#lx\n", ··· 271 271 struct resource_list *ln = list->next; 272 272 273 273 if (ln) 274 - align = resource_alignment(ln->res); 274 + align = pci_resource_alignment(ln->dev, ln->res); 275 275 276 276 if (r_align > align) { 277 277 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);