Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Nov 2009 11:27:07 +0000 (UTC)
From:      Takahashi Yoshihiro <nyan@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r199220 - head/sys/pc98/cbus
Message-ID:  <200911121127.nACBR7gn029232@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nyan
Date: Thu Nov 12 11:27:07 2009
New Revision: 199220
URL: http://svn.freebsd.org/changeset/base/199220

Log:
  MFi386: revision 199104
  
    Make isa_dma functions MPSAFE by introducing its own private lock.

Modified:
  head/sys/pc98/cbus/cbus_dma.c

Modified: head/sys/pc98/cbus/cbus_dma.c
==============================================================================
--- head/sys/pc98/cbus/cbus_dma.c	Thu Nov 12 10:59:00 2009	(r199219)
+++ head/sys/pc98/cbus/cbus_dma.c	Thu Nov 12 11:27:07 2009	(r199220)
@@ -72,6 +72,8 @@ static u_int8_t	dma_bounced = 0;
 static u_int8_t	dma_busy = 0;		/* Used in isa_dmastart() */
 static u_int8_t	dma_inuse = 0;		/* User for acquire/release */
 static u_int8_t dma_auto_mode = 0;
+static struct mtx isa_dma_lock;
+MTX_SYSINIT(isa_dma_lock, &isa_dma_lock, "isa DMA lock", MTX_DEF);
 
 #define VALID_DMA_MASK (3)
 
@@ -93,22 +95,31 @@ isa_dma_init(int chan, u_int bouncebufsi
 		panic("isa_dma_init: impossible request"); 
 #endif
 
-	dma_bouncebufsize[chan] = bouncebufsize;
 
 	/* Try malloc() first.  It works better if it works. */
 	buf = malloc(bouncebufsize, M_DEVBUF, flag);
 	if (buf != NULL) {
-		if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) {
-			dma_bouncebuf[chan] = buf;
-			return (0);
+		if (isa_dmarangecheck(buf, bouncebufsize, chan) != 0) {
+			free(buf, M_DEVBUF);
+			buf = NULL;
 		}
-		free(buf, M_DEVBUF);
 	}
-	buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful,
+
+	if (buf == NULL) {
+		buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful,
 			   1ul, chan & 4 ? 0x20000ul : 0x10000ul);
+	}
+
 	if (buf == NULL)
 		return (ENOMEM);
+
+	mtx_lock(&isa_dma_lock);
+
+	dma_bouncebufsize[chan] = bouncebufsize;
 	dma_bouncebuf[chan] = buf;
+
+	mtx_unlock(&isa_dma_lock);
+
 	return (0);
 }
 
@@ -125,12 +136,15 @@ isa_dma_acquire(chan)
 		panic("isa_dma_acquire: channel out of range");
 #endif
 
+	mtx_lock(&isa_dma_lock);
 	if (dma_inuse & (1 << chan)) {
 		printf("isa_dma_acquire: channel %d already in use\n", chan);
+		mtx_unlock(&isa_dma_lock);
 		return (EBUSY);
 	}
 	dma_inuse |= (1 << chan);
 	dma_auto_mode &= ~(1 << chan);
+	mtx_unlock(&isa_dma_lock);
 
 	return (0);
 }
@@ -147,8 +161,11 @@ isa_dma_release(chan)
 	if (chan & ~VALID_DMA_MASK)
 		panic("isa_dma_release: channel out of range");
 
+	mtx_lock(&isa_dma_lock);
 	if ((dma_inuse & (1 << chan)) == 0)
 		printf("isa_dma_release: channel %d not in use\n", chan);
+#else
+	mtx_lock(&isa_dma_lock);
 #endif
 
 	if (dma_busy & (1 << chan)) {
@@ -163,6 +180,8 @@ isa_dma_release(chan)
 
 	dma_inuse &= ~(1 << chan);
 	dma_auto_mode &= ~(1 << chan);
+
+	mtx_unlock(&isa_dma_lock);
 }
 
 /*
@@ -175,8 +194,11 @@ isa_dmastart(int flags, caddr_t addr, u_
 	vm_paddr_t phys;
 	int waport;
 	caddr_t newaddr;
+	int dma_range_checked;
 
-	GIANT_REQUIRED;
+	/* translate to physical */
+	phys = pmap_extract(kernel_pmap, (vm_offset_t)addr);
+	dma_range_checked = isa_dmarangecheck(addr, nbytes, chan);
 
 #ifdef DIAGNOSTIC
 	if (chan & ~VALID_DMA_MASK)
@@ -186,8 +208,11 @@ isa_dmastart(int flags, caddr_t addr, u_
 	    || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1)))
 		panic("isa_dmastart: impossible request");
 
+	mtx_lock(&isa_dma_lock);
 	if ((dma_inuse & (1 << chan)) == 0)
 		printf("isa_dmastart: channel %d not acquired\n", chan);
+#else
+	mtx_lock(&isa_dma_lock);
 #endif
 
 #if 0
@@ -202,7 +227,7 @@ isa_dmastart(int flags, caddr_t addr, u_
 
 	dma_busy |= (1 << chan);
 
-	if (isa_dmarangecheck(addr, nbytes, chan)) {
+	if (dma_range_checked) {
 		if (dma_bouncebuf[chan] == NULL
 		    || dma_bouncebufsize[chan] < nbytes)
 			panic("isa_dmastart: bad bounce buffer"); 
@@ -215,9 +240,6 @@ isa_dmastart(int flags, caddr_t addr, u_
 		addr = newaddr;
 	}
 
-	/* translate to physical */
-	phys = pmap_extract(kernel_pmap, (vm_offset_t)addr);
-
 	if (flags & ISADMA_RAW) {
 	    dma_auto_mode |= (1 << chan);
 	} else { 
@@ -255,6 +277,8 @@ isa_dmastart(int flags, caddr_t addr, u_
 
 	/* unmask channel */
 	outb(DMA1_SMSK, chan);
+
+	mtx_unlock(&isa_dma_lock);
 }
 
 void
@@ -275,6 +299,7 @@ isa_dmadone(int flags, caddr_t addr, int
 		printf("isa_dmadone: channel %d not acquired\n", chan);
 #endif
 
+	mtx_lock(&isa_dma_lock);
 	if (((dma_busy & (1 << chan)) == 0) && 
 	    (dma_auto_mode & (1 << chan)) == 0 )
 		printf("isa_dmadone: channel %d not busy\n", chan);
@@ -290,6 +315,7 @@ isa_dmadone(int flags, caddr_t addr, int
 		dma_bounced &= ~(1 << chan);
 	}
 	dma_busy &= ~(1 << chan);
+	mtx_unlock(&isa_dma_lock);
 }
 
 /*
@@ -306,8 +332,6 @@ isa_dmarangecheck(caddr_t va, u_int leng
 	vm_offset_t endva;
 	u_int dma_pgmsk = (chan & 4) ?  ~(128*1024-1) : ~(64*1024-1);
 
-	GIANT_REQUIRED;
-
 	endva = (vm_offset_t)round_page((vm_offset_t)va + length);
 	for (; va < (caddr_t) endva ; va += PAGE_SIZE) {
 		phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va));
@@ -364,13 +388,15 @@ isa_dmarangecheck(caddr_t va, u_int leng
  * or -1 if the channel requested is not active.
  *
  */
-int
-isa_dmastatus(int chan)
+static int
+isa_dmastatus_locked(int chan)
 {
 	u_long	cnt = 0;
 	int	ffport, waport;
 	u_long	low1, high1, low2, high2;
 
+	mtx_assert(&isa_dma_lock, MA_OWNED);
+
 	/* channel active? */
 	if ((dma_inuse & (1 << chan)) == 0) {
 		printf("isa_dmastatus: channel %d not active\n", chan);
@@ -411,6 +437,18 @@ isa_dmastatus(int chan)
 	return(cnt);
 }
 
+int
+isa_dmastatus(int chan)
+{
+	int status;
+
+	mtx_lock(&isa_dma_lock);
+	status = isa_dmastatus_locked(chan);
+	mtx_unlock(&isa_dma_lock);
+
+	return (status);
+}
+
 /*
  * Reached terminal count yet ?
  */
@@ -427,19 +465,27 @@ isa_dmatc(int chan)
 int
 isa_dmastop(int chan) 
 {
+	int status;
+
+	mtx_lock(&isa_dma_lock);
 	if ((dma_inuse & (1 << chan)) == 0)
 		printf("isa_dmastop: channel %d not acquired\n", chan);  
 
 	if (((dma_busy & (1 << chan)) == 0) &&
 	    ((dma_auto_mode & (1 << chan)) == 0)) {
 		printf("chan %d not busy\n", chan);
+		mtx_unlock(&isa_dma_lock);
 		return -2 ;
 	}
     
 	if ((chan & 4) == 0)
 		outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */);
 
-	return(isa_dmastatus(chan));
+	status = isa_dmastatus_locked(chan);
+
+	mtx_unlock(&isa_dma_lock);
+
+	return (status);
 }
 
 /*



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