Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Apr 2016 13:15:34 +0000 (UTC)
From:      "Conrad E. Meyer" <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r297746 - head/sys/dev/ioat
Message-ID:  <201604091315.u39DFYqa066670@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Sat Apr  9 13:15:34 2016
New Revision: 297746
URL: https://svnweb.freebsd.org/changeset/base/297746

Log:
  ioat(4): ioat_get_dmaengine(): Add M_WAITOK mode
  
  Sponsored by:	EMC / Isilon Storage Division

Modified:
  head/sys/dev/ioat/ioat.c
  head/sys/dev/ioat/ioat.h
  head/sys/dev/ioat/ioat_internal.h
  head/sys/dev/ioat/ioat_test.c

Modified: head/sys/dev/ioat/ioat.c
==============================================================================
--- head/sys/dev/ioat/ioat.c	Sat Apr  9 13:01:40 2016	(r297745)
+++ head/sys/dev/ioat/ioat.c	Sat Apr  9 13:15:34 2016	(r297746)
@@ -314,6 +314,9 @@ ioat_detach(device_t device)
 
 	mtx_lock(IOAT_REFLK);
 	ioat->quiescing = TRUE;
+	ioat->destroying = TRUE;
+	wakeup(&ioat->quiescing);
+
 	ioat_channel[ioat->chan_idx] = NULL;
 
 	ioat_drain_locked(ioat);
@@ -739,18 +742,40 @@ ioat_reset_hw_task(void *ctx, int pendin
  * User API functions
  */
 bus_dmaengine_t
-ioat_get_dmaengine(uint32_t index)
+ioat_get_dmaengine(uint32_t index, int flags)
 {
-	struct ioat_softc *sc;
+	struct ioat_softc *ioat;
+
+	KASSERT((flags & ~(M_NOWAIT | M_WAITOK)) == 0,
+	    ("invalid flags: 0x%08x", flags));
+	KASSERT((flags & (M_NOWAIT | M_WAITOK)) != (M_NOWAIT | M_WAITOK),
+	    ("invalid wait | nowait"));
 
 	if (index >= ioat_channel_index)
 		return (NULL);
 
-	sc = ioat_channel[index];
-	if (sc == NULL || sc->quiescing)
+	ioat = ioat_channel[index];
+	if (ioat == NULL || ioat->destroying)
 		return (NULL);
 
-	return (&ioat_get(sc, IOAT_DMAENGINE_REF)->dmaengine);
+	if (ioat->quiescing) {
+		if ((flags & M_NOWAIT) != 0)
+			return (NULL);
+
+		mtx_lock(IOAT_REFLK);
+		while (ioat->quiescing && !ioat->destroying)
+			msleep(&ioat->quiescing, IOAT_REFLK, 0, "getdma", 0);
+		mtx_unlock(IOAT_REFLK);
+
+		if (ioat->destroying)
+			return (NULL);
+	}
+
+	/*
+	 * There's a race here between the quiescing check and HW reset or
+	 * module destroy.
+	 */
+	return (&ioat_get(ioat, IOAT_DMAENGINE_REF)->dmaengine);
 }
 
 void
@@ -1571,6 +1596,7 @@ ioat_reset_hw(struct ioat_softc *ioat)
 out:
 	mtx_lock(IOAT_REFLK);
 	ioat->quiescing = FALSE;
+	wakeup(&ioat->quiescing);
 	mtx_unlock(IOAT_REFLK);
 
 	if (error == 0)

Modified: head/sys/dev/ioat/ioat.h
==============================================================================
--- head/sys/dev/ioat/ioat.h	Sat Apr  9 13:01:40 2016	(r297745)
+++ head/sys/dev/ioat/ioat.h	Sat Apr  9 13:15:34 2016	(r297746)
@@ -68,8 +68,10 @@ typedef void (*bus_dmaengine_callback_t)
 
 /*
  * Called first to acquire a reference to the DMA channel
+ *
+ * Flags may be M_WAITOK or M_NOWAIT.
  */
-bus_dmaengine_t ioat_get_dmaengine(uint32_t channel_index);
+bus_dmaengine_t ioat_get_dmaengine(uint32_t channel_index, int flags);
 
 /* Release the DMA channel */
 void ioat_put_dmaengine(bus_dmaengine_t dmaengine);

Modified: head/sys/dev/ioat/ioat_internal.h
==============================================================================
--- head/sys/dev/ioat/ioat_internal.h	Sat Apr  9 13:01:40 2016	(r297745)
+++ head/sys/dev/ioat/ioat_internal.h	Sat Apr  9 13:15:34 2016	(r297746)
@@ -410,6 +410,7 @@ struct ioat_softc {
 	struct task		reset_task;
 
 	boolean_t		quiescing;
+	boolean_t		destroying;
 	boolean_t		is_resize_pending;
 	boolean_t		is_completion_pending;
 	boolean_t		is_reset_pending;

Modified: head/sys/dev/ioat/ioat_test.c
==============================================================================
--- head/sys/dev/ioat/ioat_test.c	Sat Apr  9 13:01:40 2016	(r297745)
+++ head/sys/dev/ioat/ioat_test.c	Sat Apr  9 13:15:34 2016	(r297746)
@@ -388,7 +388,7 @@ ioat_dma_test(void *arg)
 		return;
 	}
 
-	dmaengine = ioat_get_dmaengine(test->channel_index);
+	dmaengine = ioat_get_dmaengine(test->channel_index, M_NOWAIT);
 	if (dmaengine == NULL) {
 		ioat_test_log(0, "Couldn't acquire dmaengine\n");
 		test->status[IOAT_TEST_NO_DMA_ENGINE]++;



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