Re: [PATCH v4 4/5] PCI: Try best to allocate pref mmio 64bit above 4g
From: Yinghai Lu
Date: Mon Dec 16 2013 - 19:36:38 EST
On Mon, Dec 16, 2013 at 1:36 PM, Yinghai Lu <yinghai@xxxxxxxxxx> wrote:
> On Mon, Dec 16, 2013 at 10:13 AM, Yinghai Lu <yinghai@xxxxxxxxxx> wrote:
>>>
>>> 64-bit non-prefetchable BARs are missed from caculation in the scheme,
>>> causing assign failed eventually.
>>>
>>> Will you figure out a better way to cover them or just add a 'type3' parameter?
>
> Looks like we have add type3 for that case.
please check attached delta patch.
Thanks
Yinghai
---
drivers/pci/setup-bus.c | 17 +++++++++++------
drivers/pci/setup-res.c | 8 ++++++--
2 files changed, 17 insertions(+), 8 deletions(-)
Index: linux-2.6/drivers/pci/setup-bus.c
===================================================================
--- linux-2.6.orig/drivers/pci/setup-bus.c
+++ linux-2.6/drivers/pci/setup-bus.c
@@ -916,6 +916,7 @@ static inline resource_size_t calculate_
*/
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
unsigned long type, unsigned long type2,
+ unsigned long type3,
resource_size_t min_size, resource_size_t add_size,
struct list_head *realloc_head)
{
@@ -946,7 +947,8 @@ static int pbus_size_mem(struct pci_bus
resource_size_t r_size;
if (r->parent || ((r->flags & mask) != type &&
- (r->flags & mask) != type2))
+ (r->flags & mask) != type2 &&
+ (r->flags & mask) != type3))
continue;
r_size = resource_size(r);
#ifdef CONFIG_PCI_IOV
@@ -1119,7 +1121,7 @@ void __ref __pci_bus_size_bridges(struct
struct list_head *realloc_head)
{
struct pci_dev *dev;
- unsigned long mask, prefmask, type2 = 0;
+ unsigned long mask, prefmask, type2 = 0, type3 = 0;
resource_size_t additional_mem_size = 0, additional_io_size = 0;
struct resource *b_res;
@@ -1171,26 +1173,29 @@ void __ref __pci_bus_size_bridges(struct
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
if (b_res[2].flags & IORESOURCE_MEM_64) {
prefmask |= IORESOURCE_MEM_64;
- if (pbus_size_mem(bus, prefmask, prefmask, prefmask,
+ if (pbus_size_mem(bus, prefmask, prefmask,
+ prefmask, prefmask,
realloc_head ? 0 : additional_mem_size,
additional_mem_size, realloc_head)) {
/* Success, size non-pref64 only. */
mask = prefmask;
type2 = prefmask & ~IORESOURCE_MEM_64;
+ type3 = prefmask & ~IORESOURCE_PREFETCH;
}
}
if (!type2) {
prefmask &= ~IORESOURCE_MEM_64;
- if (pbus_size_mem(bus, prefmask, prefmask, prefmask,
+ if (pbus_size_mem(bus, prefmask, prefmask,
+ prefmask, prefmask,
realloc_head ? 0 : additional_mem_size,
additional_mem_size, realloc_head)) {
/* Success, size non-prefetch only. */
mask = prefmask;
} else
additional_mem_size += additional_mem_size;
- type2 = IORESOURCE_MEM;
+ type2 = type3 = IORESOURCE_MEM;
}
- pbus_size_mem(bus, mask, IORESOURCE_MEM, type2,
+ pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,
realloc_head ? 0 : additional_mem_size,
additional_mem_size, realloc_head);
break;
Index: linux-2.6/drivers/pci/setup-res.c
===================================================================
--- linux-2.6.orig/drivers/pci/setup-res.c
+++ linux-2.6/drivers/pci/setup-res.c
@@ -212,7 +212,8 @@ static int __pci_assign_resource(struct
pcibios_align_resource, dev);
if (ret < 0 &&
- (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))) {
+ (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) ==
+ (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
/*
* That failed.
*
@@ -223,12 +224,15 @@ static int __pci_assign_resource(struct
pcibios_align_resource, dev);
}
- if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
+ if (ret < 0 &&
+ (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))) {
/*
* That failed.
*
* But a prefetching area can handle a non-prefetching
* window (it will just not perform as well).
+ *
+ * Also can put 64bit under 32bit range. (below 4g).
*/
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
pcibios_align_resource, dev);