Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Feb 2018 16:28: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: r329911 - head/sys/dev/flash
Message-ID:  <201802241628.w1OGSjfe058027@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Feb 24 16:28:45 2018
New Revision: 329911
URL: https://svnweb.freebsd.org/changeset/base/329911

Log:
  Add a functional detach() routine, to make things kldunload-friendly.

Modified:
  head/sys/dev/flash/mx25l.c

Modified: head/sys/dev/flash/mx25l.c
==============================================================================
--- head/sys/dev/flash/mx25l.c	Sat Feb 24 16:01:21 2018	(r329910)
+++ head/sys/dev/flash/mx25l.c	Sat Feb 24 16:28:45 2018	(r329911)
@@ -89,8 +89,13 @@ struct mx25l_softc 
 	struct proc	*sc_p;
 	struct bio_queue_head sc_bio_queue;
 	unsigned int	sc_flags;
+	unsigned int	sc_taskstate;
 };
 
+#define	TSTATE_STOPPED	0
+#define	TSTATE_STOPPING	1
+#define	TSTATE_RUNNING	2
+
 #define M25PXX_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	M25PXX_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define M25PXX_LOCK_INIT(_sc) \
@@ -527,6 +532,8 @@ mx25l_attach(device_t dev)
 	bioq_init(&sc->sc_bio_queue);
 
 	kproc_create(&mx25l_task, sc, &sc->sc_p, 0, 0, "task: mx25l flash");
+	sc->sc_taskstate = TSTATE_RUNNING;
+
 	device_printf(sc->sc_dev, "%s, sector %d bytes, %d sectors\n", 
 	    ident->name, ident->sectorsize, ident->sectorcount);
 
@@ -536,8 +543,33 @@ mx25l_attach(device_t dev)
 static int
 mx25l_detach(device_t dev)
 {
+	struct mx25l_softc *sc;
+	int err;
 
-	return (EIO);
+	sc = device_get_softc(dev);
+	err = 0;
+
+	M25PXX_LOCK(sc);
+	if (sc->sc_taskstate == TSTATE_RUNNING) {
+		sc->sc_taskstate = TSTATE_STOPPING;
+		wakeup(sc);
+		while (err == 0 && sc->sc_taskstate != TSTATE_STOPPED) {
+			err = msleep(sc, &sc->sc_mtx, 0, "mx25dt", hz * 3);
+			if (err != 0) {
+				sc->sc_taskstate = TSTATE_RUNNING;
+				device_printf(dev,
+				    "Failed to stop queue task\n");
+			}
+		}
+	}
+	M25PXX_UNLOCK(sc);
+
+	if (err == 0 && sc->sc_taskstate == TSTATE_STOPPED) {
+		disk_destroy(sc->sc_disk);
+		bioq_flush(&sc->sc_bio_queue, NULL, ENXIO);
+		M25PXX_LOCK_DESTROY(sc);
+	}
+	return (err);
 }
 
 static int
@@ -605,9 +637,15 @@ mx25l_task(void *arg)
 		dev = sc->sc_dev;
 		M25PXX_LOCK(sc);
 		do {
+			if (sc->sc_taskstate == TSTATE_STOPPING) {
+				sc->sc_taskstate = TSTATE_STOPPED;
+				M25PXX_UNLOCK(sc);
+				wakeup(sc);
+				kproc_exit(0);
+			}
 			bp = bioq_first(&sc->sc_bio_queue);
 			if (bp == NULL)
-				msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
+				msleep(sc, &sc->sc_mtx, PRIBIO, "mx25jq", 0);
 		} while (bp == NULL);
 		bioq_remove(&sc->sc_bio_queue, bp);
 		M25PXX_UNLOCK(sc);



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