On 24/04/12 18:56, Gerd Hoffmann wrote:
> On 04/24/12 08:17, Alexey Korolev wrote:
>> Don't round up bridge regions to the next highest size - instead track
>> alignment explicitly.  This should improve the memory layout for
>> bridge regions.
> This one got mangled too:
>
> Applying: pciinit: Track region alignment explicitly.
> fatal: corrupt patch at line 40
> Patch failed at 0005 pciinit: Track region alignment explicitly.
>
> Do you have a git tree I can pull from for testing?
Hi,
Thank you.
I don't have an public available git tree.
Not sure if I can create any from workplace.

So I just reposted the patch.
 
> thanks,
>   Gerd
>
>> Also, unused bridge regions will no longer be allocated any space.
>>
>> Signed-off-by: Kevin O'Connor <ke...@koconnor.net>
>> ---
>>  src/pciinit.c |   41 ++++++++++++++++++-----------------------
>>  1 files changed, 18 insertions(+), 23 deletions(-)
>>
>> diff --git a/src/pciinit.c b/src/pciinit.c
>> index 1b31177..2bd4426 100644
>> --- a/src/pciinit.c
>> +++ b/src/pciinit.c
>> @@ -33,6 +33,7 @@ struct pci_region_entry {
>>      struct pci_device *dev;
>>      int bar;
>>      u32 size;
>> +    u32 align;
>>      int is64;
>>      enum pci_region_type type;
>>      struct pci_region_entry *next;
>> @@ -41,7 +42,7 @@ struct pci_region_entry {
>>  struct pci_bus {
>>      struct {
>>          /* pci region stats */
>> -        u32 sum, max;
>> +        u32 sum, align;
>>          /* pci region assignments */
>>          u32 base;
>>          struct pci_region_entry *list;
>> @@ -307,12 +308,6 @@ pci_bios_init_bus(void)
>>   * Bus sizing
>>   ****************************************************************/
>>  
>> -static u32 pci_size_roundup(u32 size)
>> -{
>> -    int index = __fls(size-1)+1;
>> -    return 0x1 << index;
>> -}
>> -
>>  static void
>>  pci_bios_get_bar(struct pci_device *pci, int bar, u32 *val, u32 *size)
>>  {
>> @@ -338,7 +333,7 @@ pci_bios_get_bar(struct pci_device *pci, int bar,
>> u32 *val, u32 *size)
>>  
>>  static struct pci_region_entry *
>>  pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
>> -                        int bar, u32 size, int type, int is64)
>> +                        int bar, u32 size, u32 align, int type, int
>> is64)
>>  {
>>      struct pci_region_entry *entry = malloc_tmp(sizeof(*entry));
>>      if (!entry) {
>> @@ -349,21 +344,22 @@ pci_region_create_entry(struct pci_bus *bus,
>> struct pci_device *dev,
>>      entry->dev = dev;
>>      entry->bar = bar;
>>      entry->size = size;
>> +    entry->align = align;
>>      entry->is64 = is64;
>>      entry->type = type;
>>      // Insert into list in sorted order.
>>      struct pci_region_entry **pprev;
>>      for (pprev = &bus->r[type].list; *pprev; pprev = &(*pprev)->next) {
>>          struct pci_region_entry *pos = *pprev;
>> -        if (pos->size < size)
>> +        if (pos->align < align || (pos->align == align && pos->size <
>> size))
>>              break;
>>      }
>>      entry->next = *pprev;
>>      *pprev = entry;
>>  
>>      bus->r[type].sum += size;
>> -    if (bus->r[type].max < size)
>> -        bus->r[type].max = size;
>> +    if (bus->r[type].align < align)
>> +        bus->r[type].align = align;
>>      return entry;
>>  }
>>  
>> @@ -393,7 +389,7 @@ static int pci_bios_check_devices(struct pci_bus
>> *busses)
>>                          (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
>>                          == PCI_BASE_ADDRESS_MEM_TYPE_64);
>>              struct pci_region_entry *entry = pci_region_create_entry(
>> -                bus, pci, i, size, type, is64);
>> +                bus, pci, i, size, size, type, is64);
>>              if (!entry)
>>                  return -1;
>>  
>> @@ -411,15 +407,14 @@ static int pci_bios_check_devices(struct pci_bus
>> *busses)
>>          struct pci_bus *parent =
>> &busses[pci_bdf_to_bus(s->bus_dev->bdf)];
>>          int type;
>>          for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
>> -            u32 limit = (type == PCI_REGION_TYPE_IO) ?
>> +            u32 align = (type == PCI_REGION_TYPE_IO) ?
>>                  PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
>> -            u32 size = s->r[type].sum;
>> -            if (size < limit)
>> -                size = limit;
>> -            size = pci_size_roundup(size);
>> +            if (s->r[type].align > align)
>> +                align = s->r[type].align;
>> +            u32 size = ALIGN(s->r[type].sum, align);
>>              // entry->bar is -1 if the entry represents a bridge region
>>              struct pci_region_entry *entry = pci_region_create_entry(
>> -                parent, s->bus_dev, -1, size, type, 0);
>> +                parent, s->bus_dev, -1, size, align, type, 0);
>>              if (!entry)
>>                  return -1;
>>              dprintf(1, "PCI: secondary bus %d size %x type %s\n",
>> @@ -430,7 +425,7 @@ static int pci_bios_check_devices(struct pci_bus
>> *busses)
>>      return 0;
>>  }
>>  
>> -#define ROOT_BASE(top, sum, max) ALIGN_DOWN((top)-(sum),(max) ?: 1)
>> +#define ROOT_BASE(top, sum, align) ALIGN_DOWN((top)-(sum),(align) ?: 1)
>>  
>>  // Setup region bases (given the regions' size and alignment)
>>  static int pci_bios_init_root_regions(struct pci_bus *bus, u32 start,
>> u32 end)
>> @@ -438,14 +433,14 @@ static int pci_bios_init_root_regions(struct
>> pci_bus *bus, u32 start, u32 end)
>>      bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
>>  
>>      int reg1 = PCI_REGION_TYPE_PREFMEM, reg2 = PCI_REGION_TYPE_MEM;
>> -    if (bus->r[reg1].sum < bus->r[reg2].sum) {
>> -        // Swap regions so larger area is more likely to align well.
>> +    if (bus->r[reg1].align < bus->r[reg2].align) {
>> +        // Swap regions to improve alignment.
>>          reg1 = PCI_REGION_TYPE_MEM;
>>          reg2 = PCI_REGION_TYPE_PREFMEM;
>>      }
>> -    bus->r[reg2].base = ROOT_BASE(end, bus->r[reg2].sum,
>> bus->r[reg2].max);
>> +    bus->r[reg2].base = ROOT_BASE(end, bus->r[reg2].sum,
>> bus->r[reg2].align);
>>      bus->r[reg1].base = ROOT_BASE(bus->r[reg2].base, bus->r[reg1].sum
>> -                                  , bus->r[reg1].max);
>> +                                  , bus->r[reg1].align);
>>      if (bus->r[reg1].base < start)
>>          // Memory range requested is larger than available.
>>          return -1;

>From b29c78e59a56419ff55bc1900d68abe498376648 Mon Sep 17 00:00:00 2001
From: Kevin O'Connor <ke...@koconnor.net>
Date: Sun, 1 Apr 2012 12:30:32 -0400
Subject: [PATCH 05/12] pciinit: Track region alignment explicitly.

Don't round up bridge regions to the next highest size - instead track
alignment explicitly.  This should improve the memory layout for
bridge regions.

Also, unused bridge regions will no longer be allocated any space.

Signed-off-by: Kevin O'Connor <ke...@koconnor.net>
---
 src/pciinit.c |   41 ++++++++++++++++++-----------------------
 1 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/src/pciinit.c b/src/pciinit.c
index 1b31177..2bd4426 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -33,6 +33,7 @@ struct pci_region_entry {
     struct pci_device *dev;
     int bar;
     u32 size;
+    u32 align;
     int is64;
     enum pci_region_type type;
     struct pci_region_entry *next;
@@ -41,7 +42,7 @@ struct pci_region_entry {
 struct pci_bus {
     struct {
         /* pci region stats */
-        u32 sum, max;
+        u32 sum, align;
         /* pci region assignments */
         u32 base;
         struct pci_region_entry *list;
@@ -307,12 +308,6 @@ pci_bios_init_bus(void)
  * Bus sizing
  ****************************************************************/
 
-static u32 pci_size_roundup(u32 size)
-{
-    int index = __fls(size-1)+1;
-    return 0x1 << index;
-}
-
 static void
 pci_bios_get_bar(struct pci_device *pci, int bar, u32 *val, u32 *size)
 {
@@ -338,7 +333,7 @@ pci_bios_get_bar(struct pci_device *pci, int bar, u32 *val, u32 *size)
 
 static struct pci_region_entry *
 pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
-                        int bar, u32 size, int type, int is64)
+                        int bar, u32 size, u32 align, int type, int is64)
 {
     struct pci_region_entry *entry = malloc_tmp(sizeof(*entry));
     if (!entry) {
@@ -349,21 +344,22 @@ pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
     entry->dev = dev;
     entry->bar = bar;
     entry->size = size;
+    entry->align = align;
     entry->is64 = is64;
     entry->type = type;
     // Insert into list in sorted order.
     struct pci_region_entry **pprev;
     for (pprev = &bus->r[type].list; *pprev; pprev = &(*pprev)->next) {
         struct pci_region_entry *pos = *pprev;
-        if (pos->size < size)
+        if (pos->align < align || (pos->align == align && pos->size < size))
             break;
     }
     entry->next = *pprev;
     *pprev = entry;
 
     bus->r[type].sum += size;
-    if (bus->r[type].max < size)
-        bus->r[type].max = size;
+    if (bus->r[type].align < align)
+        bus->r[type].align = align;
     return entry;
 }
 
@@ -393,7 +389,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
                         (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
                         == PCI_BASE_ADDRESS_MEM_TYPE_64);
             struct pci_region_entry *entry = pci_region_create_entry(
-                bus, pci, i, size, type, is64);
+                bus, pci, i, size, size, type, is64);
             if (!entry)
                 return -1;
 
@@ -411,15 +407,14 @@ static int pci_bios_check_devices(struct pci_bus *busses)
         struct pci_bus *parent = &busses[pci_bdf_to_bus(s->bus_dev->bdf)];
         int type;
         for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
-            u32 limit = (type == PCI_REGION_TYPE_IO) ?
+            u32 align = (type == PCI_REGION_TYPE_IO) ?
                 PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
-            u32 size = s->r[type].sum;
-            if (size < limit)
-                size = limit;
-            size = pci_size_roundup(size);
+            if (s->r[type].align > align)
+                align = s->r[type].align;
+            u32 size = ALIGN(s->r[type].sum, align);
             // entry->bar is -1 if the entry represents a bridge region
             struct pci_region_entry *entry = pci_region_create_entry(
-                parent, s->bus_dev, -1, size, type, 0);
+                parent, s->bus_dev, -1, size, align, type, 0);
             if (!entry)
                 return -1;
             dprintf(1, "PCI: secondary bus %d size %x type %s\n",
@@ -430,7 +425,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
     return 0;
 }
 
-#define ROOT_BASE(top, sum, max) ALIGN_DOWN((top)-(sum),(max) ?: 1)
+#define ROOT_BASE(top, sum, align) ALIGN_DOWN((top)-(sum),(align) ?: 1)
 
 // Setup region bases (given the regions' size and alignment)
 static int pci_bios_init_root_regions(struct pci_bus *bus, u32 start, u32 end)
@@ -438,14 +433,14 @@ static int pci_bios_init_root_regions(struct pci_bus *bus, u32 start, u32 end)
     bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
 
     int reg1 = PCI_REGION_TYPE_PREFMEM, reg2 = PCI_REGION_TYPE_MEM;
-    if (bus->r[reg1].sum < bus->r[reg2].sum) {
-        // Swap regions so larger area is more likely to align well.
+    if (bus->r[reg1].align < bus->r[reg2].align) {
+        // Swap regions to improve alignment.
         reg1 = PCI_REGION_TYPE_MEM;
         reg2 = PCI_REGION_TYPE_PREFMEM;
     }
-    bus->r[reg2].base = ROOT_BASE(end, bus->r[reg2].sum, bus->r[reg2].max);
+    bus->r[reg2].base = ROOT_BASE(end, bus->r[reg2].sum, bus->r[reg2].align);
     bus->r[reg1].base = ROOT_BASE(bus->r[reg2].base, bus->r[reg1].sum
-                                  , bus->r[reg1].max);
+                                  , bus->r[reg1].align);
     if (bus->r[reg1].base < start)
         // Memory range requested is larger than available.
         return -1;
-- 
1.7.5.4

Reply via email to