Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Mar 2009 20:52:46 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r190109 - head/sys/sparc64/pci
Message-ID:  <200903192052.n2JKqkaY075596@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Thu Mar 19 20:52:46 2009
New Revision: 190109
URL: http://svn.freebsd.org/changeset/base/190109

Log:
  - 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]

Modified:
  head/sys/sparc64/pci/psycho.c
  head/sys/sparc64/pci/psychovar.h

Modified: head/sys/sparc64/pci/psycho.c
==============================================================================
--- head/sys/sparc64/pci/psycho.c	Thu Mar 19 20:48:47 2009	(r190108)
+++ head/sys/sparc64/pci/psycho.c	Thu Mar 19 20:52:46 2009	(r190109)
@@ -83,7 +83,7 @@ static void psycho_set_intr(struct psych
     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,
 	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 
 }
 
 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
 	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
 	}
 
 	/*
-	 * 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
 			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, devic
     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, d
 		    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);

Modified: head/sys/sparc64/pci/psychovar.h
==============================================================================
--- head/sys/sparc64/pci/psychovar.h	Thu Mar 19 20:48:47 2009	(r190108)
+++ head/sys/sparc64/pci/psychovar.h	Thu Mar 19 20:52:46 2009	(r190109)
@@ -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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903192052.n2JKqkaY075596>