diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-05 16:50:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-05 16:50:46 -0400 |
| commit | 9b6a3df372f0318bb0ffe37ac5f4610fb9bdb44d (patch) | |
| tree | 88b76c84a21927acffd02f556764c4be33258bce | |
| parent | d3acd16cda3a1cbaff7c579c0e054f0ece613d14 (diff) | |
| parent | 6faf17f6f1ffc586d16efc2f9fa2083a7785ee74 (diff) | |
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
| -rw-r--r-- | drivers/pci/iov.c | 23 | ||||
| -rw-r--r-- | drivers/pci/pci.h | 13 | ||||
| -rw-r--r-- | drivers/pci/setup-bus.c | 4 | ||||
| -rw-r--r-- | drivers/pci/setup-res.c | 8 |
4 files changed, 42 insertions, 6 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index e3a87210e947..e03fe98f0619 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
| @@ -598,6 +598,29 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, | |||
| 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 | * pci_restore_iov_state - restore the state of the IOV capability | 624 | * pci_restore_iov_state - restore the state of the IOV capability |
| 602 | * @dev: the PCI device | 625 | * @dev: the PCI device |
| 603 | */ | 626 | */ |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f73bcbedf37c..5ff4d25bf0e9 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -243,6 +243,7 @@ extern int pci_iov_init(struct pci_dev *dev); | |||
| 243 | extern void pci_iov_release(struct pci_dev *dev); | 243 | extern void pci_iov_release(struct pci_dev *dev); |
| 244 | extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, | 244 | extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, |
| 245 | enum pci_bar_type *type); | 245 | enum pci_bar_type *type); |
| 246 | extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno); | ||
| 246 | extern void pci_restore_iov_state(struct pci_dev *dev); | 247 | extern void pci_restore_iov_state(struct pci_dev *dev); |
| 247 | extern int pci_iov_bus_range(struct pci_bus *bus); | 248 | extern int pci_iov_bus_range(struct pci_bus *bus); |
| 248 | 249 | ||
| @@ -298,4 +299,16 @@ static inline int pci_ats_enabled(struct pci_dev *dev) | |||
| 298 | } | 299 | } |
| 299 | #endif /* CONFIG_PCI_IOV */ | 300 | #endif /* CONFIG_PCI_IOV */ |
| 300 | 301 | ||
| 302 | static inline int pci_resource_alignment(struct pci_dev *dev, | ||
| 303 | struct resource *res) | ||
| 304 | { | ||
| 305 | #ifdef CONFIG_PCI_IOV | ||
| 306 | int resno = res - dev->resource; | ||
| 307 | |||
| 308 | if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) | ||
| 309 | return pci_sriov_resource_alignment(dev, resno); | ||
| 310 | #endif | ||
| 311 | return resource_alignment(res); | ||
| 312 | } | ||
| 313 | |||
| 301 | #endif /* DRIVERS_PCI_H */ | 314 | #endif /* DRIVERS_PCI_H */ |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index b636e245445d..7c443b4583ab 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
| 26 | #include <linux/cache.h> | 26 | #include <linux/cache.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | 28 | #include "pci.h" | |
| 29 | 29 | ||
| 30 | static void pbus_assign_resources_sorted(const struct pci_bus *bus) | 30 | static void pbus_assign_resources_sorted(const struct pci_bus *bus) |
| 31 | { | 31 | { |
| @@ -384,7 +384,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
| 384 | continue; | 384 | continue; |
| 385 | r_size = resource_size(r); | 385 | r_size = resource_size(r); |
| 386 | /* For bridges size != alignment */ | 386 | /* For bridges size != alignment */ |
| 387 | align = resource_alignment(r); | 387 | align = pci_resource_alignment(dev, r); |
| 388 | order = __ffs(align) - 20; | 388 | order = __ffs(align) - 20; |
| 389 | if (order > 11) { | 389 | if (order > 11) { |
| 390 | dev_warn(&dev->dev, "BAR %d bad alignment %llx: " | 390 | dev_warn(&dev->dev, "BAR %d bad alignment %llx: " |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 1898c7b47907..88cdd1a937d6 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
| @@ -144,7 +144,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, | |||
| 144 | 144 | ||
| 145 | size = resource_size(res); | 145 | size = resource_size(res); |
| 146 | min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; | 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 | /* First, try exact prefetching match.. */ | 149 | /* First, try exact prefetching match.. */ |
| 150 | ret = pci_bus_alloc_resource(bus, res, size, align, min, | 150 | ret = pci_bus_alloc_resource(bus, res, size, align, min, |
| @@ -178,7 +178,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) | |||
| 178 | struct pci_bus *bus; | 178 | struct pci_bus *bus; |
| 179 | int ret; | 179 | int ret; |
| 180 | 180 | ||
| 181 | align = resource_alignment(res); | 181 | align = pci_resource_alignment(dev, res); |
| 182 | if (!align) { | 182 | if (!align) { |
| 183 | dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus " | 183 | dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus " |
| 184 | "alignment) %pR flags %#lx\n", | 184 | "alignment) %pR flags %#lx\n", |
| @@ -259,7 +259,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) | |||
| 259 | if (!(r->flags) || r->parent) | 259 | if (!(r->flags) || r->parent) |
| 260 | continue; | 260 | continue; |
| 261 | 261 | ||
| 262 | r_align = resource_alignment(r); | 262 | r_align = pci_resource_alignment(dev, r); |
| 263 | if (!r_align) { | 263 | if (!r_align) { |
| 264 | dev_warn(&dev->dev, "BAR %d: bogus alignment " | 264 | dev_warn(&dev->dev, "BAR %d: bogus alignment " |
| 265 | "%pR flags %#lx\n", | 265 | "%pR flags %#lx\n", |
| @@ -271,7 +271,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) | |||
| 271 | struct resource_list *ln = list->next; | 271 | struct resource_list *ln = list->next; |
| 272 | 272 | ||
| 273 | if (ln) | 273 | if (ln) |
| 274 | align = resource_alignment(ln->res); | 274 | align = pci_resource_alignment(ln->dev, ln->res); |
| 275 | 275 | ||
| 276 | if (r_align > align) { | 276 | if (r_align > align) { |
| 277 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | 277 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
