Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 May 2014 17:20:45 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r265690 - head/sys/arm/xilinx
Message-ID:  <201405081720.s48HKjCM034671@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Thu May  8 17:20:45 2014
New Revision: 265690
URL: http://svnweb.freebsd.org/changeset/base/265690

Log:
  Use edge-triggered interrupts rather than polling loops to avoid missing
  transitions of the INIT_B line.  Also, release the mutex during uiomove().
  
  Submitted by:	Thomas Skibo <ThomasSkibo@sbcglobal.net>

Modified:
  head/sys/arm/xilinx/zy7_devcfg.c

Modified: head/sys/arm/xilinx/zy7_devcfg.c
==============================================================================
--- head/sys/arm/xilinx/zy7_devcfg.c	Thu May  8 16:59:36 2014	(r265689)
+++ head/sys/arm/xilinx/zy7_devcfg.c	Thu May  8 17:20:45 2014	(r265690)
@@ -267,24 +267,35 @@ zy7_devcfg_reset_pl(struct zy7_devcfg_so
 
 	devcfg_ctl = RD4(sc, ZY7_DEVCFG_CTRL);
 
+	/* Clear sticky bits and set up INIT signal positive edge interrupt. */
+	WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
+	WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE);
+
 	/* Deassert PROG_B (active low). */
 	devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B;
 	WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl);
 
-	/* Wait for INIT_B deasserted (active low). */
-	tries = 0;
-	while ((RD4(sc, ZY7_DEVCFG_STATUS) &
-		ZY7_DEVCFG_STATUS_PCFG_INIT) == 0) {
-		if (++tries >= 100)
-			return (EIO);
-		DELAY(5);
+	/*
+	 * Wait for INIT to assert.  If it is already asserted, we may not get
+	 * an edge interrupt so cancel it and continue.
+	 */
+	if ((RD4(sc, ZY7_DEVCFG_STATUS) &
+	     ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) {
+		/* Already asserted.  Cancel interrupt. */
+		WR4(sc, ZY7_DEVCFG_INT_MASK, ~0);
+	}
+	else {
+		/* Wait for positive edge interrupt. */
+		err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i1", hz);
+		if (err != 0)
+			return (err);
 	}
-
-	/* Reassert PROG_B. */
+	
+	/* Reassert PROG_B (active low). */
 	devcfg_ctl &= ~ZY7_DEVCFG_CTRL_PCFG_PROG_B;
 	WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl);
 
-	/* Wait for INIT_B asserted. */
+	/* Wait for INIT deasserted.  This happens almost instantly. */
 	tries = 0;
 	while ((RD4(sc, ZY7_DEVCFG_STATUS) &
 		ZY7_DEVCFG_STATUS_PCFG_INIT) != 0) {
@@ -293,7 +304,7 @@ zy7_devcfg_reset_pl(struct zy7_devcfg_so
 		DELAY(5);
 	}
 
-	/* Clear sticky bits and set up INIT_B positive edge interrupt. */
+	/* Clear sticky bits and set up INIT positive edge interrupt. */
 	WR4(sc, ZY7_DEVCFG_INT_STATUS, ZY7_DEVCFG_INT_ALL);
 	WR4(sc, ZY7_DEVCFG_INT_MASK, ~ZY7_DEVCFG_INT_PCFG_INIT_PE);
 
@@ -301,11 +312,11 @@ zy7_devcfg_reset_pl(struct zy7_devcfg_so
 	devcfg_ctl |= ZY7_DEVCFG_CTRL_PCFG_PROG_B;
 	WR4(sc, ZY7_DEVCFG_CTRL, devcfg_ctl);
 
-	/* Wait for INIT_B deasserted indicating FPGA internal initialization
-	 * is complete.  This takes much longer than the previous waits for
-	 * INIT_B transition (on the order of 700us).
+	/*
+	 * Wait for INIT asserted indicating FPGA internal initialization
+	 * is complete.
 	 */
-	err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7in", hz);
+	err = mtx_sleep(sc, &sc->sc_mtx, PCATCH, "zy7i2", hz);
 	if (err != 0)
 		return (err);
 
@@ -404,7 +415,9 @@ zy7_devcfg_write(struct cdev *dev, struc
 
 		/* uiomove the data from user buffer to our dma map. */
 		segsz = MIN(PAGE_SIZE, uio->uio_resid);
+		DEVCFG_SC_UNLOCK(sc);
 		err = uiomove(dma_mem, segsz, uio);
+		DEVCFG_SC_LOCK(sc);
 		if (err != 0)
 			break;
 



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