summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2006-06-20 20:54:13 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2006-06-20 20:54:13 +0000
commitaeeb017bd6261c97c3dac20c24c14a8851f595cd (patch)
treed8e5ccc7371d1f67ab824f045af9fcf1f1446b20
parentf05446648bd84e435be17c2d4bd1f8347f10e12c (diff)
Notes
-rw-r--r--sys/dev/digi/digi.c6
-rw-r--r--sys/kern/kern_linker.c32
-rw-r--r--sys/kern/subr_firmware.c4
-rw-r--r--sys/sys/linker.h8
4 files changed, 43 insertions, 7 deletions
diff --git a/sys/dev/digi/digi.c b/sys/dev/digi/digi.c
index 283c2cfa8c3f..2eb72b049a75 100644
--- a/sys/dev/digi/digi.c
+++ b/sys/dev/digi/digi.c
@@ -795,7 +795,7 @@ digi_loadmoduledata(struct digi_softc *sc)
free(sym, M_TEMP);
if (symptr == NULL) {
printf("digi_%s.ko: Symbol `%s' not found\n", sc->module, sym);
- linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ linker_release_module(NULL, NULL, lf);
return (EINVAL);
}
@@ -803,7 +803,7 @@ digi_loadmoduledata(struct digi_softc *sc)
if (digi_mod->dm_version != DIGI_MOD_VERSION) {
printf("digi_%s.ko: Invalid version %d (need %d)\n",
sc->module, digi_mod->dm_version, DIGI_MOD_VERSION);
- linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ linker_release_module(NULL, NULL, lf);
return (EINVAL);
}
@@ -825,7 +825,7 @@ digi_loadmoduledata(struct digi_softc *sc)
bcopy(digi_mod->dm_link.data, sc->link.data, sc->link.size);
}
- linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+ linker_release_module(NULL, NULL, lf);
return (0);
}
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 003b70816878..6eb62b6cfda5 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -415,14 +415,44 @@ linker_reference_module(const char *modname, struct mod_depend *verinfo,
linker_file_t *result)
{
modlist_t mod;
+ int error;
+ mtx_lock(&Giant);
if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
*result = mod->container;
(*result)->refs++;
+ mtx_unlock(&Giant);
return (0);
}
- return (linker_load_module(NULL, modname, NULL, verinfo, result));
+ error = linker_load_module(NULL, modname, NULL, verinfo, result);
+ mtx_unlock(&Giant);
+ return (error);
+}
+
+int
+linker_release_module(const char *modname, struct mod_depend *verinfo,
+ linker_file_t lf)
+{
+ modlist_t mod;
+ int error;
+
+ mtx_lock(&Giant);
+ if (lf == NULL) {
+ KASSERT(modname != NULL,
+ ("linker_release_module: no file or name"));
+ mod = modlist_lookup2(modname, verinfo);
+ if (mod == NULL) {
+ mtx_unlock(&Giant);
+ return (ESRCH);
+ }
+ lf = mod->container;
+ } else
+ KASSERT(modname == NULL && verinfo == NULL,
+ ("linker_release_module: both file and name"));
+ error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
+ mtx_unlock(&Giant);
+ return (error);
}
static linker_file_t
diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c
index 0c238bf03fef..3f7fb64145ec 100644
--- a/sys/kern/subr_firmware.c
+++ b/sys/kern/subr_firmware.c
@@ -195,9 +195,7 @@ again:
"load firmware image %s\n", __func__, imagename);
return NULL;
}
- mtx_lock(&Giant); /* XXX */
(void) linker_reference_module(imagename, NULL, &result);
- mtx_unlock(&Giant); /* XXX */
requested_load = 1;
goto again; /* sort of an Algol-style for loop */
}
@@ -227,7 +225,7 @@ unloadentry(void *unused1, int unused2)
fp->file = NULL;
mtx_unlock(&firmware_mtx);
- linker_file_unload(file, LINKER_UNLOAD_NORMAL);
+ linker_release_module(NULL, NULL, file);
mtx_lock(&firmware_mtx);
}
diff --git a/sys/sys/linker.h b/sys/sys/linker.h
index 8e3c1faffb21..39311ff66509 100644
--- a/sys/sys/linker.h
+++ b/sys/sys/linker.h
@@ -116,6 +116,14 @@ int linker_reference_module(const char* _modname, struct mod_depend *_verinfo,
linker_file_t* _result);
/*
+ * Release a reference to a module, unloading it if there are no more
+ * references. Note that one should either provide a module name and
+ * optional version info or a linker file, but not both.
+ */
+int linker_release_module(const char *_modname, struct mod_depend *_verinfo,
+ linker_file_t _file);
+
+/*
* Iterate over all of the currently loaded linker files calling the
* predicate function while the function returns 0. Returns the value
* returned by the last predicate function.