svn commit: r344505 - head/sys/dev/flash
Ian Lepore
ian at FreeBSD.org
Sun Feb 24 23:08:54 UTC 2019
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);
More information about the svn-src-all
mailing list