qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/6] Redesign of pciinit.c (take 2)


From: Alexey Korolev
Subject: [Qemu-devel] [PATCH 2/6] Redesign of pciinit.c (take 2)
Date: Tue, 13 Mar 2012 17:45:19 +1300

Added pci_region_entry structure and list operations to pciinit.c
List is filled with entries during pci_check_devices.
List is used just for printing space allocation if we were using lists. 
Next step will resource allocation using mapping functions.

Signed-off-by: Alexey Korolev <address@hidden>
---
 src/pciinit.c |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/src/pciinit.c b/src/pciinit.c
index 9f3fdd4..2bf5473 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -31,6 +31,20 @@ static const char *region_type_name[] = {
     [ PCI_REGION_TYPE_PREFMEM ] = "prefmem",
 };
 
+struct pci_bus;
+struct pci_region_entry {
+    struct pci_device *dev;
+    int bar;
+    u32 base;
+    u32 size;
+    int is64bit;
+    enum pci_region_type type;
+    struct pci_bus *this_bus;
+    struct pci_bus *parent_bus;
+    struct pci_region_entry *next;
+    struct pci_region_entry **pprev;
+};
+
 struct pci_bus {
     struct {
         /* pci region stats */
@@ -41,6 +55,7 @@ struct pci_bus {
         /* pci region assignments */
         u32 bases[32 - PCI_MEM_INDEX_SHIFT];
         u32 base;
+        struct pci_region_entry *list;
     } r[PCI_REGION_TYPE_COUNT];
     struct pci_device *bus_dev;
 };
@@ -352,6 +367,31 @@ pci_bios_get_bar(struct pci_device *pci, int bar, u32 
*val, u32 *size)
     *size = (~(*val & mask)) + 1;
 }
 
+/****************************************************************
+ * Build topology and calculate size of entries
+ ****************************************************************/
+
+struct pci_region_entry *
+pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
+                       u32 size, int type, int is64bit)
+{
+    struct pci_region_entry *entry= malloc_tmp(sizeof(*entry));
+    if (!entry) {
+            warn_noalloc();
+            return NULL;
+    }
+    memset(entry, 0, sizeof(*entry));
+
+    entry->dev = dev;
+    entry->type = type;
+    entry->is64bit = is64bit;
+    entry->size = size;
+
+    list_add_head(&bus->r[type].list, entry);
+    entry->parent_bus = bus;
+    return entry;
+}
+
 static void pci_bios_bus_reserve(struct pci_bus *bus, int type, u32 size)
 {
     u32 index;
@@ -364,9 +404,10 @@ static void pci_bios_bus_reserve(struct pci_bus *bus, int 
type, u32 size)
         bus->r[type].max = size;
 }
 
-static void pci_bios_check_devices(struct pci_bus *busses)
+static int pci_bios_check_devices(struct pci_bus *busses)
 {
     dprintf(1, "PCI: check devices\n");
+    struct pci_region_entry *entry;
 
     // Calculate resources needed for regular (non-bus) devices.
     struct pci_device *pci;
@@ -378,10 +419,15 @@ static void pci_bios_check_devices(struct pci_bus *busses)
         struct pci_bus *bus = &busses[pci_bdf_to_bus(pci->bdf)];
         int i;
         for (i = 0; i < PCI_NUM_REGIONS; i++) {
-            u32 val, size;
+            u32 val, size, min_size;
+            int type;
             pci_bios_get_bar(pci, i, &val, &size);
             if (val == 0)
                 continue;
+            type = pci_addr_to_type(val);
+            min_size = (type == PCI_REGION_TYPE_IO) ? (1<<PCI_IO_INDEX_SHIFT):
+                     (1<<PCI_MEM_INDEX_SHIFT);
+            size = (size > min_size) ? size : min_size;
 
             pci_bios_bus_reserve(bus, pci_addr_to_type(val), size);
             pci->bars[i].addr = val;
@@ -390,6 +436,11 @@ static void pci_bios_check_devices(struct pci_bus *busses)
                                  (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
                                  == PCI_BASE_ADDRESS_MEM_TYPE_64);
 
+            entry = pci_region_create_entry(bus, pci, size, type, 
pci->bars[i].is64);
+            if (!entry)
+                return -1;
+            entry->bar = i;
+
             if (pci->bars[i].is64)
                 i++;
         }
@@ -411,6 +462,11 @@ static void pci_bios_check_devices(struct pci_bus *busses)
                 s->r[type].size = limit;
             s->r[type].size = pci_size_roundup(s->r[type].size);
             pci_bios_bus_reserve(parent, type, s->r[type].size);
+            entry = pci_region_create_entry(parent, s->bus_dev,
+                                            s->r[type].size, type, 0);
+            if (!entry)
+                return -1;
+            entry->this_bus = s;
         }
         dprintf(1, "PCI: secondary bus %d sizes: io %x, mem %x, prefmem %x\n",
                 secondary_bus,
@@ -418,6 +474,7 @@ static void pci_bios_check_devices(struct pci_bus *busses)
                 s->r[PCI_REGION_TYPE_MEM].size,
                 s->r[PCI_REGION_TYPE_PREFMEM].size);
     }
+    return 0;
 }
 
 #define ROOT_BASE(top, sum, max) ALIGN_DOWN((top)-(sum),(max) ?: 1)
@@ -553,6 +610,44 @@ static void pci_bios_map_devices(struct pci_bus *busses)
     }
 }
 
+static void pci_region_dump_one_entry(struct pci_region_entry *entry)
+{
+    if (!entry->this_bus ) {
+        dprintf(1, "PCI: bdf %d bar %d\tsize\t0x%08x\tbase 0x%x type %s\n",
+                      entry->dev->bdf, entry->bar, entry->size, entry->base,
+                      region_type_name[entry->type]);
+    } else {
+        entry->this_bus->r[entry->type].base = entry->base;
+        dprintf(1, "Secondary bus %d\t\tsize\t0x%08x\tbase 0x%x type %s\n",
+                  entry->dev->secondary_bus, entry->size, entry->base,
+                  region_type_name[entry->type]);
+   }
+}
+
+static void pci_bios_dump_devices(struct pci_bus *busses)
+{
+    struct pci_region_entry *entry, *next;
+
+    int bus;
+    for (bus = 0; bus<=MaxPCIBus; bus++) {
+        int type;
+        for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
+            u32 size;
+            for (size = busses[bus].r[type].max; size > 0; size >>= 1) {
+                    list_foreach_entry_safe(busses[bus].r[type].list,
+                                              next, entry) {
+                        if (size == entry->size) {
+                            entry->base = busses[bus].r[type].base;
+                            busses[bus].r[type].base += size;
+                            pci_region_dump_one_entry(entry);
+                            list_del(entry);
+                            free(entry);
+                    }
+                }
+            }
+        }
+    }
+}
 
 /****************************************************************
  * Main setup code
@@ -588,13 +683,16 @@ pci_setup(void)
         return;
     }
     memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
-    pci_bios_check_devices(busses);
+    if (pci_bios_check_devices(busses))
+        return;
+
     if (pci_bios_init_root_regions(&busses[0], start, end) != 0) {
         panic("PCI: out of address space\n");
     }
 
     dprintf(1, "=== PCI new allocation pass #2 ===\n");
     pci_bios_map_devices(busses);
+    pci_bios_dump_devices(busses);
 
     pci_bios_init_devices();
 
-- 
1.7.5.4





reply via email to

[Prev in Thread] Current Thread [Next in Thread]