Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Jan 2012 22:42:34 +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: r230664 - head/sys/sparc64/pci
Message-ID:  <201201282242.q0SMgY5o001992@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Sat Jan 28 22:42:33 2012
New Revision: 230664
URL: http://svn.freebsd.org/changeset/base/230664

Log:
  As it turns out r227960 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:
  head/sys/sparc64/pci/schizo.c
  head/sys/sparc64/pci/schizovar.h

Modified: head/sys/sparc64/pci/schizo.c
==============================================================================
--- head/sys/sparc64/pci/schizo.c	Sat Jan 28 22:24:59 2012	(r230663)
+++ head/sys/sparc64/pci/schizo.c	Sat Jan 28 22:42:33 2012	(r230664)
@@ -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: head/sys/sparc64/pci/schizovar.h
==============================================================================
--- head/sys/sparc64/pci/schizovar.h	Sat Jan 28 22:24:59 2012	(r230663)
+++ head/sys/sparc64/pci/schizovar.h	Sat Jan 28 22:42:33 2012	(r230664)
@@ -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)



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