[SeaBIOS] [PATCH v3 4/6] pci: init boot devices only on address space shortage

Gerd Hoffmann kraxel at redhat.com
Tue Jul 5 17:27:03 CEST 2011


Try to handle address space shortage by skipping any device
which isn't essential for boot.

Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
---
 src/pci.c     |    3 +++
 src/pciinit.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 src/util.h    |    2 ++
 3 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/src/pci.c b/src/pci.c
index 78bbac2..af735b2 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -193,6 +193,9 @@ pci_find_class(u16 classid)
 int pci_init_device(const struct pci_device_id *ids
                     , struct pci_device *pci, void *arg)
 {
+    if (!pci_enable_device(pci))
+        return -1;
+
     while (ids->vendid || ids->class_mask) {
         if ((ids->vendid == PCI_ANY_ID || ids->vendid == pci->vendor) &&
             (ids->devid == PCI_ANY_ID || ids->devid == pci->device) &&
diff --git a/src/pciinit.c b/src/pciinit.c
index aafdf7c..8b95132 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -44,6 +44,7 @@ static struct pci_bus {
     } r[PCI_REGION_TYPE_COUNT];
 } *busses;
 static int busses_count;
+static int boot_devices_only = 0;
 
 static void pci_bios_init_device_in_bus(int bus);
 static void pci_bios_check_device_in_bus(int bus);
@@ -157,6 +158,40 @@ static const struct pci_device_id pci_isa_bridge_tbl[] = {
 #define PCI_PREF_MEMORY_ALIGN   (1UL << 20)
 #define PCI_PREF_MEMORY_SHIFT   16
 
+static int is_boot_device(struct pci_device *pci)
+{
+    /* check base class */
+    switch (pci->class >> 8) {
+    case PCI_BASE_CLASS_STORAGE:
+    case PCI_BASE_CLASS_NETWORK:
+    case PCI_BASE_CLASS_BRIDGE:
+    case PCI_BASE_CLASS_SYSTEM:
+        return 1;
+    }
+
+    /* check class */
+    switch (pci->class) {
+    case PCI_CLASS_DISPLAY_VGA:
+    case PCI_CLASS_SERIAL_USB:
+        return 1;
+    }
+
+    /* check if ROM present */
+    if (pci->bars[PCI_ROM_SLOT].addr != 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+int pci_enable_device(struct pci_device *pci)
+{
+    if (boot_devices_only) {
+        return is_boot_device(pci);
+    }
+    return 1;
+}
+
 static void storage_ide_init(struct pci_device *pci, void *arg)
 {
     u16 bdf = pci->bdf;
@@ -385,6 +420,9 @@ static void pci_bios_check_device(struct pci_bus *bus, struct pci_device *dev)
     u32 limit;
     int i,type;
 
+    if (!pci_enable_device(dev))
+        return;
+
     if (dev->class == PCI_CLASS_BRIDGE_PCI) {
         if (dev->secondary_bus >= busses_count) {
             /* should never trigger */
@@ -433,6 +471,9 @@ static void pci_bios_map_device(struct pci_bus *bus, struct pci_device *dev)
     u16 bdf = dev->bdf;
     int type, i;
 
+    if (!pci_enable_device(dev))
+        return;
+
     if (dev->class == PCI_CLASS_BRIDGE_PCI) {
         if (dev->secondary_bus >= busses_count) {
             return;
@@ -595,8 +636,14 @@ pci_setup(void)
     busses = malloc_tmp(sizeof(*busses) * busses_count);
     pci_bios_check_device_in_bus(0 /* host bus */);
     if (pci_bios_init_root_regions(start, end) != 0) {
-        dprintf(1, "PCI: out of address space\n");
-        /* Hmm, what do now? */
+        dprintf(1, "=== PCI new allocation pass #1a (boot only) ===\n");
+        boot_devices_only = 1;
+        memset(busses, 0, busses_count * sizeof(struct pci_bus));
+        pci_bios_check_device_in_bus(0 /* host bus */);
+        if (pci_bios_init_root_regions(start, end) != 0) {
+            dprintf(1, "PCI: out of address space\n");
+            /* Hmm, what do now? */
+        }
     }
 
     dprintf(1, "=== PCI new allocation pass #2 ===\n");
diff --git a/src/util.h b/src/util.h
index d856d50..8020181 100644
--- a/src/util.h
+++ b/src/util.h
@@ -347,6 +347,8 @@ void qemu_prep_reset(void);
 // pciinit.c
 extern const u8 pci_irqs[4];
 void pci_setup(void);
+struct pci_device;
+int pci_enable_device(struct pci_device *pci);
 
 // smm.c
 void smm_init(void);
-- 
1.7.1




More information about the SeaBIOS mailing list