PCI: Fix bus align checking to support more than 8G
PATCH v4 1/3 PCI: Fix bus align checking to support more than 8G
Use 128G instead.
--- drivers/pci/setup-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/setup-bus.c +1 -1
@@ -925,7 +925,7 @@ static int pbus_size_mem(struct pci_bus {struct pci_dev *dev;resource_size_t min_align, align, size, size0, size1; -resource_size_t aligns[14 ];/* Alignments from 1Mb to 8Gb */ +resource_size_t aligns[18 ];/* Alignments from 1Mb to 128Gb */ int order, max_order;struct resource *b_res =find_free_bus_resource (bus, mask |IORESOURCE_PREFETCH , type);
PATCH v4 2/3 PCI: Fix bus align checking with 32bit bridge pref
If the bridge does not support 64bit pref mmio, we should still keep align to be 2G as old time.
So add mmio64 mask checking, keep that 2G checking in the loop.
--- drivers/pci/setup-bus.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/pci/setup-bus.c +10 -1
@@ -930,10 +930,17 @@ static int pbus_size_mem(struct pci_busstruct resource *b_res =find_free_bus_resource (bus, mask |IORESOURCE_PREFETCH , type);resource_size_t children_add_size =0 ; +unsigned int mem64_mask;if (!b_res)return -ENOSPC ; + mem64_mask = b_res->flags &IORESOURCE_MEM_64 ; + +/* kernel does not support 64bit res */ +if (sizeof (resource_size_t) ==4 ) + mem64_mask &= ~IORESOURCE_MEM_64 ; +memset (aligns,0 ,sizeof (aligns)); max_order =0 ; size =0 ;
@@ -970,12 +977,14 @@ static int pbus_size_mem(struct pci_bus order =__ffs (align) -20 ;if (order <0 ) order =0 ; -if (order >=ARRAY_SIZE (aligns)) { +if (order >=ARRAY_SIZE (aligns) || + (!mem64_mask && order >11 /* 2Gb */ )) {dev_warn (&dev->dev,"disabling BAR %d: %pR (bad alignment %#llx)\n" , i, r, (unsigned long long ) align); r->flags =0 ;continue ; } + size += r_size;/* Exclude ranges with size > align from calculation of the alignment. */
PATCH v4 3/3 PCI: Avoid size overflow for bridge 32bit resource
In reply to Yinghai LuWhen mmio64_mask is not used, overall size should not bigger than 2G for single bridge.
Get out early, so we could have chance to have some child resources get assigned instead of failing all of them, as bridge resource assigned is too small when overflow happens.
--- drivers/pci/setup-bus.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/pci/setup-bus.c +10 -0
@@ -957,6 +957,16 @@ static int pbus_size_mem(struct pci_bus (r->flags & mask) != type3))continue ; r_size =resource_size (r); + +/* reject oversize early */ +if (!mem64_mask && + ((unsigned long long )size + r_size > (1ULL <<31 ))) { +dev_warn (&dev->dev,"disabling BAR %d: %pR size %#llx overflow bridge's)\n" , + i, r, (unsigned long long )size); + r->flags =0 ; +continue ; + } +#ifdef CONFIG_PCI_IOV /* put SRIOV requested res to the optional list */ if (realloc_head && i >= PCI_IOV_RESOURCES &&
Quoted 3 lines · Yinghai Lu
Use 128G instead.
Signed-off-by Yinghai Lu <[email protected]>
I applied this one to pci/resource for v3.17, thanks!
I didn't apply [2/3] or [3/3] because the questions I raised earlier haven't been resolved.
Quoted 17 lines
--- drivers/pci/setup-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)Index:
linux-2.6/drivers/pci/setup-bus.c
===================================================================drivers/pci/setup-bus.c +1
-1@@ -925,7 +925,7 @@ static int pbus_size_mem(struct pci_bus {struct pci_dev *dev;resource_size_t min_align, align, size, size0, size1; -resource_size_t aligns[14 ];/* Alignments from 1Mb to 8Gb */ +resource_size_t aligns[18 ];/* Alignments from 1Mb to 128Gb */ int order, max_order;struct resource *b_res =find_free_bus_resource (bus, mask |IORESOURCE_PREFETCH , type);
Quoted 9 lines · Bjorn Helgaas
Quoted 3 lines · Yinghai Lu
Use 128G instead.
Signed-off-by Yinghai Lu <[email protected]>I applied this one to pci/resource for v3.17, thanks!
I didn't apply [2/3] or [3/3] because the questions I raised earlier haven't been resolved.
That is fine. We can apply [2/3] later if there is any regression ...