summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2009-03-19 20:52:46 +0000
committermarius <marius@FreeBSD.org>2009-03-19 20:52:46 +0000
commitcdec2d0d7a38b07b04ea1bf83a31002a81af9bb6 (patch)
tree4347448ad87770912966d1fecc5a68b02293f1b0 /sys/sparc64
parent2f7c8f0fd995e560d28f743f729a348e2ef47491 (diff)
downloadFreeBSD-src-cdec2d0d7a38b07b04ea1bf83a31002a81af9bb6.zip
FreeBSD-src-cdec2d0d7a38b07b04ea1bf83a31002a81af9bb6.tar.gz
- Ensure we find no unexpected partner.
- Failing to register as interrupt controller during attach shouldn't be fatal so just inform about this instead of panicing. - Disable rerun of the streaming cache as workaround for a silicon bug of certain Psycho versions. - Remove the comment regarding lack of newbus'ified bus_dma(9) as being able to associate a DMA tag with a device would allow to implement CDMA flushing/syncing in bus_dmamap_sync(9) but that would totally kill performance. Given that for devices not behind a PCI-PCI bridge the host-to-PCI bridges also only do CDMA flushing/syncing based on interrupts there's no additional disadvantage for polling(4) callbacks in the case schizo(4) has to do the CDMA flushing/syncing but rather a general problem. - Don't panic if the power failure, power management or over-temperature interrupts doesn't exist as these aren't mandatory and not available with all controllers (not even Psychos). [1] - Take advantage of KOBJMETHOD_END. - Remove some redundant variables. - Add missing const. PR: 131371 [1]
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/pci/psycho.c109
-rw-r--r--sys/sparc64/pci/psychovar.h4
2 files changed, 60 insertions, 53 deletions
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 505eec4..c8caec2 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -83,7 +83,7 @@ static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t,
driver_filter_t, driver_intr_t);
static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *,
bus_addr_t *, u_long *);
-static driver_filter_t psycho_dmasync;
+static driver_filter_t psycho_dma_sync_stub;
static void psycho_intr_enable(void *);
static void psycho_intr_disable(void *);
static void psycho_intr_assign(void *);
@@ -150,7 +150,7 @@ static device_method_t psycho_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, psycho_get_node),
- { 0, 0 }
+ KOBJMETHOD_END
};
static devclass_t psycho_devclass;
@@ -175,7 +175,7 @@ struct psycho_icarg {
bus_addr_t pica_clr;
};
-struct psycho_dmasync {
+struct psycho_dma_sync {
struct psycho_softc *pds_sc;
driver_filter_t *pds_handler; /* handler to call */
void *pds_arg; /* argument for the handler */
@@ -232,14 +232,14 @@ struct psycho_desc {
const char *pd_name;
};
-static const struct psycho_desc psycho_compats[] = {
+static const struct psycho_desc const psycho_compats[] = {
{ "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" },
{ "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre compatible" },
{ "pci108e,a001", PSYCHO_MODE_SABRE, "Hummingbird compatible" },
{ NULL, 0, NULL }
};
-static const struct psycho_desc psycho_models[] = {
+static const struct psycho_desc const psycho_models[] = {
{ "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" },
{ "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" },
{ NULL, 0, NULL }
@@ -296,8 +296,8 @@ psycho_attach(device_t dev)
phandle_t child, node;
uint32_t dvmabase, prop, prop_array[2];
int32_t rev;
- u_int ver;
- int i, n, nrange, rid;
+ u_int rerun, ver;
+ int i, n;
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
@@ -315,7 +315,7 @@ psycho_attach(device_t dev)
* (2) the shared Psycho configuration registers
*/
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
- rid = 2;
+ i = 2;
sc->sc_pcictl =
bus_get_resource_start(dev, SYS_RES_MEMORY, 0) -
bus_get_resource_start(dev, SYS_RES_MEMORY, 2);
@@ -332,18 +332,18 @@ psycho_attach(device_t dev)
/* NOTREACHED */
}
} else {
- rid = 0;
+ i = 0;
sc->sc_pcictl = PSR_PCICTL0;
sc->sc_half = 0;
}
- sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
(sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) |
RF_ACTIVE);
if (sc->sc_mem_res == NULL)
panic("%s: could not allocate registers", __func__);
/*
- * Match other Psycho's that are already configured against
+ * Match other Psychos that are already configured against
* the base physical address. This will be the same for a
* pair of devices that share register space.
*/
@@ -363,6 +363,8 @@ psycho_attach(device_t dev)
panic("%s: could not malloc mutex", __func__);
mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN);
} else {
+ if (sc->sc_mode != PSYCHO_MODE_PSYCHO)
+ panic("%s: no partner expected", __func__);
if (mtx_initialized(osc->sc_mtx) == 0)
panic("%s: mutex not initialized", __func__);
sc->sc_mtx = osc->sc_mtx;
@@ -408,16 +410,17 @@ psycho_attach(device_t dev)
case 0:
dr |= DIAG_RTRY_DIS;
dr &= ~DIAG_DWSYNC_DIS;
- /* XXX need to also disable rerun of the streaming buffers. */
+ rerun = 0;
break;
case 1:
csr &= ~PCICTL_ARB_PARK;
dr |= DIAG_RTRY_DIS | DIAG_DWSYNC_DIS;
- /* XXX need to also disable rerun of the streaming buffers. */
+ rerun = 0;
break;
default:
dr |= DIAG_DWSYNC_DIS;
dr &= ~DIAG_RTRY_DIS;
+ rerun = 1;
break;
}
@@ -460,13 +463,12 @@ psycho_attach(device_t dev)
rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0)
panic("%s: failed to set up memory rman", __func__);
- nrange = OF_getprop_alloc(node, "ranges", sizeof(*range),
- (void **)&range);
+ n = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
/*
* Make sure that the expected ranges are present. The
* OFW_PCI_CS_MEM64 one is not currently used though.
*/
- if (nrange != PSYCHO_NRANGE)
+ if (n != PSYCHO_NRANGE)
panic("%s: unsupported number of ranges", __func__);
/*
* Find the addresses of the various bus spaces.
@@ -493,7 +495,8 @@ psycho_attach(device_t dev)
/*
* Hunt through all the interrupt mapping regs and register
* our interrupt controller for the corresponding interrupt
- * vectors.
+ * vectors. We do this early in order to be able to catch
+ * stray interrupts.
*/
for (n = 0; n <= PSYCHO_MAX_INO; n++) {
if (psycho_find_intrmap(sc, n, &intrmap, &intrclr,
@@ -523,22 +526,23 @@ psycho_attach(device_t dev)
INTMAP_ENABLE(INTMAP_VEC(sc->sc_ign, n),
PCPU_GET(mid)));
#endif
- if (intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
- &psycho_ic, pica) != 0)
- panic("%s: could not register interrupt "
- "controller for INO %d", __func__, n);
+ i = intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
+ &psycho_ic, pica);
+ if (i != 0)
+ device_printf(dev, "could not register "
+ "interrupt controller for INO %d (%d)\n",
+ n, i);
}
- if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
- /* Initialize the counter-timer. */
+ if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
sparc64_counter_init(device_get_nameunit(dev),
rman_get_bustag(sc->sc_mem_res),
rman_get_bushandle(sc->sc_mem_res), PSR_TC0);
- }
/*
* Set up IOMMU and PCI configuration if we're the first
- * of a pair of Psycho's to arrive here.
+ * of a pair of Psychos to arrive here or a Hummingbird
+ * or Sabre.
*
* We should calculate a TSB size based on amount of RAM
* and number of bus controllers and number and type of
@@ -556,10 +560,10 @@ psycho_attach(device_t dev)
else
sc->sc_is->is_pmaxaddr =
IOMMU_MAXADDR(PSYCHO_IOMMU_BITS);
- sc->sc_is->is_sb[0] = 0;
- sc->sc_is->is_sb[1] = 0;
+ sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0;
if (OF_getproplen(node, "no-streaming-cache") < 0)
sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF;
+ sc->sc_is->is_flags |= (rerun != 1) ? IOMMU_RERUN_DISABLE : 0;
psycho_iommu_init(sc, 3, dvmabase);
} else {
/* Just copy IOMMU state, config tag and address. */
@@ -694,12 +698,20 @@ psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
rid = index;
sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
&rid, RF_ACTIVE);
+ if (sc->sc_irq_res[index] == NULL && intrmap >= PSR_POWER_INT_MAP) {
+ /*
+ * These interrupts aren't mandatory and not available
+ * with all controllers (not even Psychos).
+ */
+ return;
+ }
if (sc->sc_irq_res[index] == NULL ||
INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign ||
INTVEC(PSYCHO_READ8(sc, intrmap)) != vec ||
intr_vectors[vec].iv_ic != &psycho_ic ||
- bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC,
- filt, intr, sc, &sc->sc_ihand[index]) != 0)
+ bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
+ INTR_TYPE_MISC | INTR_FAST, filt, intr, sc,
+ &sc->sc_ihand[index]) != 0)
panic("%s: failed to set up interrupt %d", __func__, index);
}
@@ -1065,9 +1077,9 @@ psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
}
static int
-psycho_dmasync(void *arg)
+psycho_dma_sync_stub(void *arg)
{
- struct psycho_dmasync *pds = arg;
+ struct psycho_dma_sync *pds = arg;
(void)PCIB_READ_CONFIG(pds->pds_ppb, pds->pds_bus, pds->pds_slot,
pds->pds_func, PCIR_VENDOR, 2);
@@ -1125,7 +1137,7 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
devclass_t pci_devclass;
device_t cdev, pdev, pcidev;
struct psycho_softc *sc;
- struct psycho_dmasync *pds;
+ struct psycho_dma_sync *pds;
u_long vec;
int error;
@@ -1142,17 +1154,12 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
}
/*
- * The Sabre-APB-combination has a bug where it does not drain
- * DMA write data for devices behind additional PCI-PCI bridges
- * underneath the APB PCI-PCI bridge. The workaround is to do
- * a read on the farest PCI-PCI bridge followed by a read of the
- * PCI DMA write sync register of the Sabre.
- * XXX installing the wrapper for an affected device and the
- * actual workaround in psycho_dmasync() should be moved to
- * psycho(4)-specific bus_dma_tag_create() and bus_dmamap_sync()
- * methods, respectively, once DMA tag creation is newbus'ified,
- * so the workaround isn't only applied for interrupt handlers
- * but also for polling(4) callbacks.
+ * The Sabre-APB-combination does not automatically flush DMA
+ * write data for devices behind additional PCI-PCI bridges
+ * underneath the APB PCI-PCI bridge. The procedure for a
+ * manual flush is to do a PIO read on the far side of the
+ * farthest PCI-PCI bridge followed by a read of the PCI DMA
+ * write sync register of the Sabre.
*/
if (sc->sc_mode == PSYCHO_MODE_SABRE) {
pds = malloc(sizeof(*pds), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -1191,20 +1198,20 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
pds->pds_func = pci_get_function(pcidev);
if (bootverbose)
device_printf(dev, "installed DMA sync "
- "workaround for device %d.%d on bus %d\n",
+ "wrapper for device %d.%d on bus %d\n",
pds->pds_slot, pds->pds_func,
pds->pds_bus);
if (intr == NULL) {
pds->pds_handler = filt;
error = bus_generic_setup_intr(dev, child,
- ires, flags, psycho_dmasync, intr, pds,
- cookiep);
+ ires, flags, psycho_dma_sync_stub, intr,
+ pds, cookiep);
} else {
pds->pds_handler = (driver_filter_t *)intr;
error = bus_generic_setup_intr(dev, child,
ires, flags, filt,
- (driver_intr_t *)psycho_dmasync, pds,
- cookiep);
+ (driver_intr_t *)psycho_dma_sync_stub,
+ pds, cookiep);
}
} else
error = bus_generic_setup_intr(dev, child, ires,
@@ -1226,7 +1233,7 @@ psycho_teardown_intr(device_t dev, device_t child, struct resource *vec,
void *cookie)
{
struct psycho_softc *sc;
- struct psycho_dmasync *pds;
+ struct psycho_dma_sync *pds;
int error;
sc = device_get_softc(dev);
@@ -1314,8 +1321,8 @@ psycho_activate_resource(device_t bus, device_t child, int type, int rid,
type, rid, r));
if (type == SYS_RES_MEMORY) {
/*
- * Need to memory-map the device space, as some drivers depend
- * on the virtual address being set and useable.
+ * Need to memory-map the device space, as some drivers
+ * depend on the virtual address being set and usable.
*/
error = sparc64_bus_mem_map(rman_get_bustag(r),
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h
index ef4286b..04d81ad 100644
--- a/sys/sparc64/pci/psychovar.h
+++ b/sys/sparc64/pci/psychovar.h
@@ -49,8 +49,8 @@ struct psycho_softc {
phandle_t sc_node; /* Firmware node */
u_int sc_mode;
-#define PSYCHO_MODE_SABRE 1
-#define PSYCHO_MODE_PSYCHO 2
+#define PSYCHO_MODE_SABRE 0
+#define PSYCHO_MODE_PSYCHO 1
/* Bus A or B of a psycho pair? */
u_int sc_half;
OpenPOWER on IntegriCloud