svn commit: r303313 - projects/powernv/powerpc/powernv
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Mon Jul 25 18:24:55 UTC 2016
Author: nwhitehorn
Date: Mon Jul 25 18:24:54 2016
New Revision: 303313
URL: https://svnweb.freebsd.org/changeset/base/303313
Log:
Add some stub code for resetting the PCI host bridge that currently hoses everything.
Modified:
projects/powernv/powerpc/powernv/opal.h
projects/powernv/powerpc/powernv/opal_pci.c
Modified: projects/powernv/powerpc/powernv/opal.h
==============================================================================
--- projects/powernv/powerpc/powernv/opal.h Mon Jul 25 17:37:02 2016 (r303312)
+++ projects/powernv/powerpc/powernv/opal.h Mon Jul 25 18:24:54 2016 (r303313)
@@ -45,6 +45,7 @@ int opal_call(uint64_t token, ...);
#define OPAL_RTC_WRITE 4
#define OPAL_CEC_POWER_DOWN 5
#define OPAL_CEC_REBOOT 6
+#define OPAL_HANDLE_INTERRUPT 9
#define OPAL_POLL_EVENTS 10
#define OPAL_PCI_CONFIG_READ_BYTE 13
#define OPAL_PCI_CONFIG_READ_HALF_WORD 14
@@ -56,12 +57,16 @@ int opal_call(uint64_t token, ...);
#define OPAL_PCI_PHB_MMIO_ENABLE 27
#define OPAL_PCI_SET_PHB_MEM_WINDOW 28
#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29
+#define OPAL_PCI_SET_XIVE_PE 37
#define OPAL_PCI_RESET 49
+#define OPAL_PCI_POLL 62
#define OPAL_SET_XIVE 19
#define OPAL_GET_XIVE 20
#define OPAL_PCI_SET_PE 31
#define OPAL_START_CPU 41
#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45
+#define OPAL_RETURN_CPU 69
+#define OPAL_REINIT_CPUS 70
/* For OPAL_PCI_SET_PE */
#define OPAL_UNMAP_PE 0
@@ -69,6 +74,7 @@ int opal_call(uint64_t token, ...);
#define OPAL_SUCCESS 0
#define OPAL_PARAMETER -1
+#define OPAL_CLOSED -5
#define OPAL_BUSY_EVENT -12
#endif
Modified: projects/powernv/powerpc/powernv/opal_pci.c
==============================================================================
--- projects/powernv/powerpc/powernv/opal_pci.c Mon Jul 25 17:37:02 2016 (r303312)
+++ projects/powernv/powerpc/powernv/opal_pci.c Mon Jul 25 18:24:54 2016 (r303313)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2015 Nathan Whitehorn
+ * Copyright (c) 2015-2016 Nathan Whitehorn
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -74,12 +74,21 @@ static void opalpci_write_config(device
u_int, u_int32_t, int);
/*
+ * bus interface.
+ */
+
+static int opalpci_setup_intr(device_t dev, device_t child, struct resource *r,
+ int flags, driver_filter_t *filter, driver_intr_t *ithread,
+ void *arg, void **cookiep);
+
+/*
* Commands
*/
#define OPAL_M32_WINDOW_TYPE 1
#define OPAL_M64_WINDOW_TYPE 2
#define OPAL_IO_WINDOW_TYPE 3
+#define OPAL_RESET_PHB_COMPLETE 1
#define OPAL_RESET_PCI_IODA_TABLE 6
#define OPAL_DISABLE_M64 0
@@ -91,6 +100,11 @@ static void opalpci_write_config(device
#define OPAL_EEH_ACTION_CLEAR_FREEZE_ALL 3
/*
+ * Constants
+ */
+#define OPAL_PCI_DEFAULT_PE 1
+
+/*
* Driver methods.
*/
static device_method_t opalpci_methods[] = {
@@ -102,6 +116,9 @@ static device_method_t opalpci_methods[]
DEVMETHOD(pcib_read_config, opalpci_read_config),
DEVMETHOD(pcib_write_config, opalpci_write_config),
+ /* bus overrides */
+ DEVMETHOD(bus_setup_intr, opalpci_setup_intr),
+
DEVMETHOD_END
};
@@ -164,24 +181,58 @@ opalpci_attach(device_t dev)
device_printf(dev, "OPAL ID %#lx\n", sc->phb_id);
/*
- * Map all devices on the bus to partitionable endpoint one until
- * such time as we start wanting to do things like bhyve.
+ * Reset PCI IODA table
*/
- err = opal_call(OPAL_PCI_SET_PE, sc->phb_id, 1 /* Root PE */,
- 0, 0, 0, 0, /* All devices */
- OPAL_MAP_PE);
+ err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PCI_IODA_TABLE,
+ 1);
if (err != 0) {
- device_printf(dev, "PE mapping failed: %d\n", err);
+ device_printf(dev, "IODA table reset failed: %d\n", err);
return (ENXIO);
}
/*
- * Reset PCI IODA table
+ * Reset everything. Especially important if we have inherited the
+ * system from Linux by kexec()
*/
- err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PCI_IODA_TABLE,
- 1);
+#ifdef NOTYET
+ if (bootverbose)
+ device_printf(dev, "Resetting PCI bus\n");
+ 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);
+ }
+ while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0)
+ DELAY(1000*err); /* Returns expected delay in ms */
+ if (err < 0) {
+ device_printf(dev, "PHB reset poll failed: %d\n", err);
+ return (ENXIO);
+ }
+ DELAY(10000);
+ err = opal_call(OPAL_PCI_RESET, sc->phb_id, OPAL_RESET_PHB_COMPLETE, 0);
+ if (err < 0) {
+ device_printf(dev, "PHB reset completion failed: %d\n", err);
+ return (ENXIO);
+ }
+ while ((err = opal_call(OPAL_PCI_POLL, sc->phb_id)) > 0)
+ DELAY(1000*err); /* Returns expected delay in ms */
+ if (err < 0) {
+ device_printf(dev, "PHB reset completion poll failed: %d\n",
+ err);
+ return (ENXIO);
+ }
+ DELAY(10000);
+#endif
+
+ /*
+ * Map all devices on the bus to partitionable endpoint one until
+ * such time as we start wanting to do things like bhyve.
+ */
+ err = opal_call(OPAL_PCI_SET_PE, sc->phb_id, OPAL_PCI_DEFAULT_PE,
+ 0, 0, 0, 0, /* All devices */
+ OPAL_MAP_PE);
if (err != 0) {
- device_printf(dev, "IODA table reset failed: %d\n", err);
+ device_printf(dev, "PE mapping failed: %d\n", err);
return (ENXIO);
}
@@ -192,8 +243,8 @@ opalpci_attach(device_t dev)
!= 4)
npe = 1;
for (i = 0; i < npe; i++) {
- err = opal_call(OPAL_PCI_MAP_PE_MMIO_WINDOW, sc->phb_id, 1,
- OPAL_M32_WINDOW_TYPE, 0, i);
+ err = opal_call(OPAL_PCI_MAP_PE_MMIO_WINDOW, sc->phb_id,
+ OPAL_PCI_DEFAULT_PE, OPAL_M32_WINDOW_TYPE, 0, i);
if (err != 0)
device_printf(dev, "MMIO %d map failed: %d\n", i, err);
}
@@ -205,8 +256,9 @@ opalpci_attach(device_t dev)
OPAL_M64_WINDOW_TYPE, 0 /* index */,
((uint64_t)m64window[2] << 32) | m64window[3], 0,
((uint64_t)m64window[4] << 32) | m64window[5]);
- opal_call(OPAL_PCI_MAP_PE_MMIO_WINDOW, sc->phb_id, 1 /* PE */,
- OPAL_M64_WINDOW_TYPE, 0 /* index */, 0);
+ opal_call(OPAL_PCI_MAP_PE_MMIO_WINDOW, sc->phb_id,
+ OPAL_PCI_DEFAULT_PE, OPAL_M64_WINDOW_TYPE,
+ 0 /* index */, 0);
opal_call(OPAL_PCI_PHB_MMIO_ENABLE, sc->phb_id,
OPAL_M64_WINDOW_TYPE, 0, OPAL_ENABLE_M64_NON_SPLIT);
}
@@ -214,8 +266,9 @@ opalpci_attach(device_t dev)
/*
* Also disable the IOMMU for the time being for PE 1 (everything)
*/
- err = opal_call(OPAL_PCI_MAP_PE_DMA_WINDOW_REAL, sc->phb_id, 1, 2,
- 0 /* start address */, roundup2(Maxmem, 16*1024*1024)/* all RAM */);
+ err = opal_call(OPAL_PCI_MAP_PE_DMA_WINDOW_REAL, sc->phb_id,
+ OPAL_PCI_DEFAULT_PE, 2, 0 /* start address */,
+ roundup2(Maxmem, 16*1024*1024)/* all RAM */);
if (err != 0) {
device_printf(dev, "DMA mapping failed: %d\n", err);
return (ENXIO);
@@ -232,7 +285,7 @@ opalpci_attach(device_t dev)
* Unfreeze non-config-space PCI operations. Let this fail silently
* if e.g. there is no current freeze.
*/
- opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, 1,
+ opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, OPAL_PCI_DEFAULT_PE,
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
/*
@@ -299,7 +352,7 @@ opalpci_read_config(device_t dev, u_int
*
* XXX: Make this conditional on the existence of a freeze
*/
- opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, 1,
+ opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, OPAL_PCI_DEFAULT_PE,
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
if (error != OPAL_SUCCESS)
@@ -340,8 +393,23 @@ opalpci_write_config(device_t dev, u_int
* Poking config state for non-existant devices can make
* the host bridge hang up. Clear any errors.
*/
- opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id, 1,
- OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+ opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, sc->phb_id,
+ OPAL_PCI_DEFAULT_PE, OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
}
}
+static int
+opalpci_setup_intr(device_t dev, device_t child, struct resource *r,
+ int flags, driver_filter_t *filter, driver_intr_t *ithread,
+ void *arg, void **cookiep)
+{
+ struct opalpci_softc *sc;
+
+ sc = device_get_softc(dev);
+ opal_call(OPAL_PCI_SET_XIVE_PE, sc->phb_id, OPAL_PCI_DEFAULT_PE,
+ rman_get_start(r));
+
+ return BUS_SETUP_INTR(device_get_parent(dev), child, r, flags, filter,
+ ithread, arg, cookiep);
+}
+
More information about the svn-src-projects
mailing list