commit 191a5dc6e3202ed1ca918c8f237d2a4f4ae164df Author: Justin Hibbits Date: Wed Jul 31 22:42:04 2019 -0500 powerpc/powernv: Conditionally reset the OPAL PCH Some devices, such as some video cards, need to be reset in order to work properly. Allow the bus to be reinitialized on attach, conditionally on a tunable (dev.pcib.N.reset=0/1), defaulting to reset. On some systems, the BMC's VGA cannot be reset, lest it lose all state, and we have no driver. In this case, we don't want to reset, so the tunable can be set accordingly. Defaulting to reset should be safe for most cases. diff --git a/sys/powerpc/powernv/opal_pci.c b/sys/powerpc/powernv/opal_pci.c index 1545c04e667..95c457e12bd 100644 --- a/sys/powerpc/powernv/opal_pci.c +++ b/sys/powerpc/powernv/opal_pci.c @@ -248,8 +248,7 @@ opalpci_attach(device_t dev) uint64_t entries; uint64_t tce_size; uint64_t tce_tbl_size; - int m64bar; - int rid; + int do_reset, m64bar, rid; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); @@ -281,42 +280,48 @@ opalpci_attach(device_t dev) return (ENXIO); } -#if 0 - /* - * Reset PCI IODA table - */ - err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PCI_IODA_TABLE, - 1); - if (err != 0) { - device_printf(dev, "IODA table reset failed: %d\n", err); - return (ENXIO); - } - err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PHB_COMPLETE, - 1); - if (err < 0) { - device_printf(dev, "PHB reset failed: %d\n", err); - return (ENXIO); - } - if (err > 0) { - while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) { - DELAY(1000*(err + 1)); /* Returns expected delay in ms */ + do_reset = 1; + resource_int_value(device_get_name(dev), device_get_unit(dev), "reset", + &do_reset); + + if (do_reset) { + /* + * Reset PCI IODA table + */ + err = opal_call(OPAL_PCI_RESET, sc->phb_id, + OPAL_RESET_PCI_IODA_TABLE, 1); + if (err != 0) { + device_printf(dev, + "IODA table reset failed: %d\n", err); + return (ENXIO); } - } - if (err < 0) { - device_printf(dev, "WARNING: PHB IODA reset poll failed: %d\n", err); - } - err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PHB_COMPLETE, - 0); - if (err < 0) { - device_printf(dev, "PHB reset failed: %d\n", err); - return (ENXIO); - } - if (err > 0) { - while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) { - DELAY(1000*(err + 1)); /* Returns expected delay in ms */ + err = opal_call(OPAL_PCI_RESET, sc->phb_id, + OPAL_RESET_PHB_COMPLETE, 1); + if (err < 0) { + device_printf(dev, "PHB reset failed: %d\n", err); + return (ENXIO); + } + if (err > 0) { + while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) { + /* Returns expected delay in ms */ + DELAY(1000*(err + 1)); + } + } + if (err < 0) { + device_printf(dev, + "WARNING: PHB IODA reset poll failed: %d\n", err); + } + err = opal_call(OPAL_PCI_RESET, sc->phb_id, + OPAL_RESET_PHB_COMPLETE, 0); + if (err < 0) { + device_printf(dev, "PHB reset failed: %d\n", err); + return (ENXIO); + } + if (err > 0) { + while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0) + DELAY(1000*(err + 1)); } } -#endif /* * Map all devices on the bus to partitionable endpoint one until