[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/6] Switch from array based approach to lists of pc
From: |
Alexey Korolev |
Subject: |
[Qemu-devel] [PATCH 3/6] Switch from array based approach to lists of pci_region_entries |
Date: |
Tue, 13 Mar 2012 17:58:50 +1300 |
Now we use the list of pci_region_entries instead of arrays of bases.
In this patch in addition to dumping resource allocations using
pci_region_entry, we add actual PCI resource assignment.
Note: I commented old code and split patches 3/6 and 4/6 just for
better patch readability.
Signed-off-by: Alexey Korolev <address@hidden>
---
src/pciinit.c | 106 +++++++++++++++++++++++++--------------------------------
1 files changed, 46 insertions(+), 60 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c
index 2bf5473..f766a75 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -12,9 +12,8 @@
#include "pci_regs.h" // PCI_COMMAND
#include "xen.h" // usingXen
-#define PCI_IO_INDEX_SHIFT 2
-#define PCI_MEM_INDEX_SHIFT 12
-
+#define PCI_DEV_IO_MINSIZE 0x4
+#define PCI_DEV_MEM_MINSIZE 0x1000
#define PCI_BRIDGE_IO_MIN 0x1000
#define PCI_BRIDGE_MEM_MIN 0x100000
@@ -48,38 +47,14 @@ struct pci_region_entry {
struct pci_bus {
struct {
/* pci region stats */
- u32 count[32 - PCI_MEM_INDEX_SHIFT];
u32 sum, max;
- /* seconday bus region sizes */
u32 size;
- /* 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;
};
-static int pci_size_to_index(u32 size, enum pci_region_type type)
-{
- int index = __fls(size);
- int shift = (type == PCI_REGION_TYPE_IO) ?
- PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
-
- if (index < shift)
- index = shift;
- index -= shift;
- return index;
-}
-
-static u32 pci_index_to_size(int index, enum pci_region_type type)
-{
- int shift = (type == PCI_REGION_TYPE_IO) ?
- PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
-
- return 0x1 << (index + shift);
-}
-
static enum pci_region_type pci_addr_to_type(u32 addr)
{
if (addr & PCI_BASE_ADDRESS_SPACE_IO)
@@ -389,19 +364,10 @@ pci_region_create_entry(struct pci_bus *bus, struct
pci_device *dev,
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;
-
- index = pci_size_to_index(size, type);
- size = pci_index_to_size(index, type);
- bus->r[type].count[index]++;
bus->r[type].sum += size;
if (bus->r[type].max < size)
bus->r[type].max = size;
+ return entry;
}
static int pci_bios_check_devices(struct pci_bus *busses)
@@ -420,28 +386,24 @@ static int pci_bios_check_devices(struct pci_bus *busses)
int i;
for (i = 0; i < PCI_NUM_REGIONS; i++) {
u32 val, size, min_size; 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",
+
+ pci_set_io_region_addr(entry->dev, entry->bar, entry->base);
+ if (entry->is64bit)
+ pci_set_io_region_addr(entry->dev, entry->bar + 1, 0);
+ return;
- int type;
+ int is64, 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);
+ min_size = (type == PCI_REGION_TYPE_IO) ? PCI_DEV_IO_MINSIZE:
+ PCI_DEV_MEM_MINSIZE;
size = (size > min_size) ? size : min_size;
- pci_bios_bus_reserve(bus, pci_addr_to_type(val), size);
- pci->bars[i].addr = val;
- pci->bars[i].size = size;
- pci->bars[i].is64 = (!(val & PCI_BASE_ADDRESS_SPACE_IO) &&
- (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);
+ is64 = (!(val & PCI_BASE_ADDRESS_SPACE_IO) &&
+ (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
+ == PCI_BASE_ADDRESS_MEM_TYPE_64);
+ entry = pci_region_create_entry(bus, pci, size, type, is64);
if (!entry)
return -1;
entry->bar = i;
- if (pci->bars[i].is64)
+ if (is64)
i++;
}
}
@@ -461,7 +423,6 @@ static int pci_bios_check_devices(struct pci_bus *busses)
if (s->r[type].size < limit)
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)
@@ -503,7 +464,7 @@ static int pci_bios_init_root_regions(struct pci_bus *bus,
u32 start, u32 end)
/****************************************************************
* BAR assignment
****************************************************************/
-
+/*
static void pci_bios_init_bus_bases(struct pci_bus *bus)
{
u32 base, newbase, size;
@@ -609,22 +570,48 @@ static void pci_bios_map_devices(struct pci_bus *busses)
}
}
}
-
-static void pci_region_dump_one_entry(struct pci_region_entry *entry)
+*/
+static void pci_region_map_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",
+
+ pci_set_io_region_addr(entry->dev, entry->bar, entry->base);
+ if (entry->is64bit)
+ pci_set_io_region_addr(entry->dev, entry->bar + 1, 0);
+ return;
+ }
+
+ entry->this_bus->r[entry->type].base = entry->base;
+ dprintf(1, "PCI-2-PCI 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]);
- }
+
+ u16 bdf = entry->dev->bdf;
+ u32 base = entry->base;
+ u32 limit = entry->base + entry->size - 1;
+ if (entry->type == PCI_REGION_TYPE_IO) {
+ pci_config_writeb(bdf, PCI_IO_BASE, base >> 8);
+ pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
+ pci_config_writeb(bdf, PCI_IO_LIMIT, limit >> 8);
+ pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
+ }
+ if (entry->type == PCI_REGION_TYPE_MEM) {
+ pci_config_writew(bdf, PCI_MEMORY_BASE, base >> 16);
+ pci_config_writew(bdf, PCI_MEMORY_LIMIT, limit >> 16);
+ }
+ if (entry->type == PCI_REGION_TYPE_PREFMEM) {
+ pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, base >> 16);
+ pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, limit >> 16);
+ pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0);
+ pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0);
+ }
+ return;
}
-static void pci_bios_dump_devices(struct pci_bus *busses)
+static void pci_bios_map_devices(struct pci_bus *busses)
{
struct pci_region_entry *entry, *next;
@@ -639,7 +626,7 @@ static void pci_bios_dump_devices(struct pci_bus *busses)
if (size == entry->size) {
entry->base = busses[bus].r[type].base;
busses[bus].r[type].base += size;
- pci_region_dump_one_entry(entry);
+ pci_region_map_one_entry(entry);
list_del(entry);
free(entry);
}
@@ -692,7 +679,6 @@ pci_setup(void)
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
[Qemu-devel] [PATCH 3/6] Switch from array based approach to lists of pci_region_entries,
Alexey Korolev <=
[Qemu-devel] [PATCH 4/6] Delete array based resource assignment code., Alexey Korolev, 2012/03/13
[Qemu-devel] [PATCH 5/6] Get rid of size element of pci_bus->r structure, Alexey Korolev, 2012/03/13
[Qemu-devel] [PATCH 6/6] Use linked lists in pmm.c and stack.c, Alexey Korolev, 2012/03/13