Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 May 2011 21:15:51 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r221926 - stable/7/sys/sparc64/pci
Message-ID:  <201105142115.p4ELFp4U016381@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Sat May 14 21:15:50 2011
New Revision: 221926
URL: http://svn.freebsd.org/changeset/base/221926

Log:
  MFC: r220039, 220147
  
  - A closer inspection of the OpenSolaris code indicates that the DMA
    syncing for Hummingbird and Sabre bridges should be applied with every
    BUS_DMASYNC_POSTREAD instead of in a wrapper around interrupt handlers
    for devices behind PCI-PCI bridges only as suggested by the documentation
    (code for the latter actually exists in OpenSolaris but is disabled by
    default), which also makes more sense.
  - Take advantage of the ofw_pci_setup_device method introduced in r220038
    (MFC'ed to stable/7 in r221924) for disabling bus parking for certain
    EBus bridges in order to work around hardware bugs.
  - Mark some unused parameters as such.

Modified:
  stable/7/sys/sparc64/pci/psycho.c
  stable/7/sys/sparc64/pci/psychovar.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/sparc64/pci/psycho.c
==============================================================================
--- stable/7/sys/sparc64/pci/psycho.c	Sat May 14 21:15:49 2011	(r221925)
+++ stable/7/sys/sparc64/pci/psycho.c	Sat May 14 21:15:50 2011	(r221926)
@@ -84,7 +84,8 @@ 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_dma_sync_stub;
+static void sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map,
+    bus_dmasync_op_t op);
 static void psycho_intr_enable(void *);
 static void psycho_intr_disable(void *);
 static void psycho_intr_assign(void *);
@@ -111,18 +112,17 @@ static device_probe_t psycho_probe;
 static device_attach_t psycho_attach;
 static bus_read_ivar_t psycho_read_ivar;
 static bus_setup_intr_t psycho_setup_intr;
-static bus_teardown_intr_t psycho_teardown_intr;
 static bus_alloc_resource_t psycho_alloc_resource;
 static bus_activate_resource_t psycho_activate_resource;
 static bus_deactivate_resource_t psycho_deactivate_resource;
 static bus_release_resource_t psycho_release_resource;
-static bus_describe_intr_t psycho_describe_intr;
 static bus_get_dma_tag_t psycho_get_dma_tag;
 static pcib_maxslots_t psycho_maxslots;
 static pcib_read_config_t psycho_read_config;
 static pcib_write_config_t psycho_write_config;
 static pcib_route_interrupt_t psycho_route_interrupt;
 static ofw_bus_get_node_t psycho_get_node;
+static ofw_pci_setup_device_t psycho_setup_device;
 
 static device_method_t psycho_methods[] = {
 	/* Device interface */
@@ -136,12 +136,12 @@ static device_method_t psycho_methods[] 
 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
 	DEVMETHOD(bus_read_ivar,	psycho_read_ivar),
 	DEVMETHOD(bus_setup_intr,	psycho_setup_intr),
-	DEVMETHOD(bus_teardown_intr,	psycho_teardown_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
 	DEVMETHOD(bus_alloc_resource,	psycho_alloc_resource),
 	DEVMETHOD(bus_activate_resource,	psycho_activate_resource),
 	DEVMETHOD(bus_deactivate_resource,	psycho_deactivate_resource),
 	DEVMETHOD(bus_release_resource,	psycho_release_resource),
-	DEVMETHOD(bus_describe_intr,	psycho_describe_intr),
+	DEVMETHOD(bus_describe_intr,	bus_generic_describe_intr),
 	DEVMETHOD(bus_get_dma_tag,	psycho_get_dma_tag),
 
 	/* pcib interface */
@@ -153,6 +153,9 @@ static device_method_t psycho_methods[] 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_node,	psycho_get_node),
 
+	/* ofw_pci interface */
+	DEVMETHOD(ofw_pci_setup_device,	psycho_setup_device),
+
 	KOBJMETHOD_END
 };
 
@@ -178,17 +181,6 @@ struct psycho_icarg {
 	bus_addr_t		pica_clr;
 };
 
-struct psycho_dma_sync {
-	struct psycho_softc	*pds_sc;
-	driver_filter_t		*pds_handler;	/* handler to call */
-	void			*pds_arg;	/* argument for the handler */
-	void			*pds_cookie;	/* parent bus int. cookie */
-	device_t		pds_ppb;	/* farest PCI-PCI bridge */
-	uint8_t			pds_bus;	/* bus of farest PCI dev. */
-	uint8_t			pds_slot;	/* slot of farest PCI dev. */
-	uint8_t			pds_func;	/* func. of farest PCI dev. */
-};
-
 #define	PSYCHO_READ8(sc, off)						\
 	bus_read_8((sc)->sc_mem_res, (off))
 #define	PSYCHO_WRITE8(sc, off, v)					\
@@ -288,16 +280,14 @@ psycho_probe(device_t dev)
 static int
 psycho_attach(device_t dev)
 {
-	char name[sizeof("pci108e,1000")];
 	struct psycho_icarg *pica;
 	struct psycho_softc *asc, *sc, *osc;
 	struct ofw_pci_ranges *range;
 	const struct psycho_desc *desc;
 	bus_addr_t intrclr, intrmap;
 	uint64_t csr, dr;
-	phandle_t child, node;
+	phandle_t node;
 	uint32_t dvmabase, prop, prop_array[2];
-	int32_t rev;
 	u_int rerun, ver;
 	int i, j;
 
@@ -387,23 +377,9 @@ psycho_attach(device_t dev)
 
 	/* Set up the PCI control and PCI diagnostic registers. */
 
-	/*
-	 * Revision 0 EBus bridges have a bug which prevents them from
-	 * working when bus parking is enabled.
-	 */
-	rev = -1;
 	csr = PCICTL_READ8(sc, PCR_CS);
 	csr &= ~PCICTL_ARB_PARK;
-	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
-		if (OF_getprop(child, "name", name, sizeof(name)) == -1)
-			continue;
-		if ((strcmp(name, "ebus") == 0 ||
-		    strcmp(name, "pci108e,1000") == 0) &&
-		    OF_getprop(child, "revision-id", &rev, sizeof(rev)) > 0 &&
-		    rev == 0)
-			break;
-	}
-	if (rev != 0 && OF_getproplen(node, "no-bus-parking") < 0)
+	if (OF_getproplen(node, "no-bus-parking") < 0)
 		csr |= PCICTL_ARB_PARK;
 
 	/* Workarounds for version specific bugs. */
@@ -553,17 +529,29 @@ psycho_attach(device_t dev)
 		 *
 		 * For the moment, 32KB should be more than enough.
 		 */
-		sc->sc_is = malloc(sizeof(struct iommu_state), M_DEVBUF,
-		    M_NOWAIT | M_ZERO);
+		sc->sc_is = malloc(sizeof(*sc->sc_is), M_DEVBUF, M_NOWAIT |
+		    M_ZERO);
 		if (sc->sc_is == NULL)
-			panic("%s: malloc iommu_state failed", __func__);
+			panic("%s: could not malloc IOMMU state", __func__);
 		sc->sc_is->is_flags = IOMMU_PRESERVE_PROM;
-		if (sc->sc_mode == PSYCHO_MODE_SABRE)
+		if (sc->sc_mode == PSYCHO_MODE_SABRE) {
+			sc->sc_dma_methods =
+			    malloc(sizeof(*sc->sc_dma_methods), M_DEVBUF,
+			    M_NOWAIT);
+			if (sc->sc_dma_methods == NULL)
+				panic("%s: could not malloc DMA methods",
+				    __func__);
+			memcpy(sc->sc_dma_methods, &iommu_dma_methods,
+			    sizeof(*sc->sc_dma_methods));
+			sc->sc_dma_methods->dm_dmamap_sync =
+			    sabre_dmamap_sync;
 			sc->sc_is->is_pmaxaddr =
 			    IOMMU_MAXADDR(SABRE_IOMMU_BITS);
-		else
+		} else {
+			sc->sc_dma_methods = &iommu_dma_methods;
 			sc->sc_is->is_pmaxaddr =
 			    IOMMU_MAXADDR(PSYCHO_IOMMU_BITS);
+		}
 		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;
@@ -571,6 +559,7 @@ psycho_attach(device_t dev)
 		psycho_iommu_init(sc, 3, dvmabase);
 	} else {
 		/* Just copy IOMMU state, config tag and address. */
+		sc->sc_dma_methods = &iommu_dma_methods;
 		sc->sc_is = osc->sc_is;
 		if (OF_getproplen(node, "no-streaming-cache") < 0)
 			sc->sc_is->is_sb[1] = sc->sc_pcictl + PCR_STRBUF;
@@ -587,7 +576,7 @@ psycho_attach(device_t dev)
 		panic("%s: bus_dma_tag_create failed", __func__);
 	/* Customize the tag. */
 	sc->sc_pci_dmat->dt_cookie = sc->sc_is;
-	sc->sc_pci_dmat->dt_mt = &iommu_dma_methods;
+	sc->sc_pci_dmat->dt_mt = sc->sc_dma_methods;
 
 	i = OF_getprop(node, "bus-range", (void *)prop_array,
 	    sizeof(prop_array));
@@ -1092,15 +1081,20 @@ psycho_read_ivar(device_t dev, device_t 
 	return (ENOENT);
 }
 
-static int
-psycho_dma_sync_stub(void *arg)
+static void
+sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
 {
-	struct psycho_dma_sync *pds = arg;
+	struct iommu_state *is = dt->dt_cookie;
+
+	if ((map->dm_flags & DMF_LOADED) == 0)
+		return;
 
-	(void)PCIB_READ_CONFIG(pds->pds_ppb, pds->pds_bus, pds->pds_slot,
-	    pds->pds_func, PCIR_VENDOR, 2);
-	(void)PSYCHO_READ8(pds->pds_sc, PSR_DMA_WRITE_SYNC);
-	return (pds->pds_handler(pds->pds_arg));
+	if ((op & BUS_DMASYNC_POSTREAD) != 0)
+		(void)bus_space_read_8(is->is_bustag, is->is_bushandle,
+		    PSR_DMA_WRITE_SYNC);
+
+	if ((op & BUS_DMASYNC_PREWRITE) != 0)
+		membar(Sync);
 }
 
 static void
@@ -1146,16 +1140,8 @@ psycho_setup_intr(device_t dev, device_t
     int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
     void **cookiep)
 {
-	struct {
-		int apb:1;
-		int ppb:1;
-	} found;
-	devclass_t pci_devclass;
-	device_t cdev, pdev, pcidev;
 	struct psycho_softc *sc;
-	struct psycho_dma_sync *pds;
 	u_long vec;
-	int error;
 
 	sc = device_get_softc(dev);
 	/*
@@ -1168,114 +1154,10 @@ psycho_setup_intr(device_t dev, device_t
 		device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
 		return (EINVAL);
 	}
-
-	/*
-	 * 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);
-		if (pds == NULL)
-			return (ENOMEM);
-		pcidev = NULL;
-		found.apb = found.ppb = 0;
-		pci_devclass = devclass_find("pci");
-		for (cdev = child; cdev != dev; cdev = pdev) {
-			pdev = device_get_parent(cdev);
-			if (pcidev == NULL) {
-				if (device_get_devclass(pdev) != pci_devclass)
-					continue;
-				pcidev = cdev;
-				continue;
-			}
-			/*
-			 * NB: APB would also match as PCI-PCI bridges.
-			 */
-			if (pci_get_vendor(cdev) == 0x108e &&
-			    pci_get_device(cdev) == 0x5000) {
-				found.apb = 1;
-				break;
-			}
-			if (pci_get_class(cdev) == PCIC_BRIDGE &&
-			    pci_get_subclass(cdev) == PCIS_BRIDGE_PCI)
-				found.ppb = 1;
-		}
-		if (found.apb && found.ppb && pcidev != NULL) {
-			pds->pds_sc = sc;
-			pds->pds_arg = arg;
-			pds->pds_ppb =
-			    device_get_parent(device_get_parent(pcidev));
-			pds->pds_bus = pci_get_bus(pcidev);
-			pds->pds_slot = pci_get_slot(pcidev);
-			pds->pds_func = pci_get_function(pcidev);
-			if (bootverbose)
-				device_printf(dev, "installed DMA sync "
-				    "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_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_dma_sync_stub,
-				    pds, cookiep);
-			}
-		} else
-			error = bus_generic_setup_intr(dev, child, ires,
-			    flags, filt, intr, arg, cookiep);
-		if (error != 0) {
-			free(pds, M_DEVBUF);
-			return (error);
-		}
-		pds->pds_cookie = *cookiep;
-		*cookiep = pds;
-		return (error);
-	}
 	return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
 	    arg, cookiep));
 }
 
-static int
-psycho_teardown_intr(device_t dev, device_t child, struct resource *vec,
-    void *cookie)
-{
-	struct psycho_softc *sc;
-	struct psycho_dma_sync *pds;
-	int error;
-
-	sc = device_get_softc(dev);
-	if (sc->sc_mode == PSYCHO_MODE_SABRE) {
-		pds = cookie;
-		error = bus_generic_teardown_intr(dev, child, vec,
-		    pds->pds_cookie);
-		if (error == 0)
-			free(pds, M_DEVBUF);
-		return (error);
-	}
-	return (bus_generic_teardown_intr(dev, child, vec, cookie));
-}
-
-static int
-psycho_describe_intr(device_t dev, device_t child, struct resource *vec,
-    void *cookie, const char *descr)
-{
-	struct psycho_softc *sc;
-
-	sc = device_get_softc(dev);
-	if (sc->sc_mode == PSYCHO_MODE_SABRE)
-		cookie = ((struct psycho_dma_sync *)cookie)->pds_cookie;
-	return (bus_generic_describe_intr(dev, child, vec, cookie, descr));
-}
-
 static struct resource *
 psycho_alloc_resource(device_t bus, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
@@ -1394,7 +1276,7 @@ psycho_release_resource(device_t bus, de
 }
 
 static bus_dma_tag_t
-psycho_get_dma_tag(device_t bus, device_t child)
+psycho_get_dma_tag(device_t bus, device_t child __unused)
 {
 	struct psycho_softc *sc;
 
@@ -1403,7 +1285,7 @@ psycho_get_dma_tag(device_t bus, device_
 }
 
 static phandle_t
-psycho_get_node(device_t bus, device_t dev)
+psycho_get_node(device_t bus, device_t child __unused)
 {
 	struct psycho_softc *sc;
 
@@ -1412,6 +1294,25 @@ psycho_get_node(device_t bus, device_t d
 	return (sc->sc_node);
 }
 
+static void
+psycho_setup_device(device_t bus, device_t child)
+{
+	struct psycho_softc *sc;
+	uint32_t rev;
+
+	sc = device_get_softc(bus);
+	/*
+	 * Revision 0 EBus bridges have a bug which prevents them from
+	 * working when bus parking is enabled.
+	 */
+	if ((strcmp(ofw_bus_get_name(child), "ebus") == 0 ||
+	    strcmp(ofw_bus_get_name(child), "pci108e,1000") == 0) &&
+	    OF_getprop(ofw_bus_get_node(child), "revision-id", &rev,
+	    sizeof(rev)) > 0 && rev == 0)
+		PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS) &
+		    ~PCICTL_ARB_PARK);
+}
+
 static bus_space_tag_t
 psycho_alloc_bus_tag(struct psycho_softc *sc, int type)
 {

Modified: stable/7/sys/sparc64/pci/psychovar.h
==============================================================================
--- stable/7/sys/sparc64/pci/psychovar.h	Sat May 14 21:15:49 2011	(r221925)
+++ stable/7/sys/sparc64/pci/psychovar.h	Sat May 14 21:15:50 2011	(r221926)
@@ -38,6 +38,8 @@
  * per pair of psychos.
  */
 struct psycho_softc {
+	struct bus_dma_methods		*sc_dma_methods;
+
 	device_t			sc_dev;
 
 	struct mtx			*sc_mtx;



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