Author: marius
Date: Sat Mar 26 16:52:31 2011
New Revision: 220039
URL: http://svn.freebsd.org/changeset/base/220039

Log:
  - 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
    for disabling bus parking for certain EBus bridges in order to
  - Mark some unused parameters as such.

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       Sat Mar 26 16:49:12 2011        
(r220038)
+++ head/sys/sparc64/pci/psycho.c       Sat Mar 26 16:52:31 2011        
(r220039)
@@ -83,7 +83,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 *);
@@ -110,18 +111,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 */
@@ -135,12 +135,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 */
@@ -152,6 +152,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,15 +529,19 @@ psycho_attach(device_t dev)
                 *
                 * For the moment, 32KB should be more than enough.
                 */
+               memcpy(&sc->sc_dma_methods, &iommu_dma_methods,
+                   sizeof(sc->sc_dma_methods));
                sc->sc_is = malloc(sizeof(struct iommu_state), M_DEVBUF,
                    M_NOWAIT | M_ZERO);
                if (sc->sc_is == NULL)
                        panic("%s: malloc iommu_state failed", __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.dm_dmamap_sync =
+                           sabre_dmamap_sync;
                        sc->sc_is->is_pmaxaddr =
                            IOMMU_MAXADDR(SABRE_IOMMU_BITS);
-               else
+               } else
                        sc->sc_is->is_pmaxaddr =
                            IOMMU_MAXADDR(PSYCHO_IOMMU_BITS);
                sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0;
@@ -587,7 +567,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 +1072,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;
+
+       if ((op & BUS_DMASYNC_POSTREAD) != 0)
+               (void)bus_space_read_8(is->is_bustag, is->is_bushandle,
+                   PSR_DMA_WRITE_SYNC);
 
-       (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_PREWRITE) != 0)
+               membar(Sync);
 }
 
 static void
@@ -1146,16 +1131,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 +1145,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 +1267,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 +1276,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 +1285,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: head/sys/sparc64/pci/psychovar.h
==============================================================================
--- head/sys/sparc64/pci/psychovar.h    Sat Mar 26 16:49:12 2011        
(r220038)
+++ head/sys/sparc64/pci/psychovar.h    Sat Mar 26 16:52:31 2011        
(r220039)
@@ -36,6 +36,8 @@
  * per pair of psychos.
  */
 struct psycho_softc {
+       struct bus_dma_methods          sc_dma_methods;
+
        device_t                        sc_dev;
 
        struct mtx                      *sc_mtx;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to