Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Feb 2019 23:08:53 +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: r344505 - head/sys/dev/flash
Message-ID:  <201902242308.x1ON8rUe004946@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Feb 24 23:08:53 2019
New Revision: 344505
URL: https://svnweb.freebsd.org/changeset/base/344505

Log:
  Add a functional detach() implementation to make module unloading possible.

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

Modified: head/sys/dev/flash/at45d.c
==============================================================================
--- head/sys/dev/flash/at45d.c	Sun Feb 24 22:49:56 2019	(r344504)
+++ head/sys/dev/flash/at45d.c	Sun Feb 24 23:08:53 2019	(r344505)
@@ -65,11 +65,16 @@ struct at45d_softc
 	struct proc		*p;
 	struct intr_config_hook	config_intrhook;
 	device_t		dev;
+	u_int			taskstate;
 	uint16_t		pagecount;
 	uint16_t		pageoffset;
 	uint16_t		pagesize;
 };
 
+#define	TSTATE_STOPPED	0
+#define	TSTATE_STOPPING	1
+#define	TSTATE_RUNNING	2
+
 #define	AT45D_LOCK(_sc)			mtx_lock(&(_sc)->sc_mtx)
 #define	AT45D_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define	AT45D_LOCK_INIT(_sc) \
@@ -209,8 +214,33 @@ at45d_attach(device_t dev)
 static int
 at45d_detach(device_t dev)
 {
+	struct at45d_softc *sc;
+	int err;
 
-	return (EBUSY) /* XXX */;
+	sc = device_get_softc(dev);
+	err = 0;
+
+	AT45D_LOCK(sc);
+	if (sc->taskstate == TSTATE_RUNNING) {
+		sc->taskstate = TSTATE_STOPPING;
+		wakeup(sc);
+		while (err == 0 && sc->taskstate != TSTATE_STOPPED) {
+			err = msleep(sc, &sc->sc_mtx, 0, "at45dt", hz * 3);
+			if (err != 0) {
+				sc->taskstate = TSTATE_RUNNING;
+				device_printf(sc->dev,
+				    "Failed to stop queue task\n");
+			}
+		}
+	}
+	AT45D_UNLOCK(sc);
+
+	if (err == 0 && sc->taskstate == TSTATE_STOPPED) {
+		disk_destroy(sc->disk);
+		bioq_flush(&sc->bio_queue, NULL, ENXIO);
+		AT45D_LOCK_DESTROY(sc);
+	}
+	return (err);
 }
 
 static void
@@ -266,6 +296,7 @@ at45d_delayed_attach(void *xsc)
 		bioq_init(&sc->bio_queue);
 		kproc_create(&at45d_task, sc, &sc->p, 0, 0,
 		    "task: at45d flash");
+		sc->taskstate = TSTATE_RUNNING;
 		device_printf(sc->dev, "%s, %d bytes per page, %d pages\n",
 		    ident->name, pagesize, ident->pagecount);
 	}
@@ -324,6 +355,12 @@ at45d_task(void *arg)
 	for (;;) {
 		AT45D_LOCK(sc);
 		do {
+			if (sc->taskstate == TSTATE_STOPPING) {
+				sc->taskstate = TSTATE_STOPPED;
+				AT45D_UNLOCK(sc);
+				wakeup(sc);
+				kproc_exit(0);
+			}
 			bp = bioq_takefirst(&sc->bio_queue);
 			if (bp == NULL)
 				msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);



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