From owner-svn-src-all@FreeBSD.ORG Sat May 14 21:15:51 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2F745106564A; Sat, 14 May 2011 21:15:51 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 13AB18FC0A; Sat, 14 May 2011 21:15:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4ELFpA6016384; Sat, 14 May 2011 21:15:51 GMT (envelope-from marius@svn.freebsd.org) Received: (from marius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4ELFp4U016381; Sat, 14 May 2011 21:15:51 GMT (envelope-from marius@svn.freebsd.org) Message-Id: <201105142115.p4ELFp4U016381@svn.freebsd.org> From: Marius Strobl Date: Sat, 14 May 2011 21:15:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r221926 - stable/7/sys/sparc64/pci X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 14 May 2011 21:15:51 -0000 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;