aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/i386/lib/pci_ops_auto.c11
-rw-r--r--src/devices/pci_ops.c8
-rw-r--r--src/include/device/pci.h2
-rw-r--r--src/include/device/pci_ops.h3
4 files changed, 21 insertions, 3 deletions
diff --git a/src/arch/i386/lib/pci_ops_auto.c b/src/arch/i386/lib/pci_ops_auto.c
index b757e608fc..f453d47826 100644
--- a/src/arch/i386/lib/pci_ops_auto.c
+++ b/src/arch/i386/lib/pci_ops_auto.c
@@ -41,6 +41,8 @@ static int pci_sanity_check(const struct pci_bus_operations *o)
return 0;
}
+struct pci_bus_operations *pci_bus_fallback_ops = NULL;
+
const struct pci_bus_operations *pci_check_direct(void)
{
unsigned int tmp;
@@ -81,11 +83,18 @@ const struct pci_bus_operations *pci_check_direct(void)
return NULL;
}
+const struct pci_bus_operations *pci_remember_direct(void)
+{
+ if (!pci_bus_fallback_ops)
+ pci_bus_fallback_ops = pci_check_direct();
+ return pci_bus_fallback_ops;
+}
+
/** Set the method to be used for PCI, type I or type II
*/
void pci_set_method(device_t dev)
{
printk_info("Finding PCI configuration type.\n");
- dev->ops->ops_pci_bus = pci_check_direct();
+ dev->ops->ops_pci_bus = pci_remember_direct();
post_code(0x5f);
}
diff --git a/src/devices/pci_ops.c b/src/devices/pci_ops.c
index 6029d757ef..6ade5e0c3c 100644
--- a/src/devices/pci_ops.c
+++ b/src/devices/pci_ops.c
@@ -25,6 +25,9 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
+/* The only consumer of the return value of get_pbus() is ops_pci_bus().
+ * ops_pci_bus() can handle being passed NULL and auto-picks working ops.
+ */
static struct bus *get_pbus(device_t dev)
{
struct bus *pbus = NULL;
@@ -44,8 +47,9 @@ static struct bus *get_pbus(device_t dev)
pbus = pbus->dev->bus;
}
if (!pbus || !pbus->dev || !pbus->dev->ops || !pbus->dev->ops->ops_pci_bus) {
- printk_emerg("%s: Cannot find pci bus operations.\n", dev_path(dev));
- die("");
+ /* This can happen before the device tree is set up completely. */
+ //printk_emerg("%s: Cannot find pci bus operations.\n", dev_path(dev));
+ pbus = NULL;
}
return pbus;
}
diff --git a/src/include/device/pci.h b/src/include/device/pci.h
index df9e80dbbb..60cf4aa35c 100644
--- a/src/include/device/pci.h
+++ b/src/include/device/pci.h
@@ -97,6 +97,8 @@ static inline const struct pci_bus_operations *ops_pci_bus(struct bus *bus)
if (bus && bus->dev && bus->dev->ops) {
bops = bus->dev->ops->ops_pci_bus;
}
+ if (!bops)
+ bops = pci_remember_direct();
return bops;
}
diff --git a/src/include/device/pci_ops.h b/src/include/device/pci_ops.h
index da7e6c5d17..13eee9d4a9 100644
--- a/src/include/device/pci_ops.h
+++ b/src/include/device/pci_ops.h
@@ -21,4 +21,7 @@ void pci_mmio_write_config16(device_t dev, unsigned where, uint16_t val);
void pci_mmio_write_config32(device_t dev, unsigned where, uint32_t val);
#endif
+/* This function lives in pci_ops_auto.c */
+const struct pci_bus_operations *pci_remember_direct(void);
+
#endif /* PCI_OPS_H */