From owner-svn-src-stable-8@FreeBSD.ORG Wed Feb 1 21:28:17 2012 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 179811065677; Wed, 1 Feb 2012 21:28:17 +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 052928FC18; Wed, 1 Feb 2012 21:28:17 +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 q11LSGoD006089; Wed, 1 Feb 2012 21:28:16 GMT (envelope-from marius@svn.freebsd.org) Received: (from marius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q11LSGAi006086; Wed, 1 Feb 2012 21:28:16 GMT (envelope-from marius@svn.freebsd.org) Message-Id: <201202012128.q11LSGAi006086@svn.freebsd.org> From: Marius Strobl Date: Wed, 1 Feb 2012 21:28:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r230895 - stable/8/sys/sparc64/pci X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 01 Feb 2012 21:28:17 -0000 Author: marius Date: Wed Feb 1 21:28:16 2012 New Revision: 230895 URL: http://svn.freebsd.org/changeset/base/230895 Log: MFC: r230664 As it turns out r227960 (MFC'ed to stable/8 in r228145) may still be insufficient with PREEMPTION so try harder to get the CDMA sync interrupt delivered and also in a more efficient way: - wrap the whole process of sending and receiving the CDMA sync interrupt in a critical section so we don't get preempted, - send the CDMA sync interrupt to the CPU that is actually waiting for it to happen so we don't take a detour via another CPU, - instead of waiting for up to 15 seconds for the interrupt to trigger try the whole process for up to 15 times using a one second timeout (the code was also changed to just ignore belated interrupts of a previous tries should they appear). According to testing done by Peter Jeremy with the debugging also added as part of this commit the first two changes apparently are sufficient to now properly get the CDMA sync interrupts delivered at the first try though. Modified: stable/8/sys/sparc64/pci/schizo.c stable/8/sys/sparc64/pci/schizovar.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/e1000/ (props changed) Modified: stable/8/sys/sparc64/pci/schizo.c ============================================================================== --- stable/8/sys/sparc64/pci/schizo.c Wed Feb 1 21:28:13 2012 (r230894) +++ stable/8/sys/sparc64/pci/schizo.c Wed Feb 1 21:28:16 2012 (r230895) @@ -178,6 +178,8 @@ struct schizo_icarg { bus_addr_t sica_clr; }; +#define SCHIZO_CDMA_TIMEOUT 1 /* 1 second per try */ +#define SCHIZO_CDMA_TRIES 15 #define SCHIZO_PERF_CNT_QLTY 100 #define SCHIZO_SPC_BARRIER(spc, sc, offs, len, flags) \ @@ -706,13 +708,15 @@ schizo_attach(device_t dev) i = INTINO(bus_get_resource_start(dev, SYS_RES_IRQ, 4)); if (i == STX_CDMA_A_INO || i == STX_CDMA_B_INO) { - (void)schizo_get_intrmap(sc, i, NULL, - &sc->sc_cdma_clr); + sc->sc_cdma_vec = INTMAP_VEC(sc->sc_ign, i); + (void)schizo_get_intrmap(sc, i, + &sc->sc_cdma_map, &sc->sc_cdma_clr); schizo_set_intr(sc, 4, i, schizo_cdma); } else { i = STX_CDMA_A_INO + sc->sc_half; + sc->sc_cdma_vec = INTMAP_VEC(sc->sc_ign, i); if (bus_set_resource(dev, SYS_RES_IRQ, 5, - INTMAP_VEC(sc->sc_ign, i), 1) != 0) + sc->sc_cdma_vec, 1) != 0) panic("%s: failed to add CDMA " "interrupt", __func__); j = schizo_intr_register(sc, i); @@ -720,8 +724,8 @@ schizo_attach(device_t dev) panic("%s: could not register " "interrupt controller for CDMA " "(%d)", __func__, j); - (void)schizo_get_intrmap(sc, i, NULL, - &sc->sc_cdma_clr); + (void)schizo_get_intrmap(sc, i, + &sc->sc_cdma_map, &sc->sc_cdma_clr); schizo_set_intr(sc, 5, i, schizo_cdma); } } else { @@ -988,7 +992,8 @@ schizo_cdma(void *arg) { struct schizo_softc *sc = arg; - atomic_store_rel_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_RECEIVED); + atomic_cmpset_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_PENDING, + SCHIZO_CDMA_STATE_RECEIVED); return (FILTER_HANDLED); } @@ -1153,7 +1158,10 @@ schizo_dmamap_sync(bus_dma_tag_t dt, bus struct timeval cur, end; struct schizo_iommu_state *sis = dt->dt_cookie; struct schizo_softc *sc = sis->sis_sc; - int res; + int i, res; +#ifdef INVARIANTS + register_t pil; +#endif if ((map->dm_flags & DMF_STREAMED) != 0) { iommu_dma_methods.dm_dmamap_sync(dt, map, op); @@ -1170,20 +1178,36 @@ schizo_dmamap_sync(bus_dma_tag_t dt, bus * but given that these disable interrupts we have to emulate * one. */ + critical_enter(); + KASSERT((rdpr(pstate) & PSTATE_IE) != 0, + ("%s: interrupts disabled", __func__)); + KASSERT((pil = rdpr(pil)) <= PIL_BRIDGE, + ("%s: PIL too low (%ld)", __func__, pil)); for (; atomic_cmpset_acq_32(&sc->sc_cdma_state, SCHIZO_CDMA_STATE_IDLE, SCHIZO_CDMA_STATE_PENDING) == 0;) ; - SCHIZO_PCI_WRITE_8(sc, sc->sc_cdma_clr, INTCLR_RECEIVED); - microuptime(&cur); - end.tv_sec = 15; - end.tv_usec = 0; - timevaladd(&end, &cur); - for (; (res = atomic_cmpset_rel_32(&sc->sc_cdma_state, - SCHIZO_CDMA_STATE_RECEIVED, SCHIZO_CDMA_STATE_IDLE)) == - 0 && timevalcmp(&cur, &end, <=);) + SCHIZO_PCI_WRITE_8(sc, sc->sc_cdma_map, + INTMAP_ENABLE(sc->sc_cdma_vec, PCPU_GET(mid))); + for (i = 0; i < SCHIZO_CDMA_TRIES; i++) { + if (i > 0) + printf("%s: try %d\n", __func__, i); + SCHIZO_PCI_WRITE_8(sc, sc->sc_cdma_clr, + INTCLR_RECEIVED); microuptime(&cur); + end.tv_sec = SCHIZO_CDMA_TIMEOUT; + end.tv_usec = 0; + timevaladd(&end, &cur); + for (; (res = atomic_cmpset_rel_32(&sc->sc_cdma_state, + SCHIZO_CDMA_STATE_RECEIVED, + SCHIZO_CDMA_STATE_IDLE)) == 0 && + timevalcmp(&cur, &end, <=);) + microuptime(&cur); + if (res != 0) + break; + } if (res == 0) panic("%s: DMA does not sync", __func__); + critical_exit(); } if ((op & BUS_DMASYNC_PREWRITE) != 0) @@ -1352,7 +1376,7 @@ schizo_alloc_resource(device_t bus, devi panic("%s: XXX: interrupt range", __func__); start = end = INTMAP_VEC(sc->sc_ign, end); return (bus_generic_alloc_resource(bus, child, type, rid, - start, end, count, flags)); + start, end, count, flags)); case SYS_RES_MEMORY: rm = &sc->sc_pci_mem_rman; break; Modified: stable/8/sys/sparc64/pci/schizovar.h ============================================================================== --- stable/8/sys/sparc64/pci/schizovar.h Wed Feb 1 21:28:13 2012 (r230894) +++ stable/8/sys/sparc64/pci/schizovar.h Wed Feb 1 21:28:16 2012 (r230895) @@ -59,7 +59,9 @@ struct schizo_softc { #define SCHIZO_FLAGS_BSWAR (1 << 0) #define SCHIZO_FLAGS_XMODE (1 << 1) + bus_addr_t sc_cdma_map; bus_addr_t sc_cdma_clr; + uint32_t sc_cdma_vec; uint32_t sc_cdma_state; #define SCHIZO_CDMA_STATE_IDLE (1 << 0) #define SCHIZO_CDMA_STATE_PENDING (1 << 1)