Skip to contentSkip to conversation

PCI: refactor io size calculation code

PATCH Daniel Hellstrom 3 participants 4 messages Apr 11, 2011 PCI

lore
Share & tools
lore
#0 lore raw
Quoted 18 lines

refactor code that calculates the io size in pbus_size_io() and pbus_mem_io() into separate functions.

---
drivers/pci/setup-bus.c | 66 ++++++++++++++++++++++++++++++-----------------

1 files changed, 42 insertions(+), 24 deletions(-)
drivers/pci/setup-bus.c +0 -0
index 66cb8f4..2121215 100644
@@ -404,6 +404,43 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
 	return NULL;
 }
 

...

Quoted 23 lines
drivers/pci/setup-bus.c +17 -0
+
+static resource_size_t calculate_memsize(resource_size_t size,
+		resource_size_t min_size,
+		resource_size_t size1,
+		resource_size_t old_size,
+		resource_size_t align)
+{
+	if (size < min_size)
+		size = min_size;
+	if (old_size == 1 )
+		old_size = 0;
+	if (size < old_size)
+		size = old_size;
+	size = ALIGN(size + size1, align);
+	return size;
+}
+

/* Sizing the IO windows of the PCI-PCI bridge is trivial,
since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes.

...

Quoted 16 lines
drivers/pci/setup-bus.c +0 -8
@@ -516,14 +542,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			mem64_mask &= r->flags & IORESOURCE_MEM_64;
 		}
 	}
-	if (size < min_size)
-		size = min_size;
-	old_size = resource_size(b_res);
-	if (old_size == 1)
-		old_size = 0;
-	if (size < old_size)
-		size = old_size;
-
 	align = 0;
 	min_align = 0;
 	for (order = 0; order <= max_order; order++) {

drivers/pci/setup-bus.c static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, · line 560

Quoted 7 lines
drivers/pci/setup-bus.c +1 -1
@@ -537,7 +555,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size = ALIGN(size, min_align);
+	size = calculate_memsize(size, min_size, 0, resource_size(b_res), align);
 
 

On my SPARC32/LEON4 PCI system I get overlapped areas, double mapped resources. Some BARs on PCIBUS0 are in the same non-prefetchable memory range as the secondary bus PCIBUS1. Changing align to min_align in the above call to calculate_memsize() fixes the problem, and the memory allocation is the same as with 2.6.36.4 kernel.

I belive this is just a typo.

Best Regards,
Daniel Hellstrom
Aeroflex Gaisler

Quoted 6 lines
drivers/pci/setup-bus.c +0 -0
 	if (!size) {
		if (b_res->start || b_res->end)
			dev_info(&bus->self->dev, "disabling bridge window "
Signature · 1 line
1.6.5.2
#1 lore raw
Quoted 79 lines · Daniel Hellstrom

In commit 13583b16592a ("PCI: refactor io size calculation code"):

Quoted 19 lines

refactor  code  that  calculates  the  io  size in pbus_size_io() and pbus_mem_io() into separate functions.

---
drivers/pci/setup-bus.c |   66
++++++++++++++++++++++++++++++-----------------

1 files changed, 42 insertions(+), 24 deletions(-)
drivers/pci/setup-bus.c +0 -0
index 66cb8f4..2121215 100644
@@ -404,6 +404,43 @@ static struct resource *find_free_bus_resource(struct

pci_bus *bus, unsigned lon
       return NULL;
}

...

Quoted 22 lines
drivers/pci/setup-bus.c +17 -0
+
+static resource_size_t calculate_memsize(resource_size_t size,
+               resource_size_t min_size,
+               resource_size_t size1,
+               resource_size_t old_size,
+               resource_size_t align)
+{
+       if (size < min_size)
+               size = min_size;
+       if (old_size == 1 )
+               old_size = 0;
+       if (size < old_size)
+               size = old_size;
+       size = ALIGN(size + size1, align);
+       return size;
+}
+

/* Sizing the IO windows of the PCI-PCI bridge is trivial, since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes.

...

Quoted 17 lines
drivers/pci/setup-bus.c +0 -8
@@ -516,14 +542,6 @@ static int pbus_size_mem(struct pci_bus *bus,
 unsigned long mask,
                        mem64_mask &= r->flags & IORESOURCE_MEM_64;
                }
        }
-       if (size < min_size)
-               size = min_size;
-       old_size = resource_size(b_res);
-       if (old_size == 1)
-               old_size = 0;
-       if (size < old_size)
-               size = old_size;
-
        align = 0;
        min_align = 0;

       for (order = 0; order <= max_order; order++) {

drivers/pci/setup-bus.c static int pbus_size_mem(struct pci_bus *bus, unsigned · line 561

Quoted 8 lines
drivers/pci/setup-bus.c +1 -1
@@ -537,7 +555,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned
 long mask,
                        min_align = align1 >> 1;
                align += aligns[order];
        }
-       size = ALIGN(size, min_align);
+       size = calculate_memsize(size, min_size, 0, resource_size(b_res),
 align);
 

On my SPARC32/LEON4 PCI system I get overlapped areas, double mapped resources. Some BARs on PCIBUS0 are in the same non-prefetchable memory range as the secondary bus PCIBUS1. Changing align to min_align in the above call to calculate_memsize() fixes the problem, and the memory allocation is the same as with 2.6.36.4 kernel.

Quoted 1 line

I belive this is just a typo.

It does seem that way. The original code used 'min_align' and 'align' itself is meaningless in that place.

Can you confirm that the patch you talk about as fixing things is the attached?

Linus

 drivers/pci/setup-bus.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/pci/setup-bus.c +2 -2
index 89d0a6a88df7..ebf51ad1b714 100644
@@ -676,10 +676,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align);
+	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
 	size1 = !add_size ? size :
 		calculate_memsize(size, min_size+add_size, 0,
-				resource_size(b_res), align);
+				resource_size(b_res), min_align);
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
#2 lore raw
Quoted 91 lines · Linus Torvalds
Quoted 88 lines · Daniel Hellstrom

In commit 13583b16592a ("PCI: refactor io size calculation code"):

Quoted 20 lines

refactor code that calculates the io size in pbus_size_io() and pbus_mem_io() into separate functions.

---
drivers/pci/setup-bus.c | 66
++++++++++++++++++++++++++++++-----------------

1 files changed, 42 insertions(+), 24 deletions(-)
drivers/pci/setup-bus.c +0 -0
index 66cb8f4..2121215 100644
@@ -404,6 +404,43 @@ static struct resource *find_free_bus_resource(struct

pci_bus *bus, unsigned lon

      return NULL;
}

...

Quoted 24 lines
drivers/pci/setup-bus.c +17 -0
+
+static resource_size_t calculate_memsize(resource_size_t size,
+               resource_size_t min_size,
+               resource_size_t size1,
+               resource_size_t old_size,
+               resource_size_t align)
+{
+       if (size < min_size)
+               size = min_size;
+       if (old_size == 1 )
+               old_size = 0;
+       if (size < old_size)
+               size = old_size;
+       size = ALIGN(size + size1, align);
+       return size;
+}
+

/* Sizing the IO windows of the PCI-PCI bridge is trivial,
since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes.

...

Quoted 19 lines
drivers/pci/setup-bus.c +0 -8
@@ -516,14 +542,6 @@ static int pbus_size_mem(struct pci_bus *bus,
 unsigned long mask,
                      mem64_mask &= r->flags & IORESOURCE_MEM_64;
              }
      }
-       if (size < min_size)
-               size = min_size;
-       old_size = resource_size(b_res);
-       if (old_size == 1)
-               old_size = 0;
-       if (size < old_size)
-               size = old_size;
-
      align = 0;
      min_align = 0;
      for (order = 0; order <= max_order; order++) {

drivers/pci/setup-bus.c static int pbus_size_mem(struct pci_bus *bus, unsigned · line 561

Quoted 8 lines
drivers/pci/setup-bus.c +1 -1
@@ -537,7 +555,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned
 long mask,
                      min_align = align1 >> 1;
              align += aligns[order];
      }
-       size = ALIGN(size, min_align);
+       size = calculate_memsize(size, min_size, 0, resource_size(b_res),
 align);
 

On my SPARC32/LEON4 PCI system I get overlapped areas, double mapped resources. Some BARs on PCIBUS0 are in the same non-prefetchable memory range as the secondary bus PCIBUS1. Changing align to min_align in the above call to calculate_memsize() fixes the problem, and the memory allocation is the same as with 2.6.36.4 kernel.

Quoted 8 lines
Quoted 3 lines

I belive this is just a typo.

It does seem that way. The original code used 'min_align' and 'align' itself is meaningless in that place.

Agree.

Quoted 5 lines

Can you confirm that the patch you talk about as fixing things is the attached?

Linus

Yes, the below patch works on the system that triggered the problem before. The last min_align was added in a later patch, I missed it initially.

Thanks,
Daniel

Quoted 24 lines

------------------------------------------------------------------------

drivers/pci/setup-bus.c | 4 ++--

1 files changed, 2 insertions(+), 2 deletions(-)
drivers/pci/setup-bus.c +2 -2
index 89d0a6a88df7..ebf51ad1b714 100644
@@ -676,10 +676,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align);
+	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
 	size1 = !add_size ? size :
 		calculate_memsize(size, min_size+add_size, 0,
-				resource_size(b_res), align);
+				resource_size(b_res), min_align);
 	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
#3 lore raw
In reply to Linus Torvalds
Quoted 80 lines · Linus Torvalds
Quoted 79 lines · Daniel Hellstrom

In commit 13583b16592a ("PCI: refactor io size calculation code"):

Quoted 19 lines

refactor  code  that  calculates  the  io  size in pbus_size_io() and pbus_mem_io() into separate functions.

---
drivers/pci/setup-bus.c |   66
++++++++++++++++++++++++++++++-----------------

1 files changed, 42 insertions(+), 24 deletions(-)
drivers/pci/setup-bus.c +0 -0
index 66cb8f4..2121215 100644
@@ -404,6 +404,43 @@ static struct resource *find_free_bus_resource(struct

pci_bus *bus, unsigned lon
       return NULL;
}

...

Quoted 22 lines
drivers/pci/setup-bus.c +17 -0
+
+static resource_size_t calculate_memsize(resource_size_t size,
+               resource_size_t min_size,
+               resource_size_t size1,
+               resource_size_t old_size,
+               resource_size_t align)
+{
+       if (size < min_size)
+               size = min_size;
+       if (old_size == 1 )
+               old_size = 0;
+       if (size < old_size)
+               size = old_size;
+       size = ALIGN(size + size1, align);
+       return size;
+}
+

/* Sizing the IO windows of the PCI-PCI bridge is trivial, since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes.

...

Quoted 17 lines
drivers/pci/setup-bus.c +0 -8
@@ -516,14 +542,6 @@ static int pbus_size_mem(struct pci_bus *bus,
 unsigned long mask,
                        mem64_mask &= r->flags & IORESOURCE_MEM_64;
                }
        }
-       if (size < min_size)
-               size = min_size;
-       old_size = resource_size(b_res);
-       if (old_size == 1)
-               old_size = 0;
-       if (size < old_size)
-               size = old_size;
-
        align = 0;
        min_align = 0;

       for (order = 0; order <= max_order; order++) {

drivers/pci/setup-bus.c static int pbus_size_mem(struct pci_bus *bus, unsigned · line 561

Quoted 8 lines
drivers/pci/setup-bus.c +1 -1
@@ -537,7 +555,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned
 long mask,
                        min_align = align1 >> 1;
                align += aligns[order];
        }
-       size = ALIGN(size, min_align);
+       size = calculate_memsize(size, min_size, 0, resource_size(b_res),
 align);
 

On my SPARC32/LEON4 PCI system I get overlapped areas, double mapped resources. Some BARs on PCIBUS0 are in the same non-prefetchable memory range as the secondary bus PCIBUS1. Changing align to min_align in the above call to calculate_memsize() fixes the problem, and the memory allocation is the same as with 2.6.36.4 kernel.

Quoted 1 line
Quoted 1 line

I belive this is just a typo.

Yes it is my mistake. I got the parameter wrong. Your fix should correct the problem.

RP